Optimized free block usage.
[idzebra-moved-to-github.git] / dict / dicttest.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: dicttest.c,v $
7  * Revision 1.21  1996-10-29 14:00:03  adam
8  * Page size given by DICT_DEFAULT_PAGESIZE in dict.h.
9  *
10  * Revision 1.20  1996/03/20 09:35:16  adam
11  * Function dict_lookup_grep got extra parameter, init_pos, which marks
12  * from which position in pattern approximate pattern matching should occur.
13  *
14  * Revision 1.19  1996/02/02  13:43:50  adam
15  * The public functions simply use char instead of Dict_char to represent
16  * search strings. Dict_char is used internally only.
17  *
18  * Revision 1.18  1996/02/01  20:39:52  adam
19  * Bug fix: insert didn't work on 8-bit characters due to unsigned char
20  * compares in dict_strcmp (strcmp) and signed Dict_char. Dict_char is
21  * unsigned now.
22  *
23  * Revision 1.17  1995/12/06  17:48:30  adam
24  * Bug fix: delete didn't work.
25  *
26  * Revision 1.16  1995/10/09  16:18:31  adam
27  * Function dict_lookup_grep got extra client data parameter.
28  *
29  * Revision 1.15  1995/09/04  12:33:31  adam
30  * Various cleanup. YAZ util used instead.
31  *
32  * Revision 1.14  1994/10/04  17:46:55  adam
33  * Function options now returns arg with error option.
34  *
35  * Revision 1.13  1994/10/04  12:08:05  adam
36  * Some bug fixes and some optimizations.
37  *
38  * Revision 1.12  1994/10/03  17:23:03  adam
39  * First version of dictionary lookup with regular expressions and errors.
40  *
41  * Revision 1.11  1994/09/28  13:07:09  adam
42  * Use log_mask_str now.
43  *
44  * Revision 1.10  1994/09/26  10:17:24  adam
45  * Minor changes.
46  *
47  * Revision 1.9  1994/09/22  14:43:56  adam
48  * First functional version of lookup with error correction. A 'range'
49  * specified the maximum number of insertions+deletions+substitutions.
50  *
51  * Revision 1.8  1994/09/22  10:43:44  adam
52  * Two versions of depend. Type 1 is the tail-type compatible with
53  * all make programs. Type 2 is the GNU make with include facility.
54  * Type 2 is default. depend rule chooses current rule.
55  *
56  * Revision 1.7  1994/09/19  16:34:26  adam
57  * Depend rule change. Minor changes in dicttest.c
58  *
59  * Revision 1.6  1994/09/16  15:39:12  adam
60  * Initial code of lookup - not tested yet.
61  *
62  * Revision 1.5  1994/09/06  13:05:14  adam
63  * Further development of insertion. Some special cases are
64  * not properly handled yet! assert(0) are put here. The
65  * binary search in each page definitely reduce usr CPU.
66  *
67  * Revision 1.4  1994/09/01  17:49:37  adam
68  * Removed stupid line. Work on insertion in dictionary. Not finished yet.
69  *
70  * Revision 1.3  1994/09/01  17:44:06  adam
71  * depend include change.
72  *
73  * Revision 1.2  1994/08/18  12:40:54  adam
74  * Some development of dictionary. Not finished at all!
75  *
76  * Revision 1.1  1994/08/16  16:26:47  adam
77  * Added dict.
78  *
79  */
80
81 #include <stdlib.h>
82 #include <string.h>
83 #include <stdio.h>
84 #include <ctype.h>
85
86 #include <dict.h>
87 #include <zebrautl.h>
88
89 char *prog;
90 static Dict dict;
91
92 static int look_hits;
93
94 static int grep_handle (char *name, const char *info, void *client)
95 {
96     look_hits++;
97     printf ("%s\n", name);
98     return 0;
99 }
100
101 int main (int argc, char **argv)
102 {
103     const char *name = NULL;
104     const char *inputfile = NULL;
105     const char *base = NULL;
106     int do_delete = 0;
107     int range = -1;
108     int srange = 0;
109     int rw = 0;
110     int infosize = 4;
111     int cache = 10;
112     int ret;
113     int unique = 0;
114     char *grep_pattern = NULL;
115     char *arg;
116     int no_of_iterations = 0;
117     int no_of_new = 0, no_of_same = 0, no_of_change = 0;
118     int no_of_hits = 0, no_of_misses = 0, no_not_found = 0, no_of_deleted = 0;
119     int max_pos;
120     
121     prog = argv[0];
122     if (argc < 2)
123     {
124         fprintf (stderr, "usage:\n "
125                  " %s [-d] [-r n] [-p n] [-u] [-g pat] [-s n] [-v n] [-i f]"
126                  " [-w] [-c n] base file\n\n",
127                  prog);
128         fprintf (stderr, "  -d      delete instead of insert\n");
129         fprintf (stderr, "  -r n    set regular match range\n");
130         fprintf (stderr, "  -p n    set regular match start range\n");
131         fprintf (stderr, "  -u      report if keys change during insert\n");
132         fprintf (stderr, "  -g p    try pattern n (see -r)\n");
133         fprintf (stderr, "  -s n    set info size to n (instead of 4)\n");
134         fprintf (stderr, "  -v n    set logging level\n");
135         fprintf (stderr, "  -i f    read file with words\n");
136         fprintf (stderr, "  -w      insert/delete instead of lookup\n");
137         fprintf (stderr, "  -c n    cache size (number of pages)\n");
138         exit (1);
139     }
140     while ((ret = options ("dr:p:ug:s:v:i:wc:", argv, argc, &arg)) != -2)
141     {
142         if (ret == 0)
143         {
144             if (!base)
145                 base = arg;
146             else if (!name)
147                 name = arg;
148             else
149             {
150                 logf (LOG_FATAL, "too many files specified\n");
151                 exit (1);
152             }
153         }
154         else if (ret == 'd')
155             do_delete = 1;
156         else if (ret == 'g')
157         {
158             grep_pattern = arg;
159         }
160         else if (ret == 'r')
161         {
162             range = atoi (arg);
163         }
164         else if (ret == 'p')
165         {
166             srange = atoi (arg);
167         }
168         else if (ret == 'u')
169         {
170             unique = 1;
171         }
172         else if (ret == 'c')
173         {
174             cache = atoi(arg);
175             if (cache<2)
176                 cache = 2;
177         }
178         else if (ret == 'w')
179             rw = 1;
180         else if (ret == 'i')
181             inputfile = arg;
182         else if (ret == 's')
183         {
184             infosize = atoi(arg);
185         }
186         else if (ret == 'v')
187         {
188             log_init (log_mask_str(arg), prog, NULL);
189         }
190         else
191         {
192             logf (LOG_FATAL, "Unknown option '-%s'", arg);
193             exit (1);
194         }
195     }
196     if (!base || !name)
197     {
198         logf (LOG_FATAL, "no base and/or dictionary specified");
199         exit (1);
200     }
201     common_resource = res_open (base);
202     if (!common_resource)
203     {
204         logf (LOG_FATAL, "cannot open resource `%s'", base);
205         exit (1);
206     }
207     dict = dict_open (name, cache, rw);
208     if (!dict)
209     {
210         logf (LOG_FATAL, "dict_open fail of `%s'", name);
211         exit (1);
212     }
213     if (inputfile)
214     {
215         FILE *ipf;
216         char ipf_buf[1024];
217         int line = 1;
218         char infobytes[120];
219         memset (infobytes, 0, 120);
220
221         if (!(ipf = fopen(inputfile, "r")))
222         {
223             logf (LOG_FATAL|LOG_ERRNO, "cannot open %s", inputfile);
224             exit (1);
225         }
226         
227         while (fgets (ipf_buf, 1023, ipf))
228         {
229             char *ipf_ptr = ipf_buf;
230             sprintf (infobytes, "%d", line);
231             for (;*ipf_ptr && *ipf_ptr != '\n';ipf_ptr++)
232             {
233                 if (isalpha(*ipf_ptr) || *ipf_ptr == '_')
234                 {
235                     int i = 1;
236                     while (ipf_ptr[i] && (isalnum(ipf_ptr[i]) ||
237                                           ipf_ptr[i] == '_'))
238                         i++;
239                     if (ipf_ptr[i])
240                         ipf_ptr[i++] = '\0';
241                     if (rw)
242                     {
243                         if (do_delete)
244                             switch (dict_delete (dict, ipf_ptr))
245                             {
246                             case 0:
247                                 no_not_found++;
248                                 break;
249                             case 1:
250                                 no_of_deleted++;
251                             }
252                         else
253                             switch(dict_insert (dict, ipf_ptr,
254                                                 infosize, infobytes))
255                             {
256                             case 0:
257                                 no_of_new++;
258                                 break;
259                             case 1:
260                                 no_of_change++;
261                                 if (unique)
262                                     logf (LOG_LOG, "%s change\n", ipf_ptr);
263                                 break;
264                             case 2:
265                                 if (unique)
266                                     logf (LOG_LOG, "%s duplicate\n", ipf_ptr);
267                                 no_of_same++;
268                                 break;
269                             }
270                     }
271                     else if(range < 0)
272                     {
273                         char *cp;
274
275                         cp = dict_lookup (dict, ipf_ptr);
276                         if (cp && *cp)
277                             no_of_hits++;
278                         else
279                             no_of_misses++;
280                     }
281                     else
282                     {
283                         look_hits = 0;
284                         dict_lookup_grep (dict, ipf_ptr, range, NULL,
285                                           &max_pos, srange, grep_handle);
286                         if (look_hits)
287                             no_of_hits++;
288                         else
289                             no_of_misses++;
290                     }
291                     ++no_of_iterations;
292                     ipf_ptr += (i-1);
293                 }
294             }
295             ++line;
296         }
297         fclose (ipf);
298     }
299     if (grep_pattern)
300     {
301         if (range < 0)
302             range = 0;
303         logf (LOG_LOG, "Grepping '%s'", grep_pattern);
304         dict_lookup_grep (dict, grep_pattern, range, NULL, &max_pos,
305                           srange, grep_handle);
306     }
307     if (rw)
308     {
309         logf (LOG_LOG, "Iterations.... %d", no_of_iterations);            
310         if (do_delete)
311         {
312             logf (LOG_LOG, "No of deleted. %d", no_of_deleted);
313             logf (LOG_LOG, "No not found.. %d", no_not_found);
314         }
315         else
316         {
317             logf (LOG_LOG, "No of new..... %d", no_of_new);
318             logf (LOG_LOG, "No of change.. %d", no_of_change);
319         }
320     }
321     else
322     {
323         logf (LOG_LOG, "Lookups....... %d", no_of_iterations);
324         logf (LOG_LOG, "No of hits.... %d", no_of_hits);
325         logf (LOG_LOG, "No of misses.. %d", no_of_misses);
326     }
327     dict_close (dict);
328     res_close (common_resource);
329     return 0;
330 }