1 /*
2
3 search.c - WordNet library of search code
4
5 */
6
7 #ifdef WINDOWS
8 #include <windows.h>
9 #include <windowsx.h>
10 #endif
11 #include <stdio.h>
12 #include <ctype.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <assert.h>
16
17 #include "wn.h"
18 #ifdef WN1_6
19 #include "setutil.h"
20 #endif
21
22 static char *Id = "$Id: search.c,v 1.161 2003/06/23 15:52:27 wn Exp $";
23
24 /* For adjectives, indicates synset type */
25
26 #define DONT_KNOW 0
27 #define DIRECT_ANT 1 /* direct antonyms (cluster head) */
28 #define INDIRECT_ANT 2 /* indrect antonyms (similar) */
29 #define PERTAINYM 3 /* no antonyms or similars (pertainyms) */
30
31 /* Flags for printsynset() */
32
33 #define ALLWORDS 0 /* print all words */
34 #define SKIP_ANTS 0 /* skip printing antonyms in printsynset() */
35 #define PRINT_ANTS 1 /* print antonyms in printsynset() */
36 #define SKIP_MARKER 0 /* skip printing adjective marker */
37 #define PRINT_MARKER 1 /* print adjective marker */
38
39 /* Trace types used by printspaces() to determine print sytle */
40
41 #define TRACEP 1 /* traceptrs */
42 #define TRACEC 2 /* tracecoords() */
43 #define TRACEI 3 /* traceinherit() */
44
45 #define DEFON 1
46 #define DEFOFF 0
47
48 /* Forward function declarations */
49
50 static void WNOverview(char *, int);
51 #ifdef WN1_6
52 static void findsisters(IndexPtr), findtwins(IndexPtr), findcousins(IndexPtr);
53 static int read_cousintops(void);
54 static int groupexc(unsigned long, unsigned long);
55 #endif
56 static void findverbgroups(IndexPtr);
57 static void add_relatives(int, IndexPtr, int, int);
58 static void free_rellist(void);
59 static void printsynset(char *, SynsetPtr, char *, int, int, int, int);
60 static void printantsynset(SynsetPtr, char *, int, int);
61 static char *printant(int, SynsetPtr, int, char *, char *);
62 static void printbuffer(char *);
63 static void printsns(SynsetPtr, int);
64 static void printsense(SynsetPtr, int);
65 static void catword(char *, SynsetPtr, int, int, int);
66 static void printspaces(int, int);
67 static void printrelatives(IndexPtr, int);
68 static int HasHoloMero(IndexPtr, int);
69 static int HasPtr(SynsetPtr, int);
70 static int getsearchsense(SynsetPtr, int);
71 static int depthcheck(int, SynsetPtr);
72 static void interface_doevents();
73 static void getexample(char *, char *);
74 static int findexample(SynsetPtr);
75
76 /* Static variables */
77
78 static int prflag, sense, prlexid;
79 static int overflag = 0; /* set when output buffer overflows */
80 static char searchbuffer[SEARCHBUF];
81 static int lastholomero; /* keep track of last holo/meronym printed */
82 #define TMPBUFSIZE 1024*10
83 static char tmpbuf[TMPBUFSIZE]; /* general purpose printing buffer */
84 static char wdbuf[WORDBUF]; /* general purpose word buffer */
85 static char msgbuf[256]; /* buffer for constructing error messages */
86 static int adj_marker;
87
88 extern long last_bin_search_offset;
89
90
91 /* Find word in index file and return parsed entry in data structure.
92 Input word must be exact match of string in database. */
93
index_lookup(char * word,int dbase)94 IndexPtr index_lookup(char *word, int dbase)
95 {
96 IndexPtr idx = NULL;
97 FILE *fp;
98 char *line;
99
100 if ((fp = indexfps[dbase]) == NULL) {
101 sprintf(msgbuf, "WordNet library error: %s indexfile not open\n",
102 partnames[dbase]);
103 display_message(msgbuf);
104 return(NULL);
105 }
106
107 if ((line = bin_search(word, fp)) != NULL) {
108 idx = parse_index( last_bin_search_offset, dbase, line);
109 }
110 return (idx);
111 }
112
113 /* This function parses an entry from an index file into an Index data
114 * structure. It takes the byte offset and file number, and optionally the
115 * line. If the line is NULL, parse_index will get the line from the file.
116 * If the line is non-NULL, parse_index won't look at the file, but it still
117 * needs the dbase and offset parameters to be set, so it can store them in
118 * the Index struct.
119 */
120
parse_index(long offset,int dbase,char * line)121 IndexPtr parse_index(long offset, int dbase, char *line) {
122
123 IndexPtr idx = NULL;
124 char *ptrtok;
125 int j;
126
127 if ( !line )
128 line = read_index( offset, indexfps[dbase] );
129
130 idx = (IndexPtr)malloc(sizeof(Index));
131 assert(idx);
132
133 /* set offset of entry in index file */
134 idx->idxoffset = offset;
135
136 idx->wd='\0';
137 idx->pos='\0';
138 idx->off_cnt=0;
139 idx->tagged_cnt = 0;
140 idx->sense_cnt=0;
141 idx->offset='\0';
142 idx->ptruse_cnt=0;
143 idx->ptruse='\0';
144
145 /* get the word */
146 ptrtok=strtok(line," \n");
147
148 idx->wd = malloc(strlen(ptrtok) + 1);
149 assert(idx->wd);
150 strcpy(idx->wd, ptrtok);
151
152 /* get the part of speech */
153 ptrtok=strtok(NULL," \n");
154 idx->pos = malloc(strlen(ptrtok) + 1);
155 assert(idx->pos);
156 strcpy(idx->pos, ptrtok);
157
158 /* get the collins count */
159 ptrtok=strtok(NULL," \n");
160 idx->sense_cnt = atoi(ptrtok);
161
162 /* get the number of pointers types */
163 ptrtok=strtok(NULL," \n");
164 idx->ptruse_cnt = atoi(ptrtok);
165
166 if (idx->ptruse_cnt) {
167 idx->ptruse = (int *) malloc(idx->ptruse_cnt * (sizeof(int)));
168 assert(idx->ptruse);
169
170 /* get the pointers types */
171 for(j=0;j < idx->ptruse_cnt; j++) {
172 ptrtok=strtok(NULL," \n");
173 idx->ptruse[j] = getptrtype(ptrtok);
174 }
175 }
176
177 /* get the number of offsets */
178 ptrtok=strtok(NULL," \n");
179 idx->off_cnt = atoi(ptrtok);
180
181 /* get the number of senses that are tagged */
182 ptrtok=strtok(NULL," \n");
183 idx->tagged_cnt = atoi(ptrtok);
184
185 /* make space for the offsets */
186 idx->offset = (long *) malloc(idx->off_cnt * (sizeof(long)));
187 assert(idx->offset);
188
189 /* get the offsets */
190 for(j=0;j<idx->off_cnt;j++) {
191 ptrtok=strtok(NULL," \n");
192 idx->offset[j] = atol(ptrtok);
193 }
194 return(idx);
195 }
196
197 /* 'smart' search of index file. Find word in index file, trying different
198 techniques - replace hyphens with underscores, replace underscores with
199 hyphens, strip hyphens and underscores, strip periods. */
200
getindex(char * searchstr,int dbase)201 IndexPtr getindex(char *searchstr, int dbase)
202 {
203 int i, j, k;
204 char c;
205 char strings[MAX_FORMS][WORDBUF]; /* vector of search strings */
206 static IndexPtr offsets[MAX_FORMS];
207 static int offset;
208
209 /* This works like strrok(): if passed with a non-null string,
210 prepare vector of search strings and offsets. If string
211 is null, look at current list of offsets and return next
212 one, or NULL if no more alternatives for this word. */
213
214 if (searchstr != NULL) {
215
216 offset = 0;
217 strtolower(searchstr);
218 for (i = 0; i < MAX_FORMS; i++) {
219 strcpy(strings[i], searchstr);
220 offsets[i] = 0;
221 }
222
223 strsubst(strings[1], '_', '-');
224 strsubst(strings[2], '-', '_');
225
226 /* remove all spaces and hyphens from last search string, then
227 all periods */
228 for (i = j = k = 0; (c = searchstr[i]) != '\0'; i++) {
229 if (c != '_' && c != '-')
230 strings[3][j++] = c;
231 if (c != '.')
232 strings[4][k++] = c;
233 }
234 strings[3][j] = '\0';
235 strings[4][k] = '\0';
236
237 /* Get offset of first entry. Then eliminate duplicates
238 and get offsets of unique strings. */
239
240 if (strings[0][0] != NULL)
241 offsets[0] = index_lookup(strings[0], dbase);
242
243 for (i = 1; i < MAX_FORMS; i++)
244 if ((strings[i][0]) != NULL && (strcmp(strings[0], strings[i])))
245 offsets[i] = index_lookup(strings[i], dbase);
246 }
247
248
249 for (i = offset; i < MAX_FORMS; i++)
250 if (offsets[i]) {
251 offset = i + 1;
252 return(offsets[i]);
253 }
254
255 return(NULL);
256 }
257
258 /* Read synset from data file at byte offset passed and return parsed
259 entry in data structure. */
260
read_synset(int dbase,long boffset,char * word)261 SynsetPtr read_synset(int dbase, long boffset, char *word)
262 {
263 FILE *fp;
264
265 if((fp = datafps[dbase]) == NULL) {
266 sprintf(msgbuf, "WordNet library error: %s datafile not open\n",
267 partnames[dbase]);
268 display_message(msgbuf);
269 return(NULL);
270 }
271
272 fseek(fp, boffset, 0); /* position file to byte offset requested */
273
274 return(parse_synset(fp, dbase, word)); /* parse synset and return */
275 }
276
277 /* Read synset at current byte offset in file and return parsed entry
278 in data structure. */
279
parse_synset(FILE * fp,int dbase,char * word)280 SynsetPtr parse_synset(FILE *fp, int dbase, char *word)
281 {
282 static char line[LINEBUF];
283 char tbuf[SMLINEBUF];
284 char *ptrtok;
285 char *tmpptr;
286 int foundpert = 0;
287 char wdnum[3];
288 int i;
289 SynsetPtr synptr;
290 long loc; /* sanity check on file location */
291
292 loc = ftell(fp);
293
294 if ((tmpptr = fgets(line, LINEBUF, fp)) == NULL)
295 return(NULL);
296
297 synptr = (SynsetPtr)malloc(sizeof(Synset));
298 assert(synptr);
299
300 synptr->hereiam = 0;
301 synptr->sstype = DONT_KNOW;
302 synptr->fnum = 0;
303 synptr->pos = '\0';
304 synptr->wcount = 0;
305 synptr->words = '\0';
306 synptr->whichword = 0;
307 synptr->ptrcount = 0;
308 synptr->ptrtyp = '\0';
309 synptr->ptroff = '\0';
310 synptr->ppos = '\0';
311 synptr->pto = '\0';
312 synptr->pfrm = '\0';
313 synptr->fcount = 0;
314 synptr->frmid = '\0';
315 synptr->frmto = '\0';
316 synptr->defn = '\0';
317 synptr->key = 0;
318 synptr->nextss = NULL;
319 synptr->nextform = NULL;
320 synptr->searchtype = -1;
321 synptr->ptrlist = NULL;
322 synptr->headword = NULL;
323 synptr->headsense = 0;
324
325 ptrtok = line;
326
327 /* looking at offset */
328 ptrtok = strtok(line," \n");
329 synptr->hereiam = atol(ptrtok);
330
331 /* sanity check - make sure starting file offset matches first field */
332 if (synptr->hereiam != loc) {
333 sprintf(msgbuf, "WordNet library error: no synset at location %d\n",
334 loc);
335 display_message(msgbuf);
336 free(synptr);
337 return(NULL);
338 }
339
340 /* looking at FNUM */
341 ptrtok = strtok(NULL," \n");
342 synptr->fnum = atoi(ptrtok);
343
344 /* looking at POS */
345 ptrtok = strtok(NULL, " \n");
346 synptr->pos = malloc(strlen(ptrtok) + 1);
347 assert(synptr->pos);
348 strcpy(synptr->pos, ptrtok);
349 if (getsstype(synptr->pos) == SATELLITE)
350 synptr->sstype = INDIRECT_ANT;
351
352 /* looking at numwords */
353 ptrtok = strtok(NULL, " \n");
354 synptr->wcount = strtol(ptrtok, NULL, 16);
355
356 synptr->words = (char **)malloc(synptr->wcount * sizeof(char *));
357 assert(synptr->words);
358 synptr->wnsns = (int *)malloc(synptr->wcount * sizeof(int));
359 assert(synptr->wnsns);
360 synptr->lexid = (int *)malloc(synptr->wcount * sizeof(int));
361 assert(synptr->lexid);
362
363 for (i = 0; i < synptr->wcount; i++) {
364 ptrtok = strtok(NULL, " \n");
365 synptr->words[i] = malloc(strlen(ptrtok) + 1);
366 assert(synptr->words[i]);
367 strcpy(synptr->words[i], ptrtok);
368
369 /* is this the word we're looking for? */
370
371 if (word && !strcmp(word,strtolower(ptrtok)))
372 synptr->whichword = i+1;
373
374 ptrtok = strtok(NULL, " \n");
375 sscanf(ptrtok, "%x", &synptr->lexid[i]);
376 }
377
378 /* get the pointer count */
379 ptrtok = strtok(NULL," \n");
380 synptr->ptrcount = atoi(ptrtok);
381
382 if (synptr->ptrcount) {
383
384 /* alloc storage for the pointers */
385 synptr->ptrtyp = (int *)malloc(synptr->ptrcount * sizeof(int));
386 assert(synptr->ptrtyp);
387 synptr->ptroff = (long *)malloc(synptr->ptrcount * sizeof(long));
388 assert(synptr->ptroff);
389 synptr->ppos = (int *)malloc(synptr->ptrcount * sizeof(int));
390 assert(synptr->ppos);
391 synptr->pto = (int *)malloc(synptr->ptrcount * sizeof(int));
392 assert(synptr->pto);
393 synptr->pfrm = (int *)malloc(synptr->ptrcount * sizeof(int));
394 assert(synptr->pfrm);
395
396 for(i = 0; i < synptr->ptrcount; i++) {
397 /* get the pointer type */
398 ptrtok = strtok(NULL," \n");
399 synptr->ptrtyp[i] = getptrtype(ptrtok);
400 /* For adjectives, set the synset type if it has a direct
401 antonym */
402 if (dbase == ADJ && synptr->sstype == DONT_KNOW) {
403 if (synptr->ptrtyp[i] == ANTPTR)
404 synptr->sstype = DIRECT_ANT;
405 else if (synptr->ptrtyp[i] == PERTPTR)
406 foundpert = 1;
407 }
408
409 /* get the pointer offset */
410 ptrtok = strtok(NULL," \n");
411 synptr->ptroff[i] = atol(ptrtok);
412
413 /* get the pointer part of speech */
414 ptrtok = strtok(NULL, " \n");
415 synptr->ppos[i] = getpos(ptrtok);
416
417 /* get the lexp to/from restrictions */
418 ptrtok = strtok(NULL," \n");
419
420 tmpptr = ptrtok;
421 strncpy(wdnum, tmpptr, 2);
422 wdnum[2] = '\0';
423 synptr->pfrm[i] = strtol(wdnum, (char **)NULL, 16);
424
425 tmpptr += 2;
426 strncpy(wdnum, tmpptr, 2);
427 wdnum[2] = '\0';
428 synptr->pto[i] = strtol(wdnum, (char **)NULL, 16);
429 }
430 }
431
432 /* If synset type is still not set, see if it's a pertainym */
433
434 if (dbase == ADJ && synptr->sstype == DONT_KNOW && foundpert == 1)
435 synptr->sstype = PERTAINYM;
436
437 /* retireve optional information from verb synset */
438 if(dbase == VERB) {
439 ptrtok = strtok(NULL," \n");
440 synptr->fcount = atoi(ptrtok);
441
442 /* allocate frame storage */
443
444 synptr->frmid = (int *)malloc(synptr->fcount * sizeof(int));
445 assert(synptr->frmid);
446 synptr->frmto = (int *)malloc(synptr->fcount * sizeof(int));
447 assert(synptr->frmto);
448
449 for(i=0;i<synptr->fcount;i++) {
450 /* skip the frame pointer (+) */
451 ptrtok = strtok(NULL," \n");
452
453 ptrtok = strtok(NULL," \n");
454 synptr->frmid[i] = atoi(ptrtok);
455
456 ptrtok = strtok(NULL," \n");
457 synptr->frmto[i] = strtol(ptrtok, NULL, 16);
458 }
459 }
460
461 /* get the optional definition */
462
463 ptrtok = strtok(NULL," \n");
464 if (ptrtok) {
465 ptrtok = strtok(NULL," \n");
466 sprintf(tbuf, "");
467 while (ptrtok != NULL) {
468 strcat(tbuf,ptrtok);
469 ptrtok = strtok(NULL, " \n");
470 if(ptrtok)
471 strcat(tbuf," ");
472 }
473 assert((1 + strlen(tbuf)) < sizeof(tbuf));
474 synptr->defn = malloc(strlen(tbuf) + 4);
475 assert(synptr->defn);
476 sprintf(synptr->defn,"(%s)",tbuf);
477 }
478
479 if (keyindexfp) { /* we have unique keys */
480 sprintf(tmpbuf, "%c:%8.8d", partchars[dbase], synptr->hereiam);
481 synptr->key = GetKeyForOffset(tmpbuf);
482 }
483
484 /* Can't do earlier - calls indexlookup which messes up strtok calls */
485
486 for (i = 0; i < synptr->wcount; i++)
487 synptr->wnsns[i] = getsearchsense(synptr, i + 1);
488
489 return(synptr);
490 }
491
492 /* Free a synset linked list allocated by findtheinfo_ds() */
493
free_syns(SynsetPtr synptr)494 void free_syns(SynsetPtr synptr)
495 {
496 SynsetPtr cursyn, nextsyn;
497
498 if (synptr) {
499 cursyn = synptr;
500 while(cursyn) {
501 if (cursyn->nextform)
502 free_syns(cursyn->nextform);
503 nextsyn = cursyn->nextss;
504 free_synset(cursyn);
505 cursyn = nextsyn;
506 }
507 }
508 }
509
510 /* Free a synset */
511
free_synset(SynsetPtr synptr)512 void free_synset(SynsetPtr synptr)
513 {
514 int i;
515
516 free(synptr->pos);
517 for (i = 0; i < synptr->wcount; i++){
518 free(synptr->words[i]);
519 }
520 free(synptr->words);
521 free(synptr->wnsns);
522 free(synptr->lexid);
523 if (synptr->ptrcount) {
524 free(synptr->ptrtyp);
525 free(synptr->ptroff);
526 free(synptr->ppos);
527 free(synptr->pto);
528 free(synptr->pfrm);
529 }
530 if (synptr->fcount) {
531 free(synptr->frmid);
532 free(synptr->frmto);
533 }
534 if (synptr->defn)
535 free(synptr->defn);
536 if (synptr->headword)
537 free(synptr->headword);
538 if (synptr->ptrlist)
539 free_syns(synptr->ptrlist); /* changed from free_synset() */
540 free(synptr);
541 }
542
543 /* Free an index structure */
544
free_index(IndexPtr idx)545 void free_index(IndexPtr idx)
546 {
547 free(idx->wd);
548 free(idx->pos);
549 if (idx->ptruse)
550 free(idx->ptruse);
551 free(idx->offset);
552 free(idx);
553 }
554
555 /* Recursive search algorithm to trace a pointer tree */
556
traceptrs(SynsetPtr synptr,int ptrtyp,int dbase,int depth)557 static void traceptrs(SynsetPtr synptr, int ptrtyp, int dbase, int depth)
558 {
559 int i;
560 int extraindent = 0;
561 SynsetPtr cursyn;
562 char prefix[40], tbuf[20];
563
564 interface_doevents();
565 if (abortsearch)
566 return;
567
568 if (ptrtyp < 0) {
569 ptrtyp = -ptrtyp;
570 extraindent = 2;
571 }
572
573 for (i = 0; i < synptr->ptrcount; i++) {
574 if((synptr->ptrtyp[i] == ptrtyp) &&
575 ((synptr->pfrm[i] == 0) ||
576 (synptr->pfrm[i] == synptr->whichword))) {
577
578 if(!prflag) { /* print sense number and synset */
579 printsns(synptr, sense + 1);
580 prflag = 1;
581 }
582 printspaces(TRACEP, depth + extraindent);
583
584 switch(ptrtyp) {
585 case PERTPTR:
586 if (dbase == ADV)
587 sprintf(prefix, "Derived from %s ",
588 partnames[synptr->ppos[i]]);
589 else
590 sprintf(prefix, "Pertains to %s ",
591 partnames[synptr->ppos[i]]);
592 break;
593 case ANTPTR:
594 if (dbase != ADJ)
595 sprintf(prefix, "Antonym of ");
596 break;
597 case PPLPTR:
598 sprintf(prefix, "Participle of verb ");
599 break;
600 case HASMEMBERPTR:
601 sprintf(prefix, " HAS MEMBER: ");
602 break;
603 case HASSTUFFPTR:
604 sprintf(prefix, " HAS SUBSTANCE: ");
605 break;
606 case HASPARTPTR:
607 sprintf(prefix, " HAS PART: ");
608 break;
609 case ISMEMBERPTR:
610 sprintf(prefix, " MEMBER OF: ");
611 break;
612 case ISSTUFFPTR:
613 sprintf(prefix, " SUBSTANCE OF: ");
614 break;
615 case ISPARTPTR:
616 sprintf(prefix, " PART OF: ");
617 break;
618 default:
619 sprintf(prefix, "=> ");
620 break;
621 }
622
623 /* Read synset pointed to */
624 cursyn=read_synset(synptr->ppos[i], synptr->ptroff[i], "");
625
626 /* For Pertainyms and Participles pointing to a specific
627 sense, indicate the sense then retrieve the synset
628 pointed to and other info as determined by type.
629 Otherwise, just print the synset pointed to. */
630
631 if ((ptrtyp == PERTPTR || ptrtyp == PPLPTR) &&
632 synptr->pto[i] != 0) {
633 sprintf(tbuf, " (Sense %d)\n",
634 cursyn->wnsns[synptr->pto[i] - 1]);
635 printsynset(prefix, cursyn, tbuf, DEFOFF, synptr->pto[i],
636 SKIP_ANTS, PRINT_MARKER);
637 if (ptrtyp == PPLPTR) { /* adjective pointing to verb */
638 printsynset(" =>", cursyn, "\n",
639 DEFON, ALLWORDS, PRINT_ANTS, PRINT_MARKER);
640 traceptrs(cursyn, HYPERPTR, getpos(cursyn->pos), 0);
641 } else if (dbase == ADV) { /* adverb pointing to adjective */
642 printsynset(" =>", cursyn, "\n",DEFON, ALLWORDS,
643 ((getsstype(cursyn->pos) == SATELLITE)
644 ? SKIP_ANTS : PRINT_ANTS), PRINT_MARKER);
645 #ifdef FOOP
646 traceptrs(cursyn, HYPERPTR, getpos(cursyn->pos), 0);
647 #endif
648 } else { /* adjective pointing to noun */
649 printsynset(" =>", cursyn, "\n",
650 DEFON, ALLWORDS, PRINT_ANTS, PRINT_MARKER);
651 traceptrs(cursyn, HYPERPTR, getpos(cursyn->pos), 0);
652 }
653 } else if (ptrtyp == ANTPTR && dbase != ADJ && synptr->pto[i] != 0) {
654 sprintf(tbuf, " (Sense %d)\n",
655 cursyn->wnsns[synptr->pto[i] - 1]);
656 printsynset(prefix, cursyn, tbuf, DEFOFF, synptr->pto[i],
657 SKIP_ANTS, PRINT_MARKER);
658 printsynset(" =>", cursyn, "\n", DEFON, ALLWORDS,
659 PRINT_ANTS, PRINT_MARKER);
660 } else
661 printsynset(prefix, cursyn, "\n", DEFON, ALLWORDS,
662 PRINT_ANTS, PRINT_MARKER);
663
664 /* For HOLONYMS and MERONYMS, keep track of last one
665 printed in buffer so results can be truncated later. */
666
667 if (ptrtyp >= ISMEMBERPTR && ptrtyp <= HASPARTPTR)
668 lastholomero = strlen(searchbuffer);
669
670 if(depth) {
671 depth = depthcheck(depth, cursyn);
672 traceptrs(cursyn, ptrtyp, getpos(cursyn->pos), (depth+1));
673
674 free_synset(cursyn);
675 } else
676 free_synset(cursyn);
677 }
678 }
679 }
680
tracecoords(SynsetPtr synptr,int ptrtyp,int dbase,int depth)681 static void tracecoords(SynsetPtr synptr, int ptrtyp, int dbase, int depth)
682 {
683 int i;
684 SynsetPtr cursyn;
685
686 interface_doevents();
687 if (abortsearch)
688 return;
689
690 for(i = 0; i < synptr->ptrcount; i++) {
691 if((synptr->ptrtyp[i] == HYPERPTR) &&
692 ((synptr->pfrm[i] == 0) ||
693 (synptr->pfrm[i] == synptr->whichword))) {
694
695 if(!prflag) {
696 printsns(synptr, sense + 1);
697 prflag = 1;
698 }
699 printspaces(TRACEC, depth);
700
701 cursyn = read_synset(synptr->ppos[i], synptr->ptroff[i], "");
702
703 printsynset("-> ", cursyn, "\n", DEFON, ALLWORDS,
704 SKIP_ANTS, PRINT_MARKER);
705
706 traceptrs(cursyn, ptrtyp, getpos(cursyn->pos), depth);
707
708 if(depth) {
709 depth = depthcheck(depth, cursyn);
710 tracecoords(cursyn, ptrtyp, getpos(cursyn->pos), (depth+1));
711 free_synset(cursyn);
712 } else
713 free_synset(cursyn);
714 }
715 }
716 }
717
traceclassif(SynsetPtr synptr,int dbase,int search)718 static void traceclassif(SynsetPtr synptr, int dbase, int search)
719 {
720 int i, j, idx;
721 SynsetPtr cursyn;
722 long int prlist[1024];
723 char head[60];
724 int svwnsnsflag;
725
726 interface_doevents();
727 if (abortsearch)
728 return;
729
730 idx = 0;
731
732 for (i = 0; i < synptr->ptrcount; i++) {
733 if (((synptr->ptrtyp[i] >= CLASSIF_START) &&
734 (synptr->ptrtyp[i] <= CLASSIF_END) && search == CLASSIFICATION) ||
735
736 ((synptr->ptrtyp[i] >= CLASS_START) &&
737 (synptr->ptrtyp[i] <= CLASS_END) && search == CLASS) ) {
738
739 if (!prflag) {
740 printsns(synptr, sense + 1);
741 prflag = 1;
742 }
743
744 cursyn = read_synset(synptr->ppos[i], synptr->ptroff[i], "");
745
746 for (j = 0; j < idx; j++) {
747 if (synptr->ptroff[i] == prlist[j]) {
748 break;
749 }
750 }
751
752 if (j == idx) {
753 prlist[idx++] = synptr->ptroff[i];
754 printspaces(TRACEP, 0);
755
756 if (synptr->ptrtyp[i] == CLASSIF_CATEGORY)
757 strcpy(head, "CATEGORY->(");
758 else if (synptr->ptrtyp[i] == CLASSIF_USAGE)
759 strcpy(head, "USAGE->(");
760 else if (synptr->ptrtyp[i] == CLASSIF_REGIONAL)
761 strcpy(head, "REGION->(");
762 else if (synptr->ptrtyp[i] == CLASS_CATEGORY)
763 strcpy(head, "CATEGORY_TERM->(");
764 else if (synptr->ptrtyp[i] == CLASS_USAGE)
765 strcpy(head, "USAGE_TERM->(");
766 else if (synptr->ptrtyp[i] == CLASS_REGIONAL)
767 strcpy(head, "REGION_TERM->(");
768
769 strcat(head, partnames[synptr->ppos[i]]);
770 strcat(head, ") ");
771
772 svwnsnsflag = wnsnsflag;
773 wnsnsflag = 1;
774
775 printsynset(head, cursyn, "\n", DEFOFF, ALLWORDS,
776 SKIP_ANTS, SKIP_MARKER);
777
778 wnsnsflag = svwnsnsflag;
779 }
780
781 free_synset(cursyn);
782 }
783 }
784 }
785
tracenomins(SynsetPtr synptr,int dbase)786 static void tracenomins(SynsetPtr synptr, int dbase)
787 {
788 int i, j, idx;
789 SynsetPtr cursyn;
790 long int prlist[1024];
791 char prefix[40], tbuf[20];
792
793 interface_doevents();
794 if (abortsearch)
795 return;
796
797 idx = 0;
798
799 for (i = 0; i < synptr->ptrcount; i++) {
800 if ((synptr->ptrtyp[i] == DERIVATION) &&
801 (synptr->pfrm[i] == synptr->whichword)) {
802
803 if (!prflag) {
804 printsns(synptr, sense + 1);
805 prflag = 1;
806 }
807
808 printspaces(TRACEP, 0);
809
810 sprintf(prefix, "RELATED TO->(%s) ",
811 partnames[synptr->ppos[i]]);
812
813 cursyn = read_synset(synptr->ppos[i], synptr->ptroff[i], "");
814
815 sprintf(tbuf, "#%d\n",
816 cursyn->wnsns[synptr->pto[i] - 1]);
817 printsynset(prefix, cursyn, tbuf, DEFOFF, synptr->pto[i],
818 SKIP_ANTS, SKIP_MARKER);
819
820 /* only print synset once, even if more than one link */
821
822 for (j = 0; j < idx; j++) {
823 #ifdef FOOP
824 if (synptr->ptroff[i] == prlist[j]) {
825 break;
826 }
827 #endif
828 }
829
830 if (j == idx) {
831 prlist[idx++] = synptr->ptroff[i];
832 printspaces(TRACEP, 2);
833 printsynset("=> ", cursyn, "\n", DEFON, ALLWORDS,
834 SKIP_ANTS, PRINT_MARKER);
835 }
836
837 free_synset(cursyn);
838 }
839 }
840 }
841
842 /* Trace through the hypernym tree and print all MEMBER, STUFF
843 and PART info. */
844
traceinherit(SynsetPtr synptr,int ptrbase,int dbase,int depth)845 static void traceinherit(SynsetPtr synptr, int ptrbase, int dbase, int depth)
846 {
847 int i;
848 SynsetPtr cursyn;
849
850 interface_doevents();
851 if (abortsearch)
852 return;
853
854 for(i=0;i<synptr->ptrcount;i++) {
855 if((synptr->ptrtyp[i] == HYPERPTR) &&
856 ((synptr->pfrm[i] == 0) ||
857 (synptr->pfrm[i] == synptr->whichword))) {
858
859 if(!prflag) {
860 printsns(synptr, sense + 1);
861 prflag = 1;
862 }
863 printspaces(TRACEI, depth);
864
865 cursyn = read_synset(synptr->ppos[i], synptr->ptroff[i], "");
866
867 printsynset("=> ", cursyn, "\n", DEFON, ALLWORDS,
868 SKIP_ANTS, PRINT_MARKER);
869
870 traceptrs(cursyn, ptrbase, NOUN, depth);
871 traceptrs(cursyn, ptrbase + 1, NOUN, depth);
872 traceptrs(cursyn, ptrbase + 2, NOUN, depth);
873
874 if(depth) {
875 depth = depthcheck(depth, cursyn);
876 traceinherit(cursyn, ptrbase, getpos(cursyn->pos), (depth+1));
877 free_synset(cursyn);
878 } else
879 free_synset(cursyn);
880 }
881 }
882
883 /* Truncate search buffer after last holo/meronym printed */
884 searchbuffer[lastholomero] = '\0';
885 }
886
partsall(SynsetPtr synptr,int ptrtyp)887 static void partsall(SynsetPtr synptr, int ptrtyp)
888 {
889 int ptrbase;
890 int i, hasptr = 0;
891
892 ptrbase = (ptrtyp == HMERONYM) ? HASMEMBERPTR : ISMEMBERPTR;
893
894 /* First, print out the MEMBER, STUFF, PART info for this synset */
895
896 for (i = 0; i < 3; i++) {
897 if (HasPtr(synptr, ptrbase + i)) {
898 traceptrs(synptr, ptrbase + i, NOUN, 1);
899 hasptr++;
900 }
901 interface_doevents();
902 if (abortsearch)
903 return;
904 }
905
906 /* Print out MEMBER, STUFF, PART info for hypernyms on
907 HMERONYM search only */
908
909 /* if (hasptr && ptrtyp == HMERONYM) { */
910 if (ptrtyp == HMERONYM) {
911 lastholomero = strlen(searchbuffer);
912 traceinherit(synptr, ptrbase, NOUN, 1);
913 }
914 }
915
traceadjant(SynsetPtr synptr)916 static void traceadjant(SynsetPtr synptr)
917 {
918 SynsetPtr newsynptr;
919 int i, j;
920 int anttype = DIRECT_ANT;
921 SynsetPtr simptr, antptr;
922 static char similar[] = " => ";
923
924 /* This search is only applicable for ADJ synsets which have
925 either direct or indirect antonyms (not valid for pertainyms). */
926
927 if (synptr->sstype == DIRECT_ANT || synptr->sstype == INDIRECT_ANT) {
928 printsns(synptr, sense + 1);
929 printbuffer("\n");
930
931 /* if indirect, get cluster head */
932
933 if(synptr->sstype == INDIRECT_ANT) {
934 anttype = INDIRECT_ANT;
935 i = 0;
936 while (synptr->ptrtyp[i] != SIMPTR) i++;
937 newsynptr = read_synset(ADJ, synptr->ptroff[i], "");
938 } else
939 newsynptr = synptr;
940
941 /* find antonyms - if direct, make sure that the antonym
942 ptr we're looking at is from this word */
943
944 for (i = 0; i < newsynptr->ptrcount; i++) {
945
946 if (newsynptr->ptrtyp[i] == ANTPTR &&
947 ((anttype == DIRECT_ANT &&
948 newsynptr->pfrm[i] == newsynptr->whichword) ||
949 (anttype == INDIRECT_ANT))) {
950
951 /* read the antonym's synset and print it. if a
952 direct antonym, print it's satellites. */
953
954 antptr = read_synset(ADJ, newsynptr->ptroff[i], "");
955
956 if (anttype == DIRECT_ANT) {
957 printsynset("", antptr, "\n", DEFON, ALLWORDS,
958 PRINT_ANTS, PRINT_MARKER);
959 for(j = 0; j < antptr->ptrcount; j++) {
960 if(antptr->ptrtyp[j] == SIMPTR) {
961 simptr = read_synset(ADJ, antptr->ptroff[j], "");
962 printsynset(similar, simptr, "\n", DEFON,
963 ALLWORDS, SKIP_ANTS, PRINT_MARKER);
964 free_synset(simptr);
965 }
966 }
967 } else
968 printantsynset(antptr, "\n", anttype, DEFON);
969
970 free_synset(antptr);
971 }
972 }
973 if (newsynptr != synptr)
974 free_synset(newsynptr);
975 }
976 }
977
978
979 /* Fetch the given example sentence from the example file and print it out */
980
getexample(char * offset,char * wd)981 void getexample(char *offset, char *wd)
982 {
983 char *line;
984 char sentbuf[512];
985
986 if (vsentfilefp != NULL) {
987 if (line = bin_search(offset, vsentfilefp)) {
988 while(*line != ' ')
989 line++;
990
991 printbuffer(" EX: ");
992 sprintf(sentbuf, line, wd);
993 printbuffer(sentbuf);
994 }
995 }
996 }
997
998 /* Find the example sentence references in the example sentence index file */
999
findexample(SynsetPtr synptr)1000 int findexample(SynsetPtr synptr)
1001 {
1002 char tbuf[256], *temp, *offset;
1003 int wdnum;
1004 int found = 0;
1005
1006 if (vidxfilefp != NULL) {
1007 wdnum = synptr->whichword - 1;
1008
1009 sprintf(tbuf,"%s%%%-1.1d:%-2.2d:%-2.2d::",
1010 synptr->words[wdnum],
1011 getpos(synptr->pos),
1012 synptr->fnum,
1013 synptr->lexid[wdnum]);
1014
1015 if ((temp = bin_search(tbuf, vidxfilefp)) != NULL) {
1016
1017 /* skip over sense key and get sentence numbers */
1018
1019 temp += strlen(synptr->words[wdnum]) + 11;
1020 strcpy(tbuf, temp);
1021
1022 offset = strtok(tbuf, " ,\n");
1023
1024 while (offset) {
1025 getexample(offset, synptr->words[wdnum]);
1026 offset = strtok(NULL, ",\n");
1027 }
1028 found = 1;
1029 }
1030 }
1031 return(found);
1032 }
1033
printframe(SynsetPtr synptr,int prsynset)1034 static void printframe(SynsetPtr synptr, int prsynset)
1035 {
1036 int i;
1037
1038 if (prsynset)
1039 printsns(synptr, sense + 1);
1040
1041 if (!findexample(synptr)) {
1042 for(i = 0; i < synptr->fcount; i++) {
1043 if ((synptr->frmto[i] == synptr->whichword) ||
1044 (synptr->frmto[i] == 0)) {
1045 if (synptr->frmto[i] == synptr->whichword)
1046 printbuffer(" => ");
1047 else
1048 printbuffer(" *> ");
1049 printbuffer(frametext[synptr->frmid[i]]);
1050 printbuffer("\n");
1051 }
1052 }
1053 }
1054 }
1055
printseealso(SynsetPtr synptr)1056 static void printseealso(SynsetPtr synptr)
1057 {
1058 SynsetPtr cursyn;
1059 int i, first = 1;
1060 int svwnsnsflag;
1061 static char firstline[] = " Also See-> ";
1062 static char otherlines[] = "; ";
1063 char *prefix = firstline;
1064
1065 /* Find all SEEALSO pointers from the searchword and print the
1066 word or synset pointed to. */
1067
1068 for(i = 0; i < synptr->ptrcount; i++) {
1069 if ((synptr->ptrtyp[i] == SEEALSOPTR) &&
1070 ((synptr->pfrm[i] == 0) ||
1071 (synptr->pfrm[i] == synptr->whichword))) {
1072
1073 cursyn = read_synset(synptr->ppos[i], synptr->ptroff[i], "");
1074
1075 svwnsnsflag = wnsnsflag;
1076 wnsnsflag = 1;
1077 printsynset(prefix, cursyn, "", DEFOFF,
1078 synptr->pto[i] == 0 ? ALLWORDS : synptr->pto[i],
1079 SKIP_ANTS, SKIP_MARKER);
1080 wnsnsflag = svwnsnsflag;
1081
1082 free_synset(cursyn);
1083
1084 if (first) {
1085 prefix = otherlines;
1086 first = 0;
1087 }
1088 }
1089 }
1090 if (!first)
1091 printbuffer("\n");
1092 }
1093
freq_word(IndexPtr index)1094 static void freq_word(IndexPtr index)
1095 {
1096 int familiar=0;
1097 int cnt;
1098 static char *a_an[] = {
1099 "", "a noun", "a verb", "an adjective", "an adverb" };
1100 static char *freqcats[] = {
1101 "extremely rare","very rare","rare","uncommon","common",
1102 "familiar","very familiar","extremely familiar"
1103 };
1104
1105 if(index) {
1106 cnt = index->sense_cnt;
1107 if (cnt == 0) familiar = 0;
1108 if (cnt == 1) familiar = 1;
1109 if (cnt == 2) familiar = 2;
1110 if (cnt >= 3 && cnt <= 4) familiar = 3;
1111 if (cnt >= 5 && cnt <= 8) familiar = 4;
1112 if (cnt >= 9 && cnt <= 16) familiar = 5;
1113 if (cnt >= 17 && cnt <= 32) familiar = 6;
1114 if (cnt > 32 ) familiar = 7;
1115
1116 sprintf(tmpbuf,
1117 "\n%s used as %s is %s (polysemy count = %d)\n",
1118 index->wd, a_an[getpos(index->pos)], freqcats[familiar], cnt);
1119 printbuffer(tmpbuf);
1120 }
1121 }
1122
wngrep(char * word_passed,int pos)1123 void wngrep (char *word_passed, int pos) {
1124 FILE *inputfile;
1125 char word[256];
1126 int wordlen, linelen, loc;
1127 char line[1024];
1128 int count = 0;
1129
1130 inputfile = indexfps[pos];
1131 if (inputfile == NULL) {
1132 sprintf (msgbuf, "WordNet library error: Can't perform compounds "
1133 "search because %s index file is not open\n", partnames[pos]);
1134 display_message (msgbuf);
1135 return;
1136 }
1137 rewind(inputfile);
1138
1139 strcpy (word, word_passed);
1140 ToLowerCase(word); /* map to lower case for index file search */
1141 strsubst (word, ' ', '_'); /* replace spaces with underscores */
1142 wordlen = strlen (word);
1143
1144 while (fgets (line, 1024, inputfile) != NULL) {
1145 for (linelen = 0; line[linelen] != ' '; linelen++) {}
1146 if (linelen < wordlen)
1147 continue;
1148 line[linelen] = '\0';
1149 strstr_init (line, word);
1150 while ((loc = strstr_getnext ()) != -1) {
1151 if (
1152 /* at the start of the line */
1153 (loc == 0) ||
1154 /* at the end of the line */
1155 ((linelen - wordlen) == loc) ||
1156 /* as a word in the middle of the line */
1157 (((line[loc - 1] == '-') || (line[loc - 1] == '_')) &&
1158 ((line[loc + wordlen] == '-') || (line[loc + wordlen] == '_')))
1159 ) {
1160 strsubst (line, '_', ' ');
1161 sprintf (tmpbuf, "%s\n", line);
1162 printbuffer (tmpbuf);
1163 break;
1164 }
1165 }
1166 if (count++ % 2000 == 0) {
1167 interface_doevents ();
1168 if (abortsearch) break;
1169 }
1170 }
1171 }
1172
1173 /* Stucture to keep track of 'relative groups'. All senses in a relative
1174 group are displayed together at end of search. Transitivity is
1175 supported, so if either of a new set of related senses is already
1176 in a 'relative group', the other sense is added to that group as well. */
1177
1178 struct relgrp {
1179 int senses[MAXSENSE];
1180 struct relgrp *next;
1181 };
1182 static struct relgrp *rellist;
1183
1184 static struct relgrp *mkrellist(void);
1185
1186 /* Simple hash function */
1187 #define HASHTABSIZE 1223 /* Prime number. Must be > 2*MAXTOPS */
1188 #define hash(n) ((n) % HASHTABSIZE)
1189
1190 #ifdef WN1_6
1191 void trace_hyperptrs(SynsetPtr, void (*)(unsigned long, void *), void *, int);
1192
1193 #define MAXTOPS 300 /* Maximum number of lines in cousin.tops */
1194
1195 static struct {
1196 int topnum; /* Unique id assigned to this top node */
1197 Set_t rels; /* set of top nodes this one is paired with */
1198 unsigned long offset; /* Offset read from cousin.tops file */
1199 } cousintops[HASHTABSIZE];
1200 #endif
1201
1202 /* Find relative groups for all senses of target word in given part
1203 of speech. */
1204
relatives(IndexPtr idx,int dbase)1205 static void relatives(IndexPtr idx, int dbase)
1206 {
1207 rellist = NULL;
1208
1209 switch(dbase) {
1210 case NOUN:
1211 #ifdef WN1_6
1212 /* Don't bother for nouns - doesn't work well */
1213 findsisters(idx);
1214 interface_doevents();
1215 if (abortsearch)
1216 break;
1217 findtwins(idx);
1218 interface_doevents();
1219 if (abortsearch)
1220 break;
1221 findcousins(idx);
1222 interface_doevents();
1223 if (abortsearch)
1224 break;
1225 printrelatives(idx, NOUN);
1226 #endif
1227 break;
1228 case VERB:
1229 findverbgroups(idx);
1230 interface_doevents();
1231 if (abortsearch)
1232 break;
1233 printrelatives(idx, VERB);
1234 break;
1235 default:
1236 break;
1237 }
1238
1239 free_rellist();
1240 }
1241
1242 #ifdef WN1_6
1243
1244 /* Look for 'twins' - synsets with 3 or more words in common. */
1245
word_idx(char * wd,char * wdtable[],int nwords)1246 static int word_idx(char *wd, char *wdtable[], int nwords)
1247 {
1248 for ( ; --nwords >= 0 && strcmp(wd, wdtable[nwords]); )
1249 ;
1250 return nwords;
1251 }
1252
add_word(char * wd,char * wdtable[],int nwords)1253 static int add_word(char *wd, char *wdtable[], int nwords)
1254 {
1255 wdtable[nwords] = strdup(wd);
1256 return nwords;
1257 }
1258
1259 #define MAXWRDS 300
1260
findtwins(IndexPtr idx)1261 static void findtwins(IndexPtr idx)
1262 {
1263 char *words[MAXWRDS];
1264 Set_t s[MAXSENSE], n;
1265 SynsetPtr synset;
1266 int i, j, nwords;
1267
1268 assert(idx);
1269 nwords = 0;
1270 for (i = 0; i < idx->off_cnt; i++) {
1271
1272 synset = read_synset(NOUN, idx->offset[i], "");
1273
1274 s[i] = set_create(MAXWRDS);
1275 if (synset->wcount >= 3)
1276 for (j = 0; j < synset->wcount; j++) {
1277 char buf[256];
1278 int k;
1279 strtolower(strcpy(buf, synset->words[j]));
1280 k = word_idx(buf, words, nwords);
1281 if (k < 0) {
1282 k = add_word(buf, words, nwords);
1283 assert(nwords < MAXWRDS);
1284 nwords++;
1285 }
1286 set_addobj(s[i], k);
1287 }
1288
1289 free_synset(synset);
1290 }
1291
1292 n = set_create(MAXWRDS);
1293 for (i = 0; i < idx->off_cnt; i++)
1294 for (j = i + 1; j < idx->off_cnt; j++)
1295 if (set_intersection(n, s[i], s[j]),
1296 set_nelem(n) >= 3)
1297 add_relatives(NOUN, idx, j, i);
1298
1299 set_destroy(n);
1300 for (i = 0; i < idx->off_cnt; i++)
1301 set_destroy(s[i]);
1302 for (i = 0; i < nwords; i++)
1303 free(words[i]);
1304 }
1305
1306 /* Look for 'sisters' - senses of the search word with a common parent. */
1307
findsisters(IndexPtr idx)1308 static void findsisters(IndexPtr idx)
1309 {
1310 int i, j, id = 0;
1311 SynsetPtr synset;
1312 Set_t syns[MAXSENSE], n;
1313 struct {int id; unsigned long off;} hypers[HASHTABSIZE] = {{0}};
1314
1315 assert(idx);
1316
1317 /*Read all synsets and list all hyperptrs.*/
1318
1319 for (i = 0; i < idx->off_cnt; i++) {
1320 synset = read_synset(NOUN, idx->offset[i], idx->wd);
1321 assert(synset);
1322 syns[i] = set_create(4*MAXSENSE);
1323 assert(syns[i]);
1324
1325 for (j = 0; j < synset->ptrcount; j++)
1326 if (synset->ptrtyp[j] == HYPERPTR) {
1327 int l = hash(synset->ptroff[j]);
1328
1329 for ( ; hypers[l].off != synset->ptroff[j]; l++)
1330 if (hypers[l].off == 0) {
1331 hypers[l].off = synset->ptroff[j];
1332 hypers[l].id = id++;
1333 break;
1334 }
1335 else if (l == HASHTABSIZE - 1) l = -1;
1336
1337 /*Found or inserted it.*/
1338 set_addobj(syns[i], hypers[l].id);
1339 }
1340 free_synset(synset);
1341 }
1342 n = set_create(4*MAXSENSE);
1343 assert(n);
1344
1345 for (i = 0; i < idx->off_cnt; i++)
1346 for (j = i+1; j < idx->off_cnt; j++)
1347 if (set_intersection(n, syns[i], syns[j]),
1348 !set_isempty(n))
1349 add_relatives(NOUN, idx, i, j);
1350
1351 set_destroy(n);
1352 for (i = 0; i < idx->off_cnt; i++)
1353 set_destroy(syns[i]);
1354 }
1355
1356 /* Look for 'cousins' - two senses, each under a different predefined
1357 top node pair. Top node offset pairs are stored in cousin.tops. */
1358
1359 /* Return index of topnode if it exists */
1360
find_topnode(unsigned long offset)1361 static int find_topnode(unsigned long offset)
1362 {
1363 int hashval = hash(offset), i;
1364
1365 for (i = hashval; i < HASHTABSIZE; i++)
1366 if (cousintops[i].offset == offset)
1367 return(i);
1368 for (i = 0; i < hashval; i++)
1369 if (cousintops[i].offset == offset)
1370 return(i);
1371 return(-1); /* not found */
1372 }
1373
1374 /* Return an empty slot for <offset> to be placed in. */
1375
new_topnode(unsigned long offset)1376 static int new_topnode(unsigned long offset)
1377 {
1378 int hashval = hash(offset), i;
1379
1380 for (i = hashval; i < HASHTABSIZE; i++)
1381 if (!cousintops[i].rels)
1382 return(i);
1383 for (i = 0; i < hashval; i++)
1384 if (!cousintops[i].rels)
1385 return(i);
1386 return(-1); /* table is full */
1387 }
1388
add_topnode(int index,int id,Set_t s,unsigned long offset)1389 static void add_topnode(int index, int id, Set_t s, unsigned long offset)
1390 {
1391 if ((index >= 0) && (index < HASHTABSIZE)) {
1392 cousintops[index].rels = s;
1393 cousintops[index].topnum = id;
1394 cousintops[index].offset = offset;
1395 }
1396 }
1397
clear_topnodes()1398 static void clear_topnodes()
1399 {
1400 int i;
1401
1402 for (i = 0; i < HASHTABSIZE; i++)
1403 cousintops[i].offset = 0;
1404 }
1405
1406 /* Read cousin.tops file (one time only) and store in different form. */
1407
read_cousintops(void)1408 static int read_cousintops(void)
1409 {
1410 static char done = 0;
1411 int id = 0;
1412 unsigned long top1, top2;
1413 int tidx1, tidx2;
1414
1415 if (done) return(0);
1416
1417 rewind(cousinfp);
1418 clear_topnodes();
1419
1420 while (fscanf(cousinfp, "%ld %ld\n", &top1, &top2) != EOF) {
1421 if ((tidx1 = find_topnode(top1)) < 0)
1422 if ((tidx1 = new_topnode(top1)) != -1) {
1423 add_topnode(tidx1, id++, set_create(MAXTOPS), top1);
1424 } else {
1425 display_message("WordNet library error: cannot create topnode table for grouped sarches\n");
1426 return(-1);
1427 }
1428
1429 if ((tidx2 = find_topnode(top2)) < 0)
1430 if ((tidx2 = new_topnode(top2)) != -1) {
1431 add_topnode(tidx2, id++, set_create(MAXTOPS), top2);
1432 } else {
1433 display_message("WordNet library error: cannot create topnode table for grouped sarches\n");
1434 return(-1);
1435 }
1436
1437 set_addobj(cousintops[tidx1].rels,
1438 cousintops[tidx2].topnum);
1439 set_addobj(cousintops[tidx2].rels,
1440 cousintops[tidx1].topnum);
1441 }
1442 done = 1;
1443 return(0);
1444 }
1445
1446 /* Record all top nodes found for synset. */
1447
record_topnode(unsigned long hyperptr,void * sets)1448 static void record_topnode(unsigned long hyperptr, void *sets)
1449 {
1450 int i;
1451 assert(sets);
1452
1453 if ((i = find_topnode(hyperptr)) >= 0) {
1454 set_addobj(((Set_t *)sets)[0], cousintops[i].topnum);
1455 set_union(((Set_t *)sets)[1], ((Set_t *)sets)[1], cousintops[i].rels);
1456 }
1457 }
1458
findcousins(IndexPtr idx)1459 static void findcousins(IndexPtr idx)
1460 {
1461 int i, j, nsyns;
1462 SynsetPtr synset;
1463 Set_t n, syns_tops[MAXSENSE][2];
1464
1465 assert(idx);
1466 if (read_cousintops() != 0)
1467 return;
1468
1469 /* First read all the synsets */
1470
1471 for (nsyns = 0; nsyns < idx->off_cnt; nsyns++) { /*why -1 in orig?*/
1472 synset = read_synset(NOUN, idx->offset[nsyns], "");
1473 syns_tops[nsyns][0] = set_create(MAXTOPS);
1474 syns_tops[nsyns][1] = set_create(MAXTOPS);
1475
1476 record_topnode(idx->offset[nsyns], (void *)syns_tops[nsyns]);
1477
1478 trace_hyperptrs(synset,
1479 record_topnode,
1480 syns_tops[nsyns], 1);
1481 free_synset(synset);
1482 }
1483
1484 n = set_create(MAXTOPS);
1485 assert(n);
1486 for (i = 0; i < nsyns; i++)
1487 for (j = i + 1; j < nsyns; j++)
1488 if (set_intersection(n, syns_tops[i][0], syns_tops[j][1]),
1489 !set_isempty(n))
1490 add_relatives(NOUN, idx, i, j);
1491
1492 for (i = 0; i < nsyns; i++) {
1493 set_destroy(syns_tops[i][0]);
1494 set_destroy(syns_tops[i][1]);
1495 }
1496 set_destroy(n);
1497 }
1498 /* Trace through HYPERPTRs up to MAXDEPTH, running `fn()' on each one. */
1499
trace_hyperptrs(SynsetPtr synptr,void (* fn)(unsigned long hyperptr,void * cp),void * cp,int depth)1500 void trace_hyperptrs(SynsetPtr synptr,
1501 void (*fn)(unsigned long hyperptr, void *cp),
1502 void *cp, int depth)
1503 {
1504 SynsetPtr s;
1505 int i;
1506
1507 if (depth >= MAXDEPTH)
1508 return;
1509 for (i = 0; i < synptr->ptrcount; i++)
1510 if (synptr->ptrtyp[i] == HYPERPTR) {
1511 fn(synptr->ptroff[i], cp);
1512
1513 s = read_synset(synptr->ppos[i], synptr->ptroff[i], "");
1514 trace_hyperptrs(s, fn, cp, depth+1);
1515 free_synset(s);
1516 }
1517 }
1518 #endif
1519
findverbgroups(IndexPtr idx)1520 static void findverbgroups(IndexPtr idx)
1521 {
1522 int i, j, k;
1523 SynsetPtr synset;
1524
1525 assert(idx);
1526
1527 /* Read all senses */
1528
1529 for (i = 0; i < idx->off_cnt; i++) {
1530
1531 synset = read_synset(VERB, idx->offset[i], idx->wd);
1532
1533 /* Look for VERBGROUP ptr(s) for this sense. If found,
1534 create group for senses, or add to existing group. */
1535
1536 for (j = 0; j < synset->ptrcount; j++) {
1537 if (synset->ptrtyp[j] == VERBGROUP) {
1538 /* Need to find sense number for ptr offset */
1539 for (k = 0; k < idx->off_cnt; k++) {
1540 if (synset->ptroff[j] == idx->offset[k]) {
1541 add_relatives(VERB, idx, i, k);
1542 break;
1543 }
1544 }
1545 }
1546 }
1547 free_synset(synset);
1548 }
1549 }
1550
add_relatives(int pos,IndexPtr idx,int rel1,int rel2)1551 static void add_relatives(int pos, IndexPtr idx, int rel1, int rel2)
1552 {
1553 int i;
1554 struct relgrp *rel, *last, *r;
1555
1556 #ifdef WN1_6
1557 /* First make sure that senses are not on the excpetion list */
1558 if (pos == NOUN && groupexc(idx->offset[rel1], idx->offset[rel2]))
1559 return;
1560 #endif
1561
1562 /* If either of the new relatives are already in a relative group,
1563 then add the other to the existing group (transitivity).
1564 Otherwise create a new group and add these 2 senses to it. */
1565
1566 for (rel = rellist; rel; rel = rel->next) {
1567 if (rel->senses[rel1] == 1 || rel->senses[rel2] == 1) {
1568 rel->senses[rel1] = rel->senses[rel2] = 1;
1569
1570 /* If part of another relative group, merge the groups */
1571 for (r = rellist; r; r = r->next) {
1572 if (r != rel &&
1573 (r->senses[rel1] == 1 || r->senses[rel2] == 1)) {
1574 for (i = 0; i < MAXSENSE; i++)
1575 rel->senses[i] |= r->senses[i];
1576 }
1577 }
1578 return;
1579 }
1580 last = rel;
1581 }
1582 rel = mkrellist();
1583 rel->senses[rel1] = rel->senses[rel2] = 1;
1584 if (rellist == NULL)
1585 rellist = rel;
1586 else
1587 last->next = rel;
1588 }
1589
1590 #ifdef WN1_6
groupexc(unsigned long off1,unsigned long off2)1591 static int groupexc(unsigned long off1, unsigned long off2)
1592 {
1593 char buf[9], *p, linebuf[1024];
1594
1595 sprintf(buf, "%8.8lu", (off1 < off2 ? off1 : off2));
1596
1597 if ((p = bin_search(buf, cousinexcfp)) != NULL) {
1598 sprintf(buf, "%8.8lu", (off2 > off1 ? off2 : off1));
1599 strcpy(linebuf, p + 9); /* don't copy key */
1600 linebuf[strlen(linebuf) - 1] = '\0'; /* strip off newline */
1601 p = strtok(linebuf, " ");
1602 while (p && strcmp(p, buf))
1603 p = strtok(NULL, " ");
1604 }
1605 return(p ? 1 : 0);
1606 }
1607 #endif
1608
mkrellist(void)1609 static struct relgrp *mkrellist(void)
1610 {
1611 struct relgrp *rel;
1612 int i;
1613
1614 rel = (struct relgrp *) malloc(sizeof(struct relgrp));
1615 assert(rel);
1616 for (i = 0; i < MAXSENSE; i++)
1617 rel->senses[i] = 0;
1618 rel->next = NULL;
1619 return(rel);
1620 }
1621
free_rellist(void)1622 static void free_rellist(void)
1623 {
1624 struct relgrp *rel, *next;
1625
1626 rel = rellist;
1627 while(rel) {
1628 next = rel->next;
1629 free(rel);
1630 rel = next;
1631 }
1632 }
1633
printrelatives(IndexPtr idx,int dbase)1634 static void printrelatives(IndexPtr idx, int dbase)
1635 {
1636 SynsetPtr synptr;
1637 struct relgrp *rel;
1638 int i, flag;
1639 int outsenses[MAXSENSE];
1640
1641 for (i = 0; i < idx->off_cnt; i++)
1642 outsenses[i] = 0;
1643 prflag = 1;
1644
1645 for (rel = rellist; rel; rel = rel->next) {
1646 flag = 0;
1647 for (i = 0; i < idx->off_cnt; i++) {
1648 if (rel->senses[i] && !outsenses[i]) {
1649 flag = 1;
1650 synptr = read_synset(dbase, idx->offset[i], "");
1651 printsns(synptr, i + 1);
1652 traceptrs(synptr, HYPERPTR, dbase, 0);
1653 outsenses[i] = 1;
1654 free_synset(synptr);
1655 }
1656 }
1657 if (flag)
1658 printbuffer("--------------\n");
1659 }
1660
1661 for (i = 0; i < idx->off_cnt; i++) {
1662 if (!outsenses[i]) {
1663 synptr = read_synset(dbase, idx->offset[i], "");
1664 printsns(synptr, i + 1);
1665 traceptrs(synptr, HYPERPTR, dbase, 0);
1666 printbuffer("--------------\n");
1667 free_synset(synptr);
1668 }
1669 }
1670 }
1671
1672 /*
1673 Search code interfaces to WordNet database
1674
1675 findtheinfo() - print search results and return ptr to output buffer
1676 findtheinfo_ds() - return search results in linked list data structrure
1677 */
1678
findtheinfo(char * searchstr,int dbase,int ptrtyp,int whichsense)1679 char *findtheinfo(char *searchstr, int dbase, int ptrtyp, int whichsense)
1680 {
1681 SynsetPtr cursyn;
1682 IndexPtr idx = NULL;
1683 int depth = 0;
1684 int i, offsetcnt;
1685 char *bufstart;
1686 unsigned long offsets[MAXSENSE];
1687 int skipit;
1688
1689 /* Initializations -
1690 clear output buffer, search results structure, flags */
1691
1692 searchbuffer[0] = '\0';
1693
1694 wnresults.numforms = wnresults.printcnt = 0;
1695 wnresults.searchbuf = searchbuffer;
1696 wnresults.searchds = NULL;
1697
1698 abortsearch = overflag = 0;
1699 for (i = 0; i < MAXSENSE; i++)
1700 offsets[i] = 0;
1701
1702 switch (ptrtyp) {
1703 case OVERVIEW:
1704 WNOverview(searchstr, dbase);
1705 break;
1706 case FREQ:
1707 while ((idx = getindex(searchstr, dbase)) != NULL) {
1708 searchstr = NULL;
1709 wnresults.SenseCount[wnresults.numforms] = idx->off_cnt;
1710 freq_word(idx);
1711 free_index(idx);
1712 wnresults.numforms++;
1713 }
1714 break;
1715 case WNGREP:
1716 wngrep(searchstr, dbase);
1717 break;
1718 case RELATIVES:
1719 case VERBGROUP:
1720 while ((idx = getindex(searchstr, dbase)) != NULL) {
1721 searchstr = NULL;
1722 wnresults.SenseCount[wnresults.numforms] = idx->off_cnt;
1723 relatives(idx, dbase);
1724 free_index(idx);
1725 wnresults.numforms++;
1726 }
1727 break;
1728 default:
1729
1730 /* If negative search type, set flag for recursive search */
1731 if (ptrtyp < 0) {
1732 ptrtyp = -ptrtyp;
1733 depth = 1;
1734 }
1735 bufstart = searchbuffer;
1736 offsetcnt = 0;
1737
1738 /* look at all spellings of word */
1739
1740 while ((idx = getindex(searchstr, dbase)) != NULL) {
1741
1742 searchstr = NULL; /* clear out for next call to getindex() */
1743 wnresults.SenseCount[wnresults.numforms] = idx->off_cnt;
1744 wnresults.OutSenseCount[wnresults.numforms] = 0;
1745
1746 /* Print extra sense msgs if looking at all senses */
1747 if (whichsense == ALLSENSES)
1748 printbuffer(
1749 " \n");
1750
1751 /* Go through all of the searchword's senses in the
1752 database and perform the search requested. */
1753
1754 for (sense = 0; sense < idx->off_cnt; sense++) {
1755
1756 if (whichsense == ALLSENSES || whichsense == sense + 1) {
1757 prflag = 0;
1758
1759 /* Determine if this synset has already been done
1760 with a different spelling. If so, skip it. */
1761 for (i = 0, skipit = 0; i < offsetcnt && !skipit; i++) {
1762 if (offsets[i] == idx->offset[sense])
1763 skipit = 1;
1764 }
1765 if (skipit != 1) {
1766 offsets[offsetcnt++] = idx->offset[sense];
1767 cursyn = read_synset(dbase, idx->offset[sense], idx->wd);
1768 switch(ptrtyp) {
1769 case ANTPTR:
1770 if(dbase == ADJ)
1771 traceadjant(cursyn);
1772 else
1773 traceptrs(cursyn, ANTPTR, dbase, depth);
1774 break;
1775
1776 case COORDS:
1777 tracecoords(cursyn, HYPOPTR, dbase, depth);
1778 break;
1779
1780 case FRAMES:
1781 printframe(cursyn, 1);
1782 break;
1783
1784 case MERONYM:
1785 traceptrs(cursyn, HASMEMBERPTR, dbase, depth);
1786 traceptrs(cursyn, HASSTUFFPTR, dbase, depth);
1787 traceptrs(cursyn, HASPARTPTR, dbase, depth);
1788 break;
1789
1790 case HOLONYM:
1791 traceptrs(cursyn, ISMEMBERPTR, dbase, depth);
1792 traceptrs(cursyn, ISSTUFFPTR, dbase, depth);
1793 traceptrs(cursyn, ISPARTPTR, dbase, depth);
1794 break;
1795
1796 case HMERONYM:
1797 partsall(cursyn, HMERONYM);
1798 break;
1799
1800 case HHOLONYM:
1801 partsall(cursyn, HHOLONYM);
1802 break;
1803
1804 case SEEALSOPTR:
1805 printseealso(cursyn);
1806 break;
1807
1808 #ifdef FOOP
1809 case PPLPTR:
1810 traceptrs(cursyn, ptrtyp, dbase, depth);
1811 traceptrs(cursyn, PPLPTR, dbase, depth);
1812 break;
1813 #endif
1814
1815 case SIMPTR:
1816 case SYNS:
1817 case HYPERPTR:
1818 printsns(cursyn, sense + 1);
1819 prflag = 1;
1820
1821 traceptrs(cursyn, ptrtyp, dbase, depth);
1822
1823 if (dbase == ADJ) {
1824 traceptrs(cursyn, PERTPTR, dbase, depth);
1825 traceptrs(cursyn, PPLPTR, dbase, depth);
1826 } else if (dbase == ADV) {
1827 traceptrs(cursyn, PERTPTR, dbase, depth);
1828 }
1829
1830 if (saflag) /* print SEE ALSO pointers */
1831 printseealso(cursyn);
1832
1833 if (dbase == VERB && frflag)
1834 printframe(cursyn, 0);
1835 break;
1836
1837 case DERIVATION:
1838 tracenomins(cursyn, dbase);
1839 break;
1840
1841 case CLASSIFICATION:
1842 case CLASS:
1843 traceclassif(cursyn, dbase, ptrtyp);
1844 break;
1845
1846 default:
1847 traceptrs(cursyn, ptrtyp, dbase, depth);
1848 break;
1849
1850 } /* end switch */
1851
1852 free_synset(cursyn);
1853
1854 } /* end if (skipit) */
1855
1856 } /* end if (whichsense) */
1857
1858 if (skipit != 1) {
1859 interface_doevents();
1860 if ((whichsense == sense + 1) || abortsearch || overflag)
1861 break; /* break out of loop - we're done */
1862 }
1863
1864 } /* end for (sense) */
1865
1866 /* Done with an index entry - patch in number of senses output */
1867
1868 if (whichsense == ALLSENSES) {
1869 i = wnresults.OutSenseCount[wnresults.numforms];
1870 if (i == idx->off_cnt && i == 1)
1871 sprintf(tmpbuf, "\n1 sense of %s", idx->wd);
1872 else if (i == idx->off_cnt)
1873 sprintf(tmpbuf, "\n%d senses of %s", i, idx->wd);
1874 else if (i > 0) /* printed some senses */
1875 sprintf(tmpbuf, "\n%d of %d senses of %s",
1876 i, idx->off_cnt, idx->wd);
1877
1878 /* Find starting offset in searchbuffer for this index
1879 entry and patch string in. Then update bufstart
1880 to end of searchbuffer for start of next index entry. */
1881
1882 if (i > 0) {
1883 if (wnresults.numforms > 0) {
1884 bufstart[0] = '\n';
1885 bufstart++;
1886 }
1887 strncpy(bufstart, tmpbuf, strlen(tmpbuf));
1888 bufstart = searchbuffer + strlen(searchbuffer);
1889 }
1890 }
1891
1892 free_index(idx);
1893
1894 interface_doevents();
1895 if (overflag || abortsearch)
1896 break; /* break out of while (idx) loop */
1897
1898 wnresults.numforms++;
1899
1900 } /* end while (idx) */
1901
1902 } /* end switch */
1903
1904 interface_doevents();
1905 if (abortsearch)
1906 printbuffer("\nSearch Interrupted...\n");
1907 else if (overflag)
1908 sprintf(searchbuffer,
1909 "Search too large. Narrow search and try again...\n");
1910
1911 /* replace underscores with spaces before returning */
1912
1913 return(strsubst(searchbuffer, '_', ' '));
1914 }
1915
findtheinfo_ds(char * searchstr,int dbase,int ptrtyp,int whichsense)1916 SynsetPtr findtheinfo_ds(char *searchstr, int dbase, int ptrtyp, int whichsense)
1917 {
1918 IndexPtr idx;
1919 SynsetPtr cursyn;
1920 SynsetPtr synlist = NULL, lastsyn = NULL;
1921 int depth = 0;
1922 int newsense = 0;
1923
1924 wnresults.numforms = 0;
1925 wnresults.printcnt = 0;
1926
1927 while ((idx = getindex(searchstr, dbase)) != NULL) {
1928
1929 searchstr = NULL; /* clear out for next call */
1930 newsense = 1;
1931
1932 if(ptrtyp < 0) {
1933 ptrtyp = -ptrtyp;
1934 depth = 1;
1935 }
1936
1937 wnresults.SenseCount[wnresults.numforms] = idx->off_cnt;
1938 wnresults.OutSenseCount[wnresults.numforms] = 0;
1939 wnresults.searchbuf = NULL;
1940 wnresults.searchds = NULL;
1941
1942 /* Go through all of the searchword's senses in the
1943 database and perform the search requested. */
1944
1945 for(sense = 0; sense < idx->off_cnt; sense++) {
1946 if (whichsense == ALLSENSES || whichsense == sense + 1) {
1947 cursyn = read_synset(dbase, idx->offset[sense], idx->wd);
1948 if (lastsyn) {
1949 if (newsense)
1950 lastsyn->nextform = cursyn;
1951 else
1952 lastsyn->nextss = cursyn;
1953 }
1954 if (!synlist)
1955 synlist = cursyn;
1956 newsense = 0;
1957
1958 cursyn->searchtype = ptrtyp;
1959 cursyn->ptrlist = traceptrs_ds(cursyn, ptrtyp,
1960 getpos(cursyn->pos),
1961 depth);
1962
1963 lastsyn = cursyn;
1964
1965 if (whichsense == sense + 1)
1966 break;
1967 }
1968 }
1969 free_index(idx);
1970 wnresults.numforms++;
1971
1972 if (ptrtyp == COORDS) { /* clean up by removing hypernym */
1973 lastsyn = synlist->ptrlist;
1974 synlist->ptrlist = lastsyn->ptrlist;
1975 free_synset(lastsyn);
1976 }
1977 }
1978 wnresults.searchds = synlist;
1979 return(synlist);
1980 }
1981
1982 /* Recursive search algorithm to trace a pointer tree and return results
1983 in linked list of data structures. */
1984
traceptrs_ds(SynsetPtr synptr,int ptrtyp,int dbase,int depth)1985 SynsetPtr traceptrs_ds(SynsetPtr synptr, int ptrtyp, int dbase, int depth)
1986 {
1987 int i;
1988 SynsetPtr cursyn, synlist = NULL, lastsyn = NULL;
1989 int tstptrtyp, docoords;
1990
1991 /* If synset is a satellite, find the head word of its
1992 head synset and the head word's sense number. */
1993
1994 if (getsstype(synptr->pos) == SATELLITE) {
1995 for (i = 0; i < synptr->ptrcount; i++)
1996 if (synptr->ptrtyp[i] == SIMPTR) {
1997 cursyn = read_synset(synptr->ppos[i],
1998 synptr->ptroff[i],
1999 "");
2000 synptr->headword = malloc(strlen(cursyn->words[0]) + 1);
2001 assert(synptr->headword);
2002 strcpy(synptr->headword, cursyn->words[0]);
2003 synptr->headsense = cursyn->lexid[0];
2004 free_synset(cursyn);
2005 break;
2006 }
2007 }
2008
2009 if (ptrtyp == COORDS) {
2010 tstptrtyp = HYPERPTR;
2011 docoords = 1;
2012 } else {
2013 tstptrtyp = ptrtyp;
2014 docoords = 0;
2015 }
2016
2017 for (i = 0; i < synptr->ptrcount; i++) {
2018 if((synptr->ptrtyp[i] == tstptrtyp) &&
2019 ((synptr->pfrm[i] == 0) ||
2020 (synptr->pfrm[i] == synptr->whichword))) {
2021
2022 cursyn=read_synset(synptr->ppos[i], synptr->ptroff[i], "");
2023 cursyn->searchtype = ptrtyp;
2024
2025 if (lastsyn)
2026 lastsyn->nextss = cursyn;
2027 if (!synlist)
2028 synlist = cursyn;
2029 lastsyn = cursyn;
2030
2031 if(depth) {
2032 depth = depthcheck(depth, cursyn);
2033 cursyn->ptrlist = traceptrs_ds(cursyn, ptrtyp,
2034 getpos(cursyn->pos),
2035 (depth+1));
2036 } else if (docoords) {
2037 cursyn->ptrlist = traceptrs_ds(cursyn, HYPOPTR, NOUN, 0);
2038 }
2039 }
2040 }
2041 return(synlist);
2042 }
2043
WNOverview(char * searchstr,int pos)2044 static void WNOverview(char *searchstr, int pos)
2045 {
2046 SynsetPtr cursyn;
2047 IndexPtr idx = NULL;
2048 char *cpstring = searchstr, *bufstart;
2049 int sense, i, offsetcnt;
2050 int svdflag, skipit;
2051 unsigned long offsets[MAXSENSE];
2052
2053 cpstring = searchstr;
2054 bufstart = searchbuffer;
2055 for (i = 0; i < MAXSENSE; i++)
2056 offsets[i] = 0;
2057 offsetcnt = 0;
2058
2059 while ((idx = getindex(cpstring, pos)) != NULL) {
2060
2061 cpstring = NULL; /* clear for next call to getindex() */
2062 wnresults.SenseCount[wnresults.numforms++] = idx->off_cnt;
2063 wnresults.OutSenseCount[wnresults.numforms] = 0;
2064
2065 printbuffer(
2066 " \n");
2067
2068 /* Print synset for each sense. If requested, precede
2069 synset with synset offset and/or lexical file information.*/
2070
2071 for (sense = 0; sense < idx->off_cnt; sense++) {
2072
2073 for (i = 0, skipit = 0; i < offsetcnt && !skipit; i++)
2074 if (offsets[i] == idx->offset[sense])
2075 skipit = 1;
2076
2077 if (!skipit) {
2078 offsets[offsetcnt++] = idx->offset[sense];
2079 cursyn = read_synset(pos, idx->offset[sense], idx->wd);
2080 if (idx->tagged_cnt != -1 &&
2081 ((sense + 1) <= idx->tagged_cnt)) {
2082 sprintf(tmpbuf, "%d. (%d) ",
2083 sense + 1, GetTagcnt(idx, sense + 1));
2084 } else {
2085 sprintf(tmpbuf, "%d. ", sense + 1);
2086 }
2087
2088 svdflag = dflag;
2089 dflag = 1;
2090 printsynset(tmpbuf, cursyn, "\n", DEFON, ALLWORDS,
2091 SKIP_ANTS, SKIP_MARKER);
2092 dflag = svdflag;
2093 wnresults.OutSenseCount[wnresults.numforms]++;
2094 wnresults.printcnt++;
2095
2096 free_synset(cursyn);
2097 }
2098 }
2099
2100 /* Print sense summary message */
2101
2102 i = wnresults.OutSenseCount[wnresults.numforms];
2103
2104 if (i > 0) {
2105 if (i == 1)
2106 sprintf(tmpbuf, "\nThe %s %s has 1 sense",
2107 partnames[pos], idx->wd);
2108 else
2109 sprintf(tmpbuf, "\nThe %s %s has %d senses",
2110 partnames[pos], idx->wd, i);
2111 if (idx->tagged_cnt > 0)
2112 sprintf(tmpbuf + strlen(tmpbuf),
2113 " (first %d from tagged texts)\n", idx->tagged_cnt);
2114 else if (idx->tagged_cnt == 0)
2115 sprintf(tmpbuf + strlen(tmpbuf),
2116 " (no senses from tagged texts)\n");
2117
2118 strncpy(bufstart, tmpbuf, strlen(tmpbuf));
2119 bufstart = searchbuffer + strlen(searchbuffer);
2120 } else
2121 bufstart[0] = '\0';
2122
2123 wnresults.numforms++;
2124 free_index(idx);
2125 }
2126 }
2127
2128 /* Do requested search on synset passed, returning output in buffer. */
2129
do_trace(SynsetPtr synptr,int ptrtyp,int dbase,int depth)2130 char *do_trace(SynsetPtr synptr, int ptrtyp, int dbase, int depth)
2131 {
2132 searchbuffer[0] = '\0'; /* clear output buffer */
2133 traceptrs(synptr, ptrtyp, dbase, depth);
2134 return(searchbuffer);
2135 }
2136
2137 /* Set bit for each search type that is valid for the search word
2138 passed and return bit mask. */
2139
is_defined(char * searchstr,int dbase)2140 unsigned int is_defined(char *searchstr, int dbase)
2141 {
2142 IndexPtr index;
2143 int i;
2144 unsigned long retval = 0;
2145
2146 wnresults.numforms = wnresults.printcnt = 0;
2147 wnresults.searchbuf = NULL;
2148 wnresults.searchds = NULL;
2149
2150 while ((index = getindex(searchstr, dbase)) != NULL) {
2151 searchstr = NULL; /* clear out for next getindex() call */
2152
2153 wnresults.SenseCount[wnresults.numforms] = index->off_cnt;
2154
2155 /* set bits that must be true for all words */
2156
2157 retval |= bit(SIMPTR) | bit(FREQ) | bit(SYNS)|
2158 bit(WNGREP) | bit(OVERVIEW);
2159
2160 /* go through list of pointer characters and set appropriate bits */
2161
2162 for(i = 0; i < index->ptruse_cnt; i++) {
2163
2164 if (index->ptruse[i] <= LASTTYPE) {
2165 retval |= bit(index->ptruse[i]);
2166 }
2167
2168 #ifdef FOOP
2169
2170 if (index->ptruse[i] >= CLASSIF_START &&
2171 index->ptruse[i] <= CLASSIF_END) {
2172 retval |= bit(CLASSIFICATION);
2173 }
2174
2175
2176 if (index->ptruse[i] >= CLASS_START &&
2177 index->ptruse[i] <= CLASS_END) {
2178 retval |= bit(CLASS);
2179 }
2180 #endif
2181
2182 if (index->ptruse[i] >= ISMEMBERPTR &&
2183 index->ptruse[i] <= ISPARTPTR)
2184 retval |= bit(HOLONYM);
2185 else if (index->ptruse[i] >= HASMEMBERPTR &&
2186 index->ptruse[i] <= HASPARTPTR)
2187 retval |= bit(MERONYM);
2188
2189 if (index->ptruse[i] == SIMPTR) {
2190 retval |= bit(ANTPTR);
2191 }
2192 }
2193
2194 if (dbase == NOUN) {
2195 #ifdef WN1_6
2196 retval |= bit(RELATIVES);
2197 #endif
2198 /* check for inherited holonyms and meronyms */
2199
2200 if (HasHoloMero(index, HMERONYM))
2201 retval |= bit(HMERONYM);
2202 if (HasHoloMero(index, HHOLONYM))
2203 retval |= bit(HHOLONYM);
2204
2205 /* if synset has hypernyms, enable coordinate search */
2206
2207 if (retval & bit(HYPERPTR))
2208 retval |= bit(COORDS);
2209 } else if (dbase == VERB) {
2210
2211 /* if synset has hypernyms, enable coordinate search */
2212 if (retval & bit(HYPERPTR))
2213 retval |= bit(COORDS);
2214
2215 /* enable grouping of related synsets and verb frames */
2216
2217 retval |= bit(RELATIVES) | bit(FRAMES);
2218 }
2219
2220 free_index(index);
2221 wnresults.numforms++;
2222 }
2223 return(retval);
2224 }
2225
2226 /* Determine if any of the synsets that this word is in have inherited
2227 meronyms or holonyms. */
2228
HasHoloMero(IndexPtr index,int ptrtyp)2229 static int HasHoloMero(IndexPtr index, int ptrtyp)
2230 {
2231 int i, j;
2232 SynsetPtr synset, psynset;
2233 int found=0;
2234 int ptrbase;
2235
2236 ptrbase = (ptrtyp == HMERONYM) ? HASMEMBERPTR : ISMEMBERPTR;
2237
2238 for(i = 0; i < index->off_cnt; i++) {
2239 synset = read_synset(NOUN, index->offset[i], "");
2240 for (j = 0; j < synset->ptrcount; j++) {
2241 if (synset->ptrtyp[j] == HYPERPTR) {
2242 psynset = read_synset(NOUN, synset->ptroff[j], "");
2243 found += HasPtr(psynset, ptrbase);
2244 found += HasPtr(psynset, ptrbase + 1);
2245 found += HasPtr(psynset, ptrbase + 2);
2246
2247 free_synset(psynset);
2248 }
2249 }
2250 free_synset(synset);
2251 }
2252 return(found);
2253 }
2254
HasPtr(SynsetPtr synptr,int ptrtyp)2255 static int HasPtr(SynsetPtr synptr, int ptrtyp)
2256 {
2257 int i;
2258
2259 for(i = 0; i < synptr->ptrcount; i++) {
2260 if(synptr->ptrtyp[i] == ptrtyp) {
2261 return(1);
2262 }
2263 }
2264 return(0);
2265 }
2266
2267 /* Set bit for each POS that search word is in. 0 returned if
2268 word is not in WordNet. */
2269
in_wn(char * word,int pos)2270 unsigned int in_wn(char *word, int pos)
2271 {
2272 int i;
2273 unsigned int retval = 0;
2274
2275 if (pos == ALL_POS) {
2276 for (i = 1; i < NUMPARTS + 1; i++)
2277 if (indexfps[i] != NULL && bin_search(word, indexfps[i]) != NULL)
2278 retval |= bit(i);
2279 } else if (indexfps[pos] != NULL && bin_search(word,indexfps[pos]) != NULL)
2280 retval |= bit(pos);
2281 return(retval);
2282 }
2283
depthcheck(int depth,SynsetPtr synptr)2284 static int depthcheck(int depth, SynsetPtr synptr)
2285 {
2286 if(depth >= MAXDEPTH) {
2287 sprintf(msgbuf,
2288 "WordNet library error: Error Cycle detected\n %s\n",
2289 synptr->words[0]);
2290 display_message(msgbuf);
2291 depth = -1; /* reset to get one more trace then quit */
2292 }
2293 return(depth);
2294 }
2295
2296 /* Strip off () enclosed comments from a word */
2297
deadjify(char * word)2298 static char *deadjify(char *word)
2299 {
2300 char *y;
2301
2302 adj_marker = UNKNOWN_MARKER; /* default if not adj or unknown */
2303
2304 y=word;
2305 while(*y) {
2306 if(*y == '(') {
2307 if (!strncmp(y, "(a)", 3))
2308 adj_marker = ATTRIBUTIVE;
2309 else if (!strncmp(y, "(ip)", 4))
2310 adj_marker = IMMED_POSTNOMINAL;
2311 else if (!strncmp(y, "(p)", 3))
2312 adj_marker = PREDICATIVE;
2313 *y='\0';
2314 } else
2315 y++;
2316 }
2317 return(word);
2318 }
2319
getsearchsense(SynsetPtr synptr,int whichword)2320 static int getsearchsense(SynsetPtr synptr, int whichword)
2321 {
2322 IndexPtr idx;
2323 int i;
2324
2325 strsubst(strcpy(wdbuf, synptr->words[whichword - 1]), ' ', '_');
2326 strtolower(wdbuf);
2327
2328 if (idx = index_lookup(wdbuf, getpos(synptr->pos))) {
2329 for (i = 0; i < idx->off_cnt; i++)
2330 if (idx->offset[i] == synptr->hereiam) {
2331 free_index(idx);
2332 return(i + 1);
2333 }
2334 free_index(idx);
2335 }
2336 return(0);
2337 }
2338
printsynset(char * head,SynsetPtr synptr,char * tail,int definition,int wdnum,int antflag,int markerflag)2339 static void printsynset(char *head, SynsetPtr synptr, char *tail, int definition, int wdnum, int antflag, int markerflag)
2340 {
2341 int i, wdcnt;
2342 char tbuf[SMLINEBUF];
2343
2344 tbuf[0] = '\0'; /* clear working buffer */
2345
2346 strcat(tbuf, head); /* print head */
2347
2348 /* Precede synset with additional information as indiecated
2349 by flags */
2350
2351 if (offsetflag) /* print synset offset */
2352 sprintf(tbuf + strlen(tbuf),"{%8.8d} ", synptr->hereiam);
2353 if (fileinfoflag) { /* print lexicographer file information */
2354 sprintf(tbuf + strlen(tbuf), "<%s> ", lexfiles[synptr->fnum]);
2355 prlexid = 1; /* print lexicographer id after word */
2356 } else
2357 prlexid = 0;
2358
2359 if (wdnum) /* print only specific word asked for */
2360 catword(tbuf, synptr, wdnum - 1, markerflag, antflag);
2361 else /* print all words in synset */
2362 for(i = 0, wdcnt = synptr->wcount; i < wdcnt; i++) {
2363 catword(tbuf, synptr, i, markerflag, antflag);
2364 if (i < wdcnt - 1)
2365 strcat(tbuf, ", ");
2366 }
2367
2368 if(definition && dflag && synptr->defn) {
2369 strcat(tbuf," -- ");
2370 strcat(tbuf,synptr->defn);
2371 }
2372
2373 strcat(tbuf,tail);
2374 printbuffer(tbuf);
2375 }
2376
printantsynset(SynsetPtr synptr,char * tail,int anttype,int definition)2377 static void printantsynset(SynsetPtr synptr, char *tail, int anttype, int definition)
2378 {
2379 int i, wdcnt;
2380 char tbuf[SMLINEBUF];
2381 char *str;
2382 int first = 1;
2383
2384 tbuf[0] = '\0';
2385
2386 if (offsetflag)
2387 sprintf(tbuf,"{%8.8d} ", synptr->hereiam);
2388 if (fileinfoflag) {
2389 sprintf(tbuf + strlen(tbuf),"<%s> ", lexfiles[synptr->fnum]);
2390 prlexid = 1;
2391 } else
2392 prlexid = 0;
2393
2394 /* print anotnyms from cluster head (of indirect ant) */
2395
2396 strcat(tbuf, "INDIRECT (VIA ");
2397 for(i = 0, wdcnt = synptr->wcount; i < wdcnt; i++) {
2398 if (first) {
2399 str = printant(ADJ, synptr, i + 1, "%s", ", ");
2400 first = 0;
2401 } else
2402 str = printant(ADJ, synptr, i + 1, ", %s", ", ");
2403 if (*str)
2404 strcat(tbuf, str);
2405 }
2406 strcat(tbuf, ") -> ");
2407
2408 /* now print synonyms from cluster head (of indirect ant) */
2409
2410 for (i = 0, wdcnt = synptr->wcount; i < wdcnt; i++) {
2411 catword(tbuf, synptr, i, SKIP_MARKER, SKIP_ANTS);
2412 if (i < wdcnt - 1)
2413 strcat(tbuf, ", ");
2414 }
2415
2416 if(dflag && synptr->defn && definition) {
2417 strcat(tbuf," -- ");
2418 strcat(tbuf,synptr->defn);
2419 }
2420
2421 strcat(tbuf,tail);
2422 printbuffer(tbuf);
2423 }
2424
catword(char * buf,SynsetPtr synptr,int wdnum,int adjmarker,int antflag)2425 static void catword(char *buf, SynsetPtr synptr, int wdnum, int adjmarker, int antflag)
2426 {
2427 static char vs[] = " (vs. %s)";
2428 static char *markers[] = {
2429 "", /* UNKNOWN_MARKER */
2430 "(predicate)", /* PREDICATIVE */
2431 "(prenominal)", /* ATTRIBUTIVE */
2432 "(postnominal)", /* IMMED_POSTNOMINAL */
2433 };
2434
2435 /* Copy the word (since deadjify() changes original string),
2436 deadjify() the copy and append to buffer */
2437
2438 strcpy(wdbuf, synptr->words[wdnum]);
2439 strcat(buf, deadjify(wdbuf));
2440
2441 /* Print additional lexicographer information and WordNet sense
2442 number as indicated by flags */
2443
2444 if (prlexid && (synptr->lexid[wdnum] != 0))
2445 sprintf(buf + strlen(buf), "%d", synptr->lexid[wdnum]);
2446 if (wnsnsflag)
2447 sprintf(buf + strlen(buf), "#%d", synptr->wnsns[wdnum]);
2448
2449 /* For adjectives, append adjective marker if present, and
2450 print antonym if flag is passed */
2451
2452 if (getpos(synptr->pos) == ADJ) {
2453 if (adjmarker == PRINT_MARKER)
2454 strcat(buf, markers[adj_marker]);
2455 if (antflag == PRINT_ANTS)
2456 strcat(buf, printant(ADJ, synptr, wdnum + 1, vs, ""));
2457 }
2458 }
2459
printant(int dbase,SynsetPtr synptr,int wdnum,char * template,char * tail)2460 static char *printant(int dbase, SynsetPtr synptr, int wdnum, char *template, char *tail)
2461 {
2462 int i, j, wdoff;
2463 SynsetPtr psynptr;
2464 char tbuf[WORDBUF];
2465 static char retbuf[SMLINEBUF];
2466 int first = 1;
2467
2468 retbuf[0] = '\0';
2469
2470 /* Go through all the pointers looking for anotnyms from the word
2471 indicated by wdnum. When found, print all the antonym's
2472 antonym pointers which point back to wdnum. */
2473
2474 for (i = 0; i < synptr->ptrcount; i++) {
2475 if (synptr->ptrtyp[i] == ANTPTR && synptr->pfrm[i] == wdnum) {
2476
2477 psynptr = read_synset(dbase, synptr->ptroff[i], "");
2478
2479 for (j = 0; j < psynptr->ptrcount; j++) {
2480 if (psynptr->ptrtyp[j] == ANTPTR &&
2481 psynptr->pto[j] == wdnum &&
2482 psynptr->ptroff[j] == synptr->hereiam) {
2483
2484 wdoff = (psynptr->pfrm[j] ? (psynptr->pfrm[j] - 1) : 0);
2485
2486 /* Construct buffer containing formatted antonym,
2487 then add it onto end of return buffer */
2488
2489 strcpy(wdbuf, psynptr->words[wdoff]);
2490 strcpy(tbuf, deadjify(wdbuf));
2491
2492 /* Print additional lexicographer information and
2493 WordNet sense number as indicated by flags */
2494
2495 if (prlexid && (psynptr->lexid[wdoff] != 0))
2496 sprintf(tbuf + strlen(tbuf), "%d",
2497 psynptr->lexid[wdoff]);
2498 if (wnsnsflag)
2499 sprintf(tbuf + strlen(tbuf), "#%d",
2500 psynptr->wnsns[wdoff]);
2501 if (!first)
2502 strcat(retbuf, tail);
2503 else
2504 first = 0;
2505 sprintf(retbuf + strlen(retbuf), template, tbuf);
2506 }
2507 }
2508 free_synset(psynptr);
2509 }
2510 }
2511 return(retbuf);
2512 }
2513
printbuffer(char * string)2514 static void printbuffer(char *string)
2515 {
2516 if (overflag)
2517 return;
2518 if (strlen(searchbuffer) + strlen(string) >= SEARCHBUF)
2519 overflag = 1;
2520 else
2521 strcat(searchbuffer, string);
2522 }
2523
printsns(SynsetPtr synptr,int sense)2524 static void printsns(SynsetPtr synptr, int sense)
2525 {
2526 printsense(synptr, sense);
2527 printsynset("", synptr, "\n", DEFON, ALLWORDS, PRINT_ANTS, PRINT_MARKER);
2528 }
2529
printsense(SynsetPtr synptr,int sense)2530 static void printsense(SynsetPtr synptr, int sense)
2531 {
2532 char tbuf[256];
2533
2534 /* Append lexicographer filename after Sense # if flag is set. */
2535
2536 if (fnflag)
2537 sprintf(tbuf,"\nSense %d in file \"%s\"\n",
2538 sense, lexfiles[synptr->fnum]);
2539 else
2540 sprintf(tbuf,"\nSense %d\n", sense);
2541
2542 printbuffer(tbuf);
2543
2544 /* update counters */
2545 wnresults.OutSenseCount[wnresults.numforms]++;
2546 wnresults.printcnt++;
2547 }
2548
printspaces(int trace,int depth)2549 static void printspaces(int trace, int depth)
2550 {
2551 int j;
2552
2553 for (j = 0; j < depth; j++)
2554 printbuffer(" ");
2555
2556 switch(trace) {
2557 case TRACEP: /* traceptrs(), tracenomins() */
2558 if (depth)
2559 printbuffer(" ");
2560 else
2561 printbuffer(" ");
2562 break;
2563
2564 case TRACEC: /* tracecoords() */
2565 if (!depth)
2566 printbuffer(" ");
2567 break;
2568
2569 case TRACEI: /* traceinherit() */
2570 if (!depth)
2571 printbuffer("\n ");
2572 break;
2573 }
2574 }
2575
2576 /* Dummy function to force Tcl/Tk to look at event queue to see of
2577 the user wants to stop the search. */
2578
interface_doevents(void)2579 static void interface_doevents (void) {
2580 if (interface_doevents_func != NULL) interface_doevents_func ();
2581 }
2582
2583 /*
2584 Revision log: (since version 1.5)
2585
2586 $Log: search.c,v $
2587 Revision 1.161 2003/06/23 15:52:27 wn
2588 cleaned up format of nomin output
2589
2590 Revision 1.160 2003/06/05 15:29:45 wn
2591 added pos and sense number for domains
2592
2593 Revision 1.159 2003/04/15 13:54:16 wn
2594 *** empty log message ***
2595
2596 Revision 1.158 2003/03/20 19:31:36 wn
2597 removed NOMIN_START/NOMIN_END range and replaced with DERIVATION
2598
2599 Revision 1.157 2003/02/06 19:01:36 wn
2600 added code to print out word pointed to in derivational links.
2601
2602 Revision 1.156 2003/02/06 18:03:30 wn
2603 work on classifications
2604
2605 Revision 1.155 2002/10/29 15:46:27 wn
2606 added CLASSIFICATION code
2607
2608 Revision 1.154 2002/09/16 15:43:01 wn
2609 allow "grep" string to be in upper case
2610
2611 Revision 1.153 2002/09/16 15:39:16 wn
2612 *** empty log message ***
2613
2614 Revision 1.152 2002/03/22 19:39:15 wn
2615 fill in key field in SynsetPtr if key file found
2616
2617 Revision 1.151 2002/03/07 18:47:52 wn
2618 updates for 1.7.1
2619
2620 Revision 1.150 2001/12/04 17:48:21 wn
2621 added test to tracenomins to only print nominalizations of serach
2622 word and not all words in synset
2623
2624 Revision 1.149 2001/11/27 19:53:24 wn
2625 removed check for version on verb example sentence stuff. only
2626 needed for 1.5
2627
2628 Revision 1.148 2001/11/06 18:51:04 wn
2629 fixed bug in getindex when passed "."
2630 added code to skip classification
2631
2632 Revision 1.147 2001/10/11 18:00:56 wn
2633 fixed bug in free_syns - wasn't freeing synset pointed to by nextform
2634
2635 Revision 1.146 2001/07/27 14:32:41 wn
2636 fixed order of adjective markers
2637
2638 Revision 1.145 2001/06/19 15:01:22 wn
2639 commed out include for setutil.h
2640
2641 Revision 1.144 2001/05/30 16:24:17 wn
2642 changed is_defined to return unsigned int
2643
2644 Revision 1.143 2001/03/30 17:13:00 wn
2645 fixed is_defined - wasn't setting coords for verbs
2646
2647 Revision 1.142 2001/03/29 16:18:03 wn
2648 added newline before output from FREQ search
2649
2650 Revision 1.141 2001/03/29 16:11:39 wn
2651 added code to tractptrs to print direct antonyms nicer
2652
2653 Revision 1.140 2001/03/27 18:47:41 wn
2654 removed tcflag
2655
2656 Revision 1.139 2001/03/27 16:47:44 wn
2657 updated is_defined for holonyms and meronyms
2658
2659 Revision 1.138 2000/08/14 16:04:24 wn
2660 changed 'get_index' to call sub to do work
2661 added code for nominalizations
2662
2663 Revision 1.137 1998/08/11 18:07:11 wn
2664 minor fixes: free synptr space before rreturning if error; remove
2665 useless statement in free_syns
2666
2667 * Revision 1.136 1998/08/07 17:51:32 wn
2668 * added COORDS to traceptrs_ds and findtheinfo_ds
2669 * fixed getsearchsense code to only happen in parse_synset
2670 *
2671 * Revision 1.135 1998/08/07 13:04:24 wn
2672 * *** empty log message ***
2673 *
2674 * Revision 1.134 1997/11/07 16:27:36 wn
2675 * cleanup calls to traceptrs
2676 *
2677 * Revision 1.133 1997/10/16 17:13:08 wn
2678 * fixed bug in add_topnode when index == 0
2679 *
2680 * Revision 1.132 1997/09/05 15:33:18 wn
2681 * change printframes to only print generic frames if specific example not found
2682 *
2683 * Revision 1.131 1997/09/02 16:31:18 wn
2684 * changed includes
2685 *
2686 * Revision 1.130 1997/09/02 14:43:23 wn
2687 * added code to test wnrelease in parse_synset and WNOverview
2688 *
2689 * Revision 1.129 1997/08/29 20:45:25 wn
2690 * added location sanity check on parse_synset
2691 *
2692 * Revision 1.128 1997/08/29 18:35:03 wn
2693 * a bunch of additional cleanups; added code to traceptrs_ds to
2694 * tore wordnet sense number for each word; added wnresults structure;
2695 * terminate holo/mero search at highest level having holo/mero
2696 *
2697 * Revision 1.127 1997/08/28 17:26:46 wn
2698 * Changed "n senses from tagged data" to "n senses from tagged texts"
2699 * in the overview.
2700 *
2701 * Revision 1.126 1997/08/27 13:26:07 wn
2702 * trivial change in wngrep (initialized count to zero)
2703 *
2704 * Revision 1.125 1997/08/26 21:13:14 wn
2705 * Grep now runs quickly because it doesn't call the doevents callback
2706 * after each line of the search.
2707 *
2708 * Revision 1.124 1997/08/26 20:11:23 wn
2709 * massive cleanups to print functions
2710 *
2711 * Revision 1.123 1997/08/26 15:04:18 wn
2712 * I think I got it this time; replaced goto skipit with int skipit flag
2713 * to make compiling easier on the Mac.
2714 *
2715 * Revision 1.122 1997/08/26 14:43:40 wn
2716 * In an effort to avoid compilation errors on the
2717 * Mac caused by the use of a "goto", I had tried to replace it with
2718 * an if block, but had done so improperly. This is the restored version
2719 * from before. Next check-in will have it properly replaced with flags.
2720 *
2721 * Revision 1.121 1997/08/25 15:54:21 wn
2722 * *** empty log message ***
2723 *
2724 * Revision 1.120 1997/08/22 21:06:02 wn
2725 * added code to use wnsnsflag to print wn sense number after each word
2726 *
2727 * Revision 1.119 1997/08/22 20:52:09 wn
2728 * cleaned up findtheinfo and other fns a bit
2729 *
2730 * Revision 1.118 1997/08/21 20:59:20 wn
2731 * grep now uses strstr instead of regexp searches. the old version is
2732 * still there but commented out.
2733 *
2734 * Revision 1.117 1997/08/21 18:41:30 wn
2735 * now eliminates duplicates on search returns, but not yet in overview
2736 *
2737 Revision 1.116 1997/08/13 17:23:45 wn
2738 fixed mac defines
2739
2740 * Revision 1.115 1997/08/08 20:56:33 wn
2741 * now uses built-in grep
2742 *
2743 * Revision 1.114 1997/08/08 19:15:41 wn
2744 * added code to read attest_cnt field in index file.
2745 * made searchbuffer fixed size
2746 * added WNOverview (OVERVIEW) search
2747 * added offsetflag to print synset offset before synset
2748 *
2749 * Revision 1.113 1997/08/05 14:20:29 wn
2750 * changed printbuffer to not realloc space, removed calls to stopsearch()
2751 *
2752 * Revision 1.112 1997/07/25 17:30:03 wn
2753 * various cleanups for release 1.6
2754 *
2755 Revision 1.111 1997/07/11 20:20:04 wn
2756 Added interface_doevents code for making searches interruptable in single-threaded environments.
2757
2758 * Revision 1.110 1997/07/10 19:01:57 wn
2759 * changed evca stuff
2760 *
2761 Revision 1.109 1997/04/22 19:59:08 wn
2762 allow pertainyms to have antonyms
2763
2764 * Revision 1.108 1996/09/17 20:05:01 wn
2765 * cleaned up EVCA code
2766 *
2767 * Revision 1.107 1996/08/16 18:34:13 wn
2768 * fixed minor bug in findcousins
2769 *
2770 * Revision 1.106 1996/07/17 14:02:17 wn
2771 * Added Kohl's verb example sentences. See getexample() and findExample().
2772 *
2773 * Revision 1.105 1996/06/14 18:49:49 wn
2774 * upped size of tmpbuf
2775 *
2776 * Revision 1.104 1996/02/08 16:42:30 wn
2777 * added some newlines to separate output and clear out tmpbuf
2778 * so invalid searches return empty string
2779 *
2780 * Revision 1.103 1995/11/30 14:54:53 wn
2781 * added grouped search for verbs
2782 *
2783 * Revision 1.102 1995/07/19 13:17:38 bagyenda
2784 * *** empty log message ***
2785 *
2786 * Revision 1.101 1995/07/18 19:15:30 wn
2787 * *** empty log message ***
2788 *
2789 * Revision 1.100 1995/07/18 18:56:24 bagyenda
2790 * New implementation of grouped searches --Paul.
2791 *
2792 * Revision 1.99 1995/06/30 19:21:23 wn
2793 * added code to findtheinfo_ds to link additional word forms
2794 * onto synset chain
2795 *
2796 * Revision 1.98 1995/06/12 18:33:51 wn
2797 * Minor change to getindex() -- Paul.
2798 *
2799 * Revision 1.97 1995/06/09 14:46:42 wn
2800 * *** empty log message ***
2801 *
2802 * Revision 1.96 1995/06/09 14:32:49 wn
2803 * changed code for PPLPTR and PERTPTR to print synsets pointed to
2804 *
2805 * Revision 1.95 1995/06/01 15:50:34 wn
2806 * cleanup of code dealing with various hyphenations
2807 *
2808 */
2809