[comp.sources.misc] Patch #2 to Ispell Version 2.0 Beta

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);