This is Homophones.m in view mode; [Download] [Up]
/* File: Homophones.m - Manipulates HashFile of homophones extracted from Webster
*
* By: Christopher Lane
* Symbolic Systems Resources Group
* Knowledge Systems Laboratory
* Stanford University
*
* Date: 14 September 1990
*
* Copyright: 1990 by The Leland Stanford Junior University. This program
* may be distributed without restriction for non-commercial use.
*/
#import <c.h>
#import <libc.h>
#import <stdlib.h>
#import <ctype.h>
#import <string.h>
#import <stdio.h>
#import <getopt.h>
#import <objc/Storage.h>
#import <objc/HashFile.h>
#import <objc/HashTable.h>
#import <text/webster.h>
#import <text/strutil.h>
#import <text/pathutil.h>
#define DATABASE "/usr/local/lib/homophones/Homophones"
#define REFERENCE "Webster-Dictionary"
#define ATOM "%" /* @encode(NXAtom) doesn't work :-( */
#define OBJECT @encode(id)
#define BUFFER_SIZE 512
#define MAX_PRONUNCIATIONS 48
#define SPACE ' '
#define HYPHEN '-'
#define LPAREN '('
#define RPAREN ')'
#define SEPARATOR ", "
#define BEGINPRONUNCIATION "["
#define ENDPRONUNCIATION "]"
#define OPEN "%s: Can't open %s.\n"
#define OPTIONSTRING "bdrh:w:"
#define USAGE "usage: %s [-b] [-d] [-r] [-h database] [-w dictionary]\n"
typedef enum { BUILD = 'b', DUMP = 'd', RAW = 'r', HASHFILE = 'h', DICTIONARY = 'w' } OPTIONS;
typedef enum { PROGRAM } ARGUMENTS;
BOOL rawFlag = NO;
BOOL complete(char *string)
{
int head = 0, tail = strlen(string) - 1;
while(head < tail && string[head] != HYPHEN && ! isalpha(string[head])) ++head;
while(tail > head && string[tail] != HYPHEN && ! isalpha(string[tail])) --tail;
return (BOOL) string[head] != HYPHEN && string[tail] != HYPHEN ;
}
BOOL garbage(char *string)
{
return (BOOL) strlen(string) <= 1 || blank(string) || index(string, SPACE) || hasdigit(string) || hasupper(string);
}
void printPronunciation(NXAtom atom)
{
int c;
(void) fputs(BEGINPRONUNCIATION, stdout);
if(rawFlag) (void) fputs(atom, stdout);
else while((c = toascii(*(atom++))) != '\0') if(isprint(c)) (void) putchar(c);
(void) fputs(ENDPRONUNCIATION, stdout);
}
void options(char *strings[], unsigned int *size) /* /(')wich/ => /'wich/ & /wich/ */
{
unsigned int i, offset;
char *s, *t, buffer[BUFFER_SIZE];
for(i = 0; i < *size; i++) {
if((s = index(strings[i], LPAREN)) != NULL && (t = index(s, RPAREN)) != NULL) {
strncpy(buffer, strings[i], (offset = s++ - strings[i]));
strcpy(buffer + offset, t + 1);
strings[(*size)++] = NXCopyStringBuffer(buffer);
strncpy(buffer + offset, s, t - s);
strcpy(buffer + offset + (t - s), t + 1);
strings[i--] = NXCopyStringBuffer(buffer);
} /* if */
} /* for */
}
unsigned int pronunciations(char *string, NXAtom atoms[])
{
unsigned int i = 0, j;
char *s, buffer[BUFFER_SIZE], *strings[MAX_PRONUNCIATIONS];
string = strcpy(buffer, string);
while((s = strindex(string, SEPARATOR)) != NULL) {
*(s++) = '\0';
if(!garbage(string) && complete(string)) strings[i++] = NXCopyStringBuffer(string);
string = ++s;
} /* while */
if(!garbage(string) && complete(string)) strings[i++] = NXCopyStringBuffer(string);
options(strings, &i);
for(j = 0; j < i; j++) {
atoms[j] = NXUniqueString(strings[j]);
free(strings[j]);
}
return i;
}
void buildTable(id table, ReferenceBook *book)
{
Storage *list;
SenseList *sense;
NXHashState state;
void *key, *value;
Definition *definition;
unsigned int p, pCount, wCount;
NXAtom string, atoms[MAX_PRONUNCIATIONS];
HashTable *scratch = [HashTable newKeyDesc:ATOM valueDesc:OBJECT];
while((definition = nextDefinition(book)) != NULL) {
sense = definition->l;
while(sense != NULL) {
if((sense->s)[0] == dPronunciation && (pCount = pronunciations((sense->s) + 1, atoms)) != 0) {
for(p = 0; p < pCount; p++) {
if([scratch isKey:(void *) atoms[p]]) list = [scratch valueForKey:(void *) atoms[p]];
else {
list = [Storage newCount:0 elementSize:sizeof(char *) description:ATOM];
[scratch insertKey:(void *) atoms[p] value:(void *) list];
} /* else */
string = NXUniqueString(definition->entry);
if((wCount = [list count]) == 0 || string != *((char **) [list elementAt:wCount - 1]))
[list insert:(void *) &string at:wCount];
} /* for */
} /* if */
sense = sense->next;
} /* while */
freeDefinition(definition);
} /* while */
state = [scratch initState];
while([scratch nextState:&state key:&key value:&value]) {
if([(Storage *) value count] > 1) [table insertKey:key value:value];
else [(Storage *) value free];
} /* while */
[scratch free];
}
void lookupTable(char *word, id table, ReferenceBook *book)
{
Storage *list;
SenseList *sense;
Definition *definition;
NXAtom atoms[MAX_PRONUNCIATIONS];
unsigned int p, w, pCount, wCount;
definition = getDefinition(word, book, TRUE);
while(definition != NULL) {
if(strcmp(word, definition->entry) == 0) {
sense = definition->l;
while(sense != NULL) {
if((sense->s)[0] == dPronunciation && (pCount = pronunciations((sense->s) + 1, atoms)) != 0) {
for(p = 0; p < pCount; p++) {
if([table isKey:(void *) atoms[p]]) {
printPronunciation(atoms[p]);
list = [table valueForKey:(void *) atoms[p]];
wCount = [list count];
for(w = 0; w < wCount; w++) (void) printf(" %s", *((char **) [list elementAt:w]));
(void) printf("\n");
} /* if */
#ifdef DEBUG
else {
printPronunciation(atoms[p]);
(void) printf("\n");
}
#endif
} /* for */
} /* if */
sense = sense->next;
} /* while */
} /* if */
freeDefinition(definition);
definition = getNextDefinition(word, book, TRUE);
} /* while */
}
void dumpTable(id table)
{
void *key, *value;
unsigned int w, wCount;
NXHashState state = [table initState];
while([table nextState:&state key:&key value:&value]) {
printPronunciation((NXAtom) key);
wCount = [(Storage *) value count];
for(w = 0; w < wCount; w++)
(void) printf(" %s", *((char **) [(Storage *) value elementAt:w]));
(void) printf("\n");
} /* while */
}
void main(int argc, char *argv[])
{
HashFile *file;
ReferenceBook *book;
int option, status = EXIT_SUCCESS;
BOOL buildFlag = NO, dumpFlag = NO;
char buffer[BUFFER_SIZE], *reference = REFERENCE, *database = DATABASE;
while((option = getopt(argc, argv, OPTIONSTRING)) != EOF)
switch(option) {
case BUILD : buildFlag = YES; break;
case DUMP : dumpFlag = YES; break;
case RAW : rawFlag = YES; break;
case HASHFILE : database = optarg; break;
case DICTIONARY : reference = optarg; break;
default : status = EXIT_FAILURE;
} /* while */
if(optind < argc || status == EXIT_FAILURE) {
(void) fprintf(stderr, USAGE, basename(argv[PROGRAM]));
exit(EXIT_FAILURE);
} /* if */
if((buildFlag || [HashFile isHashFile:database]) &&
(file = [HashFile newFromFile:database keyDesc:ATOM valueDesc:OBJECT]) != nil) {
if(dumpFlag) dumpTable(file);
else if((book = referenceOpen(reference)) != NULL) {
if(buildFlag) buildTable(file, book);
else while(scanf("%s", buffer) != EOF) lookupTable(buffer, file, book);
(void) referenceClose(book);
} /* else if */
else (void) fprintf(stderr, OPEN, basename(argv[PROGRAM]), reference, status = EXIT_FAILURE);
[file free];
} /* if */
else (void) fprintf(stderr, OPEN, basename(argv[PROGRAM]), database, status = EXIT_FAILURE);
exit(status);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.