allbery@ncoast.UUCP (05/31/87)
#! /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:
# ispell.c
# ispell.el
# ispell.h
# lookup.c
# makedict.sh
# This archive created: Sat May 30 17:13:36 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'ispell.c'" '(25840 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 #define MAIN
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 * -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 #include <stdio.h>
X #include <ctype.h>
X #include <sys/param.h>
X #ifdef USG
X #include <sys/types.h>
X #endif
X #include <sys/stat.h>
X #include "config.h"
X #include "ispell.h"
X #include "version.h"
X
X FILE *infile;
X FILE *outfile;
X
X char hashname[MAXPATHLEN];
X
X extern struct dent *treeinsert();
X extern char *upcase ();
X extern char *lowcase ();
X
X extern char *rindex();
X extern char *strcpy ();
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 static int sortit = 1;
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 while (getchar () != ' ')
X ;
X }
X
X
X char *getline();
X
X int cflag = 0;
X int lflag = 0;
X int incfileflag = 0;
X int aflag = 0;
X int fflag = 0;
X #ifndef USG
X int sflag = 0;
X #endif
X int xflag = 0;
X int tflag = 0;
X
X char *askfilename;
X
X static char *Cmd;
X
X usage ()
X {
X fprintf (stderr,
X "Usage: %s [-dfile | -pfile | -wchars | -t | -x | -S] file .....\n",
X Cmd);
X fprintf (stderr,
X " %s [-dfile | -pfile | -wchars | -t] -l\n",
X Cmd);
X #ifndef USG
X fprintf (stderr,
X " %s [-dfile | -pfile | -ffile | -t | -s] {-a | -A}\n",
X Cmd);
X #else
X fprintf (stderr,
X " %s [-dfile | -pfile | -ffile | -t] {-a | -A}\n",
X Cmd);
X #endif
X fprintf (stderr, " %s [-wchars] -c\n", Cmd);
X fprintf (stderr, " %s -v\n", Cmd);
X exit (1);
X }
X
X static initckch()
X {
X register 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 static char outbuf[BUFSIZ];
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 'v':
X printf ("%s\n", Version_ID);
X exit (0);
X case 't':
X tflag++;
X break;
X case 'A':
X incfileflag = 1;
X aflag = 1;
X break;
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 'S':
X sortit = 0;
X break;
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' && *p != '\\') {
X Checkch[((unsigned)(*p))&mask] = (char) 1;
X Try[Trynum] = *p & mask;
X ++p;
X }
X else {
X ++p;
X num[0] = '\0';
X num[1] = '\0';
X num[2] = '\0';
X num[3] = '\0';
X if (isdigit (p[0]))
X num[0] = p[0];
X if (isdigit (p[1]))
X num[1] = p[1];
X if (isdigit (p[2]))
X num[2] = p[2];
X if (p[-1] == 'n') {
X p += strlen (num);
X num[0] = atoi (num);
X }
X else {
X p += strlen (num);
X if (num[0])
X num[0] -= '0';
X if (num[1]) {
X num[0] <<= 3;
X num[0] += num[1] - '0';
X }
X if (num[2]) {
X num[0] <<= 3;
X num[0] += num[2] - '0';
X }
X }
X Try[Trynum] = num[0] & mask;
X Checkch[num[0] & mask] = 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 setbuf (stdout, outbuf);
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 struct stat statbuf;
X char *cp;
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 fstat (fileno (infile), &statbuf);
X strcpy(tempfile, TEMPNAME);
X mktemp (tempfile);
X chmod (tempfile, statbuf.st_mode);
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 /* See if the file is a .tex file. If so, set the appropriate flag. */
X if ((cp = rindex (filename, '.')) != NULL && strcmp (cp, ".tex") == 0)
X tflag = 1;
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, "temporary file disappeared (%s)\r\n", tempfile);
X sleep (2);
X return;
X }
X
X sprintf(bakfile, "%s%s", filename, BAKEXT);
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 chmod (filename, statbuf.st_mode);
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 register int c;
X register char *p;
X register int len;
X
X secondbuf[0] = 0;
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
X /* skip over .if */
X if (strncmp(currentchar,".if t",5) == 0
X || strncmp(currentchar,".if n",5) == 0) {
X copyout(¤tchar,5);
X while (*currentchar && isspace(*currentchar))
X copyout(¤tchar, 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(¤tchar, 3);
X while (*currentchar && isspace(*currentchar))
X copyout(¤tchar, 1);
X while (*currentchar && !isspace(*currentchar))
X copyout(¤tchar, 1);
X if (*currentchar == 0) {
X if (!lflag) putc ('\n', outfile);
X continue;
X }
X }
X
X if (secondbuf [ len ] == '\n')
X secondbuf [ len ] = 0;
X
X /* if this is a formatter command, skip over it */
X if (!tflag && *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 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 if (*currentchar == '\\') {
X switch ( currentchar [1] ) {
X case 'f':
X if(currentchar[2] != '(') {
X /* font change: \fX */
X copyout(¤tchar, 3);
X }
X else {
X /* font change: \f(XY */
X copyout(¤tchar, 5);
X }
X continue;
X case 's':
X /* size change */
X p = currentchar + 2;
X if (*p == '+' || *p == '-')
X p++;
X /* This looks wierd 'cause we assume
X ** *p is now a digit.
X */
X if (isdigit (p[1]))
X p++;
X copyout (¤tchar,
X p - currentchar + 1);
X continue;
X case '(':
X /* extended char set escape: \(XX */
X copyout(¤tchar, 4);
X continue;
X case '*':
X if ( currentchar[2] != '(' )
X copyout(¤tchar, 3);
X else
X copyout(¤tchar, 5);
X continue;
X default:
X break;
X }
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\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 #define MAXPOSSIBLE 100 /* Max no. of possibilities to generate */
X
X char possibilities[MAXPOSSIBLE][BUFSIZ];
X int pcount;
X int maxposslen;
X
X correct (token, currentchar)
X char *token;
X char **currentchar;
X {
X register int c;
X register int i;
X int col_ht;
X int ncols;
X register char *p;
X char *start_l2;
X char *begintoken;
X
X begintoken = *currentchar - strlen (token);
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 /*
X * Make sure we have enough room on the screen to hold the
X * possibilities. Reduce the list if necessary. co / (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 = co / (maxposslen + 8);
X if (pcount > ncols * col_ht)
X pcount = ncols * col_ht;
X
X #ifdef EQUAL_COLUMNS
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 move (li - 3, 0);
X show_line (firstbuf, firstbuf, 0);
X
X start_l2 = secondbuf;
X if (line_size (secondbuf, *currentchar) > co - 1) {
X start_l2 = begintoken - (co / 2);
X while (start_l2 < begintoken) {
X i = line_size (start_l2, *currentchar) + 1;
X if (i <= co)
X break;
X start_l2 += i - co;
X }
X if (start_l2 > begintoken)
X start_l2 = begintoken;
X if (start_l2 < secondbuf)
X start_l2 = secondbuf;
X }
X show_line (start_l2, begintoken, strlen (token));
X
X
X while (1) {
X fflush (stdout);
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 fflush (stdout);
X return;
X case 'x': case 'X':
X printf ("Are you sure you want to throw away your changes? ");
X fflush (stdout);
X c = (getchar () & NOPARITY);
X if (c == 'y' || c == 'Y') {
X erase ();
X fflush (stdout);
X done ();
X }
X putchar (7);
X goto checkagain;
X case 'i': case 'I':
X treeinsert (token, 1);
X erase ();
X fflush (stdout);
X return;
X case 'a': case 'A':
X treeinsert (token, 0);
X erase ();
X fflush (stdout);
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 (li - 1, 0);
X putchar ('!');
X if (getline (buf) == NULL) {
X putchar (7);
X erase ();
X fflush (stdout);
X goto checkagain;
X }
X printf ("\r\n");
X fflush (stdout);
X shellescape (buf);
X erase ();
X goto checkagain;
X }
X case 'r': case 'R':
X move (li - 1, 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 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 putchar (7);
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 char buf[100];
X move (li - 1, 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 fflush (stdout);
X lookharder (buf);
X erase ();
X goto checkagain;
X }
X case 'q': case 'Q':
X quit = 1;
X erase ();
X fflush (stdout);
X return;
X default:
X putchar (7);
X break;
X }
X }
X }
X
X show_line (line, invstart, invlen)
X register char *line;
X register char *invstart;
X register int invlen;
X {
X register int width;
X
X width = 0;
X while (line != invstart && width < co - 1)
X width += show_char (*line++, width);
X if (invlen) {
X inverse ();
X while (--invlen >= 0 && width < co - 1)
X width += show_char (*line++, width);
X normal ();
X }
X while (*line && width < co - 1)
X width += show_char (*line++, width);
X printf ("\r\n");
X }
X
X show_char (ch, linew)
X register int ch;
X int linew;
X {
X if (ch == '\t') {
X putchar ('\t');
X return 8 - (linew & 0x07);
X }
X else if (ch < ' ') {
X putchar ('^');
X putchar (ch + 'A' - '\001');
X return 2;
X }
X putchar (ch);
X return 1;
X }
X
X line_size (buf, bufend)
X register char *buf;
X register char *bufend;
X {
X register int width;
X
X for (width = 0; buf < bufend && *buf; buf++) {
X if (*buf == '\t')
X width = (width + 8) & ~0x07;
X else if (*buf < ' ')
X width += 2;
X else
X width++;
X }
X return width;
X }
X
X inserttoken (buf, start, token, currentchar)
X char *buf, *start;
X register char *token;
X char **currentchar;
X {
X char copy[BUFSIZ];
X register char *p, *q;
X
X strcpy (copy, buf);
X
X for (p = buf, q = copy; p != start; p++, q++)
X *p = *q;
X q += *currentchar - start;
X while (*token && iswordch (*token))
X *p++ = *token++;
X *currentchar = p;
X if (*token) {
X
X /*
X ** The token changed to two words. Split it up and save the
X ** second one for later.
X */
X
X *p++ = *token;
X *token++ = '\0';
X while (*token)
X *p++ = *token++;
X }
X while (*p++ = *q++)
X ;
X }
X
X int casecmp (a, b)
X char *a;
X char *b;
X {
X register char *ap;
X register char *bp;
X
X for (ap = a, bp = b; *ap; ap++, bp++) {
X if (mylower (*ap)) {
X if (mylower (*bp)) {
X if (*ap != *bp)
X return *ap - *bp;
X }
X else {
X if (toupper (*ap) != *bp)
X return toupper (*ap) - *bp;
X }
X }
X else {
X if (myupper (*bp)) {
X if (*ap != *bp)
X return *ap - *bp;
X }
X else {
X if (tolower (*ap) != *bp)
X return tolower (*ap) - *bp;
X }
X }
X }
X if (*bp != '\0')
X return -*bp;
X return strcmp (a, b);
X }
X
X makepossibilities (word)
X register char *word;
X {
X register int i;
X
X for (i = 0; i < MAXPOSSIBLE; i++)
X possibilities[i][0] = 0;
X pcount = 0;
X maxposslen = 0;
X
X #ifdef CAPITALIZE
X wrongcapital (word);
X #endif
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 if (sortit && pcount)
X qsort ((char *) possibilities, pcount,
X sizeof (possibilities[0]), casecmp);
X }
X
X insert (word)
X register char *word;
X {
X register 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 i = strlen (word);
X if (i > maxposslen)
X maxposslen = i;
X if (pcount >= MAXPOSSIBLE)
X return (-1);
X else
X return (0);
X }
X
X #ifdef CAPITALIZE
X wrongcapital (word)
X register char *word;
X {
X char newword[BUFSIZ];
X
X /*
X ** All-uppercase is always legal. If the word matches, "ins_cap"
X ** will recapitalize it correctly.
X */
X strcpy (newword, word);
X upcase (newword);
X if (good (newword))
X return ins_cap (newword, word);
X return 0;
X }
X #endif
X
X wrongletter (word)
X register char *word;
X {
X register int i, j, c, n;
X char newword[BUFSIZ];
X
X n = strlen (word);
X strcpy (newword, word);
X #ifdef CAPITALIZE
X upcase (newword);
X #endif
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 (ins_cap (newword, word) < 0)
X return;
X }
X }
X newword[i] = word[i];
X }
X }
X
X extraletter (word)
X register char *word;
X {
X char newword[BUFSIZ];
X register char *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 #ifdef CAPITALIZE
X if (good (upcase (newword))) {
X if (ins_cap (newword, word) < 0)
X return;
X }
X #else
X if (good (newword)) {
X if (ins_cap (newword, word) < 0)
X return;
X }
X #endif
X }
X }
X
X missingletter (word)
X char word[];
X {
X char newword[BUFSIZ];
X register char *p, *r, *s, *t;
X register 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 #ifdef CAPITALIZE
X if (good (upcase (newword))) {
X if (ins_cap (newword, word) < 0)
X return;
X }
X #else
X if (good (newword)) {
X if (ins_cap (newword, word) < 0)
X return;
X }
X #endif
X }
X }
X }
X
X transposedletter (word)
X register char *word;
X {
X char newword[BUFSIZ];
X register int t;
X register 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 #ifdef CAPITALIZE
X if (good (upcase (newword))) {
X if (ins_cap (newword, word) < 0)
X return;
X }
X #else
X if (good (newword)) {
X if (ins_cap (newword, word) < 0)
X return;
X }
X #endif
X t = p[0];
X p[0] = p[1];
X p[1] = t;
X }
X }
X
X /* Insert one or more correctly capitalized versions of pattern */
X ins_cap (word, pattern)
X register char *word, *pattern;
X {
X static char newword[BUFSIZ];
X register char *p, *q;
X char *psave;
X register int wcount;
X
X if (*word == 0)
X return;
X
X strcpy (newword, word);
X #ifdef CAPITALIZE
X if (lastdent->allcaps)
X return insert (upcase (newword)); /* Uppercase required */
X for (p = pattern; *p; p++)
X if (mylower (*p))
X break;
X if (*p == '\0')
X return insert (upcase (newword)); /* Pattern was all caps */
X for (p = pattern; *p; p++)
X if (myupper (*p))
X break;
X if (*p == '\0') { /* Pattern was all lower */
X if (!lastdent->followcase && !lastdent->capitalize)
X return insert (lowcase (newword));
X /*
X ** If there's a followcase version that's all-lower,
X ** insert only that version.
X */
X if (lastdent->followcase) {
X p = lastdent->word;
X p += strlen (p) + 1;
X wcount = (*p++ & 0xFF);
X while (--wcount >= 0) {
X for (psave = ++p;
X *p && !myupper (*p);
X p++)
X ;
X if (*p == '\0') /* Was it all lowercase? */
X return insert (psave); /* Yup, quit */
X while (*p++)
X ; /* Skip to next case sample */
X }
X }
X }
X /*
X ** The sample wasn't all-upper, and either it wasn't all-lower or
X ** all-lower is illegal. Insert all legal capitalizations. In
X ** some cases, this may include all-lowercase.
X */
X if (lastdent->capitalize) {
X lowcase (newword);
X if (mylower (newword[0]))
X newword[0] = toupper (newword[0]);
X insert (newword);
X }
X if (lastdent->followcase) {
X p = lastdent->word;
X p += strlen (p) + 1;
X wcount = (*p++ & 0xFF);
X while (--wcount >= 0) {
X /* Insert every variation; it's easier */
X if (insert (++p) < 0)
X return -1;
X while (*p++)
X ; /* Skip to end of sample */
X }
X return 0;
X }
X if (lastdent->capitalize)
X return 0;
X /*
X ** We get here only if none of the special capitalization flags are
X ** set. If first letter of the pattern is capitalized, capitalize
X ** the first letter of the result. Otherwise produce all lowercase.
X */
X lowcase (newword);
X if (myupper (pattern[0]) && mylower (newword[0]))
X newword[0] = toupper (newword[0]);
X return insert (newword);
X #else
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 insert (newword);
X #endif
X }
X
X char *
X getline (s)
X register char *s;
X {
X register char *p;
X register int c;
X
X p = s;
X
X while (1) {
X fflush (stdout);
X c = (getchar () & NOPARITY);
X if (c == '\\') {
X putchar ('\\');
X fflush (stdout);
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 register 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 (xgets (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 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 < MAXPOSSIBLE; 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 /* Copy/ignore "cnt" number of characters pointed to by *cc. */
X copyout(cc, cnt)
X register char **cc;
X register cnt;
X {
X while (--cnt >= 0) {
X if (*(*cc) == 0)
X break;
X if (!lflag)
X putc (*(*cc), outfile);
X (*cc)++;
X }
X }
X
X lookharder(string)
X char *string;
X {
X char cmd[150], grepstr[100];
X register char *g, *s;
X register 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, "%s %s %s", LOOK, grepstr, WORDS);
X #else
X sprintf (cmd, "%s '^%s$' %s", EGREPCMD, grepstr, WORDS);
X #endif
X shellescape (cmd);
X }
X }
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'ispell.el'" '(12958 characters)'
if test -f 'ispell.el'
then
echo shar: will not over-write existing file "'ispell.el'"
else
sed 's/^X //' << \SHAR_EOF > 'ispell.el'
X ;;; Spelling correction interface for GNU EMACS using "ispell"
X
X ;;; Walt Buehring
X ;;; Texas Instruments - Computer Science Center
X ;;; ARPA: Buehring%TI-CSL@CSNet-Relay
X ;;; UUCP: {smu, texsun, im4u, rice} ! ti-csl ! buehring
X
X ;;; ispell-region and associated routines added by
X ;;; Perry Smith
X ;;; pedz@bobkat
X ;;; Tue Jan 13 20:18:02 CST 1987
X
X ;;; extensively modified by Mark Davies and Andrew Vignaux
X ;;; {mark,andrew}@vuwcomp
X ;;; Sun May 10 11:45:04 NZST 1987
X
X ;;; Depends on the ispell program snarfed from MIT-PREP in early
X ;;; 1986. The only interactive command is "ispell-word" which should be
X ;;; bound to M-$. If someone writes an "ispell-region" command,
X ;;; I would appreciate a copy. -- ispell-region, ispell-buffer now added.
X
X ;;; To fully install this, add this file to your GNU lisp directory and
X ;;; compile it with M-X byte-compile-file. Then add the following to the
X ;;; appropriate init file:
X
X ;;; (autoload 'ispell-word "ispell"
X ;;; "Check the spelling of word in buffer." t)
X ;;; (global-set-key "\e$" 'ispell-word)
X ;;; (autoload 'ispell-region "ispell"
X ;;; "Check the spelling of region." t)
X ;;; (autoload 'ispell-buffer "ispell"
X ;;; "Check the spelling of buffer." t)
X
X ;;; If run on a heavily loaded system, the initial sleep time in
X ;;; ispell-init-process may need to be increased.
X
X ;;; No warranty expressed or implied. All sales final. Void where prohibited.
X ;;; If you don't like it, change it.
X
X (defconst ispell-out-name " *ispell*"
X "Name of the buffer that is associated with the 'ispell' process")
X
X (defconst ispell-temp-name " *ispell-temp*"
X "Name of the temporary buffer that 'ispell-region' uses to hold the
X filtered region")
X
X (defvar ispell-program-name "ispell"
X "Program invoked by ispell-word and ispell-region commands.")
X
X (defvar ispell-syntax-table nil)
X
X (if (null ispell-syntax-table)
X ;; The following assumes that the standard-syntax-table
X ;; is static. If you add words with funky characters
X ;; to your dictionary, the following may have to change.
X (progn
X (setq ispell-syntax-table (make-syntax-table))
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 (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 (modify-syntax-entry ?% ". " ispell-syntax-table)))
X
X
X (defun ispell-word (&optional quietly)
X "Check spelling of word at or before dot.
X If word not found in dictionary, display possible corrections in a window
X and let user select."
X (interactive)
X (let* ((current-syntax (syntax-table))
X start end word poss replace)
X (unwind-protect
X (save-excursion
X ;; Ensure syntax table is reasonable
X (set-syntax-table ispell-syntax-table)
X ;; Move backward for word if not already on one.
X (if (not (looking-at "\\w"))
X (re-search-backward "\\w" (point-min) 'stay))
X ;; Move to start of word
X (re-search-backward "\\W" (point-min) 'stay)
X ;; Find start and end of word
X (or (re-search-forward "\\w+" nil t)
X (error "No word to check."))
X (setq start (match-beginning 0)
X end (match-end 0)
X word (buffer-substring start end)))
X (set-syntax-table current-syntax))
X (ispell-init-process) ; erases ispell output buffer
X (or quietly (message "Checking spelling of %s..." (upcase word)))
X (save-excursion
X (set-buffer ispell-out-name)
X (send-string ispell-process (concat word "\n"))
X ;; wait until we have a complete line
X (while (progn
X (goto-char (point-max))
X (/= (preceding-char) ?\n))
X (accept-process-output ispell-process))
X (goto-char (point-min))
X (setq poss (ispell-parse-output
X (buffer-substring (point)
X (progn (end-of-line) (point))))))
X (cond ((eq poss t)
X (or quietly (message "Found %s" (upcase word))))
X ((stringp poss)
X (or quietly (message "Found it because of %s" (upcase poss))))
X ((null poss)
X (or quietly (message "Could Not Find %s" (upcase word))))
X (t (setq replace (ispell-choose poss word))
X (if replace
X (progn
X (goto-char end)
X (delete-region start end)
X (insert-string replace)))))
X poss))
X
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 (save-window-excursion
X (let ((count 0)
X (line 2)
X (words choices)
X (window-min-height 2)
X char num result)
X (save-excursion
X (set-buffer (get-buffer-create "*Choices*")) (erase-buffer)
X (setq mode-line-format "-- %b --")
X (while words
X (if (<= (+ 7 (current-column) (length (car words)))
X (window-width))
X nil
X (insert "\n")
X (setq line (1+ line)))
X (insert "(" (+ count ?0) ") " (car words) " ")
X (setq words (cdr words)
X count (1+ count))))
X (overlay-window line)
X (switch-to-buffer "*Choices*")
X (select-window (next-window))
X (while (eq t
X (setq result
X (progn
X (message "Enter letter to replace word; Space to leave unchanged")
X (setq char (read-char))
X (setq num (- char ?0))
X (cond ((= char ? ) nil)
X ((= char ?i)
X (send-string ispell-process
X (concat "*" word "\n"))
X (if (get-buffer ispell-temp-name)
X (save-excursion
X (set-buffer ispell-temp-name)
X (save-excursion
X (replace-regexp (concat "^" word "$")
X (concat "+" word)))))
X nil)
X ((= char ?a)
X (send-string ispell-process
X (concat "@" word "\n"))
X (if (get-buffer ispell-temp-name)
X (save-excursion
X (set-buffer ispell-temp-name)
X (save-excursion
X (replace-regexp (concat "^" word "$")
X (concat "+" word)))))
X nil)
X ((= char ?r) (read-string "Replacement: " nil))
X ((and (>= num 0) (< num count)) (nth num choices))
X ((= char ?\C-r)
X ; Note: does not reset syntax table
X (save-excursion (recursive-edit)) t) ; dangerous
X ((= char ?\C-z)
X (suspend-emacs) t)
X ((= char help-char)
X (message "[r]eplace; [a]ccept for session; [i] accept and add to private dictionary")
X (sit-for 3) t)
X (t (ding) t))))))
X result))
X ;; Protected forms...
X (bury-buffer "*Choices*")))
X
X
X (defun overlay-window (height)
X "Create a (usually small) window with HEIGHT lines and avoid
X recentering."
X (save-excursion
X (let ((oldot (save-excursion (beginning-of-line) (dot)))
X (top (save-excursion (move-to-window-line height) (dot)))
X newin)
X (if (< oldot top) (setq top oldot))
X (setq newin (split-window-vertically height))
X (set-window-start newin top))))
X
X
X (defvar ispell-process nil
X "Holds the process object for 'ispell'")
X
X (defun ispell-parse-output (output)
X "Parse the OUTPUT string of 'ispell' and return either t for an exact
X match, a string containing the root word for a match via suffix
X removal, a list of possible correct spellings, or nil for a complete
X miss."
X (cond
X ((string= output "*") t)
X ((string= output "#") nil)
X ((string= (substring output 0 1) "+")
X (substring output 2))
X (t
X (let ((choice-list '()))
X (while (not (string= output ""))
X (let* ((start (string-match "[A-z]" output))
X (end (string-match " \\|$" output start)))
X (if start
X (setq choice-list (cons (substring output start end)
X choice-list)))
X (setq output (substring output (1+ end)))))
X choice-list))))
X
X
X (defun ispell-init-process ()
X "Check status of 'ispell' process and start if necessary."
X (if (and ispell-process
X (eq (process-status ispell-process) 'run))
X (save-excursion
X (set-buffer ispell-out-name)
X (erase-buffer))
X (message "Starting new ispell process...")
X (and (get-buffer ispell-out-name) (kill-buffer ispell-out-name))
X (setq ispell-process (start-process "ispell" ispell-out-name
X ispell-program-name "-A"))
X (process-kill-without-query ispell-process)
X (sit-for 3)))
X
X (defvar ispell-filter-hook "/usr/bin/tr"
X "Filter to pass a region through before sending it to ispell.
X Must produce output one word per line. Typically this is set to tr,
X deroff, detex, etc.")
X (make-variable-buffer-local 'ispell-filter-hook)
X
X (defvar ispell-filter-hook-args '("-cs" "A-Za-z" "\n")
X "Argument LIST 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 ; ``concatenate'' if it happens to occur before.
X ; `ispell-region' filters the region into `*ispell-temp*', writes the
X ; buffer to a temporary file, and sends a ``&Include_File&foobar''
X ; string to the ispell process which is writing into `*ispell*'.
X ; `ispell-region' then searches `*ispell*' for a spelling error (`#' or
X ; `&'), checks the `*ispell-temp*' buffer for the misspelled word and
X ; then skips forward `count' words (the number of correct lines in
X ; `*ispell*') in the region. It then searches for the misspelled
X ; word. This is not a foolproof heuristic but it is fast and works
X ; most of the time.
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-file (make-temp-name "/usr/tmp/is"))
X (spell-buf (get-buffer-create ispell-temp-name))
X (current-syntax (syntax-table))
X (tracker 1)
X word poss replace endbound ispell-out)
X (ispell-init-process)
X (setq ispell-out (get-buffer ispell-out-name))
X (unwind-protect
X (save-excursion
X (message "Prefrobnicating...")
X (sit-for 0)
X (set-syntax-table ispell-syntax-table)
X (set-buffer spell-buf)
X (erase-buffer)
X (set-buffer this-buf)
X (apply 'call-process-region
X (append (list start end ispell-filter-hook nil spell-buf nil)
X ispell-filter-hook-args))
X (goto-char start)
X (set-buffer spell-buf)
X (and (/= (preceding-char) ?\n) ; couple of hacks for tr
X (insert "\n"))
X (goto-char (point-min))
X (while (= (following-char) ?\n)
X (delete-char 1))
X (write-region (point-min) (point-max) spell-file nil 1)
X (send-string ispell-process
X (concat "&Include_File&" spell-file "\n"))
X (message "Looking for a misspelled word") (sit-for 0)
X (while (not (eobp))
X (set-buffer ispell-out)
X (goto-char (point-max))
X (beginning-of-line)
X (setq endbound (point))
X (goto-char tracker)
X (if (prog1
X (not (re-search-forward "^[#&]" endbound 1))
X (beginning-of-line)
X (setq count (count-lines tracker (point))
X tracker (point))
X (set-buffer spell-buf)
X (forward-line count))
X (accept-process-output) ; give it some time to get something
X (setq word (buffer-substring (point)
X (progn (end-of-line) (point))))
X (forward-char 1)
X (set-buffer ispell-out) ; (goto-char tracker)
X (setq poss (ispell-parse-output
X (buffer-substring (point)
X (progn (end-of-line) (point)))))
X (forward-char 1)
X (setq tracker (point))
X (set-buffer this-buf)
X (re-search-forward "\\W*\\(\\w+\\)" nil t (1- count)) ; get close
X (if (string= "+" (substring word 0 1))
X (search-forward (substring word 1) nil t)
X (if (search-forward word nil t)
X (progn
X (sit-for 0)
X (setq replace (ispell-choose poss word))
X (if replace
X (replace-match replace)))
X (message "Can not find %s in original text -- Any key to continue" word)
X (and (= ?\C-z (read-char)) (suspend-emacs)))
X (message "Looking for a misspelled word") (sit-for 0))
X (set-buffer spell-buf))))
X (message "")
X (set-syntax-table current-syntax)
X (and (file-exists-p spell-file)
X (delete-file spell-file)))))
X
X (defun ispell-buffer ()
X "Check the current buffer for spelling errors interactively. The variable
X which should be buffer or mode specific ispell-filter-hook is called to
X filter out text processing commands."
X (interactive)
X (ispell-region (point-min) (point-max)))
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'ispell.h'" '(6646 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 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 #ifdef CAPITALIZE
X /*
X ** if followcase is set, the actual word entry (dent->word)
X ** is followed by one or more further strings giving exact
X ** capitalizations. The first byte after the uppercase word
X ** gives the number of capitalizations. Each capitalization
X ** is preceded by the character "+" if it is to be kept, or
X ** "-" if it is to be discarded from the personal dictionary.
X ** For example, the entry "ITCORP\0\3+ITcorp\0+ITCorp\0+ItCorp\0"
X ** gives various ways of writing my e-mail address. If all-lowercase
X ** is acceptable, an all-lower entry must appear. Simple
X ** capitalization, on the other hand, is signified by the "capitalize"
X ** flag.
X **
X ** Suffixes always match the case of the final character of a word.
X **
X ** If "allcaps" is set, the other two flags must be clear.
X */
X unsigned short allcaps : 1; /* Word must be all capitals */
X unsigned short capitalize : 1; /* Capitalize the word */
X unsigned short followcase : 1; /* Follow capitalization exactly */
X /*
X ** The following entries denote the flag values that are actually
X ** to be kept for this dictionary entry. They may differ if the
X ** "a" command is used for a word that differs only in capitalization.
X */
X unsigned short k_allcaps : 1;
X unsigned short k_capitalize : 1;
X unsigned short k_followcase : 1;
X #endif
X
X };
X
X #define WORDLEN 30
X
X struct hashheader {
X int magic;
X int stringsize;
X int tblsize;
X };
X
X /* hash table magic number */
X #define MAGIC 2
X
X
X /*
X * termcap variables
X */
X #ifdef MAIN
X # define EXTERN /* nothing */
X #else
X # define EXTERN extern
X #endif
X
X EXTERN char *tgetstr();
X EXTERN char PC; /* padding character */
X EXTERN char *BC; /* backspace if not ^H */
X EXTERN char *UP; /* Upline (cursor up) */
X EXTERN char *cd; /* clear to end of display */
X EXTERN char *ce; /* clear to end of line */
X EXTERN char *cl; /* clear display */
X EXTERN char *cm; /* cursor movement */
X EXTERN char *dc; /* delete character */
X EXTERN char *dl; /* delete line */
X EXTERN char *dm; /* delete mode */
X EXTERN char *ed; /* exit delete mode */
X EXTERN char *ei; /* exit insert mode */
X EXTERN char *ho; /* home */
X EXTERN char *ic; /* insert character */
X EXTERN char *il; /* insert line */
X EXTERN char *im; /* insert mode */
X EXTERN char *ip; /* insert padding */
X EXTERN char *nd; /* non-destructive space */
X EXTERN char *vb; /* visible bell */
X EXTERN char *so; /* standout */
X EXTERN char *se; /* standout end */
X EXTERN int bs;
X EXTERN int li, co; /* lines, columns */
X
X EXTERN char termcap[1024];
X EXTERN char termstr[1024]; /* for string values */
X EXTERN char *termptr;
X
X EXTERN char rootword[BUFSIZ];
X EXTERN struct dent *lastdent;
X
X EXTERN char *hashstrings;
X EXTERN struct hashheader hashheader;
X
X extern int aflag;
X extern int lflag;
X
X EXTERN int erasechar;
X EXTERN int killchar;
X
X EXTERN char tempfile[200];
X
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lookup.c'" '(2758 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 <stdio.h>
X #include "config.h"
X #include "ispell.h"
X
X
X struct dent *treelookup();
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 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
fi # end of overwriting check
echo shar: extracting "'makedict.sh'" '(964 characters)'
if test -f 'makedict.sh'
then
echo shar: will not over-write existing file "'makedict.sh'"
else
sed 's/^X //' << \SHAR_EOF > 'makedict.sh'
X : Use /bin/sh
X #
X # Make a beginning dictionary file for ispell, using an existing
X # speller.
X #
X # Usage:
X #
X # makedict file-list
X #
X # The specified files are collected, split into words, and run through
X # the system speller (usually spell(1)). Any words that the speller
X # accepts will be written to the standard output for use in making
X # an ispell dictionary. Usually, you will want to run the output
X # of this script through "munchlist" to get a final dictionary.
X #
X
X # This program must produce a list of INCORRECTLY spelled words on standard
X # output, given a list of words on standard input. If you don't have a
X # speller, but do have a lot of correctly-spelled files, try /bin/true.
X #
X SPELLPROG="${SPELLPROG:-spell}"
X
X TMP=${TMPDIR:-/tmp}/mkdict$$
X
X case "$#" in
X 0)
X set X -
X shift
X ;;
X esac
X
X trap "/bin/rm ${TMP}; exit 1" 1 2 15
X
X cat "$@" | deroff | tr -cs "[A-Z][a-z]'" '[\012*]' | sort -uf -o ${TMP}
X $SPELLPROG < ${TMP} | comm -13 - ${TMP}
X /bin/rm ${TMP}
SHAR_EOF
chmod +x 'makedict.sh'
fi # end of overwriting check
# End of shell archive
exit 0
--
Brandon S. Allbery {decvax,cbatt,cbosgd}!cwruecmp!ncoast!allbery
Tridelta Industries {ames,mit-eddie,talcott}!necntc!ncoast!allbery
7350 Corporate Blvd. necntc!ncoast!allbery@harvard.HARVARD.EDU
Mentor, OH 44060 +01 216 255 1080 (also eddie.MIT.EDU)