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