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)