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