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