home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD2.bin
/
bbs
/
gnu
/
ispell-4.0-src.lha
/
ispell-4.0
/
ispell.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-01
|
28KB
|
910 lines
/* Copyright (C) 1990, 1993 Free Software Foundation, Inc.
This file is part of GNU ISPELL.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ISPELL is an interactive spelling corrector generates a list
of near misses for each misspelled word. The direct parantage
of this version seems to have begun in California in the
early 70's. A child of that version was known as SPELL on
the MIT ITS systems, and later ISPELL on MIT TOPS-20 systems.
I wrote the first C implementation in 1983, and then developed
this version in 1988. See the History section of ispell.texinfo
for more information.
Pace Willisson
pace@ai.mit.edu pace@hx.lcs.mit.edu
(617) 625-3452
See ChangeLog for further author information. */
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "getopt.h"
#include "ispell.h"
#include "hash.h"
#include "charset.h"
static void show_warranty (NOARGS);
static void show_copying (NOARGS);
static void show_signon (NOARGS);
char **lexdecode = NULL;
/* this array contains letters to use when generating near misses */
char near_miss_letters[256];
int nnear_miss_letters;
/* this array has 1 for any character that is in near_miss_letters */
char near_map[256];
enum formatter formatter;
/* set to 1 if any interaction takes place */
int interaction_flag = 1;
int lflag;
int aflag;
int dflag;
int pflag;
int Sflag;
int askflag;
int Dflag;
int Eflag;
int hflag;
int uflag;
int iflag;
char *dname;
char *privname;
int intr_typed;
FILE *sortf;
void
usage ()
{
(void) fprintf (stderr, "Usage: ispell [-d dict] [-p privdict] file\n");
(void) fprintf (stderr, "or: ispell [-a | -l]\n");
exit (1);
}
RETSIGTYPE
intr ()
{
signal (SIGINT, (RETSIGTYPE (*)()) intr);
intr_typed = 1;
}
void
done ()
{
extern char tempfile[];
if (tempfile[0])
{
(void) unlink (tempfile);
tempfile[0] = 0;
}
termuninit ();
exit (0);
}
int
main (argc, argv)
int argc;
char **argv;
{
int c;
extern char *optarg;
extern int optind;
char *p;
int i;
for (i = 0; i < 256; i++)
if (charset[i].word_component)
(ctbl + 1)[i] |= LEXLETTER;
/* if invoked by the name 'spell', set uflag */
if ((p = (char *) strrchr (argv[0], '/')))
p++;
else
p = argv[0];
if (strcmp (p, "spell") == 0)
{
uflag = 1;
lflag = 1;
}
formatter = formatter_generic;
while ((c = getopt (argc, argv, "alp:d:SDEhuvbixtWC")) != EOF)
{
switch (c)
{
case 'W':
show_warranty ();
exit (0);
case 'C':
show_copying ();
exit (0);
case 't':
formatter = formatter_tex;
break;
/* traditional spell options */
/* ignore these */
case 'v': /* don't trust original suffix stripper */
case 'b': /* check british spelling */
break;
case 'i': /* don't follow any .so's or .nx's */
iflag = 1;
break;
/* case 'l': */
/* follow nroff .so's, and .nx's into /usr/lib */
/* in ispell, this means make a list. luckily,
* if the user wants old style, lflag is turned
* on anyway
*/
case 'x': /* print stems with '='s */
(void) fprintf (stderr, "-x is not supported\n");
exit (1);
/* end of traditional options */
case 'u':
uflag = 1;
lflag = 1;
break;
case 'h':
hflag = 1;
break;
default:
usage ();
case 'D':
Dflag = 1;
break;
case 'E':
Eflag = 1;
break;
case 'p':
pflag = 1;
privname = optarg;
break;
case 'd':
dflag = 1;
dname = optarg;
break;
case 'a':
aflag = 1;
break;
case 'l':
lflag = 1;
break;
case 'S':
Sflag = 1;
break;
}
}
if (optind < argc && argv[optind][0] == '+')
{
/* this is for traditional spell - add words in
* named file to OK list
*/
(void) p_load (argv[optind] + 1, 0);
optind++;
}
if (dflag == 0)
{
dname = (char *) getenv ("ISPELL_DICTIONARY");
if (dname == NULL)
{
dname = (char *) xmalloc ((unsigned) strlen (DICT_LIB) + 30);
(void) strcpy (dname, DICT_LIB);
(void) strcat (dname, "/ispell.dict");
}
}
if (access (dname, 4) < 0)
{
(void) fprintf (stderr, "can't read dictionary %s\n", dname);
exit (1);
}
if (!Dflag && !Eflag && !Sflag && !aflag && !lflag)
show_signon ();
if (hash_init (dname) < 0)
{
(void) fprintf (stderr, "hash_init failed\n");
exit (1);
}
if (hflag)
{
prhashchain ();
exit (0);
}
if (Dflag)
{
hash_awrite (stdout);
exit (0);
}
if (Eflag)
{
hash_ewrite (stdout);
exit (0);
}
if (pflag == 0)
{
if ((p = (char *) getenv ("HOME")) != NULL)
{
privname = (char *) xmalloc ((unsigned) (strlen (p) + 50));
(void) strcpy (privname, p);
(void) strcat (privname, "/ispell.words");
}
}
if (privname)
(void) p_load (privname, 1);
if (Sflag)
{
submode ();
}
else if (aflag)
{
askmode (0);
}
else if (uflag)
{
spellmode (argc, argv, optind);
exit (0);
}
else if (lflag)
{
checkfile (stdin, (FILE *) NULL, (long) 0);
exit (0);
}
else
{
/* normal interactive mode */
if (optind == argc)
{
askmode (1);
exit (0);
}
signal (SIGINT, (RETSIGTYPE (*)()) intr);
terminit ();
while (optind < argc)
dofile (argv[optind++]);
if (interaction_flag == 0)
printf ("No errors detected\r\n");
}
if (privname)
(void) p_dump (privname);
done ();
exit (0);
}
extern struct sp_corrections corrections;
static char stdoutbuf[BUFSIZ];
void
submode (NOARGS)
{
char buf[BUFSIZ];
int i;
int c;
int len;
signal (SIGINT, SIG_IGN);
setbuf (stdin, (char *) NULL);
setbuf (stdout, stdoutbuf);
(void) printf ("(1 \"%s\")", VERSION_STRING);
while (1)
{
again:
intr_typed = 0;
putchar ('=');
fflush (stdout);
if (fgets (buf, sizeof buf, stdin) == NULL)
break;
len = strlen (buf);
if (len && buf[len - 1] == '\n')
{
buf[--len] = 0;
}
else
{
/* line was too long to hold newline -
* just return an error without otherwise
* looking at it
*/
while (1)
{
if ((c = getchar ()) == EOF)
return;
if (c == '\n')
{
(void) printf ("nil\n");
goto again;
}
}
}
if (buf[0] == 0)
continue;
if (buf[0] == ':')
{
if (subcmd (buf) < 0)
(void) printf ("nil\n");
else
(void) printf ("t\n");
continue;
}
if (good (buf, strlen (buf), 0))
{
(void) printf ("t\n");
}
else
{
makepossibilities (buf);
if (corrections.posbuf[0][0])
{
(void) printf ("(");
for (i = 0; i < 10; i++)
{
if (corrections.posbuf[i][0] == 0)
break;
(void) printf ("\"%s\" ",
corrections.posbuf[i]);
}
(void) printf (")\n");
}
else
{
(void) printf ("nil\n");
}
}
}
}
struct cmd
{
char *name;
#ifdef __STDC__
int (*func) (char *);
#else
int (*func) ();
#endif
};
extern struct cmd subcmds[];
int
subcmd (buf)
char *buf;
{
char *p;
struct cmd *cp;
buf++; /* skip colon */
for (p = buf; *p && !isspace (*p); p++)
;
if (*p)
*p++ = 0;
for (cp = subcmds; cp->name; cp++)
if (strcmp (cp->name, buf) == 0)
break;
if (cp->name == NULL)
return (-1);
return ((*cp->func) (p));
}
int
cmd_insert (arg)
char *arg;
{
return (p_enter (arg, 1, 1));
}
int
cmd_accept (arg)
char *arg;