Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!ames!cit-vax!usc-oberon!sdcrdcf!trwrb!desint!geoff From: geoff@desint.UUCP Newsgroups: net.sources Subject: ispell repost (less dict) 02/02: enhanced, fixed Message-ID: <297@desint.UUCP> Date: Sat, 14-Mar-87 05:04:14 EST Article-I.D.: desint.297 Posted: Sat Mar 14 05:04:14 1987 Date-Received: Sun, 15-Mar-87 05:07:40 EST Reply-To: geoff@desint.UUCP (Geoff Kuenning) Followup-To: net.sources.bugs Distribution: world Organization: Interrupt Technology Corp., Manhattan Beach, CA Lines: 2749 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # config.h # good.c # hash.c # ispell.c # ispell.h # lookup.c # term.c # tree.c # This archive created: Sat Mar 14 00:59:10 1987 export PATH; PATH=/bin:$PATH echo shar: extracting "'config.h'" '(2543 characters)' if test -f 'config.h' then echo shar: will not over-write existing file "'config.h'" else sed 's/^X //' << \SHAR_EOF > 'config.h' X /* X ** library directory for hash table(s) / default hash table name X ** If you intend to use multiple dictionary files, I would suggest X ** LIBDIR be a directory which will contain nothing else, so sensible X ** names can be constructed for the -d option without conflict. X */ X #define LIBDIR "/usr/local/lib" X #define DEFHASH "ispell.hash" X X #ifdef SYSV X #define index strchr X #endif X X /* environment variable for user's word list */ X #define PDICTVAR "WORDLIST" X X /* default word list */ X #define DEFPDICT "ispell.words" X X /* mktemp template for temporary file - MUST contain 6 consecutive X's */ X #define TEMPNAME "/usr/tmp/spellXXXXXX" X X /* default dictionary file */ X #define DEFDICT "dict.191" X X /* define LOOK if look(1) command is available */ X #define LOOK X X /* path to egrep (use speeded up version if available) */ X #define EGREPCMD "/usr/local/egrep -i" X X /* path to wordlist for Lookup command (typically /usr/dict/{words|web2} */ X #define WORDS "/usr/dict/web2" X X /* buffer size to use for file names if not in sys/param.h */ X #ifndef MAXPATHLEN X #define MAXPATHLEN 240 X #endif X X /* word length allowed in dictionary by buildhash */ X #define WORDLEN 30 X X /* hash table magic number */ X #define MAGIC 1 X X /* suppress the 8-bit character feature */ X #define NO8BIT X X /* Approximate number of words in the full dictionary, after munching. X ** Err on the high side unless you are very short on memory, in which X ** case you might want to change the tables in tree.c and also increase X ** MAXPCT. X ** X ** (Note: dict.191 is a bit over 15000 words. dict.191 munched with X ** /usr/dict/words is a little over 28000). X */ X #define BIG_DICT 29000 X X /* X ** Maximum hash table fullness percentage. Larger numbers trade space X ** for time. X **/ X #define MAXPCT 70 /* Expand table when 70% full */ X X /* X ** the isXXXX macros normally only check ASCII range. These are used X ** instead for text characters, which we assume may be 8 bit. The X ** NO8BIT ifdef shuts off significance of 8 bit characters. If you are X ** using this, and your ctype.h already masks, you can simplify. X */ X #ifdef NO8BIT X #define myupper(X) isupper((X)&0x7f) X #define mylower(X) islower((X)&0x7f) X #define myspace(X) isspace((X)&0x7f) X #define myalpha(X) isalpha((X)&0x7f) X #else X #define myupper(X) (!((X)&0x80) && isupper(X)) X #define mylower(X) (!((X)&0x80) && islower(X)) X #define myspace(X) (!((X)&0x80) && isspace(X)) X #define myalpha(X) (!((X)&0x80) && isalpha(X)) X #endif X X /* X ** the NOPARITY mask is applied to user input characters from the terminal X ** in order to mask out the parity bit. X */ X #define NOPARITY 0x7f SHAR_EOF if test 2543 -ne "`wc -c < 'config.h'`" then echo shar: error transmitting "'config.h'" '(should have been 2543 characters)' fi fi # end of overwriting check echo shar: extracting "'good.c'" '(10274 characters)' if test -f 'good.c' then echo shar: will not over-write existing file "'good.c'" else sed 's/^X //' << \SHAR_EOF > 'good.c' X /* -*- Mode:Text -*- */ X X /* X * good.c - see if a word or its root word X * is in the dictionary. X * X * Pace Willisson, 1983 X */ X X #include X #include X #include "ispell.h" X #include "config.h" X X struct dent *lookup(); X X static int wordok; X X extern int cflag; X X good (w) X register char *w; X { X char nword[100]; X register char *p, *q; X register n; X X for (p = w, q = nword; *p; p++, q++) { X if (mylower (*p)) X *q = toupper (*p); X else X *q = *p; X } X *q = 0; X X rootword[0] = 0; X X if (cflag) X printf ("%s\n", nword); X else if (lookup (nword, q - nword, 1) != NULL) { X return (1); X } X X /* try stripping off suffixes */ X X n = strlen (w); X if (n == 1) X return (1); X X if (n < 4) X return 0; X X wordok = 0; X X /* this part from 'check.mid' */ X switch (q[-1]) { X case 'D': d_ending (nword); break; /* FOR "CREATED", "IMPLIED", "CROSSED" */ X case 'T': t_ending (nword); break; /* FOR "LATEST", "DIRTIEST", "BOLDEST" */ X case 'R': r_ending (nword); break; /* FOR "LATER", "DIRTIER", "BOLDER" */ X case 'G': g_ending (nword); break; /* FOR "CREATING", "FIXING" */ X case 'H': h_ending (nword); break; /* FOR "HUNDREDTH", "TWENTIETH" */ X case 'S': s_ending (nword); break; /* FOR ALL SORTS OF THINGS ENDING IN "S" */ X case 'N': n_ending (nword); break; /* "TIGHTEN", "CREATION", "MULIPLICATION" */ X case 'E': e_ending (nword); break; /* FOR "CREATIVE", "PREVENTIVE" */ X case 'Y': y_ending (nword); break; /* FOR "QUICKLY" */ X default: X break; X } X X if (wordok) { X strcpy (rootword, lastdent->word); X } X return (wordok); X X } X X X g_ending (w) X char *w; X { X char *p; X struct dent *dent; X X p = w + strlen (w) - 3; /* if the word ends in 'ing', then *p == 'i' */ X X if (strcmp (p, "ING") != 0) X return; X X *p = 'E'; /* change I to E, like in CREATING */ X *(p+1) = 0; X X if (strlen (w) < 2) X return; X X if (cflag) X printf ("%s/G\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->g_flag) { X wordok = 1; X return; X } X X X *p = 0; X X if (strlen (w) < 2) X return; X X if (p[-1] == 'E') X return; /* this stops CREATEING */ X X if (cflag) X printf ("%s/G\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL) { X if (dent->g_flag) X wordok = 1; X return; X } X return; X } X X d_ending (w) X char *w; X { X char *p; X struct dent *dent; X X p = w + strlen (w) - 2; X X if (strcmp (p, "ED") != 0) X return; X X p[1] = 0; /* kill 'D' */ X X if (cflag) X printf ("%s/D\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL) { /* eg CREATED */ X if (dent->d_flag) X wordok = 1; X return; X } X X if (strlen (w) < 3) X return; X X p[0] = 0; X p--; X X /* ED is now completely gone */ X X if (p[0] == 'I' && !vowel (p[-1])) { X p[0] = 'Y'; X if (cflag) X printf ("%s/D\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->d_flag) { X wordok = 1; X return; X } X p[0] = 'I'; X } X X if ((p[0] != 'E' && p[0] != 'Y') || X (p[0] == 'Y' && vowel (p[-1]))) { X if (cflag) X printf ("%s/D\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL) { X if (dent->d_flag) X wordok = 1; X return; X } X } X } X X t_ending (w) X char *w; X { X X char *p; X struct dent *dent; X X p = w + strlen (w) - 3; X X if (strcmp (p, "EST") != 0) X return; X X p[1] = 0; /* kill 'S' */ X X if (cflag) X printf ("%s/T\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->t_flag) { X wordok = 1; X return; X } X X if (strlen (w) < 3) X return; X X p[0] = 0; X p--; X X /* EST is now completely gone */ X X if (p[0] == 'I' && !vowel (p[-1])) { X p[0] = 'Y'; X if (cflag) X printf ("%s/T\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->t_flag) { X wordok = 1; X return; X } X p[0] = 'I'; X } X X if ((p[0] != 'E' && p[0] != 'Y') || X (p[0] == 'Y' && vowel (p[-1]))) { X if (cflag) X printf ("%s/T\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL) { X if (dent->t_flag) X wordok = 1; X return; X } X } X X } X X X r_ending (w) X char *w; X { X char *p; X struct dent *dent; X X p = w + strlen (w) - 2; X X if (strcmp (p, "ER") != 0) X return; X X p[1] = 0; /* kill 'R' */ X X if (cflag) X printf ("%s/R\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->r_flag) { X wordok = 1; X return; X } X X if (strlen (w) < 3) X return; X X p[0] = 0; X p--; X X /* ER is now completely gone */ X X if (p[0] == 'I' && !vowel (p[-1])) { X p[0] = 'Y'; X if (cflag) X printf ("%s/R\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->r_flag) { X wordok = 1; X return; X } X p[0] = 'I'; X } X X if ((p[0] != 'E' && p[0] != 'Y') || X (p[0] == 'Y' && vowel (p[-1]))) { X if (cflag) X printf ("%s/R\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL) { X if (dent->r_flag) X wordok = 1; X return; X } X } X X } X X h_ending (w) X char *w; X { X char *p; X struct dent *dent; X X p = w + strlen (w) - 2; X X if (strcmp (p, "TH") != 0) X return; X X *p = 0; X X p -= 2; X X if (p[1] != 'Y') { X if (cflag) X printf ("%s/H\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->h_flag) X wordok = 1; X } X X if (strcmp (p, "IE") != 0) X return; X X p[0] = 'Y'; X p[1] = 0; X X if (cflag) X printf ("%s/H\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL) X if (dent->h_flag) X wordok = 1; X X } X X /* X * check for flags: X, J, Z, S, P, M X * X * X -ions or -ications or -ens X * J -ings X * Z -ers or -iers X * S -ies or -es or -s X * P -iness or -ness X * M -'S X */ X X s_ending (w) X char *w; X { X char *p; X struct dent *dent; X X p = w + strlen (w); X X p[-1] = 0; X X if (index ("SXZHY", p[-2]) == NULL || (p[-2] == 'Y' && vowel (p[-3]))) { X if (cflag) X printf ("%s/S\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->s_flag) { X wordok = 1; X return; X } X } X X X switch (p[-2]) { /* letter before S */ X case 'N': /* X */ X if (strcmp (p-4, "ION") == 0) { X p[-4] = 'E'; X p[-3] = 0; X if (cflag) X printf ("%s/X\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->x_flag) { X wordok = 1; X return; X } X } X if (strcmp (p-8, "ICATE") == 0) { X p[-8] = 'Y'; X p[-7] = 0; X if (cflag) X printf ("%s/X\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->x_flag) X wordok = 1; X return; X } X if (strcmp (p-3, "EN") == 0 && p[-4] != 'E' && p[-4] != 'Y') { X p[-3] = 0; X if (cflag) X printf ("%s/X\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->x_flag) X wordok = 1; X return; X } X case 'G': /* J */ X if (strcmp (p-4, "ING") != 0) X return; X p[-4] = 'E'; X p[-3] = 0; X if (cflag) X printf ("%s/J\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->j_flag) { X wordok = 1; X return; X } X if (p[-5] == 'E') X return; /* This stops CREATEING */ X p[-4] = 0; X if (cflag) X printf ("%s/J\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->j_flag) X wordok = 1; X return; X case 'R': /* Z */ X if (strcmp (p-3, "ER") != 0) X return; X X p[-2] = 0; X if (cflag) X printf ("%s/Z\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->z_flag) { X wordok = 1; X return; X } X if (p[-4] == 'I' && !vowel (p[-5])) { X p[-4] = 'Y'; X p[-3] = 0; X if (cflag) X printf ("%s/Z\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->z_flag) { X wordok = 1; X return; X } X p[-4] = 'I'; X } X if ((p[-4] != 'E' && p[-4] != 'Y') || X (p[-4] == 'Y' && vowel (p[-5]))) { X p[-3] = 0; X if (cflag) X printf ("%s/Z\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->z_flag) X wordok = 1; X } X return; X case 'E': /* S (except simple adding of an S) */ X p[-2] = 0; /* drop the ES */ X if (index ("SXZH", p[-3]) != NULL) { X if (cflag) X printf ("%s/S\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL) { X if (dent->s_flag) X wordok = 1;; X return; X } X } X if (p[-3] == 'I') { X p[-3] = 'Y'; X if (cflag) X printf ("%s/S\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->s_flag) X wordok = 1; X return; X } X return; X X case 'S': /* P */ X if (strcmp (p-4, "NES") != 0) X return; X X p[-4] = 0; /* kill 'N' */ X if (p[-5] != 'Y' || vowel (p[-6])) { X if (cflag) X printf ("%s/P\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->p_flag) { X wordok = 1; X return; X } X } X if (p[-5] == 'I') { X p[-5] = 'Y'; X if (cflag) X printf ("%s/P\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->p_flag) X wordok = 1; X } X return; X case '\'': /* M */ X p[-2] = '\0'; X if (cflag) X printf ("%s/M\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->m_flag) X wordok = 1; X return; X } X } X X /* only the N flag */ X n_ending (w) X char *w; X { X char *p; X struct dent *dent; X X p = w + strlen (w); X X if (p[-2] == 'E') { X if (p[-3] == 'E' || p[-3] == 'Y') X return; X p[-2] = 0; X if (cflag) X printf ("%s/N\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->n_flag) X wordok = 1; X return; X } X X if (strcmp (p-3, "ION") != 0) X return; X X p[-3] = 'E'; X p[-2] = 0; X X if (cflag) X printf ("%s/N\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL) { X if (dent->n_flag) X wordok = 1; X return; X } X X if (strcmp (p-7, "ICATE") != 0) /* check is really against "ICATION" */ X return; X X p[-7] = 'Y'; X p[-6] = 0; X X if (cflag) X printf ("%s/N\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL && dent->n_flag) X wordok = 1; X return; X } X X /* flags: v */ X e_ending (w) X char *w; X { X char *p; X struct dent *dent; X X p = w + strlen (w); X X if (strcmp (p-3, "IVE") != 0) X return; X p[-3] = 'E'; X p[-2] = 0; X X if (cflag) X printf ("%s/V\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL X && dent->v_flag) { X wordok = 1; X return; X } X X if (p[-4] == 'E') X return; X X p[-3] = 0; X X if (cflag) X printf ("%s/V\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL && dent->v_flag) X wordok = 1; X return; X } X X /* flags: y */ X y_ending (w) X char *w; X { X char *p; X struct dent *dent; X X p = w + strlen (w); X X if (strcmp (p-2, "LY") != 0) X return; X X p[-2] = 0; X X if (cflag) X printf ("%s/Y\n", w); X else if ((dent = lookup (w, strlen (w), 1)) != NULL && dent->y_flag) X wordok = 1; X return; X } X X vowel (c) X char c; X { X return (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U'); X } SHAR_EOF if test 10274 -ne "`wc -c < 'good.c'`" then echo shar: error transmitting "'good.c'" '(should have been 10274 characters)' fi fi # end of overwriting check echo shar: extracting "'hash.c'" '(343 characters)' if test -f 'hash.c' then echo shar: will not over-write existing file "'hash.c'" else sed 's/^X //' << \SHAR_EOF > 'hash.c' X /* -*- Mode:Text -*- */ X /* X * hash.c - a simple hash function for ispell X * X * Pace Willisson, 1983 X */ X X hash (s, n, hashsize) X register char *s; X register n; X register hashsize; X { X register short h = 0; X X while (n--) { X h ^= *s++; X if (h < 0) { X h <<= 1; X h++; X } else { X h <<= 1; X } X } X X h &= 077777; X return (h %= hashsize); X } X X X X SHAR_EOF if test 343 -ne "`wc -c < 'hash.c'`" then echo shar: error transmitting "'hash.c'" '(should have been 343 characters)' fi fi # end of overwriting check echo shar: extracting "'ispell.c'" '(16239 characters)' if test -f 'ispell.c' then echo shar: will not over-write existing file "'ispell.c'" else sed 's/^X //' << \SHAR_EOF > 'ispell.c' X /* -*- Mode:Text -*- */ X X /* X * ispell.c - An interactive spelling corrector. X * X * Copyright (c), 1983, by Pace Willisson X * Permission for non-profit use is hereby granted. X * All other rights reserved. X * X * 1987, Robert McQueer, added: X * -w option & handling of extra legal word characters X * -d option for alternate dictionary file X * -p option & WORDLIST variable for alternate personal dictionary X * -x option to suppress .bak files. X * 8 bit text & config.h parameters X * 1987, Geoff Kuenning, added: X * -c option for creating suffix suggestions from raw words X * suffixes in personal dictionary file X * hashed personal dictionary file X */ X X #include X #include X #include X #include "ispell.h" X #include "config.h" X X FILE *infile; X FILE *outfile; X X char hashname[MAXPATHLEN]; X X extern struct dent *treeinsert(); X X /* X ** we use extended character set range specifically to allow intl. X ** character set characters. We are being REALLY paranoid about indexing X ** this array - explicitly cast into unsigned INTEGER, then mask X ** If NO8BIT is set, text will be masked to ascii range. X */ X static int Trynum; X #ifdef NO8BIT X static char Try[128]; X static char Checkch[128]; X #define iswordch(X) (Checkch[((unsigned)(X))&0x7f]) X #else X static char Try[256]; X static char Checkch[256]; X #define iswordch(X) (Checkch[((unsigned)(X))&0xff]) X #endif X X givehelp () X { X erase (); X printf ("Whenever a word is found that is not in the dictionary,\r\n"); X printf ("it is printed on the first line of the screen. If the dictionary\r\n"); X printf ("contains any similar words, they are listed with a single digit\r\n"); X printf ("next to each one. You have the option of replacing the word\r\n"); X printf ("completely, or choosing one of the suggested words.\r\n"); X printf ("\r\n"); X printf ("Commands are:\r\n\r\n"); X printf ("R Replace the misspelled word completely.\r\n"); X printf ("Space Accept the word this time only\r\n"); X printf ("A Accept the word for the rest of this file.\r\n"); X printf ("I Accept the word, and put it in your private dictionary.\r\n"); X printf ("0-9 Replace with one of the suggested words.\r\n"); X printf ("L Look up words in system dictionary.\r\n"); X printf ("Q Write the rest of this file, ignoring misspellings, "); X printf ( "and start next file.\r\n"); X printf ("X Exit immediately. Asks for confirmation. "); X printf ( "Leaves file unchanged.\r\n"); X printf ("! Shell escape.\r\n"); X printf ("^L Redraw screen.\r\n"); X printf ("\r\n\r\n"); X printf ("-- Type space to continue --"); X fflush (stdout); X getchar (); X } X X X char *getline(); X X int cflag = 0; X int lflag = 0; X int aflag = 0; X int fflag = 0; X #ifndef USG X int sflag = 0; X #endif X int xflag = 0; X X char *askfilename; X X static char *Cmd; X X usage () X { X fprintf (stderr, "Usage: %s [-dfile | -pfile | -wchars | -x] file .....\n",Cmd); X fprintf (stderr, " %s [-dfile | -pfile | -wchars] -l\n",Cmd); X #ifdef USG X fprintf (stderr, " %s [-dfile | -pfile | -ffile | -s] -a\n",Cmd); X #else X fprintf (stderr, " %s [-dfile | -pfile | -ffile] -a\n",Cmd); X #endif X fprintf (stderr, " %s [-wchars] -c\n"); X exit (1); X } X X static initckch() X { X int c; X X Trynum = 0; X #ifdef NO8BIT X for (c = 0; c < 128; ++c) { X #else X for (c = 0; c < 256; ++c) { X #endif X if (myalpha((char) c)) { X Checkch[c] = (char) 1; X if (myupper((char) c)) { X Try[Trynum] = (char) c; X ++Trynum; X } X } X else X Checkch[c] = (char) 0; X } X } X X main (argc, argv) X char **argv; X { X char *p; X char *cpd; X char num[4]; X unsigned mask; X X Cmd = *argv; X X initckch(); X sprintf(hashname,"%s/%s",LIBDIR,DEFHASH); X X cpd = NULL; X X argv++; X argc--; X while (argc && **argv == '-') { X switch ((*argv)[1]) { X case 'a': X aflag++; X break; X case 'c': X cflag++; X lflag++; X break; X case 'x': X xflag++; X break; X case 'f': X fflag++; X p = (*argv)+2; X if (*p == '\0') { X argv++; argc--; X if (argc == 0) X usage (); X p = *argv; X } X askfilename = p; X break; X case 'l': X lflag++; X break; X #ifndef USG X case 's': X sflag++; X break; X #endif X case 'p': X cpd = (*argv)+2; X if (*cpd == '\0') { X argv++; argc--; X if (argc == 0) X usage (); X cpd = *argv; X } X break; X case 'd': X p = (*argv)+2; X if (*p == '\0') { X argv++; argc--; X if (argc == 0) X usage (); X p = *argv; X } X if (*p == '/') X strcpy(hashname,p); X else X sprintf(hashname,"%s/%s",LIBDIR,p); X break; X case 'w': X num[3] = '\0'; X #ifdef NO8BIT X mask = 0x7f; X #else X mask = 0xff; X #endif X p = (*argv)+2; X if (*p == '\0') { X argv++; argc--; X if (argc == 0) X usage (); X p = *argv; X } X while (Trynum <= mask && *p != '\0') { X if (*p != 'n') { X Checkch[((unsigned)(*p))&mask] = (char) 1; X Try[Trynum] = *p & mask; X ++p; X } X else { X ++p; X num[0] = *p; ++p; X num[1] = *p; ++p; X num[2] = *p; ++p; X Try[Trynum] = atoi(num) & mask; X Checkch[atoi(num)&mask] = (char) 1; X } X ++Trynum; X } X break; X default: X usage(); X } X argv++; argc--; X } X X if (!argc && !lflag && !aflag) X usage (); X X if (linit () < 0) X exit (0); X X treeinit (cpd); X X if (aflag) { X askmode (); X exit (0); X } X X if (lflag) { X infile = stdin; X checkfile (); X exit (0); X } X X terminit (); X X while (argc--) X dofile (*argv++); X X done (); X } X X char firstbuf[BUFSIZ], secondbuf[BUFSIZ]; X char *currentchar; X char token[BUFSIZ]; X X int quit; X X char *currentfile = NULL; X X dofile (filename) X char *filename; X { X int c; X char bakfile[256]; X X currentfile = filename; X X if ((infile = fopen (filename, "r")) == NULL) { X fprintf (stderr, "Can't open %s\r\n", filename); X sleep (2); X return; X } X X if (access (filename, 2) < 0) { X fprintf (stderr, "Can't write to %s\r\n", filename); X sleep (2); X return; X } X X strcpy(tempfile, TEMPNAME); X mktemp (tempfile); X if ((outfile = fopen (tempfile, "w")) == NULL) { X fprintf (stderr, "Can't create %s\r\n", tempfile); X sleep (2); X return; X } X X quit = 0; X X checkfile (); X X fclose (infile); X fclose (outfile); X X if (!cflag) X treeoutput (); X X if ((infile = fopen (tempfile, "r")) == NULL) { X fprintf (stderr, "tempoary file disappeared (%s)\r\n", tempfile); X sleep (2); X return; X } X X sprintf(bakfile, "%s.bak", filename); X if(link(filename, bakfile) == 0) X unlink(filename); X X /* if we can't write new, preserve .bak regardless of xflag */ X if ((outfile = fopen (filename, "w")) == NULL) { X fprintf (stderr, "can't create %s\r\n", filename); X sleep (2); X return; X } X X while ((c = getc (infile)) != EOF) X putc (c, outfile); X X fclose (infile); X fclose (outfile); X X unlink (tempfile); X if (xflag) X unlink(bakfile); X } X X checkfile () X { X int c; X char *p; X int len; X X secondbuf[0] = 0; X currentchar = secondbuf; X X while (1) { X strcpy (firstbuf, secondbuf); X if (quit) { /* quit can't be set in l mode */ X while (fgets (secondbuf, sizeof secondbuf, infile) != NULL) X fputs (secondbuf, outfile); X break; X } X X if (fgets (secondbuf, sizeof secondbuf, infile) == NULL) X break; X currentchar = secondbuf; X X len = strlen (secondbuf) - 1; X if (secondbuf [ len ] == '\n') X secondbuf [ len ] = 0; X X /* if this is a formatter command, skip over it */ X if (*currentchar == '.') { X while (*currentchar && !myspace (*currentchar)) { X if (!lflag) X putc (*currentchar, outfile); X currentchar++; X } X if (*currentchar == 0) { X if (!lflag) X putc ('\n', outfile); X continue; X } X } X X while (1) { X while (*currentchar && !iswordch(*currentchar)) { X /* formatting escape sequences */ X if (*currentchar == '\\') { X if(currentchar[1] == 'f') { X /* font change: \fX */ X copyout(¤tchar, 3); X continue; X } X else if(currentchar[1] == 's') { X /* size change */ X if(currentchar[2] < 6 && X currentchar[2] != 0) X /* two digit size */ X copyout(¤tchar, 4); X else X /* one digit size */ X copyout(¤tchar, 3); X continue; X } X else if(currentchar[1] == '(') { X /* extended char set escape: \(XX */ X copyout(¤tchar, 4); X continue; X } X } X X if (!lflag) X putc (*currentchar, outfile); X currentchar++; X } X X if (*currentchar == 0) X break; X X p = token; X while (iswordch(*currentchar) || X (*currentchar == '\'' && X iswordch(*(currentchar + 1)))) X *p++ = *currentchar++; X *p = 0; X if (lflag) { X if (!good (token) && !cflag) X printf ("%s\r\n", token); X } else { X if (!quit) X correct (token, ¤tchar); X } X if (!lflag) X fprintf (outfile, "%s", token); X } X if (!lflag) X putc ('\n', outfile); X } X } X X char possibilities[10][BUFSIZ]; X int pcount; X X correct (token, currentchar) X char *token; X char **currentchar; X { X int c; X int i; X char *p; X int len; X char *begintoken; X X len = strlen (token); X begintoken = *currentchar - len; X X checkagain: X if (good (token)) X return; X X erase (); X printf (" %s", token); X if (currentfile) X printf (" File: %s", currentfile); X printf ("\r\n\r\n"); X X makepossibilities (token); X X for (i = 0; i < 10; i++) { X if (possibilities[i][0] == 0) X break; X printf ("%d: %s\r\n", i, possibilities[i]); X } X X move (15, 0); X printf ("%s\r\n", firstbuf); X X for (p = secondbuf; p != begintoken; p++) X putchar (*p); X inverse (); X for (i = strlen (token); i > 0; i--) X putchar (*p++); X normal (); X while (*p) X putchar (*p++); X printf ("\r\n"); X X while (1) { X switch (c = (getchar () & NOPARITY)) { X #ifndef USG X case 'Z' & 037: X stop (); X erase (); X goto checkagain; X #endif X case ' ': X erase (); X return; X case 'x': case 'X': X printf ("Are you sure you want to throw away your changes? "); X c = (getchar () & NOPARITY); X if (c == 'y' || c == 'Y') { X erase (); X done (); X } X putchar (7); X goto checkagain; X case 'i': case 'I': X treeinsert (token, 1); X erase (); X return; X case 'a': case 'A': X treeinsert (token, 0); X erase (); X return; X case 'L' & 037: X goto checkagain; X case '?': X givehelp (); X goto checkagain; X case '!': X { X char buf[200]; X move (18, 0); X putchar ('!'); X if (getline (buf) == NULL) { X putchar (7); X erase (); X goto checkagain; X } X printf ("\r\n"); X shellescape (buf); X erase (); X goto checkagain; X } X case 'r': case 'R': X move (18, 0); X printf ("Replace with: "); X if (getline (token) == NULL) { X putchar (7); X erase (); X goto checkagain; X } X inserttoken (secondbuf, begintoken, token, currentchar); X erase (); X goto checkagain; X case '0': case '1': case '2': case '3': case '4': X case '5': case '6': case '7': case '8': case '9': X if (possibilities[c - '0'][0] != 0) { X strcpy (token, possibilities[c - '0']); X inserttoken (secondbuf, begintoken, token, currentchar); erase (); X return; X } X putchar (7); X break; X case 'l': case 'L': X { X char buf[100]; X move (18, 0); X printf ("Lookup string ('*' is wildcard): "); X if (getline (buf) == NULL) { X putchar (7); X erase (); X goto checkagain; X } X printf ("\r\n\r\n"); X lookharder (buf); X erase (); X goto checkagain; X } X case 'q': case 'Q': X quit = 1; X erase (); X return; X default: X putchar (7); X break; X } X } X } X X inserttoken (buf, start, token, currentchar) X char *buf, *start, *token; X char **currentchar; X { X char copy[BUFSIZ]; X char *p, *q; X X strcpy (copy, buf); X X for (p = buf, q = copy; p != start; p++, q++) X *p = *q; X while (*token) X *p++ = *token++; X q += *currentchar - start; X *currentchar = p; X while (*p++ = *q++) X ; X } X X X makepossibilities (word) X char word[]; X { X int i; X X for (i = 0; i < 10; i++) X possibilities[i][0] = 0; X pcount = 0; X X if (pcount < 10) wrongletter (word); X if (pcount < 10) extraletter (word); X if (pcount < 10) missingletter (word); X if (pcount < 10) transposedletter (word); X X } X X char *cap(); X X insert (word) X char *word; X { X int i; X X for (i = 0; i < pcount; i++) X if (strcmp (possibilities[i], word) == 0) X return (0); X X strcpy (possibilities[pcount++], word); X if (pcount >= 10) X return (-1); X else X return (0); X } X X wrongletter (word) X char word[]; X { X int i, j, c, n; X char newword[BUFSIZ]; X X n = strlen (word); X strcpy (newword, word); X X for (i = 0; i < n; i++) { X for (j=0; j < Trynum; ++j) { X newword[i] = Try[j]; X if (good (newword)) { X if (insert (cap (newword, word)) < 0) X return; X } X } X newword[i] = word[i]; X } X } X X extraletter (word) X char word[]; X { X char newword[BUFSIZ], *p, *s, *t; X X if (strlen (word) < 3) X return; X X for (p = word; *p; p++) { X for (s = word, t = newword; *s; s++) X if (s != p) X *t++ = *s; X *t = 0; X if (good (newword)) { X if (insert (cap (newword, word)) < 0) X return; X } X } X } X X missingletter (word) X char word[]; X { X char newword[BUFSIZ], *p, *r, *s, *t; X int i; X X for (p = word; p == word || p[-1]; p++) { X for (s = newword, t = word; t != p; s++, t++) X *s = *t; X r = s++; X while (*t) X *s++ = *t++; X *s = 0; X for (i=0; i < Trynum; ++i) { X *r = Try[i]; X if (good (newword)) { X if (insert (cap (newword, word)) < 0) X return; X } X } X } X } X X transposedletter (word) X char word[]; X { X char newword[BUFSIZ]; X int t; X char *p; X X strcpy (newword, word); X for (p = newword; p[1]; p++) { X t = p[0]; X p[0] = p[1]; X p[1] = t; X if (good (newword)) { X if (insert (cap (newword, word)) < 0) X return; X } X t = p[0]; X p[0] = p[1]; X p[1] = t; X } X } X X char * X cap (word, pattern) X char word[], pattern[]; X { X static char newword[BUFSIZ]; X char *p, *q; X X if (*word == 0) X return; X X if (myupper (pattern[0])) { X if (myupper (pattern[1])) { X for (p = word, q = newword; *p; p++, q++) { X if (mylower (*p)) X *q = toupper (*p); X else X *q = *p; X } X *q = 0; X } else { X if (mylower (word [0])) X newword[0] = toupper (word[0]); X else X newword[0] = word[0]; X X for (p = word + 1, q = newword + 1; *p; p++, q++) X if (myupper (*p)) X *q = tolower (*p); X else X *q = *p; X X *q = 0; X } X } else { X for (p = word, q = newword; *p; p++, q++) X if (myupper (*p)) X *q = tolower (*p); X else X *q = *p; X *q = 0; X } X return (newword); X } X X char * X getline (s) X char *s; X { X char *p; X int c; X X p = s; X X while (1) { X c = (getchar () & NOPARITY); X if (c == '\\') { X putchar ('\\'); X c = (getchar () & NOPARITY); X backup (); X putchar (c); X *p++ = c; X } else if (c == ('G' & 037)) { X return (NULL); X } else if (c == '\n' || c == '\r') { X *p = 0; X return (s); X } else if (c == erasechar) { X if (p != s) { X p--; X backup (); X putchar (' '); X backup (); X } X } else if (c == killchar) { X while (p != s) { X p--; X backup (); X putchar (' '); X backup (); X } X } else { X *p++ = c; X putchar (c); X } X } X } X X askmode () X { X char buf[BUFSIZ]; X int i; X X if (fflag) { X if (freopen (askfilename, "w", stdout) == NULL) { X fprintf (stderr, "Can't create %s\n", askfilename); X exit (1); X } X } X X setbuf (stdin, NULL); X setbuf (stdout, NULL); X X while (gets (buf) != NULL) { X if (good (buf)) { X if (rootword[0] == 0) { X printf ("*\n"); /* perfect match */ X } else { X printf ("+ %s\n", rootword); X } X } else { X makepossibilities (buf); X if (possibilities[0][0]) { X printf ("& "); X for (i = 0; i < 10; i++) { X if (possibilities[i][0] == 0) X break; X printf ("%s ", possibilities[i]); X } X printf ("\n"); X } else { X printf ("#\n"); X } X } X #ifndef USG X if (sflag) { X stop (); X if (fflag) { X rewind (stdout); X creat (askfilename, 0666); X } X } X #endif X } X } X X X copyout(cc, cnt) X char **cc; X { X while (--cnt >= 0) { X if (*(*cc) == 0) X break; X if (!lflag) X putc (*(*cc), outfile); X (*cc)++; X } X X } X X lookharder(string) X char *string; X { X char cmd[150]; X char *g, *s, grepstr[100]; X int wild = 0; X X g = grepstr; X for (s = string; *s != '\0'; s++) X if (*s == '*') { X wild++; X *g++ = '.'; X *g++ = '*'; X } else X *g++ = *s; X *g = '\0'; X if (grepstr[0]) { X #ifdef LOOK X if (wild) X /* string has wild card characters */ X sprintf (cmd, "%s '^%s$' %s", EGREPCMD, grepstr, WORDS); X else X /* no wild, use look(1) */ X sprintf (cmd, "/usr/bin/look -df %s %s", grepstr, WORDS); X #else X sprintf (cmd, "%s '^%s$' %s", EGREPCMD, grepstr, WORDS); X #endif X shellescape (cmd); X } X } SHAR_EOF if test 16239 -ne "`wc -c < 'ispell.c'`" then echo shar: error transmitting "'ispell.c'" '(should have been 16239 characters)' fi fi # end of overwriting check echo shar: extracting "'ispell.h'" '(4964 characters)' if test -f 'ispell.h' then echo shar: will not over-write existing file "'ispell.h'" else sed 's/^X //' << \SHAR_EOF > 'ispell.h' X /* -*- Mode: Text -*- */ X X #define LIBDIR "/tmp2/lib" X X struct dent { X struct dent *next; X char *word; X X unsigned short used : 1; X X /* bit fields for all of the flags */ X unsigned short v_flag : 1; X /* X "V" flag: X ...E --> ...IVE as in CREATE --> CREATIVE X if # .ne. E, ...# --> ...#IVE as in PREVENT --> PREVENTIVE X */ X unsigned short n_flag : 1; X /* X "N" flag: X ...E --> ...ION as in CREATE --> CREATION X ...Y --> ...ICATION as in MULTIPLY --> MULTIPLICATION X if # .ne. E or Y, ...# --> ...#EN as in FALL --> FALLEN X */ X unsigned short x_flag : 1; X /* X "X" flag: X ...E --> ...IONS as in CREATE --> CREATIONS X ...Y --> ...ICATIONS as in MULTIPLY --> MULTIPLICATIONS X if # .ne. E or Y, ...# --> ...#ENS as in WEAK --> WEAKENS X */ X unsigned short h_flag : 1; X /* X "H" flag: X ...Y --> ...IETH as in TWENTY --> TWENTIETH X if # .ne. Y, ...# --> ...#TH as in HUNDRED --> HUNDREDTH X */ X unsigned short y_flag : 1; X /* X "Y" FLAG: X ... --> ...LY as in QUICK --> QUICKLY X */ X unsigned short g_flag : 1; X /* X "G" FLAG: X ...E --> ...ING as in FILE --> FILING X if # .ne. E, ...# --> ...#ING as in CROSS --> CROSSING X */ X unsigned short j_flag : 1; X /* X "J" FLAG" X ...E --> ...INGS as in FILE --> FILINGS X if # .ne. E, ...# --> ...#INGS as in CROSS --> CROSSINGS X */ X unsigned short d_flag : 1; X /* X "D" FLAG: X ...E --> ...ED as in CREATE --> CREATED X if @ .ne. A, E, I, O, or U, X ...@Y --> ...@IED as in IMPLY --> IMPLIED X if # .ne. E or Y, or (# = Y and @ = A, E, I, O, or U) X ...@# --> ...@#ED as in CROSS --> CROSSED X or CONVEY --> CONVEYED X */ X unsigned short t_flag : 1; X /* X "T" FLAG: X ...E --> ...EST as in LATE --> LATEST X if @ .ne. A, E, I, O, or U, X ...@Y --> ...@IEST as in DIRTY --> DIRTIEST X if # .ne. E or Y, or (# = Y and @ = A, E, I, O, or U) X ...@# --> ...@#EST as in SMALL --> SMALLEST X or GRAY --> GRAYEST X */ X unsigned short r_flag : 1; X /* X "R" FLAG: X ...E --> ...ER as in SKATE --> SKATER X if @ .ne. A, E, I, O, or U, X ...@Y --> ...@IER as in MULTIPLY --> MULTIPLIER X if # .ne. E or Y, or (# = Y and @ = A, E, I, O, or U) X ...@# --> ...@#ER as in BUILD --> BUILDER X or CONVEY --> CONVEYER X */ X unsigned short z_flag : 1; X /* X "Z FLAG: X ...E --> ...ERS as in SKATE --> SKATERS X if @ .ne. A, E, I, O, or U, X ...@Y --> ...@IERS as in MULTIPLY --> MULTIPLIERS X if # .ne. E or Y, or (# = Y and @ = A, E, I, O, or U) X ...@# --> ...@#ERS as in BUILD --> BUILDERS X or SLAY --> SLAYERS X */ X unsigned short s_flag : 1; X /* X "S" FLAG: X if @ .ne. A, E, I, O, or U, X ...@Y --> ...@IES as in IMPLY --> IMPLIES X if # .eq. S, X, Z, or H, X ...# --> ...#ES as in FIX --> FIXES X if # .ne. S,X,Z,H, or Y, or (# = Y and @ = A, E, I, O, or U) X ...# --> ...#S as in BAT --> BATS X or CONVEY --> CONVEYS X */ X unsigned short p_flag : 1; X /* X "P" FLAG: X if @ .ne. A, E, I, O, or U, X ...@Y --> ...@INESS as in CLOUDY --> CLOUDINESS X if # .ne. Y, or @ = A, E, I, O, or U, X ...@# --> ...@#NESS as in LATE --> LATENESS X or GRAY --> GRAYNESS X */ X unsigned short m_flag : 1; X /* X "M" FLAG: X ... --> ...'S as in DOG --> DOG'S X */ X X unsigned short keep : 1; X X }; X X #define WORDLEN 30 X X struct hashheader { X int magic; X int stringsize; X int tblsize; X }; X X #define MAGIC 1 X X X /* X * termcap variables X */ X char *tgetstr(); X char PC; /* padding character */ X char *BC; /* backspace if not ^H */ X char *UP; /* Upline (cursor up) */ X char *cd; /* clear to end of display */ X char *ce; /* clear to end of line */ X char *cl; /* clear display */ X char *cm; /* cursor movement */ X char *dc; /* delete character */ X char *dl; /* delete line */ X char *dm; /* delete mode */ X char *ed; /* exit delete mode */ X char *ei; /* exit insert mode */ X char *ho; /* home */ X char *ic; /* insert character */ X char *il; /* insert line */ X char *im; /* insert mode */ X char *ip; /* insert padding */ X char *nd; /* non-destructive space */ X char *vb; /* visible bell */ X char *so; /* standout */ X char *se; /* standout end */ X int bs; X int li, co; /* lines, columns */ X X char termcap[1024]; X char termstr[1024]; /* for string values */ X char *termptr; X X char rootword[BUFSIZ]; X struct dent *lastdent; X X char *hashstrings; X X X int aflag; X int lflag; X X int erasechar; X int killchar; X X char tempfile[200]; SHAR_EOF if test 4964 -ne "`wc -c < 'ispell.h'`" then echo shar: error transmitting "'ispell.h'" '(should have been 4964 characters)' fi fi # end of overwriting check echo shar: extracting "'lookup.c'" '(2762 characters)' if test -f 'lookup.c' then echo shar: will not over-write existing file "'lookup.c'" else sed 's/^X //' << \SHAR_EOF > 'lookup.c' X /* -*- Mode:Text -*- */ X X /* X * lookup.c - see if a word appears in the dictionary X * X * Pace Willisson, 1983 X */ X X #include X #include "ispell.h" X #include "config.h" X X X struct dent *hashtbl; X int hashsize; X X extern char hashname[]; X X static inited = 0; X X linit () X { X int hashfd; X struct hashheader hashheader; X register int i; X register struct dent *dp; X X if (inited) X return; X X if ((hashfd = open (hashname, 0)) < 0) { X fprintf (stderr, "can't open %s\r\n", hashname); X return (-1); X } X X hashsize = read (hashfd, &hashheader, sizeof hashheader); X if (hashsize == 0) { X /* X * Empty file - create an empty dummy table. We X * actually have to have one entry since the hash X * algorithm involves a divide by the table size X * (actually modulo, but zero is still unacceptable). X * So we create an entry with a word of all lowercase, X * which can't match because the comparison string has X * been converted to uppercase by then. X */ X close (hashfd); X hashsize = 1; /* This prevents divides by zero */ X hashtbl = (struct dent *) calloc (1, sizeof (struct dent)); X if (hashtbl == NULL) { X (void) fprintf (stderr, X "Couldn't allocate space for hash table\n"); X return (-1); X } X hashtbl[0].word = "xxxxxxxxxxx"; X hashtbl[0].next = NULL; X hashtbl[0].keep = 0; X hashtbl[0].used = 1; X /* The flag bits don't matter, but calloc cleared them. */ X inited = 1; X return 0; X } X else if (hashsize < 0 || hashheader.magic != MAGIC) { X fprintf (stderr, "Illegal format hash table\r\n"); X return (-1); X } X hashstrings = (char *) malloc (hashheader.stringsize); X hashtbl = (struct dent *) malloc (hashheader.tblsize * sizeof (struct dent)); X if (hashtbl == NULL || hashstrings == NULL) { X (void) fprintf (stderr, X "Couldn't allocate space for hash table\n"); X return (-1); X } X hashsize = hashheader.tblsize; X X read (hashfd, hashstrings, hashheader.stringsize); X read (hashfd, hashtbl, hashheader.tblsize * sizeof (struct dent)); X close (hashfd); X X for (i = hashsize, dp = hashtbl; --i >= 0; dp++) { X dp->word = &hashstrings [ (int)(dp->word) ]; X if (dp->next == (struct dent *) -1) X dp->next = NULL; X else X dp->next = &hashtbl [ (int)(dp->next) ]; X } X X inited = 1; X return (0); X } X X /* n is length of s */ X struct dent * X lookup (s, n, dotree) X register char *s; X { X int i; X register struct dent *dp; X register char *s1, *s2; X X dp = &hashtbl [ hash (s, n, hashsize) ]; X for ( ; dp != NULL; dp = dp->next) { X /* quick strcmp, but only for equality */ X s1 = dp->word; X s2 = s; X while (*s1 == *s2++) X if (*s1++=='\0') { X lastdent = dp; X return (lastdent); X } X } X if (dotree) { X i = s[n]; X s[n] = '\0'; X if ((dp = treelookup (s)) != NULL) X lastdent = dp; X s[n] = i; X return dp; X } X else X return NULL; X } X SHAR_EOF if test 2762 -ne "`wc -c < 'lookup.c'`" then echo shar: error transmitting "'lookup.c'" '(should have been 2762 characters)' fi fi # end of overwriting check echo shar: extracting "'term.c'" '(3781 characters)' if test -f 'term.c' then echo shar: will not over-write existing file "'term.c'" else sed 's/^X //' << \SHAR_EOF > 'term.c' X /* -*- Mode:Text -*- */ X X /* X * term.c - deal with termcap, and unix terminal mode settings X * X * Pace Willisson, 1983 X */ X X #include X #ifdef USG X #include X #else X #include X #endif X #include X #include "ispell.h" X X int putch(); X X erase () X { X if (cl) X tputs(cl, li, putch); X else { X if (ho) X tputs(ho, 100, putch); X else if (cm) X tputs(tgoto(cm, 0, 0), 100, putch); X tputs(cd, li, putch); X } X } X X move (row, col) X { X tputs (tgoto (cm, col, row), 100, putch); X } X X inverse () X { X tputs (so, 10, putch); X } X X normal () X { X tputs (se, 10, putch); X } X X backup () X { X if (BC) X tputs (BC, 1, putch); X else X putchar ('\b'); X } X X putch (c) X { X putchar (c); X } X X #ifdef USG X struct termio sbuf, osbuf; X #else X struct sgttyb sbuf, osbuf; X #endif X static termchanged = 0; X X X terminit () X { X int done(); X #ifdef USG X if (!isatty(0)) { X fprintf (stderr, "Can't deal with non interactive use yet.\n"); X exit (1); X } X ioctl (0, TCGETA, &osbuf); X termchanged = 1; X X sbuf = osbuf; X sbuf.c_lflag &= ~(ECHO | ECHOK | ECHONL | ICANON); X sbuf.c_oflag &= ~(OPOST); X sbuf.c_iflag &= ~(INLCR | IGNCR | ICRNL); X sbuf.c_cc[VMIN] = 1; X sbuf.c_cc[VTIME] = 1; X ioctl (0, TCSETAW, &sbuf); X X erasechar = osbuf.c_cc[VERASE]; X killchar = osbuf.c_cc[VKILL]; X X signal (SIGINT, done); X #else X int tpgrp; X int onstop(); X X retry: X sigsetmask(1< 'tree.c' X /* -*- Mode:Text -*- */ X X /* X * tree.c - a hash style dictionary for user's personal words X * X * Pace Willisson, 1983 X * Hash support added by Geoff Kuenning, 1987 X */ X X #include X #include X #include X #include "ispell.h" X #include "config.h" X X char *getenv(); X struct dent *lookup(); X char *upcase(); X X static int cantexpand = 0; /* NZ if an expansion fails */ X static struct dent *htab = NULL; /* Hash table for our stuff */ X static int hsize = 0; /* Space available in hash table */ X static int hcount = 0; /* Number of items in hash table */ X X /* X * Hash table sizes. Prime is probably a good idea, though in truth I X * whipped the algorithm up on the spot rather than looking it up, so X * who knows what's really best? If we overflow the table, we just X * use a double-and-add-1 algorithm. X * X * The strange pattern in the table is because this table is sometimes X * used with huge dictionaries, and we want to get the table bigger fast. X * 23003 just happens to be such that the original dict.191 will fill X * the table to just under 70%. 31469 is similarly selected for dict.191 X * combined with /usr/dict/words. The other numbers are on 10000-word X * intervals starting at 30000. (The table is still valid if MAXPCT X * is changed, but the dictionary sizes will no longer fall on neat X * boundaries). X */ X static int goodsizes[] = { X 53, 223, 907, X #if ((BIG_DICT * 100) / MAXPCT) <= 23003 X 23003, /* ~16000 words */ X #endif X #if ((BIG_DICT * 100) / MAXPCT) <= 31469 X 31469, /* ~22000 words */ X #endif X #if ((BIG_DICT * 100) / MAXPCT) <= 42859 X 42859, /* ~30000 words */ X #endif X #if ((BIG_DICT * 100) / MAXPCT) <= 57143 X 57143, /* ~40000 words */ X #endif X 71429 /* ~50000 words */ X }; X X struct dent *treeinsert(); X struct dent *tinsert(); X struct dent *treelookup(); X X static char personaldict[MAXPATHLEN]; X static FILE *dictf; X static newwords = 0; X X extern char *index (); X extern struct dent *hashtbl; X extern int hashsize; X X treeinit (p) X char *p; X { X char *h; X char *orig; X char buf[BUFSIZ]; X struct dent *dp; X X /* X ** if p exists and begins with '/' we don't really need HOME, X ** but it's not very likely that HOME isn't set anyway. X */ X orig = p; X if (p == NULL) X p = getenv (PDICTVAR); X if ((h = getenv ("HOME")) == NULL) X return; X X if (p == NULL) X sprintf(personaldict,"%s/%s",h,DEFPDICT); X else { X if (*p == '/') X strcpy(personaldict,p); X else { X /* X ** The user gave us a relative pathname. How we X ** interpret it depends on how it was given: X ** X ** -p switch: as-is first, then $HOME/name X ** PDICTVAR: $HOME/name first, then as-is X **/ X if (orig == NULL) X sprintf (personaldict, "%s/%s", h, p); X else /* -p switch */ X strcpy (personaldict, p); X } X } X X if ((dictf = fopen (personaldict, "r")) == NULL) { X /* The file doesn't exist. */ X if (p != NULL) { X /* If pathname is relative, try another place */ X if (*p != '/') { X if (orig == NULL) X strcpy (personaldict, p); X else /* -p switch */ X sprintf (personaldict, "%s/%s", h, p); X dictf = fopen (personaldict, "r"); X } X if (dictf == NULL) { X (void) fprintf (stderr, "Couldn't open "); X perror (p); X if (*p != '/') { X /* X ** Restore the preferred default, so X ** that output will go th the right X ** place. X */ X if (orig == NULL) X sprintf (personaldict, X "%s/%s", h, p); X else /* -p switch */ X strcpy (personaldict, p); X } X } X } X /* If the name wasn't specified explicitly, we don't object */ X return; X } X X while (fgets (buf, sizeof buf, dictf) != NULL) { X int len = strlen (buf) - 1; X X if (buf [ len ] == '\n') X buf [ len-- ] = '\0'; X if ((h = index (buf, '/')) != NULL) X *h++ = '\0'; X dp = treeinsert (buf, 1); X while (h != NULL) { X switch (*h++) { X case 'D': X case 'd': X dp->d_flag = 1; X break; X case 'G': X case 'g': X dp->g_flag = 1; X break; X case 'H': X case 'h': X dp->h_flag = 1; X break; X case 'J': X case 'j': X dp->j_flag = 1; X break; X case 'M': X case 'm': X dp->m_flag = 1; X break; X case 'N': X case 'n': X dp->n_flag = 1; X break; X case 'P': X case 'p': X dp->p_flag = 1; X break; X case 'R': X case 'r': X dp->r_flag = 1; X break; X case 'S': X case 's': X dp->s_flag = 1; X break; X case 'T': X case 't': X dp->t_flag = 1; X break; X case 'V': X case 'v': X dp->v_flag = 1; X break; X case 'X': X case 'x': X dp->x_flag = 1; X break; X case 'Y': X case 'y': X dp->y_flag = 1; X break; X case 'Z': X case 'z': X dp->z_flag = 1; X break; X default: X fprintf (stderr, X "Illegal flag in personal dictionary - %c (word %s)\n", X h[-1], buf); X break; X } X /* Exit loop if no more flags */ X if (*h++ != '/') X break; X } X } X X fclose (dictf); X X newwords = 0; X X if (!lflag && !aflag && access (personaldict, 2) < 0) X printf ("Warning: Cannot update personal dictionary (%s)\r\n", personaldict); X } X X treeprint () X { X register int i; X register struct dent *dp; X register struct dent *cp; X X printf ("("); X for (i = 0; i < hsize; i++) { X dp = &htab[i]; X if (dp->used) { X for (cp = dp; cp != NULL; cp = cp->next) X printf ("%s ", cp->word); X } X } X printf (")"); X } X X struct dent * X treeinsert (word, keep) X char *word; X { X register int i; X struct dent *dp; X struct dent *olddp; X struct dent *oldhtab; X int oldhsize; X char nword[BUFSIZ]; X X strcpy (nword, word); X upcase (nword); X if ((dp = lookup (nword, strlen (nword), 0)) != NULL) { X if (keep) X dp->keep = 1; X return dp; X } X /* X * Expand hash table when it is MAXPCT % full. X */ X if (!cantexpand && (hcount * 100) / MAXPCT >= hsize) { X oldhsize = hsize; X oldhtab = htab; X for (i = 0; i < sizeof goodsizes / sizeof (goodsizes[0]); i++) X if (goodsizes[i] > hsize) X break; X if (i >= sizeof goodsizes / sizeof goodsizes[0]) X hsize += hsize + 1; X else X hsize = goodsizes[i]; X htab = (struct dent *) calloc (hsize, sizeof (struct dent)); X if (htab == NULL) { X (void) fprintf (stderr, X "Ran out of space for personal dictionary\n"); X /* X * Try to continue anyway, since our overflow X * algorithm can handle an overfull (100%+) table, X * and the malloc very likely failed because we X * already have such a huge table, so small mallocs X * for overflow entries will still work. X */ X if (oldhtab == NULL) X exit (1); /* No old table, can't go on */ X (void) fprintf (stderr, X "Continuing anyway (with reduced performance).\n"); X cantexpand = 1; /* Suppress further messages */ X hsize = oldhsize; /* Put this back how the were */ X htab = oldhtab; /* ... */ X newwords = 1; /* And pretend it worked */ X return tinsert (nword, (struct dent *) NULL, keep); X } X /* X * Re-insert old entries into new table X */ X for (i = 0; i < oldhsize; i++) { X dp = &oldhtab[i]; X if (oldhtab[i].used) { X tinsert ((char *) NULL, dp, 0); X dp = dp->next; X while (dp != NULL) { X tinsert ((char *) NULL, dp, 0); X olddp = dp; X dp = dp->next; X free ((char *) olddp); X } X } X } X if (oldhtab != NULL) X free ((char *) oldhtab); X } X newwords = 1; X return tinsert (nword, (struct dent *) NULL, keep); X } X X static X struct dent * X tinsert (word, proto, keep) X char *word; /* One of word/proto must be null */ X struct dent *proto; X { X int hcode; X register struct dent *hp; /* Next trial entry in hash table */ X struct dent *php; /* Previous value of hp, for chaining */ X X if (word == NULL) X word = proto->word; X hcode = hash (word, strlen (word), hsize); X php = NULL; X hp = &htab[hcode]; X if (hp->used) { X while (hp != NULL) { X if (strcmp (word, hp->word) == 0) { X if (keep) X hp->keep = 1; X return hp; X } X php = hp; X hp = hp->next; X } X hp = (struct dent *) calloc (1, sizeof (struct dent)); X if (hp == NULL) { X (void) fprintf (stderr, X "Ran out of space for personal dictionary\n"); X exit (1); X } X } X if (proto != NULL) { X *hp = *proto; X if (php != NULL) X php->next = hp; X hp->next = NULL; X return &htab[hcode]; X } else { X if (php != NULL) X php->next = hp; X hp->word = (char *) malloc (strlen (word) + 1); X if (hp->word == NULL) { X (void) fprintf (stderr, X "Ran out of space for personal dictionary\n"); X exit (1); X } X hp->used = 1; X hp->next = NULL; X hp->d_flag = 0; X hp->g_flag = 0; X hp->h_flag = 0; X hp->j_flag = 0; X hp->m_flag = 0; X hp->n_flag = 0; X hp->p_flag = 0; X hp->r_flag = 0; X hp->s_flag = 0; X hp->t_flag = 0; X hp->v_flag = 0; X hp->x_flag = 0; X hp->y_flag = 0; X hp->z_flag = 0; X strcpy (hp->word, word); X hp->keep = keep; X hcount++; X return (hp); X } X } X X struct dent * X treelookup (word) X char *word; X { X int hcode; X register struct dent *hp; X char nword[BUFSIZ]; X X if (hsize <= 0) X return NULL; X strcpy (nword, word); X hcode = hash (nword, strlen (nword), hsize); X hp = &htab[hcode]; X while (hp != NULL && hp->used) { X if (strcmp (nword, hp->word) == 0) X break; X hp = hp->next; X } X if (hp != NULL && hp->used) X return hp; X else X return NULL; X } X X treeoutput () X { X if (newwords == 0) X return; X X if ((dictf = fopen (personaldict, "w")) == NULL) { X fprintf (stderr, "Can't create %s\r\n", personaldict); X return; X } X X toutput1 (); X X fclose (dictf); X } X X static X toutput1 () X { X register struct dent *cent; /* Current entry */ X register struct dent *lent; /* Linked entry */ X X for (cent = htab; cent - htab < hsize; cent++) { X for (lent = cent; lent != NULL; lent = lent->next) { X if (lent->used && lent->keep) X toutput2 (lent); X } X } X for (cent = hashtbl, lent = hashtbl + hashsize; X cent < lent; X cent++) { X if (cent->used && cent->keep) X toutput2 (cent); X } X } X X static X toutput2 (cent) X register struct dent *cent; X { X fprintf (dictf, "%s", cent->word); X if (cent->d_flag) X fprintf (dictf, "/D"); X if (cent->g_flag) X fprintf (dictf, "/G"); X if (cent->h_flag) X fprintf (dictf, "/H"); X if (cent->j_flag) X fprintf (dictf, "/J"); X if (cent->m_flag) X fprintf (dictf, "/M"); X if (cent->n_flag) X fprintf (dictf, "/N"); X if (cent->p_flag) X fprintf (dictf, "/P"); X if (cent->r_flag) X fprintf (dictf, "/R"); X if (cent->s_flag) X fprintf (dictf, "/S"); X if (cent->t_flag) X fprintf (dictf, "/T"); X if (cent->v_flag) X fprintf (dictf, "/V"); X if (cent->x_flag) X fprintf (dictf, "/X"); X if (cent->y_flag) X fprintf (dictf, "/Y"); X if (cent->z_flag) X fprintf (dictf, "/Z"); X fprintf (dictf, "\n"); X } X X char * X upcase (s) X register char *s; X { X register char *os = s; X X while (*s) { X if (mylower (*s)) X *s = toupper (*s); X s++; X } X return (os); X } SHAR_EOF if test 10534 -ne "`wc -c < 'tree.c'`" then echo shar: error transmitting "'tree.c'" '(should have been 10534 characters)' fi fi # end of overwriting check # End of shell archive exit 0 -- Geoff Kuenning {hplabs,ihnp4}!trwrb!desint!geoff