More explain work.
[yaz-moved-to-github.git] / retrieval / d1_espec.c
1 /*
2  * Copyright (c) 1995-1997, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: d1_espec.c,v $
7  * Revision 1.12  1997-10-31 12:20:09  adam
8  * Improved memory debugging for xmalloc/nmem.c. References to NMEM
9  * instead of ODR in n ESPEC-1 handling in source d1_espec.c.
10  * Bug fix: missing fclose in data1_read_espec1.
11  *
12  * Revision 1.11  1997/09/29 13:18:59  adam
13  * Added function, oid_ent_to_oid, to replace the function
14  * oid_getoidbyent, which is not thread safe.
15  *
16  * Revision 1.10  1997/09/29 07:21:10  adam
17  * Added typecast to avoid warnings on MSVC.
18  *
19  * Revision 1.9  1997/09/17 12:10:35  adam
20  * YAZ version 1.4.
21  *
22  * Revision 1.8  1997/09/05 09:50:56  adam
23  * Removed global data1_tabpath - uses data1_get_tabpath() instead.
24  *
25  * Revision 1.7  1997/05/14 06:54:02  adam
26  * C++ support.
27  *
28  * Revision 1.6  1996/07/06 19:58:34  quinn
29  * System headerfiles gathered in yconfig
30  *
31  * Revision 1.5  1996/01/02  08:57:44  quinn
32  * Changed enums in the ASN.1 .h files to #defines. Changed oident.class to oclass
33  *
34  * Revision 1.4  1995/12/05  11:16:10  quinn
35  * Fixed malloc of 0.
36  *
37  * Revision 1.3  1995/11/13  09:27:34  quinn
38  * Fiddling with the variant stuff.
39  *
40  * Revision 1.2  1995/11/01  16:34:56  quinn
41  * Making data1 look for tables in data1_tabpath
42  *
43  * Revision 1.1  1995/11/01  11:56:07  quinn
44  * Added Retrieval (data management) functions en masse.
45  *
46  *
47  */
48
49
50 #include <stdlib.h>
51 #include <assert.h>
52 #include <string.h>
53 #include <ctype.h>
54 #include <odr.h>
55 #include <proto.h>
56 #include <log.h>
57 #include <readconf.h>
58 #include <tpath.h>
59 #include <data1.h>
60
61 static Z_Variant *read_variant(int argc, char **argv, NMEM nmem)
62 {
63     Z_Variant *r = nmem_malloc(nmem, sizeof(*r));
64     oident var1;
65     int i;
66     int oid[OID_SIZE];
67
68     var1.proto = PROTO_Z3950;
69     var1.oclass = CLASS_VARSET;
70     var1.value = VAL_VAR1;
71     r->globalVariantSetId = odr_oiddup_nmem(nmem, oid_ent_to_oid(&var1, oid));
72
73     if (argc)
74         r->triples = nmem_malloc(nmem, sizeof(Z_Triple*) * argc);
75     else
76         r->triples = 0;
77     r->num_triples = argc;
78     for (i = 0; i < argc; i++)
79     {
80         int zclass, type;
81         char value[512];
82         Z_Triple *t;
83
84         if (sscanf(argv[i], "(%d,%d,%[^)])", &zclass, &type, value) < 3)
85         {
86             logf(LOG_WARN, "Syntax error in variant component '%s'",
87                 argv[i]);
88             return 0;
89         }
90         t = r->triples[i] = nmem_malloc(nmem, sizeof(Z_Triple));
91         t->variantSetId = 0;
92         t->zclass = nmem_malloc(nmem, sizeof(int));
93         *t->zclass = zclass;
94         t->type = nmem_malloc(nmem, sizeof(int));
95         *t->type = type;
96         /*
97          * This is wrong.. we gotta look up the correct type for the
98          * variant, I guess... damn this stuff.
99          */
100         if (*value == '@')
101         {
102             t->which = Z_Triple_null;
103             t->value.null = ODR_NULLVAL;
104         }
105         else if (isdigit(*value))
106         {
107             t->which = Z_Triple_integer;
108             t->value.integer = nmem_malloc(nmem, sizeof(*t->value.integer));
109             *t->value.integer = atoi(value);
110         }
111         else
112         {
113             t->which = Z_Triple_internationalString;
114             t->value.internationalString = nmem_malloc(nmem, strlen(value)+1);
115             strcpy(t->value.internationalString, value);
116         }
117     }
118     return r;
119 }
120
121 static Z_Occurrences *read_occurrences(char *occ, NMEM nmem)
122 {
123     Z_Occurrences *op = nmem_malloc(nmem, sizeof(*op));
124     char *p;
125
126     if (!occ)
127     {
128         op->which = Z_Occurrences_values;
129         op->u.values = nmem_malloc(nmem, sizeof(Z_OccurValues));
130         op->u.values->start = nmem_malloc(nmem, sizeof(int));
131         *op->u.values->start = 1;
132         op->u.values->howMany = 0;
133     }
134     else if (!strcmp(occ, "all"))
135     {
136         op->which = Z_Occurrences_all;
137         op->u.all = ODR_NULLVAL;
138     }
139     else if (!strcmp(occ, "last"))
140     {
141         op->which = Z_Occurrences_last;
142         op->u.all = ODR_NULLVAL;
143     }
144     else
145     {
146         Z_OccurValues *ov = nmem_malloc(nmem, sizeof(*ov));
147
148         if (!isdigit(*occ))
149         {
150             logf(LOG_WARN, "Bad occurrences-spec in %s", occ);
151             return 0;
152         }
153         op->which = Z_Occurrences_values;
154         op->u.values = ov;
155         ov->start = nmem_malloc(nmem, sizeof(*ov->start));
156         *ov->start = atoi(occ);
157         if ((p = strchr(occ, '+')))
158         {
159             ov->howMany = nmem_malloc(nmem, sizeof(*ov->howMany));
160             *ov->howMany = atoi(p + 1);
161         }
162         else
163             ov->howMany = 0;
164     }
165     return op;
166 }
167
168
169 static Z_ETagUnit *read_tagunit(char *buf, NMEM nmem)
170 {
171     Z_ETagUnit *u = nmem_malloc(nmem, sizeof(*u));
172     int terms;
173     int type;
174     char value[512], occ[512];
175
176     if (*buf == '*')
177     {
178         u->which = Z_ETagUnit_wildPath;
179         u->u.wildPath = ODR_NULLVAL;
180     }
181     else if (*buf == '?')
182     {
183         u->which = Z_ETagUnit_wildThing;
184         if (buf[1] == ':')
185             u->u.wildThing = read_occurrences(buf+2, nmem);
186         else
187             u->u.wildThing = read_occurrences(0, nmem);
188     }
189     else if ((terms = sscanf(buf, "(%d,%[^)]):%[a-z0-9+]", &type, value,
190         occ)) >= 2)
191     {
192         int numval;
193         Z_SpecificTag *t;
194         char *valp = value;
195         int force_string = 0;
196
197         if (*valp == '\'')
198         {
199             valp++;
200             force_string = 1;
201         }
202         u->which = Z_ETagUnit_specificTag;
203         u->u.specificTag = t = nmem_malloc(nmem, sizeof(*t));
204         t->tagType = nmem_malloc(nmem, sizeof(*t->tagType));
205         *t->tagType = type;
206         t->tagValue = nmem_malloc(nmem, sizeof(*t->tagValue));
207         if (!force_string && (numval = atoi(valp)))
208         {
209             t->tagValue->which = Z_StringOrNumeric_numeric;
210             t->tagValue->u.numeric = nmem_malloc(nmem, sizeof(int));
211             *t->tagValue->u.numeric = numval;
212         }
213         else
214         {
215             t->tagValue->which = Z_StringOrNumeric_string;
216             t->tagValue->u.string = nmem_malloc(nmem, strlen(valp)+1);
217             strcpy(t->tagValue->u.string, valp);
218         }
219         if (terms > 2) /* an occurrences-spec exists */
220             t->occurrences = read_occurrences(occ, nmem);
221         else
222             t->occurrences = 0;
223     }
224     return u;
225 }
226
227 /*
228  * Read an element-set specification from a file.
229  * NOTE: If !o, memory is allocated directly from the heap by nmem_malloc().
230  */
231 Z_Espec1 *data1_read_espec1 (data1_handle dh, const char *file)
232 {
233     FILE *f;
234     NMEM nmem = data1_nmem_get (dh);
235     int argc, size_esn = 0;
236     char *argv[50], line[512];
237     Z_Espec1 *res = nmem_malloc(nmem, sizeof(*res));
238
239     if (!(f = yaz_path_fopen(data1_get_tabpath(dh), file, "r")))
240     {
241         logf(LOG_WARN|LOG_ERRNO, "%s", file);
242         return 0;
243     }
244
245     res->num_elementSetNames = 0;
246     res->elementSetNames = 0;
247     res->defaultVariantSetId = 0;
248     res->defaultVariantRequest = 0;
249     res->defaultTagType = 0;
250     res->num_elements = 0;
251     res->elements = 0;
252
253     while ((argc = readconf_line(f, line, 512, argv, 50)))
254         if (!strcmp(argv[0], "elementsetnames"))
255         {
256             int nnames = argc-1, i;
257
258             if (!nnames)
259             {
260                 logf(LOG_WARN, "%s: Empty elementsetnames directive",
261                     file);
262                 continue;
263             }
264
265             res->elementSetNames = nmem_malloc(nmem, sizeof(char**)*nnames);
266             for (i = 0; i < nnames; i++)
267             {
268                 res->elementSetNames[i] = nmem_malloc(nmem,
269                                                       strlen(argv[i+1])+1);
270                 strcpy(res->elementSetNames[i], argv[i+1]);
271             }
272             res->num_elementSetNames = nnames;
273         }
274         else if (!strcmp(argv[0], "defaultvariantsetid"))
275         {
276             if (argc != 2 || !(res->defaultVariantSetId =
277                 odr_getoidbystr_nmem(nmem, argv[1])))
278             {
279                 logf(LOG_WARN, "%s: Bad defaultvariantsetid directive", file);
280                 continue;
281             }
282         }
283         else if (!strcmp(argv[0], "defaulttagtype"))
284         {
285             if (argc != 2)
286             {
287                 logf(LOG_WARN, "%s: Bad defaulttagtype directive", file);
288                 continue;
289             }
290             res->defaultTagType = nmem_malloc(nmem, sizeof(int));
291             *res->defaultTagType = atoi(argv[1]);
292         }
293         else if (!strcmp(argv[0], "defaultvariantrequest"))
294         {
295             if (!(res->defaultVariantRequest = read_variant(argc-1,
296                                                             argv+1, nmem)))
297             {
298                 logf(LOG_WARN, "%s: Bad defaultvariantrequest", file);
299                 continue;
300             }
301         }
302         else if (!strcmp(argv[0], "simpleelement"))
303         {
304             Z_ElementRequest *er;
305             Z_SimpleElement *se;
306             Z_ETagPath *tp;
307             char *path = argv[1];
308             char *ep;
309             int num, i = 0;
310             
311             if (!res->elements)
312                 res->elements = nmem_malloc(nmem, size_esn = 24*sizeof(er));
313             else if (res->num_elements >= (int) (size_esn/sizeof(er)))
314             {
315                 Z_ElementRequest **oe = res->elements;
316                 size_esn *= 2;
317                 res->elements = nmem_malloc (nmem, size_esn*sizeof(er));
318                 memcpy (res->elements, oe, size_esn/2);
319             }
320             if (argc < 2)
321             {
322                 logf(LOG_WARN, "%s: Empty simpleelement directive", file);
323                 continue;
324             }
325             
326             res->elements[res->num_elements++] = er =
327                 nmem_malloc(nmem, sizeof(*er));
328             er->which = Z_ERequest_simpleElement;
329             er->u.simpleElement = se = nmem_malloc(nmem, sizeof(*se));
330             se->variantRequest = 0;
331             se->path = tp = nmem_malloc(nmem, sizeof(*tp));
332             tp->num_tags = 0;
333             /*
334              * Parse the element selector.
335              */
336             for (num = 1, ep = path; (ep = strchr(ep, '/')); num++, ep++)
337                 ;
338             tp->tags = nmem_malloc(nmem, sizeof(Z_ETagUnit*)*num);
339             
340             for ((ep = strchr(path, '/')) ; path ;
341                  (void)((path = ep) && (ep = strchr(path, '/'))))
342             {
343                 if (ep)
344                     ep++;
345                 
346                 assert(i<num);
347                 tp->tags[tp->num_tags++] = read_tagunit(path, nmem);
348             }
349             
350             if (argc > 2 && !strcmp(argv[2], "variant"))
351                 se->variantRequest= read_variant(argc-3, argv+3, nmem);
352         }
353         else
354         {
355             logf(LOG_WARN, "%s: Unknown directive %s", file, argv[0]);
356             fclose(f);
357             return 0;
358         }
359     fclose (f);
360     return res;
361 }