home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume26
/
philspell-1.0
/
part01
/
main.c
next >
Wrap
C/C++ Source or Header
|
1993-05-01
|
8KB
|
264 lines
/*
*
* main.c for "philspell"
*
* This file is Copyright (c) 1992 Phillip "Edward" Nunez. Phillip grants
* you full permission to copy and distribute this code provided you do not
* interfere with any of the copyrights (c)s installed therein.
*
* Phillip grants permission to extract portions of this code for use in
* other code provided you give full credit to him in all documentation
* pertaining to your program, preserve copyrights in files from which code
* is extracted, and put his name in your program's output.
*
*
* This header automatically generated by the UNIX program philcopyright,
* Copyright (c) 1991 Phillip "Edward" Nunez. For information regarding
* philcopyright, mail phillip@soda.berkeley.edu.
*
*/
#include <stdio.h>
#include <ctype.h>
#include "skiplist.h"
static char philSCCSid[] = "@(#)main.c 1.0 Phillip `Edward' Nunez";
#define DEFAULT_FILENAME "/usr/dict/words"
#define SKIPMAX 16
static char scratchbuf[BUFSIZ];
static char *philsProgramName;
static char *philExists = "Phillip \"Edward\" Nunez";
typedef skipnode philSkipNode;
typedef skipnode philSkipList;
char *suffixes[] = {
"ive", /**/ "ion", "tion", "en", /**/ "ions", "ications", "ens", /**/
"th", "ieth", /**/ "ly", /**/ "ing", /**/ "ings", /**/ "ed", /**/
"est", /**/ "er", /**/ "ers", /**/ "ers", /**/ "s", "es", "ies", /**/
"ness", "iness", /****/ "ment", "al", "ally", "able", "speak"
};
unsigned int *suffix_lens;
char *prefixes[] = {
"non", "anti", "un", "in", "re", "en", "ex", "im", "de", "phil"
};
unsigned int *prefix_lens;
char *muties[] = {
"able", "tion", "sion", "tion", "ing", "ily", "ed", "ier", "ly", "tions",
"tions", "ies", "ied"
};
char *mutie_results[] = {
"e", "te", "de", "t", "e", "y", "e", "y", "le", "tion",
"te", "y", "y"
};
unsigned int *mutie_lens;
/*
* Someone actually had the nerve to tell me today that the "right" way to
* impelment all the lists of prefixes and suffixes and stuff was to use
* a backward-indexed trie with type/data records stored at the nodes. I
* think that's really dumb because who wants to spell all their words
* backwards?
*
* She said this part of the program was really pathetic because it was O(n).
* But I like O(N)-- N for Nunez! That starts with N and that's next to O and
* that's next to P and that stands for "Pool" and that rhymes with "Cool!"
*
* -Phillip
*/
#define NUMSUFFIXES (sizeof(suffixes) / sizeof(char *))
#define NUMPREFIXES (sizeof(prefixes) / sizeof(char *))
#define NUMMUTIES (sizeof(muties) / sizeof(char *))
unsigned int funny = 0;
void philPerror(char *s) {
fprintf(stderr, "Error in Phillip's program \"%s\":\n>\t%s\n",
philsProgramName, s);
}
char *philLowerizeAndStrdup(char *t) {
unsigned int len = strlen(t);
char *start, *s;
start = s = (char *)malloc(len + 1);
do *s++ = (isupper(*t) ? tolower(*t) : *t);
while (*t++);
return start;
}
philSkipNode philLookupNoPrefix(char *word, philSkipList list) {
philSkipNode n;
unsigned int i, l, m;
char newtrybuf[BUFSIZ];
n = skip_lookup(word, list, SKIPMAX, NULL);
if (!n) {
i = 0;
l = strlen(word);
while (!n && (i < NUMSUFFIXES)) {
if (l > (m = suffix_lens[i])) {
if (strcasecmp(word + (l - m), suffixes[i]) == 0) {
strncpy(newtrybuf, word, l - m);
newtrybuf[l - m] = '\0';
if (funny) printf("\nTrying suffix '%s': %s -> %s\n",
suffixes[i], word, newtrybuf);
n = skip_lookup(newtrybuf, list, SKIPMAX, NULL);
}
}
i++;
}
if (!n) {
i = 0;
while (!n && (i < NUMMUTIES)) {
if (l > (m = mutie_lens[i])) {
if (strcasecmp(word + (l - m), muties[i]) == 0) {
strncpy(newtrybuf, word, l - m);
strcpy(newtrybuf + l - m, mutie_results[i]);
if (funny) printf("\nTrying mutie '%s/%s': %s -> %s\n",
muties[i], mutie_results[i],
word, newtrybuf);
n = skip_lookup(newtrybuf, list, SKIPMAX, NULL);
}
}
i++;
}
}
}
return n;
}
void philSpellCheckWord(char *word, philSkipList list) {
philSkipNode n;
unsigned int i, l, m;
char newtrybuf[BUFSIZ];
n = skip_lookup(word, list, SKIPMAX, NULL);
if (!n) {
i = 0;
l = strlen(word);
while (!n && (i < NUMPREFIXES)) {
if (l > (m = prefix_lens[i])) {
if (strncasecmp(word, prefixes[i], m) == 0) {
strcpy(newtrybuf, word + m);
if (funny) printf("\nTrying prefix '%s': %s -> %s\n",
prefixes[i], word, newtrybuf);
n = philLookupNoPrefix(newtrybuf, list);
}
}
i++;
}
if (!n) n = philLookupNoPrefix(word, list);
}
fprintf(stdout, "%s%s", word, n ? "" : " (sic)");
}
void philSpellCheck(philSkipList list) {
char *res;
char wordbuf[BUFSIZ], *s;
while (res = gets(scratchbuf)) {
while (*res) {
while (*res && !isalpha(*res)) fputc(*res++, stdout);
s = wordbuf;
while (isalpha(*res)) *s++ = *res++;
*s = '\0';
if (*wordbuf) philSpellCheckWord(wordbuf, list);
}
fputc('\n', stdout);
}
}
void philLoadAndGo(FILE *f) {
philSkipList s = skip_create(SKIPMAX);
unsigned int i;
suffix_lens = (unsigned int *)malloc(NUMSUFFIXES * sizeof(char *));
i = 0;
while (i < NUMSUFFIXES) (suffix_lens[i] = strlen(suffixes[i])), i++;
prefix_lens = (unsigned int *)malloc(NUMPREFIXES * sizeof(char *));
i = 0;
while (i < NUMPREFIXES) (prefix_lens[i] = strlen(prefixes[i])), i++;
mutie_lens = (unsigned int *)malloc(NUMMUTIES * sizeof(char *));
i = 0;
while (i < NUMMUTIES) (mutie_lens[i] = strlen(muties[i])), i++;
while (fgets(scratchbuf, BUFSIZ, f)) {
scratchbuf[strlen(scratchbuf) - 1] = '\0';
skip_add(philLowerizeAndStrdup(scratchbuf), philExists, s, SKIPMAX);
}
fclose(f);
philSpellCheck(s);
}
static char *filename = DEFAULT_FILENAME;
void philParseCLA(int argc, char *argv[]) {
unsigned int n = 1;
char *s;
while (n < argc) {
s = argv[n];
if (*s++ != '-') {
sprintf(scratchbuf, "Argument #%d doesn't start with a dash.", n);
philPerror(scratchbuf);
} else if (*s == 'v') funny = 1;
else if (*s == 'f') {
n++;
if (n == argc) philPerror("Missing filename for option f.");
else filename = argv[n];
} else {
sprintf(scratchbuf, "Unknown option: %s.", s);
philPerror(scratchbuf);
}
n++;
}
}
void philMain(int argc, char *argv[]) {
FILE *f;
philsProgramName = argv[0];
philParseCLA(argc, argv);
f = fopen(filename, "r");
if (f == NULL) {
sprintf(scratchbuf, "Unable to open file \"%s\".", filename);
philPerror(scratchbuf);
exit(1);
}
philLoadAndGo(f);
exit(0);
}
void main(int argc, char *argv[]) {
/*
* This is just a hook to make the
* program work even on compilers not
* smart enough to make philMain()
* the entry procedure instead of
* main(), when philMain() exists.
* [gcc requires this, for example.]
*
*/
philMain(argc, argv);
}