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