1 #include "system.h"
2 #include <stdio.h>
3 #include "popt.h"
4
5 static int _debug = 0;
6 static int _verbose = 1;
7 static const char * dictfn = "/usr/share/dict/words";
8 static poptBits dictbits = NULL;
9 static struct {
10 unsigned total;
11 unsigned hits;
12 unsigned misses;
13 } e;
14
loadDict(const char * fn,poptBits * ap)15 static int loadDict(const char * fn, poptBits * ap)
16 {
17 char b[BUFSIZ];
18 FILE * fp = fopen(fn, "r");
19 char * t, *te;
20 int nlines = -1;
21
22 if (fp == NULL || ferror(fp)) goto exit;
23
24 nlines = 0;
25 while ((t = fgets(b, sizeof(b), fp)) != NULL) {
26 while (*t && isspace(*t)) t++;
27 if (*t == '#') continue;
28 te = t + strlen(t);
29 while (te-- > t && isspace(*te)) *te = '\0';
30 if (*t == '\0') continue;
31 if (ap) {
32 if (_debug)
33 fprintf(stderr, "==> poptSaveBits(%p, \"%s\")\n", *ap, t);
34 (void) poptSaveBits(ap, 0, t);
35 }
36 nlines++;
37 }
38 exit:
39 if (fp) (void) fclose(fp);
40 return nlines;
41 }
42
43 static struct poptOption options[] = {
44 { "debug", 'd', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &_debug, 1,
45 "Set debugging.", NULL },
46 { "verbose", 'v', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &_verbose, 1,
47 "Set verbosity.", NULL },
48
49 POPT_AUTOALIAS
50 POPT_AUTOHELP
51 POPT_TABLEEND
52 };
53
main(int argc,const char ** argv)54 int main(int argc, const char ** argv)
55 {
56 poptContext optCon = NULL;
57 const char ** av = NULL;
58 poptBits avbits = NULL;
59 int ec = 2; /* assume failure */
60 int rc;
61
62 #if defined(HAVE_MCHECK_H) && defined(HAVE_MTRACE)
63 mtrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
64 #endif
65
66 /* XXX Scale the Bloom filters in popt. */
67 if ((rc = loadDict(dictfn, NULL)) <= 0)
68 goto exit;
69 _poptBitsK = 2;
70 _poptBitsM = 0;
71 _poptBitsN = _poptBitsK * (unsigned)rc;
72
73 optCon = poptGetContext("tdict", argc, argv, options, 0);
74
75 /* Read all the options (if any). */
76 while ((rc = poptGetNextOpt(optCon)) > 0) {
77 char * optArg = poptGetOptArg(optCon);
78 if (optArg) free(optArg);
79 switch (rc) {
80 default: goto exit;
81 }
82 }
83 if (rc < -1) {
84 fprintf(stderr, "tdict: %s: %s\n",
85 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
86 poptStrerror(rc));
87 goto exit;
88 }
89
90 if ((rc = loadDict(dictfn, &dictbits)) <= 0)
91 goto exit;
92
93 av = poptGetArgs(optCon);
94 if ((rc = poptBitsArgs(optCon, &avbits)) != 0)
95 goto exit;
96 if (avbits) {
97 poptBits Ibits = NULL;
98 (void) poptBitsUnion(&Ibits, dictbits);
99 rc = poptBitsIntersect(&Ibits, avbits);
100 fprintf(stdout, "===== %s words are in %s\n", (rc ? "Some" : "No"), dictfn);
101 if (Ibits) free(Ibits);
102 }
103 if (av && avbits)
104 while (*av) {
105 rc = poptBitsChk(dictbits, *av);
106 if (rc < 0) goto exit;
107 e.total++;
108 if (rc > 0) {
109 if (_verbose)
110 fprintf(stdout, "%s:\tYES\n", *av);
111 e.hits++;
112 } else {
113 if (_verbose)
114 fprintf(stdout, "%s:\tNO\n", *av);
115 e.misses++;
116 }
117 av++;
118 }
119
120 ec = 0;
121
122 exit:
123 fprintf(stdout, "===== poptBits N:%u M:%u K:%u (%uKb) total(%u) = hits(%u) + misses(%u)\n",
124 _poptBitsN, _poptBitsM, _poptBitsK, (((_poptBitsM/8)+1)+1023)/1024, e.total, e.hits, e.misses);
125 if (avbits) free(avbits);
126 optCon = poptFreeContext(optCon);
127 #if defined(HAVE_MCHECK_H) && defined(HAVE_MTRACE)
128 muntrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
129 #endif
130 return ec;
131 }
132