geoff@desint.UUCP (09/21/87)
This is Patch Number 2 to the beta posting of ispell. Ispell is an interactive spell-checking program that is faster, more friendly, and more flexible than standard UNIX spell. The beta posting itself and patch 1 are available from the comp.sources.misc archives. This patch only addresses serious bugs. Minor fixes and improvements will be held over until the next release. Bugs fixed in this patch: (1) Ispell accepted "conveies" as a spelling of "conveys", contrary to the documentation in ispell.4. (2) If ispell was run from emacs, or with multiple files, and words were added to the dictionary, the personal dictionary was clobbered. (Michael Wester, Doug Lind) To install this patch: From rn, type "|patch -d dir", where dir is the directory where you have ispell installed. From other newsreaders, save the article, then type "patch -d dir <savefile" where savefile is the name of the file you just created. Geoff Kuenning geoff@ITcorp.com {uunet,trwrb}!desint!geoff Index: version.h Prereq: 2.0.01, *** version.h.old Wed Sep 9 23:51:31 1987 --- version.h Wed Sep 9 23:48:26 1987 *************** *** 1,2 static char Version_ID[] = ! "@(#) Ispell Version 2.0.01, May 1987 Beta posting"; --- 1,2 ----- static char Version_ID[] = ! "@(#) Ispell Version 2.0.02, May 1987 Beta posting"; Index: good.c *** good.c.old Wed Sep 9 23:53:14 1987 --- good.c Wed Sep 9 23:50:50 1987 *************** *** 613,619 return; } } ! if (p[-3] == 'I') { p[-3] = 'Y'; if (cflag) flagpr (w, 'S', p - 3); --- 613,619 ----- return; } } ! if (p[-3] == 'I' && !vowel (p[-4])) { p[-3] = 'Y'; if (cflag) flagpr (w, 'S', p - 3); Index: tree.c *** tree.c.old Thu Sep 10 12:11:56 1987 --- tree.c Thu Sep 10 12:10:24 1987 *************** *** 242,247 struct dent *oldhtab; int oldhsize; char nword[BUFSIZ]; #ifdef CAPITALIZE register char *cp; char *saveword; --- 242,248 ----- struct dent *oldhtab; int oldhsize; char nword[BUFSIZ]; + int len; #ifdef CAPITALIZE register char *cp; char *saveword; *************** *** 250,256 strcpy (nword, word); upcase (nword); ! if ((dp = lookup (nword, strlen (nword), 0)) != NULL) dp->keep = keep; /* * Expand hash table when it is MAXPCT % full. --- 251,258 ----- strcpy (nword, word); upcase (nword); ! len = strlen (nword); ! if ((dp = lookup (nword, len, 0)) != NULL) dp->keep = keep; /* * Expand hash table when it is MAXPCT % full. *************** *** 286,300 newwords = 1; /* And pretend it worked */ return tinsert (nword, (struct dent *) NULL, keep); } ! /* ! * Re-insert old entries into new table ! */ ! for (i = 0; i < oldhsize; i++) { ! dp = &oldhtab[i]; ! if (oldhtab[i].used) { ! tinsert ((char *) NULL, dp, 0); ! dp = dp->next; ! while (dp != NULL) { tinsert ((char *) NULL, dp, 0); olddp = dp; dp = dp->next; --- 288,300 ----- newwords = 1; /* And pretend it worked */ return tinsert (nword, (struct dent *) NULL, keep); } ! else { ! /* ! * Re-insert old entries into new table ! */ ! for (i = 0; i < oldhsize; i++) { ! dp = &oldhtab[i]; ! if (oldhtab[i].used) { tinsert ((char *) NULL, dp, 0); dp = dp->next; while (dp != NULL) { *************** *** 296,302 dp = dp->next; while (dp != NULL) { tinsert ((char *) NULL, dp, 0); - olddp = dp; dp = dp->next; free ((char *) olddp); } --- 296,301 ----- dp = &oldhtab[i]; if (oldhtab[i].used) { tinsert ((char *) NULL, dp, 0); dp = dp->next; while (dp != NULL) { tinsert ((char *) NULL, dp, 0); *************** *** 298,304 tinsert ((char *) NULL, dp, 0); olddp = dp; dp = dp->next; ! free ((char *) olddp); } } } --- 297,308 ----- if (oldhtab[i].used) { tinsert ((char *) NULL, dp, 0); dp = dp->next; ! while (dp != NULL) { ! tinsert ((char *) NULL, dp, 0); ! olddp = dp; ! dp = dp->next; ! free ((char *) olddp); ! } } } if (oldhtab != NULL) *************** *** 301,306 free ((char *) olddp); } } } if (oldhtab != NULL) free ((char *) oldhtab); --- 305,313 ----- } } } + if (oldhtab != NULL) + free ((char *) oldhtab); + dp = NULL; /* This will force the insert below */ } } newwords |= keep; *************** *** 302,310 } } } - if (oldhtab != NULL) - free ((char *) oldhtab); - dp = NULL; /* This will force the insert below */ } newwords |= keep; if (dp == NULL) --- 309,314 ----- free ((char *) oldhtab); dp = NULL; /* This will force the insert below */ } } newwords |= keep; if (dp == NULL) *************** *** 372,378 dp->followcase = 1; if (keep) dp->k_followcase = 1; ! capspace = 2 * (strlen (dp->word) + 2); if (dp->word >= hashstrings && dp->word <= hashstrings --- 376,382 ----- dp->followcase = 1; if (keep) dp->k_followcase = 1; ! capspace = 2 * len + 4; if (dp->word >= hashstrings && dp->word <= hashstrings *************** *** 390,396 "Ran out of space for personal dictionary\n"); exit (1); } ! cp = dp->word + strlen (dp->word) + 1; if (dp->capitalize || dp->allcaps) *cp++ = 0; else { --- 394,400 ----- "Ran out of space for personal dictionary\n"); exit (1); } ! cp = dp->word + len + 1; if (dp->capitalize || dp->allcaps) *cp++ = 0; else { *************** *** 403,423 dp->allcaps = 0; if (keep) dp->k_allcaps = 0; ! cp = dp->word + strlen (dp->word) + 1; ! /* Add a new capitalization */ ! (*cp)++; ! capspace = (cp - dp->word + 1) ! * ((*cp & 0xFF) + 1); ! if (dp->word >= hashstrings ! && dp->word <= ! hashstrings + hashheader.stringsize) { ! saveword = dp->word; ! dp->word = malloc (capspace); ! if (dp->word) { ! cp = dp->word; ! while (--capspace >= 0) ! *cp++ = *saveword++; ! } } else dp->word = realloc (dp->word, capspace); --- 407,420 ----- dp->allcaps = 0; if (keep) dp->k_allcaps = 0; ! cp = dp->word + len + 1; ! /* See if the capitalization is already there */ ! for (i = 0, saveword = cp + 1; ! i < (*cp & 0xFF); ! i++) { ! if (strcmp (saveword + 1, word) == 0) ! break; ! saveword += len + 2; } if (i != (*cp & 0xFF)) { if (keep) *************** *** 419,430 *cp++ = *saveword++; } } ! else ! dp->word = realloc (dp->word, capspace); ! if (dp->word == NULL) { ! fprintf (stderr, ! "Ran out of space for personal dictionary\n"); ! exit (1); } cp = dp->word + strlen (dp->word) + 1; cp += --- 416,424 ----- break; saveword += len + 2; } ! if (i != (*cp & 0xFF)) { ! if (keep) ! *saveword = '+'; } else { /* Add a new capitalization */ *************** *** 426,436 "Ran out of space for personal dictionary\n"); exit (1); } ! cp = dp->word + strlen (dp->word) + 1; ! cp += ! ((*cp & 0xFF) - 1) * (cp - dp->word + 1) + 1; ! *cp++ = keep ? '+' : '-'; ! strcpy (cp, word); } } } --- 420,456 ----- if (keep) *saveword = '+'; } ! else { ! /* Add a new capitalization */ ! (*cp)++; ! capspace = (cp - dp->word + 1) ! * ((*cp & 0xFF) + 1); ! if (dp->word >= hashstrings ! && dp->word <= ! hashstrings + hashheader.stringsize) { ! saveword = dp->word; ! dp->word = malloc (capspace); ! if (dp->word) { ! cp = dp->word; ! while (--capspace >= 0) ! *cp++ = ! *saveword++; ! } ! } ! else ! dp->word = ! realloc (dp->word, capspace); ! if (dp->word == NULL) { ! fprintf (stderr, ! "Ran out of space for personal dictionary\n"); ! exit (1); ! } ! cp = dp->word + len + 1; ! cp += ((*cp & 0xFF) - 1) ! * (cp - dp->word + 1) + 1; ! *cp++ = keep ? '+' : '-'; ! strcpy (cp, word); ! } } } } *************** *** 541,546 return NULL; } treeoutput () { register struct dent *cent; /* Current entry */ --- 561,581 ----- return NULL; } + #if SORTPERSONAL != 0 + /* Comparison routine for sorting the personal dictionary with qsort */ + pdictcmp (enta, entb) + struct dent **enta; + struct dent **entb; + { + /* The parentheses around *enta/*entb below are NECESSARY! + ** Otherwise the compiler reads it as *(enta->word), or + ** enta->word[0], which is illegal (but pcc takes it and + ** produces wrong code). + **/ + return casecmp ((*enta)->word, (*entb)->word); + } + #endif + treeoutput () { register struct dent *cent; /* Current entry */ *************** *** 545,553 { register struct dent *cent; /* Current entry */ register struct dent *lent; /* Linked entry */ ! #ifdef SORTPERSONAL ! register struct dent *lowent; /* Alphabetically lowest entry */ ! struct dent *firstent; /* First entry to be kept */ #endif if (newwords == 0) return; --- 580,589 ----- { register struct dent *cent; /* Current entry */ register struct dent *lent; /* Linked entry */ ! #if SORTPERSONAL != 0 ! int pdictsize; /* Number of entries to write */ ! struct dent **sortlist; /* List of entries to be sorted */ ! register struct dent **sortptr; /* Handy pointer into sortlist */ #endif register struct dent *ehtab; /* End of htab, for quick looping */ *************** *** 549,554 register struct dent *lowent; /* Alphabetically lowest entry */ struct dent *firstent; /* First entry to be kept */ #endif if (newwords == 0) return; --- 585,592 ----- struct dent **sortlist; /* List of entries to be sorted */ register struct dent **sortptr; /* Handy pointer into sortlist */ #endif + register struct dent *ehtab; /* End of htab, for quick looping */ + if (newwords == 0) return; *************** *** 557,564 return; } ! #ifdef SORTPERSONAL ! if (hcount >= SORTPERSONAL) { #endif for (cent = htab; cent - htab < hsize; cent++) { for (lent = cent; lent != NULL; lent = lent->next) { --- 595,627 ----- return; } ! #if SORTPERSONAL != 0 ! /* ! ** If we are going to sort the personal dictionary, we must know ! ** how many items are going to be sorted. ! */ ! if (hcount >= SORTPERSONAL) ! sortlist = NULL; ! else { ! pdictsize = 0; ! for (cent = htab, ehtab = htab + hsize; ! cent < ehtab; ! cent++) { ! for (lent = cent; lent != NULL; lent = lent->next) { ! if (lent->used && lent->keep) ! pdictsize++; ! } ! } ! for (cent = hashtbl, ehtab = hashtbl + hashsize; ! cent < ehtab; ! cent++) { ! if (cent->keep && cent->used) ! pdictsize++; ! } ! sortlist = (struct dent **) ! malloc (pdictsize * sizeof (struct dent)); ! } ! if (sortlist == NULL) { #endif for (cent = htab, ehtab = htab + hsize; cent < ehtab; *************** *** 560,566 #ifdef SORTPERSONAL if (hcount >= SORTPERSONAL) { #endif ! for (cent = htab; cent - htab < hsize; cent++) { for (lent = cent; lent != NULL; lent = lent->next) { if (lent->used && lent->keep) toutent (lent); --- 623,631 ----- } if (sortlist == NULL) { #endif ! for (cent = htab, ehtab = htab + hsize; ! cent < ehtab; ! cent++) { for (lent = cent; lent != NULL; lent = lent->next) { if (lent->used && lent->keep) toutent (lent); *************** *** 566,573 toutent (lent); } } ! for (cent = hashtbl, lent = hashtbl + hashsize; ! cent < lent; cent++) { if (cent->used && cent->keep) toutent (cent); --- 631,638 ----- toutent (lent); } } ! for (cent = hashtbl, ehtab = hashtbl + hashsize; ! cent < ehtab; cent++) { if (cent->used && cent->keep) toutent (cent); *************** *** 572,578 if (cent->used && cent->keep) toutent (cent); } ! #ifdef SORTPERSONAL return; } /* --- 637,643 ----- if (cent->used && cent->keep) toutent (cent); } ! #if SORTPERSONAL != 0 return; } /* *************** *** 576,584 return; } /* ! ** Produce dictionary in sorted order. We use a selection sort, ! ** which is moderately inefficient, but easy to do in our hash table. ! ** We start by linking all "keep" entries together to save time. */ for (lowent = NULL, cent = hashtbl, lent = hashtbl + hashsize; cent < lent; --- 641,651 ----- return; } /* ! ** Produce dictionary in sorted order. We used to do this ! ** destructively, but that turns out to fail because in some modes ! ** the dictionary is written more than once. So we build an ! ** auxiliary pointer table (in sortlist) and sort that. This ! ** is faster anyway, though it uses more memory. */ sortptr = sortlist; for (cent = htab, ehtab = htab + hsize; cent < ehtab; cent++) { *************** *** 580,591 ** which is moderately inefficient, but easy to do in our hash table. ** We start by linking all "keep" entries together to save time. */ ! for (lowent = NULL, cent = hashtbl, lent = hashtbl + hashsize; ! cent < lent; ! cent++) { ! if (cent->keep && cent->used) { ! cent->next = lowent; ! lowent = cent; } } firstent = lowent; --- 647,657 ----- ** auxiliary pointer table (in sortlist) and sort that. This ** is faster anyway, though it uses more memory. */ ! sortptr = sortlist; ! for (cent = htab, ehtab = htab + hsize; cent < ehtab; cent++) { ! for (lent = cent; lent != NULL; lent = lent->next) { ! if (lent->used && lent->keep) ! *sortptr++ = lent; } } for (cent = hashtbl, ehtab = hashtbl + hashsize; *************** *** 588,602 lowent = cent; } } ! firstent = lowent; ! for (cent = htab; cent - htab < hsize; cent++) { ! for (lent = cent; lent != NULL; lent = lowent) { ! lowent = lent->next; ! if (lent->keep && lent->used) { ! lent->next = firstent; ! firstent = lent; ! } ! } } /* Now do the sort. */ while (1) { --- 654,664 ----- *sortptr++ = lent; } } ! for (cent = hashtbl, ehtab = hashtbl + hashsize; ! cent < ehtab; ! cent++) { ! if (cent->used && cent->keep) ! *sortptr++ = cent; } /* Sort the list */ qsort ((char *) sortlist, pdictsize, sizeof (sortlist[0]), pdictcmp); *************** *** 598,624 } } } ! /* Now do the sort. */ ! while (1) { ! lowent = NULL; ! for (cent = firstent; cent != NULL; cent = cent->next) { ! if (cent->used && cent->keep) { ! if (lowent != NULL) { ! if (casecmp (cent->word, ! lowent->word) < 0) ! lowent = cent; ! } ! else ! lowent = cent; ! } ! } ! if (lowent == NULL) ! break; ! else { ! toutent (lowent); ! lowent->used = 0; ! } ! } #endif newwords = 0; --- 660,671 ----- if (cent->used && cent->keep) *sortptr++ = cent; } ! /* Sort the list */ ! qsort ((char *) sortlist, pdictsize, sizeof (sortlist[0]), pdictcmp); ! /* Write it out */ ! for (sortptr = sortlist; --pdictsize >= 0; ) ! toutent (*sortptr++); ! free ((char *) sortlist); #endif newwords = 0; *************** *** 636,641 register char *cp; int len; register int wcount; if (cent->k_followcase) { if (cent->k_capitalize) { --- 683,689 ----- register char *cp; int len; register int wcount; + char wbuf[WORDLEN + 1]; strcpy (wbuf, cent->word); if (cent->k_followcase) { *************** *** 637,642 int len; register int wcount; if (cent->k_followcase) { if (cent->k_capitalize) { lowcase (cent->word); --- 685,691 ----- register int wcount; char wbuf[WORDLEN + 1]; + strcpy (wbuf, cent->word); if (cent->k_followcase) { if (cent->k_capitalize) { lowcase (wbuf); *************** *** 639,648 if (cent->k_followcase) { if (cent->k_capitalize) { ! lowcase (cent->word); ! if (mylower (cent->word[0])) ! cent->word[0] = toupper (cent->word[0]); ! toutword (cent->word, cent); } len = strlen (cent->word) + 1; cp = cent->word + len; --- 688,697 ----- strcpy (wbuf, cent->word); if (cent->k_followcase) { if (cent->k_capitalize) { ! lowcase (wbuf); ! if (mylower (wbuf[0])) ! wbuf[0] = toupper (wbuf[0]); ! toutword (wbuf, cent); } len = strlen (wbuf) + 1; cp = cent->word + len; *************** *** 644,650 cent->word[0] = toupper (cent->word[0]); toutword (cent->word, cent); } ! len = strlen (cent->word) + 1; cp = cent->word + len; wcount = *cp++ & 0xFF; while (--wcount >= 0) { --- 693,699 ----- wbuf[0] = toupper (wbuf[0]); toutword (wbuf, cent); } ! len = strlen (wbuf) + 1; cp = cent->word + len; wcount = *cp++ & 0xFF; while (--wcount >= 0) { *************** *** 655,664 } else { if (!cent->k_allcaps) ! lowcase (cent->word); ! if (cent->k_capitalize && mylower (cent->word[0])) ! cent->word[0] = toupper (cent->word[0]); ! toutword (cent->word, cent); } #else toutword (cent->word, cent); --- 704,713 ----- } else { if (!cent->k_allcaps) ! lowcase (wbuf); ! if (cent->k_capitalize && mylower (wbuf[0])) ! wbuf[0] = toupper (wbuf[0]); ! toutword (wbuf, cent); } #else toutword (cent->word, cent);