Bug fix (introduced by previous commit).
[idzebra-moved-to-github.git] / util / zebramap.c
1 /*
2  * Copyright (C) 1994-1997, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: zebramap.c,v $
7  * Revision 1.5  1997-11-19 10:22:14  adam
8  * Bug fix (introduced by previous commit).
9  *
10  * Revision 1.4  1997/11/18 10:05:08  adam
11  * Changed character map facility so that admin can specify character
12  * mapping files for each register type, w, p, etc.
13  *
14  * Revision 1.3  1997/11/17 15:35:26  adam
15  * Bug fix. Relation=relevance wasn't observed.
16  *
17  * Revision 1.2  1997/10/31 12:39:30  adam
18  * Changed log message.
19  *
20  * Revision 1.1  1997/10/27 14:33:06  adam
21  * Moved towards generic character mapping depending on "structure"
22  * field in abstract syntax file. Fixed a few memory leaks. Fixed
23  * bug with negative integers when doing searches with relational
24  * operators.
25  *
26  */
27
28 #include <assert.h>
29 #include <ctype.h>
30
31 #include <yaz-util.h>
32 #include <charmap.h>
33 #include <zebramap.h>
34
35 struct zebra_map {
36     int reg_type;
37     int completeness;
38     chrmaptab maptab;
39     const char *maptab_name;
40     struct zebra_map *next;
41 };
42
43 struct zebra_maps {
44     char *tabpath;
45     NMEM nmem;
46     struct zebra_map *map_list;
47     char temp_map_str[2];
48     const char *temp_map_ptr[2];
49 };
50
51 void zebra_maps_close (ZebraMaps zms)
52 {
53     struct zebra_map *zm = zms->map_list;
54     while (zm)
55     {
56         if (zm->maptab)
57             chrmaptab_destroy (zm->maptab);
58         zm = zm->next;
59     }
60     nmem_destroy (zms->nmem);
61     xfree (zms);
62 }
63
64 static void zebra_map_read (ZebraMaps zms, const char *name)
65 {
66     FILE *f;
67     char line[512];
68     char *argv[10];
69     int argc;
70     struct zebra_map **zm = 0;
71
72     if (!(f = yaz_path_fopen(zms->tabpath, name, "r")))
73     {
74         logf(LOG_WARN|LOG_ERRNO, "%s", name);
75         return ;
76     }
77     while ((argc = readconf_line(f, line, 512, argv, 10)))
78     {
79         if (!strcmp (argv[0], "index") && argc == 2)
80         {
81             if (!zm)
82                 zm = &zms->map_list;
83             else
84                 zm = &(*zm)->next;
85             *zm = nmem_malloc (zms->nmem, sizeof(**zm));
86             (*zm)->reg_type = argv[1][0];
87             (*zm)->maptab_name = NULL;
88             (*zm)->maptab = NULL;
89             (*zm)->completeness = 0;
90         }
91         else if (zm && !strcmp (argv[0], "charmap") && argc == 2)
92         {
93             (*zm)->maptab_name = nmem_strdup (zms->nmem, argv[1]);
94         }
95         else if (zm && !strcmp (argv[0], "completeness") && argc == 2)
96         {
97             (*zm)->completeness = atoi (argv[1]);
98         }
99     }
100     if (zm)
101         (*zm)->next = NULL;
102     fclose (f);
103 }
104 static void zms_map_handle (void *p, const char *name, const char *value)
105 {
106     ZebraMaps zms = p;
107     
108     zebra_map_read (zms, value);
109 }
110
111 ZebraMaps zebra_maps_open (const char *tabpath, Res res)
112 {
113     ZebraMaps zms = xmalloc (sizeof(*zms));
114
115     zms->nmem = nmem_create ();
116     zms->tabpath = nmem_strdup (zms->nmem, tabpath);
117     zms->map_list = NULL;
118
119     zms->temp_map_str[0] = '\0';
120     zms->temp_map_str[1] = '\0';
121
122     zms->temp_map_ptr[0] = zms->temp_map_str;
123     zms->temp_map_ptr[1] = NULL;
124     
125     if (!res_trav (res, "index", zms, zms_map_handle))
126         zebra_map_read (zms, "default.idx");
127     return zms;
128 }
129
130 chrmaptab zebra_map_get (ZebraMaps zms, int reg_type)
131 {
132     struct zebra_map *zm;
133     
134     for (zm = zms->map_list; zm; zm = zm->next)
135         if (reg_type == zm->reg_type)
136             break;
137     if (!zm)
138     {
139         logf (LOG_WARN, "Unknown register type: %c", reg_type);
140         return NULL;
141     }
142     if (!zm->maptab)
143     {
144         if (!strcmp (zm->maptab_name, "@"))
145             return NULL;
146         if (!(zm->maptab = chrmaptab_create (zms->tabpath,
147                                              zm->maptab_name, 0)))
148             logf(LOG_WARN, "Failed to read character table %s",
149                  zm->maptab_name);
150         else
151             logf(LOG_DEBUG, "Read character table %s", zm->maptab_name);
152     }
153     return zm->maptab;
154 }
155
156 const char **zebra_maps_input (ZebraMaps zms, int reg_type,
157                                const char **from, int len)
158 {
159     chrmaptab maptab;
160
161     maptab = zebra_map_get (zms, reg_type);
162     if (maptab)
163         return chr_map_input(maptab, from, len);
164     
165     zms->temp_map_str[0] = **from;
166
167     (*from)++;
168     return zms->temp_map_ptr;
169 }
170
171 const char *zebra_maps_output(ZebraMaps zms, int reg_type, const char **from)
172 {
173     chrmaptab maptab;
174     unsigned char i = (unsigned char) **from;
175     static char buf[2] = {0,0};
176
177     maptab = zebra_map_get (zms, reg_type);
178     if (maptab)
179         return chr_map_output (maptab, from, 1);
180     (*from)++;
181     buf[0] = i;
182     return buf;
183 }
184
185
186 /* ------------------------------------ */
187
188 typedef struct {
189     int type;
190     int major;
191     int minor;
192     Z_AttributesPlusTerm *zapt;
193 } AttrType;
194
195 static int attr_find (AttrType *src, oid_value *attributeSetP)
196 {
197     while (src->major < src->zapt->num_attributes)
198     {
199         Z_AttributeElement *element;
200
201         element = src->zapt->attributeList[src->major];
202         if (src->type == *element->attributeType)
203         {
204             switch (element->which) 
205             {
206             case Z_AttributeValue_numeric:
207                 ++(src->major);
208                 if (element->attributeSet && attributeSetP)
209                 {
210                     oident *attrset;
211
212                     attrset = oid_getentbyoid (element->attributeSet);
213                     *attributeSetP = attrset->value;
214                 }
215                 return *element->value.numeric;
216                 break;
217             case Z_AttributeValue_complex:
218                 if (src->minor >= element->value.complex->num_list ||
219                     element->value.complex->list[src->minor]->which !=  
220                     Z_StringOrNumeric_numeric)
221                     break;
222                 ++(src->minor);
223                 if (element->attributeSet && attributeSetP)
224                 {
225                     oident *attrset;
226
227                     attrset = oid_getentbyoid (element->attributeSet);
228                     *attributeSetP = attrset->value;
229                 }
230                 return *element->value.complex->list[src->minor-1]->u.numeric;
231             default:
232                 assert (0);
233             }
234         }
235         ++(src->major);
236     }
237     return -1;
238 }
239
240 static void attr_init (AttrType *src, Z_AttributesPlusTerm *zapt,
241                        int type)
242 {
243     src->zapt = zapt;
244     src->type = type;
245     src->major = 0;
246     src->minor = 0;
247 }
248
249 /* ------------------------------------ */
250
251 int zebra_maps_is_complete (ZebraMaps zms, int reg_type)
252
253     struct zebra_map *zm;
254     
255     for (zm = zms->map_list; zm; zm = zm->next)
256         if (reg_type == zm->reg_type)
257             return zm->completeness;
258     return 0;
259 }
260
261 int zebra_maps_attr (ZebraMaps zms, Z_AttributesPlusTerm *zapt,
262                      int *reg_type, char **search_type, int *complete_flag)
263 {
264     AttrType completeness;
265     AttrType structure;
266     AttrType relation;
267     int completeness_value;
268     int structure_value;
269     int relation_value;
270
271     attr_init (&structure, zapt, 4);
272     attr_init (&completeness, zapt, 6);
273     attr_init (&relation, zapt, 2);
274
275     completeness_value = attr_find (&completeness, NULL);
276     structure_value = attr_find (&structure, NULL);
277     relation_value = attr_find (&relation, NULL);
278
279     if (completeness_value == 2 || completeness_value == 3)
280         *complete_flag = 1;
281     else
282         *complete_flag = 0;
283     *reg_type = 0;
284
285     *search_type = "phrase";
286     if (relation_value == 102)
287         *search_type = "ranked";
288     
289     switch (structure_value)
290     {
291     case -1:
292     case 1:   /* phrase */
293     case 2:   /* word */
294     case 3:   /* key */
295     case 6:   /* word list */
296     case 105: /* free-form-text */
297     case 106: /* document-text */
298     case 108: /* string */ 
299         if (*complete_flag)
300             *reg_type = 'p';
301         else
302             *reg_type = 'w';
303         break;
304     case 107: /* local-number */
305         *search_type = "local";
306         *reg_type = 0;
307     case 109: /* numeric string */
308         *reg_type = 'n';
309         break;
310     case 104: /* urx */
311         *reg_type = 'u';
312         break;
313     default:
314         return -1;
315     }
316     return 0;
317 }