[net.sources.bugs] Patch #1 to the "enhanced" ispell

geoff@desint.UUCP (03/29/87)

:
: 'See below (file Patch1) for explanations and instructions'
:
#! /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:
#	Patch1
#	icombine.c
#	munchlist.X
# This archive created: Sun Mar 29 01:06:36 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Patch1'" '(37715 characters)'
if test -f 'Patch1'
then
	echo shar: will not over-write existing file "'Patch1'"
else
sed 's/^X //' << \SHAR_EOF > 'Patch1'
X 
X This is patch number 1 for the version of ispell I posted recently.  My
X thanks to the many people (listed in the man page) who submitted changes,
X fixes, and improvements, and my apologies to Walt Buehring, whom I
X inadvertently failed to credit fully in my previous posting.
X 
X This patch consists of three parts:  this file (Patch1), a new program named
X icombine.c (thanks to Gary Puckering), and a replacement for the
X "munchlist.sh" shell script (now called "munchlist.X" thanks to Rich Salz's
X configurability improvements).
X 
X To apply this patch:
X 
X     (1) Unshar this file by piping it through /bin/sh
X     (2) Remove "munchlist.sh"
X     (3) Type "patch < Patch1" in the ispell directory.
X     (4) Move all ispell.words files to ".ispell_words" after rebuilding.
X 
X Improvements added in this patch:
X 
X     (1) Configuration is simpler.  You still must edit both the Makefile
X 	and config.h, but each variable is defined in only one place, so
X 	there are no consistency worries.  There are also a few
X 	explanatory comments.  (Rich Salz)
X     (2) The LOOK command is now configurable.  If LOOK is defined, it is
X 	the command to use for lookup.
X     (2) The install dependency now installs the manual.  (Rich Salz)
X     (3) Buildhash is a hair faster.  (Rich Salz)
X     (4) The dictionary file does not require slashes separating each flag.
X 	Thus, "PLOT/G/S" can now be written "PLOT/GS".  This saves a bit
X 	of dictionary space.  This format is not required, but is generated
X 	by ispell (for the personal dictionary), icombine, and munchlist.
X 	(Rich Salz)
X     (5) The default personal dictionary is now a dot file, ".ispell_words".
X     (6) Ispell will now offer up to 100 possible corrections, instead of
X 	only 10.  Most corrections still require only a single keystroke.
X     (7) Ispell now makes use of the extra lines on tall terminals.
X     (8) Perry Smith's region support for ispell.el has been reintegrated.
X     (9) Ispell now sorts the list of possible corrections.
X    (10) The -t switch selects TeX mode, wherein TeX-style constructs are
X 	skipped.  (Don Kark, Greg Schaffer)
X    (11) The troff processing has been improved somewhat so that string
X 	and number defines are ignored.  (Gary Puckering)
X 
X Problems fixed by this patch:
X 
X     (1) The Makefile wouldn't find buildhash if "." wasn't in the path.
X 	(Rich Salz)
X     (2) On BSD systems, param.h gets types.h, so buildhash.c can't
X 	include both.  (Jim Knutson)
X     (3) Buildhash was neglecting to initialize the "keep" flag.  (Don Kark)
X     (4) In config.h (now config.X), there was an ifdef that used SYSV
X 	instead of USG.  (Dave Mason)
X     (5) Ispell's temp file was named "spell*" and was in /usr/tmp, not /tmp.
X 	(Rich Salz)
X     (6) The s_ending routine in good.c had an unintended, but harmless,
X 	fallthrough in one of the case statements.  (Greg Schaffer)
X     (7) If the dictionary has more than 32K words, the hash routine could
X 	generate a negative hash code.
X     (8) Ispell no longer generates a spurious CR on every line in -l mode.
X         (Gary Puckering)
X     (9) A missing type declaration in lookup.c could cause bugs on
X 	pointer != int machines.  (Jim Knutson, Rich Salz, Bill Randle)
X    (10)	The startup code didn't set ospeed, so padding didn't work.
X 	(Perry Smith)
X 
X 
X 
X Index: Makefile
X 
X *** Makefile.old	Sun Mar 29 00:09:29 1987
X --- Makefile	Sun Mar 29 00:09:32 1987
X ***************
X *** 2,4
X   
X ! # Look over config.h before building.
X   #
X 
X --- 2,4 -----
X   
X ! # Look over config.X before building.
X   #
X ***************
X *** 4,6
X   #
X ! # LIBDIR, DEFHASH, DEFDICT should match definitions in config.h.
X   #
X 
X --- 4,7 -----
X   #
X ! # You may want to edit BINDIR, LIBDIR, DEFHASH, DEFDICT, MANDIR, and
X ! # MANEXT below; the Makefile will update all other files to match.
X   #
X ***************
X *** 6,7
X   #
X   # The ifdef NO8BIT may be used if 8 bit extended text characters
X 
X --- 7,10 -----
X   #
X + # On USG systems, add -DUSG to CFLAGS.
X + #
X   # The ifdef NO8BIT may be used if 8 bit extended text characters
X ***************
X *** 15,16
X   CFLAGS = -O
X   BINDIR = /usr/local/bin
X 
X --- 18,20 -----
X   CFLAGS = -O
X + # BINDIR, LIBDIR, DEFHASH, DEFDICT, MANDIR, MANEXT
X   BINDIR = /usr/local/bin
X ***************
X *** 19,20
X   DEFDICT = dict.191
X   
X 
X --- 23,27 -----
X   DEFDICT = dict.191
X + MANDIR	= /usr/man/u_man/man1
X + MANEXT	= .1l
X + SHELL = /bin/sh
X   
X ***************
X *** 22,24
X   TERMLIB = -ltermlib
X - all: buildhash ispell $(DEFHASH)
X   
X 
X --- 29,30 -----
X   TERMLIB = -ltermlib
X   
X ***************
X *** 24,25
X   
X   ispell.hash: buildhash $(DEFDICT)
X 
X --- 30,33 -----
X   
X + all: buildhash ispell icombine munchlist $(DEFHASH)
X + 
X   ispell.hash: buildhash $(DEFDICT)
X ***************
X *** 25,27
X   ispell.hash: buildhash $(DEFDICT)
X ! 	buildhash
X   
X 
X --- 33,35 -----
X   ispell.hash: buildhash $(DEFDICT)
X ! 	./buildhash $(DEFDICT) $(DEFHASH)
X   
X ***************
X *** 27,35
X   
X ! install: buildhash ispell $(DEFHASH)
X ! 	cp ispell ${BINDIR}/ispell
X ! 	cp munchlist.sh $(BINDIR)/munchlist
X ! 	cp ispell.hash ${LIBDIR}/${DEFHASH}
X ! 	cp expand1.sed expand2.sed $(LIBDIR)
X ! 	chmod 755 ${BINDIR}/ispell $(BINDIR)/munchlist
X ! 	chmod 644 ${LIBDIR}/$(DEFHASH) $(LIBDIR)/expand1.sed \
X   	  $(LIBDIR)/expand2.sed
X 
X --- 35,43 -----
X   
X ! install: all
X ! 	cp ispell $(BINDIR)/ispell
X ! 	cp munchlist $(BINDIR)/munchlist
X ! 	cp ispell.hash $(LIBDIR)/$(DEFHASH)
X ! 	cp expand1.sed expand2.sed icombine $(LIBDIR)
X ! 	chmod 755 $(BINDIR)/ispell $(BINDIR)/munchlist $(LIBDIR)/icombine
X ! 	chmod 644 $(LIBDIR)/$(DEFHASH) $(LIBDIR)/expand1.sed \
X   	  $(LIBDIR)/expand2.sed
X ***************
X *** 35,36
X   	  $(LIBDIR)/expand2.sed
X   
X 
X --- 43,45 -----
X   	  $(LIBDIR)/expand2.sed
X + 	cp ispell.1 $(MANDIR)/ispell$(MANEXT)
X   
X ***************
X *** 37,39
X   buildhash: buildhash.o hash.o
X ! 	cc -o buildhash buildhash.o hash.o
X   
X 
X --- 46,48 -----
X   buildhash: buildhash.o hash.o
X ! 	$(CC) $(CFLAGS) -o buildhash buildhash.o hash.o
X   
X ***************
X *** 39,43
X   
X ! ispell: ispell.o term.o good.o lookup.o hash.o tree.o
X ! 	cc $(CFLAGS) -o ispell ispell.o term.o good.o lookup.o \
X ! 		hash.o tree.o $(TERMLIB)
X   
X 
X --- 48,51 -----
X   
X ! icombine:	icombine.c
X ! 	$(CC) $(CFLAGS) -o icombine icombine.c
X   
X ***************
X *** 43,44
X   
X   clean:
X 
X --- 51,67 -----
X   
X + munchlist:	munchlist.X Makefile
X + 	sed -e 's@!!LIBDIR!!@$(LIBDIR)@' -e 's@!!DEFDICT!!@$(DEFDICT)@' \
X + 		<munchlist.X >munchlist
X + 	chmod +x munchlist
X + 
X + OBJS=ispell.o term.o good.o lookup.o hash.o tree.o
X + ispell: $(OBJS)
X + 	cc $(CFLAGS) -o ispell $(OBJS) $(TERMLIB)
X + 
X + $(OBJS) buildhash.o: config.h
X + 
X + config.h:	config.X Makefile
X + 	sed -e 's@!!LIBDIR!!@$(LIBDIR)@' -e 's@!!DEFDICT!!@$(DEFDICT)@' \
X + 	    -e 's@!!DEFHASH!!@$(DEFHASH)@' <config.X >config.h
X + 
X   clean:
X ***************
X *** 45,46
X   	rm -f *.o buildhash ispell core a.out mon.out hash.out \
X ! 		*.stat *.cnt
X 
X --- 68,69 -----
X   	rm -f *.o buildhash ispell core a.out mon.out hash.out \
X ! 		*.stat *.cnt munchlist config.h
X 
X 
X Index: buildhash.c
X 
X *** buildhash.c.old	Sun Mar 29 00:09:44 1987
X --- buildhash.c	Sun Mar 29 00:09:48 1987
X ***************
X *** 8,9
X   #include <stdio.h>
X   #include <sys/types.h>
X 
X --- 8,10 -----
X   #include <stdio.h>
X + #ifdef USG
X   #include <sys/types.h>
X ***************
X *** 9,10
X   #include <sys/types.h>
X   #include <sys/stat.h>
X 
X --- 10,12 -----
X   #include <sys/types.h>
X + #endif
X   #include <sys/stat.h>
X ***************
X *** 202,204
X   	while (fgets (lbuf, sizeof lbuf, dictf) != NULL) {
X ! 		if (i % 1000 == 0) {
X   			printf ("%d ", i);
X 
X --- 204,206 -----
X   	while (fgets (lbuf, sizeof lbuf, dictf) != NULL) {
X ! 		if ((i & 1023) == 0) {
X   			printf ("%d ", i);
X ***************
X *** 269,270
X   	d->m_flag = 0;
X   
X 
X --- 271,273 -----
X   	d->m_flag = 0;
X + 	d->keep = 0;
X   
X ***************
X *** 282,284
X   	p++;
X ! 	while (*p != NULL) {
X   		switch (*p) {
X 
X --- 285,287 -----
X   	p++;
X ! 	while (*p != '\0'  &&  *p != '\n') {
X   		switch (*p) {
X ***************
X *** 299,301
X   		case 0:
X !  			fprintf (stderr, "no key word %s\n", lbuf);
X   			continue;
X 
X --- 302,304 -----
X   		case 0:
X !  			fprintf (stderr, "no flags on word %s\n", lbuf);
X   			continue;
X ***************
X *** 307,314
X   		p++;
X ! 		if (*p != '/' && *p != NULL && *p != '\n') {
X ! 			fprintf (stderr, "bad format %s (%c 0%o)\n", 
X ! 					lbuf, *p, *p);
X ! 			break;
X ! 		}
X ! 		if (*p)
X   			p++;
X 
X --- 310,312 -----
X   		p++;
X ! 		if (*p == '/')		/* Handle old-format dictionaries too */
X   			p++;
X ***************
X *** 314,316
X   			p++;
X - 	
X   	}
X 
X --- 312,313 -----
X   			p++;
X   	}
X ***************
X *** 332,337
X   
X ! 	i = 0;
X ! 	while (fgets (buf, sizeof buf, d) != NULL) {
X ! 		i++;
X ! 		if (i % 1000 == 0) {
X   			printf ("%d ", i);
X 
X --- 329,332 -----
X   
X ! 	for (i = 0; fgets (buf, sizeof buf, d); )
X ! 		if ((++i & 1023) == 0) {
X   			printf ("%d ", i);
X ***************
X *** 339,341
X   		}
X - 	}
X   	fclose (d);
X 
X --- 334,335 -----
X   		}
X   	fclose (d);
X 
X 
X Index: config.X
X 
X *** config.X.old	Sun Mar 29 00:10:04 1987
X --- config.X	Sun Mar 29 00:10:08 1987
X ***************
X *** 1,2
X   /*
X   ** library directory for hash table(s) / default hash table name
X 
X --- 1,16 -----
X   /*
X +  * This is the configuration file for ispell.  Thanks to Bob McQueer
X +  * for creating it and making the necessary changes elsewhere to
X +  * support it.
X +  * Look through this file from top to bottom, and edit anything that
X +  * needs editing.  There are also five or six variables in the
X +  * Makefile that you must edit.  Note that the Makefile edits this
X +  * file (config.X) to produce config.h.  If you are looking at
X +  * config.h, you're in the wrong file.
X +  *
X +  * Don't change the funny-looking lines with !!'s in them;  see the
X +  * Makefile!
X +  */
X + 
X + /*
X   ** library directory for hash table(s) / default hash table name
X ***************
X *** 6,9
X   */
X ! #define LIBDIR "/usr/local/lib"
X ! #define DEFHASH "ispell.hash"
X   
X 
X --- 20,23 -----
X   */
X ! #define LIBDIR "!!LIBDIR!!"
X ! #define DEFHASH "!!DEFHASH!!"
X   
X ***************
X *** 9,11
X   
X ! #ifdef SYSV
X   #define index strchr
X 
X --- 23,25 -----
X   
X ! #ifdef USG
X   #define index strchr
X ***************
X *** 17,19
X   /* default word list */
X ! #define DEFPDICT "ispell.words"
X   
X 
X --- 31,33 -----
X   /* default word list */
X ! #define DEFPDICT ".ispell_words"
X   
X ***************
X *** 20,22
X   /* mktemp template for temporary file - MUST contain 6 consecutive X's */
X ! #define TEMPNAME "/usr/tmp/spellXXXXXX"
X   
X 
X --- 34,36 -----
X   /* mktemp template for temporary file - MUST contain 6 consecutive X's */
X ! #define TEMPNAME "/tmp/ispellXXXXXX"
X   
X ***************
X *** 23,25
X   /* default dictionary file */
X ! #define DEFDICT "dict.191"
X   
X 
X --- 37,39 -----
X   /* default dictionary file */
X ! #define DEFDICT "!!DEFDICT!!"
X   
X ***************
X *** 26,28
X   /* define LOOK if look(1) command is available */
X ! #define LOOK
X   
X 
X --- 40,42 -----
X   /* define LOOK if look(1) command is available */
X ! #define LOOK	"/usr/bin/look -df"
X   
X 
X 
X Index: good.c
X 
X *** good.c.old	Sun Mar 29 00:10:19 1987
X --- good.c	Sun Mar 29 00:10:23 1987
X ***************
X *** 385,386
X   		}
X   	case 'G':	/* J */
X 
X --- 385,387 -----
X   		}
X + 		return;
X   	case 'G':	/* J */
X 
X 
X Index: hash.c
X 
X *** hash.c.old	Sun Mar 29 00:10:47 1987
X --- hash.c	Sun Mar 29 00:10:49 1987
X ***************
X *** 25,27
X   	h &= 077777;
X ! 	return (h %= hashsize);
X   }
X 
X --- 25,27 -----
X   	h &= 077777;
X ! 	return (unsigned long) h % hashsize;
X   }
X ***************
X *** 27,31
X   }
X - 
X - 
X - 
X - 		
X 
X --- 27 -----
X   }
X 
X 
X Index: ispell.1
X 
X *** ispell.1.old	Sun Mar 29 00:11:04 1987
X --- ispell.1	Sun Mar 29 00:11:10 1987
X ***************
X *** 10,11
X   [
X   .B \-x
X 
X --- 10,13 -----
X   [
X + .B \-t
X + |
X   .B \-x
X ***************
X *** 12,13
X   |
X   .B \-d
X 
X --- 14,17 -----
X   |
X + .B \-S
X + |
X   .B \-d
X ***************
X *** 21,22
X   [
X   .B \-d
X 
X --- 25,28 -----
X   [
X + .B \-t
X + |
X   .B \-d
X ***************
X *** 31,32
X   [
X   .B \-d
X 
X --- 37,40 -----
X   [
X + .B \-t
X + |
X   .B \-d
X ***************
X *** 74,76
X   dictionary.  If one of the near misses is the word you want, type the
X ! corresponding number.  Finally, if none of these choices is right, you
X   can type "R" and you will be prompted for a replacement word.
X 
X --- 82,87 -----
X   dictionary.  If one of the near misses is the word you want, type the
X ! corresponding number.
X ! (If there are more than 10 choices,
X ! you may have to type a carriage return to complete a single-digit number).
X ! Finally, if none of these choices is right, you
X   can type "R" and you will be prompted for a replacement word.
X ***************
X *** 92,93
X   .B \-a
X   is intended to be used from other programs through a pipe.  In this
X 
X --- 103,105 -----
X   .B \-a
X + option
X   is intended to be used from other programs through a pipe.  In this
X ***************
X *** 95,97
X   .I ispell
X ! expects the standard input to consist of single words.  Each word is
X   read, and a single line is written to the standard output.  If the word
X 
X --- 107,110 -----
X   .I ispell
X ! expects the standard input to consist of lines containing single words.
X ! Each word is
X   read, and a single line is written to the standard output.  If the word
X ***************
X *** 109,110
X   .PP
X   The
X 
X --- 122,135 -----
X   .PP
X + When in the
X + .B \-a
X + mode,
X + .I ispell
X + will also accept lines of single words prefixed with either a '*' or a '@'.
X + A line starting with '*' tells
X + .I ispell
X + to insert the word into the user's dictionary (similar to the I command).
X + A line starting with '@' causes
X + .I ispell
X + to accept this word in the future (similar to the A command).
X + .PP
X   The
X ***************
X *** 118,119
X   The
X   .B \-d
X 
X --- 143,168 -----
X   The
X + .B \-S
X + option suppresses
X + .IR ispell "'s"
X + normal behavior of sorting the list of possible replacement words.
X + Some people may prefer this, since it somewhat enhances the probability
X + that the correct word will be low-numbered.
X + .PP
X + The
X + .B \-t
X + option selects TeX/LaTeX input mode.
X + In this mode, whenever a backslash ("\e") is found,
X + .I ispell
X + will skip to the next whitespace.
X + Thus, for example, given
X + .RS
X + \echapter {This is a Ckapter}
X + \ecite{SCH86}
X + .RE
X + will find "Ckapter" but will not look for SCH.
X + The
X + .B \-t
X + option does not recognize the TeX comment character "%".
X + .PP
X + The
X   .B \-d
X ***************
X *** 226,228
X   in such a way as to only support ASCII range text if desired.
X ! .SH DEFAULT FILES
X   /usr/public/lib/ispell.hash
X 
X --- 275,277 -----
X   in such a way as to only support ASCII range text if desired.
X ! .SH FILES
X   /usr/public/lib/ispell.hash
X ***************
X *** 278,280
X   .br
X ! Enhanced by James Woods, Bob McQueer, Bill Randle, Marc Ries, Rob McMahon,
X ! and Geoff Kuenning.
X 
X --- 327,344 -----
X   .br
X ! Collected, revised, and enhanced for the Usenet by Walt Buehring.
X ! .br
X ! Further enhanced and debugged by
X ! Don Kark,
X ! Jim Knutson,
X ! Geoff Kuenning,
X ! Dave Mason,
X ! Rob McMahon,
X ! Bob McQueer,
X ! Gary Puckering,
X ! Bill Randle,
X ! Marc Ries,
X ! Rich Salz,
X ! Greg Schaffer,
X ! Perry Smith,
X ! and
X ! James Woods.
X 
X 
X Index: ispell.c
X 
X *** ispell.c.old	Sun Mar 29 00:11:41 1987
X --- ispell.c	Sun Mar 29 00:11:47 1987
X ***************
X *** 19,20
X    *	hashed personal dictionary file
X    */
X 
X --- 19,25 -----
X    *	hashed personal dictionary file
X +  *	-S option for unsorted word lists
X +  * 1987, Greg Schaffer, added:
X +  *	-T option (for TeX and LaTeX instead of troff) [later changed to -t]
X +  *	   passes over \ till next whitespace.
X +  *	   does not recognize % (comment)
X    */
X ***************
X *** 51,52
X   
X   givehelp ()
X 
X --- 56,59 -----
X   
X + static int sortit = 1;
X + 
X   givehelp ()
X ***************
X *** 90,91
X   int xflag = 0;
X   
X 
X --- 97,99 -----
X   int xflag = 0;
X + int tflag = 0;
X   
X ***************
X *** 97,100
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 
X --- 105,108 -----
X   {
X ! 	fprintf (stderr, "Usage: %s [-dfile | -pfile | -wchars | -t | -x | -S] file .....\n",Cmd);
X ! 	fprintf (stderr, "       %s [-dfile | -pfile | -wchars | -t] -l\n",Cmd);
X   #ifdef USG
X ***************
X *** 100,102
X   #ifdef USG
X ! 	fprintf (stderr, "       %s [-dfile | -pfile | -ffile | -s] -a\n",Cmd);
X   #else
X 
X --- 108,110 -----
X   #ifdef USG
X ! 	fprintf (stderr, "       %s [-dfile | -pfile | -ffile | -t | -s] -a\n",Cmd);
X   #else
X ***************
X *** 102,104
X   #else
X ! 	fprintf (stderr, "       %s [-dfile | -pfile | -ffile] -a\n",Cmd);
X   #endif
X 
X --- 110,112 -----
X   #else
X ! 	fprintf (stderr, "       %s [-dfile | -pfile | -ffile | -t] -a\n",Cmd);
X   #endif
X ***************
X *** 149,150
X   		switch ((*argv)[1]) {
X   		case 'a':
X 
X --- 157,161 -----
X   		switch ((*argv)[1]) {
X + 		case 't':
X + 			tflag++;
X + 			break;
X   		case 'a':
X ***************
X *** 178,179
X   #endif
X   		case 'p':
X 
X --- 189,193 -----
X   #endif
X + 		case 'S':
X + 			sortit = 0;
X + 			break;
X   		case 'p':
X ***************
X *** 311,313
X   	if ((infile = fopen (tempfile, "r")) == NULL) {
X ! 		fprintf (stderr, "tempoary file disappeared (%s)\r\n", tempfile);	
X   		sleep (2);
X 
X --- 325,327 -----
X   	if ((infile = fopen (tempfile, "r")) == NULL) {
X ! 		fprintf (stderr, "temporary file disappeared (%s)\r\n", tempfile);	
X   		sleep (2);
X ***************
X *** 360,361
X   		len = strlen (secondbuf) - 1;
X   		if (secondbuf [ len ] == '\n')
X 
X --- 374,399 -----
X   		len = strlen (secondbuf) - 1;
X + 
X + 		/* skip over .if */
X + 		if (strncmp(currentchar,".if t",5) == 0 
X + 		||  strncmp(currentchar,".if n",5) == 0) {
X + 			copyout(&currentchar,5);
X + 			while (*currentchar && isspace(*currentchar)) 
X + 				copyout(&currentchar, 1);
X + 		}
X + 
X + 		/* skip over .ds XX or .nr XX */
X + 		if (strncmp(currentchar,".ds ",4) == 0 
X + 		||  strncmp(currentchar,".de ",4) == 0
X + 		||  strncmp(currentchar,".nr ",4) == 0) {
X + 			copyout(&currentchar, 3);
X + 			while (*currentchar && isspace(*currentchar)) 
X + 				copyout(&currentchar, 1);
X + 			while (*currentchar && !isspace(*currentchar))
X + 				copyout(&currentchar, 1);
X + 			if (*currentchar == 0) {
X + 				if (!lflag) putc ('\n', outfile);
X + 				continue;
X + 			}
X + 		}
X + 
X   		if (secondbuf [ len ] == '\n')
X ***************
X *** 364,366
X   		/* if this is a formatter command, skip over it */
X ! 		if (*currentchar == '.') {
X   			while (*currentchar && !myspace (*currentchar)) {
X 
X --- 402,404 -----
X   		/* if this is a formatter command, skip over it */
X ! 		if (!tflag && *currentchar == '.') {
X   			while (*currentchar && !myspace (*currentchar)) {
X ***************
X *** 379,380
X   			while (*currentchar && !iswordch(*currentchar)) {
X   				/* formatting escape sequences */
X 
X --- 417,433 -----
X   			while (*currentchar && !iswordch(*currentchar)) {
X + 			    if (tflag)		/* TeX or LaTeX stuff */
X + 			    {
X + 				if (*currentchar == '\\') {
X + 				    /* skip till whitespace */
X + 				    while (*currentchar && 
X + 					!isspace(*currentchar)) {
X + 					    if (!lflag)
X + 						putc(*currentchar, outfile);
X + 					    currentchar++;
X + 					}
X + 				    continue;
X + 				}
X + 			    }
X + 			    else
X + 			    {
X   				/* formatting escape sequences */
X ***************
X *** 403,404
X   				}
X   
X 
X --- 456,458 -----
X   				}
X + 			    }
X   
X ***************
X *** 420,422
X   				if (!good (token)  &&  !cflag)
X ! 					printf ("%s\r\n", token);
X   			} else {
X 
X --- 474,477 -----
X   				if (!good (token)  &&  !cflag)
X ! 					if (lflag) printf ("%s\n", token);
X ! 					else       printf ("%s\r\n", token);
X   			} else {
X ***************
X *** 433,435
X   
X ! char possibilities[10][BUFSIZ];
X   int pcount;
X 
X --- 488,492 -----
X   
X ! #define MAXPOSSIBLE	99	/* Max no. of possibilities to generate */
X ! 
X ! char possibilities[MAXPOSSIBLE][BUFSIZ];
X   int pcount;
X ***************
X *** 435,436
X   int pcount;
X   
X 
X --- 492,494 -----
X   int pcount;
X + int maxposslen;
X   
X ***************
X *** 442,443
X   	int i;
X   	char *p;
X 
X --- 500,503 -----
X   	int i;
X + 	int col_ht;
X + 	int ncols;
X   	char *p;
X ***************
X *** 461,466
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 --- 521,542 -----
X   
X ! 	/*
X ! 	 * Make sure we have enough room on the screen to hold the
X ! 	 * possibilities.  Reduce the list if necessary.  80 / (maxposslen + 8)
X ! 	 * is the maximum number of columns that will fit.
X ! 	 */
X ! 	col_ht = li - 6;		/* Height of columns of words */
X ! 	ncols = 80 / (maxposslen + 8);
X ! 	if (pcount > ncols * col_ht)
X ! 		pcount = ncols * col_ht;
X ! 
X ! #if 0
X ! 	/*
X ! 	 * Equalize the column sizes.  The last column will be short.
X ! 	 */
X ! 	col_ht = (pcount + ncols - 1) / ncols;
X ! #endif
X ! 
X ! 	for (i = 0; i < pcount; i++) {
X ! 		move (2 + (i % col_ht), (maxposslen + 8) * (i / col_ht));
X ! 		printf ("%2d: %s", i, possibilities[i]);
X   	}
X ***************
X *** 467,469
X   
X ! 	move (15, 0);
X   	printf ("%s\r\n", firstbuf);
X 
X --- 543,545 -----
X   
X ! 	move (li - 3, 0);
X   	printf ("%s\r\n", firstbuf);
X ***************
X *** 516,518
X   				char buf[200];
X ! 				move (18, 0);
X   				putchar ('!');
X 
X --- 592,594 -----
X   				char buf[200];
X ! 				move (li - 1, 0);
X   				putchar ('!');
X ***************
X *** 529,531
X   		case 'r': case 'R':
X ! 			move (18, 0);
X   			printf ("Replace with: ");
X 
X --- 605,607 -----
X   		case 'r': case 'R':
X ! 			move (li - 1, 0);
X   			printf ("Replace with: ");
X ***************
X *** 541,545
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 --- 617,634 -----
X   		case '5': case '6': case '7': case '8': case '9':
X ! 			i = c - '0';
X ! 			if (pcount > 10
X ! 			    &&  i > 0  &&  i <= (pcount - 1) / 10) {
X ! 				c = getchar () & NOPARITY;
X ! 				if (c >= '0'  &&  c <= '9')
X ! 					i = i * 10 + c - '0';
X ! 				else if (c != '\r'  &&  c != '\n') {
X ! 					putchar (7);
X ! 					break;
X ! 				}
X ! 			}
X ! 			if (i < pcount) {
X ! 				strcpy (token, possibilities[i]);
X ! 				inserttoken (secondbuf, begintoken,
X ! 				    token, currentchar);
X ! 				erase ();
X   				return;
X ***************
X *** 548,549
X   			break;
X   		case 'l': case 'L':
X 
X --- 637,641 -----
X   			break;
X + 		case '\r':	/* This makes typing \n after single digits */
X + 		case '\n':	/* ..less obnoxious */
X + 			break;
X   		case 'l': case 'L':
X ***************
X *** 551,553
X   				char buf[100];
X ! 				move (18, 0);
X   				printf ("Lookup string ('*' is wildcard): ");
X 
X --- 643,645 -----
X   				char buf[100];
X ! 				move (li - 1, 0);
X   				printf ("Lookup string ('*' is wildcard): ");
X ***************
X *** 598,599
X   	int i;
X   
X 
X --- 690,692 -----
X   	int i;
X + 	extern int strcmp ();
X   
X ***************
X *** 599,601
X   
X ! 	for (i = 0; i < 10; i++)
X   		possibilities[i][0] = 0;
X 
X --- 692,694 -----
X   
X ! 	for (i = 0; i < MAXPOSSIBLE; i++)
X   		possibilities[i][0] = 0;
X ***************
X *** 602,603
X   	pcount = 0;
X   
X 
X --- 695,697 -----
X   	pcount = 0;
X + 	maxposslen = 0;
X   
X ***************
X *** 603,608
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 --- 697,702 -----
X   
X ! 	if (pcount < MAXPOSSIBLE) wrongletter (word);
X ! 	if (pcount < MAXPOSSIBLE) extraletter (word);
X ! 	if (pcount < MAXPOSSIBLE) missingletter (word);
X ! 	if (pcount < MAXPOSSIBLE) transposedletter (word);
X   
X ***************
X *** 608,609
X   
X   }
X 
X --- 702,706 -----
X   
X + 	if (sortit  &&  pcount)
X + 		qsort ((char *) possibilities, pcount,
X + 		    sizeof (possibilities[0]), strcmp);
X   }
X ***************
X *** 622,624
X   	strcpy (possibilities[pcount++], word);
X ! 	if (pcount >= 10)
X   		return (-1);
X 
X --- 719,724 -----
X   	strcpy (possibilities[pcount++], word);
X ! 	i = strlen (word);
X ! 	if (i > maxposslen)
X ! 		maxposslen = i;
X ! 	if (pcount >= MAXPOSSIBLE)
X   		return (-1);
X ***************
X *** 817,819
X   	while (gets (buf) != NULL) {
X ! 		if (good (buf)) {
X   			if (rootword[0] == 0) {
X 
X --- 917,924 -----
X   	while (gets (buf) != NULL) {
X ! 		/* *line is like `i', @line is like `a' */
X ! 		if (buf[0] == '*' || buf[0] == '@') {
X ! 			treeinsert(buf + 1, buf[0] == '*');
X ! 			printf("*\n");
X ! 			treeoutput ();
X ! 		} else if (good (buf)) {
X   			if (rootword[0] == 0) {
X ***************
X *** 827,829
X   				printf ("& ");
X ! 				for (i = 0; i < 10; i++) {
X   					if (possibilities[i][0] == 0)
X 
X --- 932,934 -----
X   				printf ("& ");
X ! 				for (i = 0; i < MAXPOSSIBLE; i++) {
X   					if (possibilities[i][0] == 0)
X ***************
X *** 886,888
X   			/* no wild, use look(1) */
X ! 			sprintf (cmd, "/usr/bin/look -df %s %s", grepstr, WORDS);
X   #else
X 
X --- 991,993 -----
X   			/* no wild, use look(1) */
X ! 			sprintf (cmd, "%s %s %s", LOOK, grepstr, WORDS);
X   #else
X 
X 
X Index: ispell.el
X 
X *** ispell.el.old	Sun Mar 29 00:12:28 1987
X --- ispell.el	Sun Mar 29 00:12:31 1987
X ***************
X *** 7,8
X   
X   ;;; Depends on the ispell program snarfed from MIT-PREP in early 
X 
X --- 7,13 -----
X   
X + ;;; ispell-region and associate routines added by
X + ;;; Perry Smith
X + ;;; pedz@bobkat
X + ;;; Tue Jan 13 20:18:02 CST 1987
X + 
X   ;;; Depends on the ispell program snarfed from MIT-PREP in early 
X ***************
X *** 35,38
X         ;; Make certain characters word constituents
X !       (modify-syntax-entry ?' "w   " ispell-syntax-table)
X !       (modify-syntax-entry ?- "w   " ispell-syntax-table)
X         ;; Get rid on existing word syntax on certain characters 
X 
X --- 40,43 -----
X         ;; Make certain characters word constituents
X !       ;; (modify-syntax-entry ?' "w   " ispell-syntax-table)
X !       ;; (modify-syntax-entry ?- "w   " ispell-syntax-table)
X         ;; Get rid on existing word syntax on certain characters 
X ***************
X *** 38,39
X         ;; Get rid on existing word syntax on certain characters 
X         (modify-syntax-entry ?$ ".   " ispell-syntax-table)
X 
X --- 43,54 -----
X         ;; Get rid on existing word syntax on certain characters 
X +       (modify-syntax-entry ?0 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?1 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?2 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?3 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?4 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?5 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?6 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?7 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?8 ".   " ispell-syntax-table)
X +       (modify-syntax-entry ?9 ".   " ispell-syntax-table)
X         (modify-syntax-entry ?$ ".   " ispell-syntax-table)
X ***************
X *** 73,75
X   	   (or quietly (message "Could Not Find %s" (upcase word))))
X ! 	  (t (setq replace (ispell-choose poss))
X   	     (if replace
X 
X --- 88,90 -----
X   	   (or quietly (message "Could Not Find %s" (upcase word))))
X ! 	  (t (setq replace (ispell-choose poss word))
X   	     (if replace
X ***************
X *** 76,80
X   		 (progn
X ! 		   (goto-char end)
X ! 		   (delete-region start end)
X ! 		   (insert-string replace)))))
X       poss))
X 
X --- 91,95 -----
X   		 (progn
X ! 		    (goto-char end)
X ! 		    (delete-region start end)
X ! 		    (insert-string replace)))))
X       poss))
X ***************
X *** 82,86
X   
X ! (defun ispell-choose (choices)
X !   "Display possible corrections from list CHOICES.  Return chosen word or nil 
X ! if none chosen."
X     (unwind-protect 
X 
X --- 97,101 -----
X   
X ! (defun ispell-choose (choices word)
X !   "Display possible corrections from list CHOICES.  Return chosen word
X ! if one is chosen; Return nil to keep word"
X     (unwind-protect 
X ***************
X *** 89,92
X   	      (words choices)
X ! 	      (pick -1)
X ! 	      (window-min-height 2))
X   	  (overlay-window 3)
X 
X --- 104,107 -----
X   	      (words choices)
X ! 	      (window-min-height 2)
X ! 	      char num result)
X   	  (overlay-window 3)
X ***************
X *** 97,99
X   		(insert "\n"))
X ! 	    (insert "(" (+ count ?a) ") " (car words) "  ")
X   	    (setq words (cdr words)
X 
X --- 112,114 -----
X   		(insert "\n"))
X ! 	    (insert "(" (+ count ?1) ") " (car words) "  ")
X   	    (setq words (cdr words)
X ***************
X *** 101,110
X   	  (select-window (next-window))
X ! 	  (while (eq pick -1)
X ! 	    (message "Enter letter to replace word;  Space to flush")
X ! 	    (let* ((char (read-char))
X ! 		   (num (1+ (- (upcase char) ?A))))
X ! 	      (cond ((= char ? ) (setq pick 0))
X ! 		    ((or (<= num 0) (> num count)) (ding))
X ! 		    (t (setq pick num)))))
X ! 	  (and (> pick 0) (nth (1- pick) choices))))
X       ;; Protected forms...
X 
X --- 116,134 -----
X   	  (select-window (next-window))
X ! 	  (while (eq t
X ! 		     (setq result
X ! 			   (progn
X ! 			     (message "Enter letter to replace word;  Space to flush")
X ! 			     (setq char (upcase (read-char)))
X ! 			     (setq num (- char ?1))
X ! 			     (cond ((= char ? ) nil)
X ! 				   ((= char ?I)
X ! 				    (ispell-check (concat "*" word))
X ! 				    nil)
X ! 				   ((= char ?A)
X ! 				    (ispell-check (concat "@" word))
X ! 				    nil)
X ! 				   ((= char ?R) (read-string "Replacement: " nil))
X ! 				   ((and (>= num 0) (< num count)) (nth num choices))
X ! 				   (t (ding) t))))))
X ! 	  result))
X       ;; Protected forms...
X ***************
X *** 191
X   
X 
X --- 215,273 -----
X   
X + (defvar ispell-filter-hook "/bin/cat"
X +   "Filter to pass a region through before sending it to ispell.
X + Typically this is set to cat, deroff, detex, etc.")
X + (make-variable-buffer-local 'ispell-filter-hook)
X + 
X + (defvar ispell-filter-hook-args nil
X +   "Arguments to pass to ispell-filter-hook")
X + (make-variable-buffer-local 'ispell-filter-hook-args)
X + 
X + ; This routine has certain limitations brought about by the filter
X + ; hook.  For example, deroff will take ``\fBcat\fR'' and spit out
X + ; ``cat''.  This is hard to search for since word-search-forward will
X + ; not match at all and search-forward for ``cat'' will match
X + ; ``concatinate'' if it happens to occur before.  I attempt to
X + ; minimize these problems by always searching for each word in the
X + ; original buffer even if it is not misspelled.  This slows things
X + ; down.
X + 
X + (defun ispell-region (start end)
X +   "Check a region for spelling errors interactively.  The variable
X + which should be buffer or mode specific ispell-filter-hook is called
X + to filter out text processing commands."
X +   (interactive "r")
X +   (let ((this-buf (current-buffer))
X + 	(spell-buf (get-buffer-create "ispell-temp"))
X + 	(current-syntax (syntax-table))
X + 	word poss replace word-start word-end)
X +     (unwind-protect
X + 	(save-excursion
X + 	  (set-buffer spell-buf)
X + 	  (erase-buffer)
X + 	  (set-buffer this-buf)
X + 	  (if ispell-filter-hook-args
X + 	      (call-process-region start end ispell-filter-hook nil
X + 				   spell-buf nil ispell-filter-hook-args)
X + 	    (call-process-region start end ispell-filter-hook nil
X + 				 spell-buf nil))
X + 	  (goto-char start)
X + 	  (set-buffer spell-buf)
X + 	  (set-syntax-table ispell-syntax-table)
X + 	  (goto-char (point-min))
X + 	  (while (progn
X + 		   (message "Looking for a misspelled word")
X + 		   (re-search-forward "\\W*\\(\\w+\\)" nil t))
X + 	    (setq word (buffer-substring (setq word-start (match-beginning 1))
X + 					 (setq word-end (match-end 1))))
X + 	    (setq poss (ispell-check word))
X + 	    (set-buffer this-buf)
X + 	    (or (search-forward word nil t)
X + 		(error "Can not find %s in original text" word))
X + 	    (if (not (or (eq poss t) (stringp poss))) ;bad word
X + 		(progn
X + 		  (sit-for 0)
X + 		  (setq replace (ispell-choose poss word))
X + 		  (if replace
X + 		      (replace-match replace))))
X + 	    (set-buffer spell-buf)))
X +       (set-syntax-table current-syntax))))
X 
X 
X Index: ispell.h
X 
X *** ispell.h.old	Sun Mar 29 00:12:45 1987
X --- ispell.h	Sun Mar 29 00:12:49 1987
X ***************
X *** 2,5
X   
X - #define LIBDIR "/tmp2/lib"
X - 
X   struct dent {
X 
X --- 2,3 -----
X   
X   struct dent {
X 
X 
X Index: lookup.c
X 
X *** lookup.c.old	Sun Mar 29 00:12:59 1987
X --- lookup.c	Sun Mar 29 00:13:02 1987
X ***************
X *** 13,14
X   
X   struct dent *hashtbl;
X 
X --- 13,15 -----
X   
X + struct dent *treelookup();
X   struct dent *hashtbl;
X 
X 
X Index: term.c
X 
X *** term.c.old	Sun Mar 29 00:13:10 1987
X --- term.c	Sun Mar 29 00:13:13 1987
X ***************
X *** 94,95
X   	int onstop();
X   
X 
X --- 94,96 -----
X   	int onstop();
X + 	extern short ospeed;
X   
X ***************
X *** 119,120
X   	killchar = sbuf.sg_kill;
X   
X 
X --- 120,122 -----
X   	killchar = sbuf.sg_kill;
X + 	ospeed = sbuf.sg_ospeed;
X   
X 
X 
X Index: tree.c
X 
X *** tree.c.old	Sun Mar 29 00:13:27 1987
X --- tree.c	Sun Mar 29 00:13:32 1987
X ***************
X *** 146,210
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 
X --- 146,215 -----
X   		dp = treeinsert (buf, 1);
X ! 		if (h != NULL) {
X ! 			while (*h != '\0'  &&  *h != '\n') {
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 ! 				/* Accept old-format dicts with extra slashes */
X ! 				if (*h == '/')
X ! 					h++;
X   			}
X ***************
X *** 210,214
X   			}
X - 			/* Exit loop if no more flags */
X - 			if (*h++ != '/')
X - 				break;
X   		}
X 
X --- 215,216 -----
X   			}
X   		}
X ***************
X *** 312,314
X   	}
X ! 	newwords = 1;
X   	return tinsert (nword, (struct dent *) NULL, keep);
X 
X --- 314,316 -----
X   	}
X ! 	newwords |= keep;
X   	return tinsert (nword, (struct dent *) NULL, keep);
X ***************
X *** 421,422
X   	toutput1 ();
X   
X 
X --- 423,425 -----
X   	toutput1 ();
X + 	newwords = 0;
X   
X ***************
X *** 445,446
X   
X   static
X 
X --- 448,451 -----
X   
X + static int hasslash;
X + 
X   static
X ***************
X *** 449,450
X   {
X   	fprintf (dictf, "%s", cent->word);
X 
X --- 454,457 -----
X   {
X + 
X + 	hasslash = 0;
X   	fprintf (dictf, "%s", cent->word);
X ***************
X *** 451,453
X   	if (cent->d_flag)
X ! 		fprintf (dictf, "/D");
X   	if (cent->g_flag)
X 
X --- 458,460 -----
X   	if (cent->d_flag)
X ! 		flagout ('D');
X   	if (cent->g_flag)
X ***************
X *** 453,455
X   	if (cent->g_flag)
X ! 		fprintf (dictf, "/G");
X   	if (cent->h_flag)
X 
X --- 460,462 -----
X   	if (cent->g_flag)
X ! 		flagout ('G');
X   	if (cent->h_flag)
X ***************
X *** 455,457
X   	if (cent->h_flag)
X ! 		fprintf (dictf, "/H");
X   	if (cent->j_flag)
X 
X --- 462,464 -----
X   	if (cent->h_flag)
X ! 		flagout ('H');
X   	if (cent->j_flag)
X ***************
X *** 457,459
X   	if (cent->j_flag)
X ! 		fprintf (dictf, "/J");
X   	if (cent->m_flag)
X 
X --- 464,466 -----
X   	if (cent->j_flag)
X ! 		flagout ('J');
X   	if (cent->m_flag)
X ***************
X *** 459,461
X   	if (cent->m_flag)
X ! 		fprintf (dictf, "/M");
X   	if (cent->n_flag)
X 
X --- 466,468 -----
X   	if (cent->m_flag)
X ! 		flagout ('M');
X   	if (cent->n_flag)
X ***************
X *** 461,463
X   	if (cent->n_flag)
X ! 		fprintf (dictf, "/N");
X   	if (cent->p_flag)
X 
X --- 468,470 -----
X   	if (cent->n_flag)
X ! 		flagout ('N');
X   	if (cent->p_flag)
X ***************
X *** 463,465
X   	if (cent->p_flag)
X ! 		fprintf (dictf, "/P");
X   	if (cent->r_flag)
X 
X --- 470,472 -----
X   	if (cent->p_flag)
X ! 		flagout ('P');
X   	if (cent->r_flag)
X ***************
X *** 465,467
X   	if (cent->r_flag)
X ! 		fprintf (dictf, "/R");
X   	if (cent->s_flag)
X 
X --- 472,474 -----
X   	if (cent->r_flag)
X ! 		flagout ('R');
X   	if (cent->s_flag)
X ***************
X *** 467,469
X   	if (cent->s_flag)
X ! 		fprintf (dictf, "/S");
X   	if (cent->t_flag)
X 
X --- 474,476 -----
X   	if (cent->s_flag)
X ! 		flagout ('S');
X   	if (cent->t_flag)
X ***************
X *** 469,471
X   	if (cent->t_flag)
X ! 		fprintf (dictf, "/T");
X   	if (cent->v_flag)
X 
X --- 476,478 -----
X   	if (cent->t_flag)
X ! 		flagout ('T');
X   	if (cent->v_flag)
X ***************
X *** 471,473
X   	if (cent->v_flag)
X ! 		fprintf (dictf, "/V");
X   	if (cent->x_flag)
X 
X --- 478,480 -----
X   	if (cent->v_flag)
X ! 		flagout ('V');
X   	if (cent->x_flag)
X ***************
X *** 473,475
X   	if (cent->x_flag)
X ! 		fprintf (dictf, "/X");
X   	if (cent->y_flag)
X 
X --- 480,482 -----
X   	if (cent->x_flag)
X ! 		flagout ('X');
X   	if (cent->y_flag)
X ***************
X *** 475,477
X   	if (cent->y_flag)
X ! 		fprintf (dictf, "/Y");
X   	if (cent->z_flag)
X 
X --- 482,484 -----
X   	if (cent->y_flag)
X ! 		flagout ('Y');
X   	if (cent->z_flag)
X ***************
X *** 477,479
X   	if (cent->z_flag)
X ! 		fprintf (dictf, "/Z");
X   	fprintf (dictf, "\n");
X 
X --- 484,486 -----
X   	if (cent->z_flag)
X ! 		flagout ('Z');
X   	fprintf (dictf, "\n");
X ***************
X *** 479,480
X   	fprintf (dictf, "\n");
X   }
X 
X --- 486,496 -----
X   	fprintf (dictf, "\n");
X + }
X + 
X + static
X + flagout (flag)
X + {
X + 	if (!hasslash)
X + 		putc ('/', dictf);
X + 	hasslash = 1;
X + 	putc (flag, dictf);
X   }
SHAR_EOF
if test 37715 -ne "`wc -c < 'Patch1'`"
then
	echo shar: error transmitting "'Patch1'" '(should have been 37715 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'icombine.c'" '(2738 characters)'
if test -f 'icombine.c'
then
	echo shar: will not over-write existing file "'icombine.c'"
else
sed 's/^X //' << \SHAR_EOF > 'icombine.c'
X /* 
X    icombine:  combine multiple ispell dictionary entries into a single 
X               entry with the options of all entries
X 
X    Author:  Gary Puckering
X             Cognos, Inc.
X 
X    Written:  January 29, 1987
X    
X    Notes:  Input lines consist of a word followed optionally by
X            by one or more flags.  e.g CREATE/V/N/S
X            
X            No editing on flags is performed.
X            The input line is upshifted.
X            An improper flag, like /XN will be output as /X/N.
X            Flags are output in alphabetical order.
X            Non-letter appearing before the first "/" are retained,
X              those after are dropped.
X */
X 
X #include <stdio.h>
X #include <ctype.h>
X 
X #define MAXFLAGS 26     /* letters A-Z */
X #define MAXLINE 255     /* maximum line size */
X 
X #define TRUE 1
X #define FALSE 0
X typedef int bool;
X 
X bool flagtbl[MAXFLAGS]; /* array of flag options */
X 
X char line[MAXLINE];     /* current line */
X char lastword[MAXLINE]; /* previous word */
X char word[MAXLINE];     /* current word */
X char flags[MAXLINE];    /* current flags */
X int  expand = 0;	/* if NZ, expand instead of combining */
X 
X extern char *strcpy ();
X 
X 
X char *getline()
X {
X     char *rvalue;
X     char *p;
X 
X     if (rvalue=gets(line))      
X     { p = line;
X       while (*p) { if (islower(*p)) *p=toupper(*p); p++; }
X     }
X     return(rvalue);
X }
X 
X main(argc,argv)
X int argc;
X char *argv[];
X {
X 
X     if (argc > 1  &&  strcmp (argv[1], "-e") == 0)
X 	expand = 1;
X     if (getline()) 
X     {
X         parse(line,lastword,flags);
X         getflags(flags);
X     }
X     else
X 	return 0;
X 
X     while (getline())
X     {
X         parse(line,word,flags);
X         if (strcmp(word,lastword)!=0)   /* different word */
X         {
X             putword();
X             strcpy(lastword,word);
X         }
X         getflags(flags);
X     }
X     putword();
X     return 0;
X }
X 
X putword()
X {
X     printf("%s",lastword);
X     putflags();
X }
X 
X parse(ln,wrd,flgs)
X     char ln[];
X     char wrd[];
X     char flgs[];
X {
X     register char *p, *q;
X 
X     /* copy line up to first "/" or to end */
X     for (p=ln,q=wrd; *p && *p != '/'; p++,q++) *q = *p;
X     *q = NULL;
X 
X     strcpy(flgs,p);     /* copy from "/" to end */
X }
X 
X getflags(flgs)
X     char *flgs;
X {
X     register char *p;
X 
X     for (p=flgs; *p; p++) 
X         if (*p != '/')
X 	{
X 	    if (islower (*p))
X 		*p = toupper (*p);
X 	    if (isupper(*p))
X 		flagtbl[(*p)-'A'] = TRUE;
X 	}
X }
X 
X putflags()
X {
X     register int i;
X     int slashout = 0;
X 
X     if (expand)
X 	putchar ('\n');
X 
X     for (i=0; i<MAXFLAGS; i++) 
X         if (flagtbl[i]) 
X         {
X 	    if (expand)
X 		printf("%s/%c\n", lastword, i + 'A');
X             else
X 	    {
X 		if (!slashout)
X 		    putchar('/');
X 		slashout = 1;
X 		putchar(i+'A');
X 	    }
X             flagtbl[i]=FALSE;
X         }
X     if (!expand)
X 	putchar('\n');
X }
SHAR_EOF
if test 2738 -ne "`wc -c < 'icombine.c'`"
then
	echo shar: error transmitting "'icombine.c'" '(should have been 2738 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'munchlist.X'" '(5582 characters)'
if test -f 'munchlist.X'
then
	echo shar: will not over-write existing file "'munchlist.X'"
else
sed 's/^X //' << \SHAR_EOF > 'munchlist.X'
X : Use /bin/sh
X #
X #	Given a list of words for ispell, generate a reduced list
X #	in which all possible suffixes have been collapsed.  The reduced
X #	list will match the same list as the original.
X #
X #	Usage:
X #
X #	munchlist [ -d hashfile ] [ -e ] [ -w chars ] [ file ] ...
X #
X #	Options:
X #
X #	-d hashfile
X #		Remove any words that are covered by 'hashfile'.  The
X #		default is the default ispell dictionary.  The words
X #		will be removed only if all suffixes are covered by
X #		the hash file.  A hashfile of /dev/null should be
X #		specified when the main dictionary is being munched.
X #	-e	Economical algorithm.  This will use much less temporary
X #		disk space, at the expense of time.  Useful with large files
X #		(such as complete dictionaries).
X #	-w	Passed on to ispell (specify chars that are part of a word)
X #
X #	The given input files are merged, then processed by 'ispell -c'
X #	to generate possible suffix lists;  these are then combined
X #	and reduced.  The final result is written to standard output.
X #
X #	For portability to older systems, I have avoided getopt.
X #
X #		Geoff Kuenning
X #		2/28/87
X #
X LIBDIR=!!LIBDIR!!
X COMBINE=${LIBDIR}/icombine
X EXPAND1=${LIBDIR}/expand1.sed
X EXPAND2=${LIBDIR}/expand2.sed
X TDIR=${TMPDIR:-/usr/tmp}
X TMP=${TDIR}/munch$$
X 
X cheap=no
X dictopt=
X wchars=
X while [ $# != 0 ]
X do
X     case "$1" in
X 	-d)
X 	    case "$2" in
X 		/dev/null)
X 		    dictopt=NONE
X 		    ;;
X 		*)
X 		    dictopt="-d $2"
X 		    ;;
X 	    esac
X 	    shift
X 	    ;;
X 	-e)
X 	    cheap=yes
X 	    ;;
X 	-w)
X 	    wchars="-w $2"
X 	    shift
X 	    ;;
X 	*)
X 	    break
X     esac
X     shift
X done
X trap "/bin/rm -f ${TMP}*; exit 1" 1 2 15
X #
X # Collect all the input (cat), convert to uppercase (tr), expand all
X # the suffix options (two sed's), and preserve (sorted) for later
X # joining in ${TMP}a.
X #
X if [ $# -eq 0 ]
X then
X     tr '[a-z]' '[A-Z]' \
X       | sed -f $EXPAND1 | sed -f $EXPAND2 | sort -u > ${TMP}a
X else
X     cat "$@" | tr '[a-z]' '[A-Z]' \
X       | sed -f $EXPAND1 | sed -f $EXPAND2 | sort -u > ${TMP}a
X fi
X #
X # Unless an explicitly null dictionary was specified, remove all
X # expanded words that are covered by the dictionary.  This produces
X # the final list of expanded words that this dictionary must cover.
X # Leave the list in ${TMP}b.
X #
X if [ "X$dictopt" = "XNONE" ]
X then
X     ln ${TMP}a ${TMP}b
X else
X     ispell -l $dictopt -p /dev/null < ${TMP}a > ${TMP}b
X fi
X #
X # Munch the input to generate roots and suffixes (ispell -c).  We are
X # only interested in words that have at least one suffix (egrep /);  the
X # next step will pick up the rest.  Some of the roots are illegal.  We
X # use join to restrict the output to those root words that are found
X # in the original dictionary.
X #
X # Note:  one disadvantage of this pipeline is that for a large file,
X # the join and icombine may be sitting around for a long time while ispell
X # and sort run.  You can get rid of this by splitting the pipe, at
X # the expense of more temp file space.
X #
X if [ $cheap = yes ]
X then
X     ispell $wchars -c -d /dev/null -p /dev/null < ${TMP}b \
X       | egrep / | sort -u -t/ +0 -1 +1 \
X       | join -t/ - ${TMP}a | $COMBINE > ${TMP}c
X else
X     ispell $wchars -c -d /dev/null -p /dev/null < ${TMP}b \
X       | egrep / | sort -u -t/ +0 -1 +1 \
X       | join -t/ - ${TMP}a > ${TMP}c
X fi
X #
X # There is now one slight problem:  the suffix flags X, J, and Z
X # are simply the addition of an "S" to the suffixes N, G, and R,
X # respectively.  This produces redundant entries in the output file;
X # for example, ABBREVIATE/N/X and ABBREVIATION/S.  We must get rid
X # of the unnecessary duplicates.  The candidates are those words that
X # have only an "S" flag (egrep).  We strip off the "S" (sed), and
X # generate a list of roots that might have made these words (ispell -c).
X # Of these roots, we select those that have the N, G, or R flags,
X # replacing each with the plural equivalent X, J, or Z (sed -n).
X # Using join once again, we select those that have legal roots
X # and put them in ${TMP}d.
X #
X if [ $cheap = yes ]
X then
X     egrep '^[^/]*/S$' ${TMP}c | sed 's@/S$@@' \
X       | ispell $wchars -c -d /dev/null -p /dev/null \
X       | sed -n -e '/\/N/s/N$/X/p' -e '/\/G/s/G$/J/p' -e '/\/R/s/R$/Z/p' \
X       | sort -u -t/ +0 -1 +1 \
X       | join -t/ - ${TMP}a \
X       | $COMBINE > ${TMP}d
X else
X     egrep '^[^/]*/S$' ${TMP}c | sed 's@/S$@@' \
X       | ispell $wchars -c -d /dev/null -p /dev/null \
X       | sed -n -e '/\/N/s/N$/X/p' -e '/\/G/s/G$/J/p' -e '/\/R/s/R$/Z/p' \
X       | sort -u -t/ +0 -1 +1 \
X       | join -t/ - ${TMP}a > ${TMP}d
X fi
X /bin/rm -f ${TMP}a
X #
X # Now we have to eliminate the stuff covered by ${TMP}d from ${TMP}c.
X # First, we re-expand the suffixes we just made (sed -f pair), and let
X # ispell re-create the /S version (ispell -c).  We select the /S versions
X # only (egrep), sort them (sort) for comm, and use comm to delete these
X # from ${TMP}c.  The output of comm (i.e., the trimmed version of
X # ${TMP}c) is combined with our special-suffixes file ${TMP}d (sort again)
X # and reduced in size (icombine) to produce a final list of all words
X # that have at least one suffix.
X #
X sed -f $EXPAND1 < ${TMP}d | sed -f $EXPAND2 \
X   | ispell $wchars -c -d /dev/null -p /dev/null \
X   | egrep '\/S$' | sort -u -t/ +0 -1 +1 | comm -13 - ${TMP}c \
X   | sort -u -t/ +0 -1 +1 - ${TMP}d \
X   | $COMBINE > ${TMP}e
X /bin/rm -f ${TMP}[cd]
X #
X # Now a slick trick.  Use ispell to select those (root) words from the original
X # list (${TMP}b) that are not covered by the suffix list (${TMP}e).  Then we
X # merge these with the suffix list and sort it to produce the final output.
X #
X ispell $wchars -d /dev/null -p ${TMP}e -l < ${TMP}b \
X   | sort -u -t/ +0 -1 +1 - ${TMP}e
X /bin/rm -f ${TMP}*
SHAR_EOF
if test 5582 -ne "`wc -c < 'munchlist.X'`"
then
	echo shar: error transmitting "'munchlist.X'" '(should have been 5582 characters)'
fi
chmod +x 'munchlist.X'
fi # end of overwriting check
#	End of shell archive
exit 0
-- 

	Geoff Kuenning
	{hplabs,ihnp4}!trwrb!desint!geoff

geoff@desint.UUCP (04/01/87)

Sigh.  I should know better than to post when I'm tired.

I'm sorry about all the trouble you probably had with Patch #1.  I forgot to
mention a CRITICAL little detail:  I changed some file names.  Before
applying the patch, you must mv three files:

	mv config.h config.X
	mv munchlist.sh munchlist.X
	mv ispell.man ispell.1

Also, on BSD systems you must edit buildhash.c to interchange the includes
of stat.h and param.h.  The next patch will also include a fix for this.
Thanks to Ken Yap for identifying the problem.

Finally, I neglected to mention that 'munchlist' is now much faster, thanks
to Gary Puckering's handy 'icombine' program.
-- 

	Geoff Kuenning
	{hplabs,ihnp4}!trwrb!desint!geoff