1 /*
2 
3   wn.c - Command line interface to WordNet
4 
5 */
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include "wn.h"
11 
12 __FBSDID("$Id: wn.c,v 1.13 2005/01/31 19:19:09 wn Rel $");
13 
14 static struct {
15     const char *option;		/* user's search request */
16     int search;			/* search to pass findtheinfo() */
17     int pos;			/* part-of-speech to pass findtheinfo() */
18     int helpmsgidx;		/* index into help message table */
19     const char *label;		/* text for search header message */
20 } *optptr, optlist[] = {
21     { "-synsa", SIMPTR,	ADJ, 0, "Similarity" },
22     { "-antsa", ANTPTR,	ADJ, 1, "Antonyms" },
23     { "-perta", PERTPTR, ADJ, 0, "Pertainyms" },
24     { "-attra", ATTRIBUTE, ADJ, 2, "Attributes" },
25     { "-domna", CLASSIFICATION, ADJ, 3, "Domain" },
26     { "-domta", CLASS, ADJ, 4, "Domain Terms" },
27     { "-famla", FREQ, ADJ, 5, "Familiarity" },
28     { "-grepa", WNGREP, ADJ, 6, "Grep" },
29 
30     { "-synsn", HYPERPTR, NOUN, 0, "Synonyms/Hypernyms (Ordered by Estimated Frequency)" },
31     { "-antsn", ANTPTR,	NOUN, 2, "Antonyms" },
32     { "-coorn", COORDS, NOUN, 3, "Coordinate Terms (sisters)" },
33     { "-hypen", -HYPERPTR, NOUN, 4, "Synonyms/Hypernyms (Ordered by Estimated Frequency)" },
34     { "-hypon", HYPOPTR, NOUN, 5, "Hyponyms" },
35     { "-treen", -HYPOPTR, NOUN, 6, "Hyponyms" },
36     { "-holon", HOLONYM, NOUN, 7, "Holonyms" },
37     { "-sprtn", ISPARTPTR, NOUN, 7, "Part Holonyms" },
38     { "-smemn", ISMEMBERPTR, NOUN, 7, "Member Holonyms" },
39     { "-ssubn", ISSTUFFPTR, NOUN, 7, "Substance Holonyms" },
40     { "-hholn",	-HHOLONYM, NOUN, 8, "Holonyms" },
41     { "-meron", MERONYM, NOUN, 9, "Meronyms" },
42     { "-subsn", HASSTUFFPTR, NOUN, 9, "Substance Meronyms" },
43     { "-partn", HASPARTPTR, NOUN, 9, "Part Meronyms" },
44     { "-membn", HASMEMBERPTR, NOUN, 9, "Member Meronyms" },
45     { "-hmern", -HMERONYM, NOUN, 10, "Meronyms" },
46     { "-nomnn", DERIVATION, NOUN, 11, "Derived Forms" },
47     { "-derin", DERIVATION, NOUN, 11, "Derived Forms" },
48     { "-domnn", CLASSIFICATION, NOUN, 13, "Domain" },
49     { "-domtn", CLASS, NOUN, 14, "Domain Terms" },
50     { "-attrn", ATTRIBUTE, NOUN, 12, "Attributes" },
51     { "-famln", FREQ, NOUN, 15, "Familiarity" },
52     { "-grepn", WNGREP, NOUN, 16, "Grep" },
53 
54     { "-synsv", HYPERPTR, VERB, 0, "Synonyms/Hypernyms (Ordered by Estimated Frequency)" },
55     { "-simsv", RELATIVES, VERB, 1, "Synonyms (Grouped by Similarity of Meaning)" },
56     { "-antsv", ANTPTR, VERB, 2, "Antonyms" },
57     { "-coorv", COORDS, VERB, 3, "Coordinate Terms (sisters)" },
58     { "-hypev", -HYPERPTR, VERB, 4, "Synonyms/Hypernyms (Ordered by Estimated Frequency)" },
59     { "-hypov", HYPOPTR, VERB, 5, "Troponyms (hyponyms)" },
60     { "-treev", -HYPOPTR, VERB, 5, "Troponyms (hyponyms)" },
61     { "-tropv", -HYPOPTR, VERB, 5, "Troponyms (hyponyms)" },
62     { "-entav", ENTAILPTR, VERB, 6, "Entailment" },
63     { "-causv", CAUSETO, VERB, 7, "\'Cause To\'" },
64     { "-nomnv", DERIVATION, VERB, 8, "Derived Forms" },
65     { "-deriv", DERIVATION, VERB, 8, "Derived Forms" },
66     { "-domnv", CLASSIFICATION, VERB, 10, "Domain" },
67     { "-domtv", CLASS, VERB, 11, "Domain Terms" },
68     { "-framv", FRAMES, VERB, 9, "Sample Sentences" },
69     { "-famlv", FREQ, VERB, 12, "Familiarity" },
70     { "-grepv", WNGREP, VERB, 13, "Grep" },
71 
72     { "-synsr", SYNS, ADV, 0, "Synonyms" },
73     { "-antsr", ANTPTR, ADV, 1, "Antonyms" },
74     { "-pertr", PERTPTR, ADV, 0, "Pertainyms" },
75     { "-domnr", CLASSIFICATION, ADV, 2, "Domain" },
76     { "-domtr", CLASS, ADV, 3, "Domain Terms" },
77     { "-famlr", FREQ, ADV, 4, "Familiarity" },
78     { "-grepr", WNGREP, ADV, 5, "Grep" },
79 
80     { "-over", OVERVIEW, ALL_POS, -1, "Overview" },
81     { NULL, 0, 0, 0, NULL }
82 };
83 
84 struct {
85     const char *template;		/* template for generic search message */
86     const char *option;		/* text for help message */
87     const char *helpstr;
88 } searchstr[] = {		/* index by search type type */
89     { NULL, NULL, NULL },
90     { "-ants%c",	"-ants{n|v|a|r}",	"\t\tAntonyms", },
91     { "-hype%c",	"-hype{n|v}",	"\t\tHypernyms", },
92     { "-hypo%c, -tree%c",	"-hypo{n|v}, -tree{n|v}",
93 	  "\tHyponyms & Hyponym Tree", },
94     { "-enta%c",	"-entav\t",	"\t\tVerb Entailment", },
95     { "-syns%c",	"-syns{n|v|a|r}",	"\t\tSynonyms (ordered by estimated frequency)", },
96     { "-smem%c",	"-smemn\t",	"\t\tMember of Holonyms", },
97     { "-ssub%c",	"-ssubn\t",	"\t\tSubstance of Holonyms", },
98     { "-sprt%c",	"-sprtn\t",	"\t\tPart of Holonyms", },
99     { "-memb%c",	"-membn\t",	"\t\tHas Member Meronyms", },
100     { "-subs%c",	"-subsn\t",	"\t\tHas Substance Meronyms", },
101     { "-part%c",	"-partn\t",	"\t\tHas Part Meronyms", },
102     { "-mero%c",	"-meron\t",	"\t\tAll Meronyms", },
103     { "-holo%c",	"-holon\t",	"\t\tAll Holonyms", },
104     { "-caus%c",	"-causv\t",	"\t\tCause to", },
105     { NULL, NULL, NULL },	/* PPLPTR - no specific search */
106     { NULL, NULL, NULL },	/* SEEALSOPTR - no specific search */
107     { "-pert%c",	"-pert{a|r}",	"\t\tPertainyms", },
108     { "-attr%c",	"-attr{n|a}",	"\t\tAttributes", },
109     { NULL, NULL, NULL },	/* verb groups - no specific pointer */
110     { "-deri%c",        "-deri{n|v}",   "\t\tDerived Forms",},
111     { "-domn%c", "-domn{n|v|a|r}", "\t\tDomain" },
112     { "-domt%c", "-domt{n|v|a|r}", "\t\tDomain Terms" },
113     { NULL, NULL, NULL },	/* SYNS - taken care of with SIMPTR */
114     { "-faml%c",	"-faml{n|v|a|r}",	"\t\tFamiliarity & Polysemy Count", },
115     { "-fram%c",	"-framv\t",	"\t\tVerb Frames", },
116     { "-coor%c",	"-coor{n|v}",	"\t\tCoordinate Terms (sisters)", },
117     { "-sims%c",	"-simsv\t",	"\t\tSynonyms (grouped by similarity of meaning)", },
118     { "-hmer%c",	"-hmern\t",	"\t\tHierarchical Meronyms", },
119     { "-hhol%c", 	"-hholn\t",	"\t\tHierarchical Holonyms" },
120     { "-grep%c",	"-grep{n|v|a|r}", "\t\tList of Compound Words" },
121     { "-over", "-over\t", "\t\tOverview of Senses" },
122 };
123 
124 static int getoptidx(const char *), cmdopt(const char *);
125 static int searchwn(int, char *[]);
126 static int do_search(char *, int, int, int, const char *);
127 static int do_is_defined(char *);
128 static void printusage(), printlicense(),
129        printsearches(const char *, int, unsigned long);
130 static int error_message(const char *);
131 
132 int
main(int argc,char * argv[])133 main(int argc,char *argv[])
134 {
135     display_message = error_message;
136 
137     if (argc < 2) {
138 	printusage();
139 	exit(-1);
140     } else if (argc == 2 && !strcmp("-l", argv[1])) {
141 	printlicense();
142 	exit(-1);
143     }
144 
145     if (wninit()) {		/* open database */
146 	display_message("wn: Fatal error - cannot open WordNet database\n");
147 	exit (-1);
148     }
149 
150     exit(searchwn(argc, argv));
151 }
152 
searchwn(int ac,char * av[])153 static int searchwn(int ac, char *av[])
154 {
155     int i, j = 1, pos;
156     int whichsense = ALLSENSES, help = 0;
157     int errcount = 0, outsenses = 0;
158     char tmpbuf[256];		/* buffer for constuction error messages */
159 
160     if (ac == 2)		/* print available searches for word */
161 	exit(do_is_defined(av[1]));
162 
163     /* Parse command line options once and set flags */
164 
165     dflag = fileinfoflag = offsetflag = wnsnsflag = 0;
166 
167     for(i = 1; i < ac; i++) {
168 	if(!strcmp("-g",av[i]))
169 	    dflag++;
170 	else if (!strcmp("-h",av[i]))
171 	    help++;
172 	else if (!strcmp("-l", av[i]))
173 	    printlicense();
174 	else if (!strncmp("-n", av[i], 2) && strncmp("-nomn", av[i] ,5))
175 	    whichsense = atoi(av[i] + 2);
176 	else if (!strcmp("-a", av[i]))
177 	    fileinfoflag = 1;
178 	else if (!strcmp("-o", av[i]))
179 	    offsetflag = 1;
180 	else if (!strcmp("-s", av[i]))
181 	    wnsnsflag = 1;
182     }
183 
184     /* Replace spaces with underscores before looking in database */
185 
186     strtolower(strsubst(av[1], ' ', '_'));
187 
188     /* Look at each option in turn.  If it's not a command line option
189        (which was processed earlier), perform the search requested. */
190 
191     while(av[++j]) {
192 	if (!cmdopt(av[j])) {	/* not a command line option */
193 	    if ((i = getoptidx(av[j])) != -1) {
194 		optptr = &optlist[i];
195 
196 		/* print help text before search output */
197 		if (help && optptr->helpmsgidx >= 0)
198 		    printf("%s\n", helptext[optptr->pos][optptr->helpmsgidx]);
199 
200 		if (optptr->pos == ALL_POS)
201 		    for (pos = 1; pos <= NUMPARTS; pos++)
202 			outsenses += do_search(av[1], pos, optptr->search,
203 						whichsense, optptr->label);
204 		else
205 		    outsenses += do_search(av[1], optptr->pos, optptr->search,
206 					    whichsense, optptr->label);
207 	    } else {
208 		sprintf(tmpbuf, "wn: invalid search option: %s\n", av[j]);
209 		display_message(tmpbuf);
210 		errcount++;
211 	    }
212 	}
213     }
214     return(errcount ? -errcount : outsenses);
215 }
216 
217 static int
do_search(char * searchword,int pos,int search,int whichsense,const char * label)218 do_search(char *searchword, int pos, int search, int whichsense,
219     const char *label)
220 {
221     int totsenses = 0;
222     const char *morphword, *outbuf;
223 
224     outbuf = findtheinfo(searchword, pos, search, whichsense);
225     totsenses += wnresults.printcnt;
226     if (strlen(outbuf) > 0)
227 	printf("\n%s of %s %s\n%s",
228 	       label, partnames[pos], searchword, outbuf);
229 
230     if (morphword = morphstr(searchword, pos))
231 	do {
232 	    outbuf = findtheinfo(morphword, pos, search, whichsense);
233 	    totsenses += wnresults.printcnt;
234 	    if (strlen(outbuf) > 0)
235 		printf("\n%s of %s %s\n%s",
236 		       label, partnames[pos], morphword, outbuf);
237 	} while (morphword = morphstr(NULL, pos));
238 
239     return(totsenses);
240 }
241 
do_is_defined(char * searchword)242 static int do_is_defined(char *searchword)
243 {
244     int i, found = 0;
245     unsigned int search;
246     const char *morphword;
247 
248     if (searchword[0] == '-') {
249 	display_message("wn: invalid search word\n");
250 	return(-1);
251     }
252 
253     /* Print all valid searches for word in all parts of speech */
254 
255     strtolower(strsubst(searchword, ' ', '_'));
256 
257     for (i = 1; i <= NUMPARTS; i++) {
258 	if ((search = is_defined(searchword, i)) != 0) {
259 	    printsearches(searchword, i, search);
260 	    found = 1;
261 	} else
262 	    printf("\nNo information available for %s %s\n",
263 		   partnames[i], searchword);
264 
265 	if ((morphword = morphstr(searchword, i)) != NULL)
266 	    do {
267 		if ((search = is_defined(morphword, i)) != 0) {
268 		    printsearches(morphword, i, search);
269 		    found = 1;
270 		} else
271 		    printf("\nNo information available for %s %s\n",
272 			   partnames[i], morphword);
273 	    } while ((morphword = morphstr(NULL, i)) != NULL );
274     }
275     return(found);
276 }
277 
278 static void
printsearches(const char * word,int dbase,unsigned long search)279 printsearches(const char *word, int dbase, unsigned long search)
280 {
281     int j;
282 
283     printf("\nInformation available for %s %s\n", partnames[dbase], word);
284     for (j = 1; j <= MAXSEARCH; j++)
285 	if ((search & bit(j)) && searchstr[j].option) {
286 	    printf("\t");
287 	    printf(searchstr[j].template,
288 		   partchars[dbase], partchars[dbase]);
289 	    puts(searchstr[j].helpstr);
290 	}
291 }
292 
printusage()293 static void printusage()
294 {
295     int i;
296 
297     fprintf(stdout,
298 	    "\nusage: wn word [-hgla] [-n#] -searchtype [-searchtype...]\n");
299     fprintf(stdout, "       wn [-l]\n\n");
300     fprintf(stdout, "\t-h\t\tDisplay help text before search output\n");
301     fprintf(stdout, "\t-g\t\tDisplay gloss\n");
302     fprintf(stdout, "\t-l\t\tDisplay license and copyright notice\n");
303     fprintf(stdout, "\t-a\t\tDisplay lexicographer file information\n");
304     fprintf(stdout, "\t-o\t\tDisplay synset offset\n");
305     fprintf(stdout, "\t-s\t\tDisplay sense numbers in synsets\n");
306     fprintf(stdout, "\t-n#\t\tSearch only sense number #\n");
307     fprintf(stdout,"\nsearchtype is at least one of the following:\n");
308 
309     for (i = 1; i <= OVERVIEW; i++)
310 	if (searchstr[i].option)
311 	    fprintf(stdout, "\t%s%s\n",
312 		    searchstr[i].option, searchstr[i].helpstr);
313 }
314 
printlicense()315 static void printlicense()
316 {
317     printf("WordNet Release %s\n\n%s", wnrelease, license);
318 }
319 
320 static int
cmdopt(const char * str)321 cmdopt(const char *str)
322 {
323 
324     if (!strcmp("-g", str) ||
325 	!strcmp("-h", str) ||
326 	!strcmp("-o", str) ||
327 	!strcmp("-l", str) ||
328 	!strcmp("-a", str) ||
329 	!strcmp("-s", str) ||
330 	(!strncmp("-n", str, 2) && strncmp("-nomn", str,5)))
331 
332 	return (1);
333     else
334 	return(0);
335 }
336 
337 static int
getoptidx(const char * searchtype)338 getoptidx(const char *searchtype)
339 {
340     int i;
341 
342     for (i = 0; optlist[i].option; i++)
343 	if (!strcmp(optlist[i].option, searchtype))
344 	    return(i);
345 
346     return(-1);
347 }
348 
349 static int
error_message(const char * msg)350 error_message(const char *msg)
351 {
352     fputs(msg, stderr);
353     return(0);
354 }
355 
356 /*
357   Revision log: (since version 1.5)
358 
359   $Log: wn.c,v $
360   Revision 1.13  2005/01/31 19:19:09  wn
361   removed include for license.h
362 
363   Revision 1.12  2005/01/27 17:32:37  wn
364   removed wnhelp.h
365 
366   Revision 1.11  2004/10/25 16:34:43  wn
367   removed 1.6 references
368 
369   Revision 1.10  2003/07/15 16:50:53  wn
370   added domain and domain term searches
371 
372   Revision 1.9  2003/07/15 15:53:05  wn
373   updated search numbers
374 
375   Revision 1.8  2002/03/07 17:52:49  wn
376   fixes for 1.7.1
377 
378   Revision 1.7  2001/11/06 18:51:59  wn
379   added CLASSIFICATION placeholders
380 
381   Revision 1.6  2001/10/25 16:56:11  wn
382   changed text on synsnym searches to say 'estimated frequency'
383 
384   Revision 1.5  2001/07/20 18:15:10  wn
385   changed Nominalizations to Derived Forms
386 
387   Revision 1.4  2001/06/19 15:06:17  wn
388   changed search from long to int
389 
390   Revision 1.3  2001/03/30 17:16:05  wn
391   cleanups for 1.7
392 
393   Revision 1.2  2000/10/30 19:06:49  wn
394   added code to handle nominalizations
395 
396   Revision 1.1  1998/05/06 18:22:57  wn
397   Initial revision
398 
399  * Revision 1.58  1997/11/21  19:01:17  wn
400  * added simsv search
401  *
402  * Revision 1.57  1997/09/02  17:10:32  wn
403  * changed includes
404  *
405  * Revision 1.56  1997/08/29  18:43:37  wn
406  * rearranged functions
407  *
408  * Revision 1.55  1997/08/29  16:44:24  wn
409  * added code to exit with total senses printed
410  *
411  * Revision 1.54  1997/08/26  20:29:38  wn
412  * added -s option, reorganized code
413  *
414  * Revision 1.53  1997/08/08  19:19:03  wn
415  * major cleanup
416  *
417  * Revision 1.52  1997/08/05  20:15:31  wn
418  * removed WNDEBUG, cleanups
419  *
420  * Revision 1.51  1995/06/30  19:25:02  wn
421  * access first element of OutSenseCount array
422  *
423   *
424   * Revision 1.1  91/09/17  15:51:09  wn
425   * Initial revision
426   *
427   */
428 
429