IDZEBRA  2.2.7
d1_espec.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) Index Data
3 
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 
18 */
19 
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdlib.h>
24 #include <assert.h>
25 #include <string.h>
26 #include <ctype.h>
27 
28 #include <yaz/log.h>
29 #include <yaz/odr.h>
30 #include <yaz/proto.h>
31 #include <idzebra/data1.h>
32 #include <yaz/oid_db.h>
33 
34 static Z_Variant *read_variant(int argc, char **argv, NMEM nmem,
35  const char *file, int lineno)
36 {
37  Z_Variant *r = (Z_Variant *)nmem_malloc(nmem, sizeof(*r));
38  int i;
39 
40  r->globalVariantSetId = odr_oiddup_nmem(nmem, yaz_oid_varset_variant_1);
41  if (argc)
42  r->triples = (Z_Triple **)nmem_malloc(nmem, sizeof(Z_Triple*) * argc);
43  else
44  r->triples = 0;
45  r->num_triples = argc;
46  for (i = 0; i < argc; i++)
47  {
48  int zclass, type;
49  char value[512];
50  Z_Triple *t;
51 
52  if (sscanf(argv[i], "(%d,%d,%511[^)])", &zclass, &type, value) < 3)
53  {
54  yaz_log(YLOG_WARN, "%s:%d: Syntax error in variant component '%s'",
55  file, lineno, argv[i]);
56  return 0;
57  }
58  t = r->triples[i] = (Z_Triple *)nmem_malloc(nmem, sizeof(Z_Triple));
59  t->variantSetId = 0;
60  t->zclass = nmem_intdup(nmem, zclass);
61  t->type = nmem_intdup(nmem, type);
62  /*
63  * This is wrong.. we gotta look up the correct type for the
64  * variant, I guess... damn this stuff.
65  */
66  if (*value == '@')
67  {
68  t->which = Z_Triple_null;
69  t->value.null = odr_nullval();
70  }
71  else if (d1_isdigit(*value))
72  {
73  t->which = Z_Triple_integer;
74  t->value.integer = nmem_intdup(nmem, atoi(value));
75  }
76  else
77  {
78  t->which = Z_Triple_internationalString;
79  t->value.internationalString = nmem_strdup(nmem, value);
80  }
81  }
82  return r;
83 }
84 
85 static Z_Occurrences *read_occurrences(char *occ, NMEM nmem,
86  const char *file, int lineno)
87 {
88  Z_Occurrences *op = (Z_Occurrences *)nmem_malloc(nmem, sizeof(*op));
89  char *p;
90 
91  if (!occ)
92  {
93  op->which = Z_Occurrences_values;
94  op->u.values = (Z_OccurValues *)
95  nmem_malloc(nmem, sizeof(Z_OccurValues));
96  op->u.values->start = nmem_intdup(nmem, 1);
97  op->u.values->howMany = 0;
98  }
99  else if (!strcmp(occ, "all"))
100  {
101  op->which = Z_Occurrences_all;
102  op->u.all = odr_nullval();
103  }
104  else if (!strcmp(occ, "last"))
105  {
106  op->which = Z_Occurrences_last;
107  op->u.all = odr_nullval();
108  }
109  else
110  {
111  Z_OccurValues *ov = (Z_OccurValues *)nmem_malloc(nmem, sizeof(*ov));
112 
113  if (!d1_isdigit(*occ))
114  {
115  yaz_log(YLOG_WARN, "%s:%d: Bad occurrences-spec %s",
116  file, lineno, occ);
117  return 0;
118  }
119  op->which = Z_Occurrences_values;
120  op->u.values = ov;
121  ov->start = nmem_intdup(nmem, atoi(occ));
122  if ((p = strchr(occ, '+')))
123  ov->howMany = nmem_intdup(nmem, atoi(p + 1));
124  else
125  ov->howMany = 0;
126  }
127  return op;
128 }
129 
130 
131 static Z_ETagUnit *read_tagunit(char *buf, NMEM nmem,
132  const char *file, int lineno)
133 {
134  Z_ETagUnit *u = (Z_ETagUnit *)nmem_malloc(nmem, sizeof(*u));
135  int terms;
136  int type;
137  char value[512], occ[512];
138 
139  if (*buf == '*')
140  {
141  u->which = Z_ETagUnit_wildPath;
142  u->u.wildPath = odr_nullval();
143  }
144  else if (*buf == '?')
145  {
146  u->which = Z_ETagUnit_wildThing;
147  if (buf[1] == ':')
148  u->u.wildThing = read_occurrences(buf+2, nmem, file, lineno);
149  else
150  u->u.wildThing = read_occurrences(0, nmem, file, lineno);
151  }
152  else if ((terms = sscanf(buf, "(%d,%511[^)]):%511[a-zA-Z0-9+]",
153  &type, value, occ)) >= 2)
154  {
155  int numval;
156  Z_SpecificTag *t;
157  char *valp = value;
158  int force_string = 0;
159 
160  if (*valp == '\'')
161  {
162  valp++;
163  force_string = 1;
164  if (*valp && valp[strlen(valp)-1] == '\'')
165  *valp = '\0';
166  }
167  u->which = Z_ETagUnit_specificTag;
168  u->u.specificTag = t = (Z_SpecificTag *)nmem_malloc(nmem, sizeof(*t));
169  t->tagType = nmem_intdup(nmem, type);
170  t->tagValue = (Z_StringOrNumeric *)
171  nmem_malloc(nmem, sizeof(*t->tagValue));
172  if (!force_string && isdigit(*(unsigned char *)valp))
173  {
174  numval = atoi(valp);
175  t->tagValue->which = Z_StringOrNumeric_numeric;
176  t->tagValue->u.numeric = nmem_intdup(nmem, numval);
177  }
178  else
179  {
180  t->tagValue->which = Z_StringOrNumeric_string;
181  t->tagValue->u.string = nmem_strdup(nmem, valp);
182  }
183  if (terms > 2) /* an occurrences-spec exists */
184  t->occurrences = read_occurrences(occ, nmem, file, lineno);
185  else
186  t->occurrences = 0;
187  }
188  else if ((terms = sscanf(buf, "%511[^)]", value)) >= 1)
189  {
190  Z_SpecificTag *t;
191  char *valp = value;
192 
193  u->which = Z_ETagUnit_specificTag;
194  u->u.specificTag = t = (Z_SpecificTag *)nmem_malloc(nmem, sizeof(*t));
195  t->tagType = nmem_intdup(nmem, 3);
196  t->tagValue = (Z_StringOrNumeric *)
197  nmem_malloc(nmem, sizeof(*t->tagValue));
198  t->tagValue->which = Z_StringOrNumeric_string;
199  t->tagValue->u.string = nmem_strdup(nmem, valp);
200  t->occurrences = read_occurrences("all", nmem, file, lineno);
201  }
202  else
203  {
204  return 0;
205  }
206  return u;
207 }
208 
209 /*
210  * Read an element-set specification from a file.
211  * NOTE: If !o, memory is allocated directly from the heap by nmem_malloc().
212  */
213 Z_Espec1 *data1_read_espec1 (data1_handle dh, const char *file)
214 {
215  FILE *f;
216  NMEM nmem = data1_nmem_get (dh);
217  int lineno = 0;
218  int argc, size_esn = 0;
219  char *argv[50], line[512];
220  Z_Espec1 *res = (Z_Espec1 *)nmem_malloc(nmem, sizeof(*res));
221 
222  if (!(f = data1_path_fopen(dh, file, "r")))
223  return 0;
224 
225  res->num_elementSetNames = 0;
226  res->elementSetNames = 0;
227  res->defaultVariantSetId = 0;
228  res->defaultVariantRequest = 0;
229  res->defaultTagType = 0;
230  res->num_elements = 0;
231  res->elements = 0;
232 
233  while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
234  if (!strcmp(argv[0], "elementsetnames"))
235  {
236  int nnames = argc-1, i;
237 
238  if (!nnames)
239  {
240  yaz_log(YLOG_WARN, "%s:%d: Empty elementsetnames directive",
241  file, lineno);
242  continue;
243  }
244 
245  res->elementSetNames =
246  (char **)nmem_malloc(nmem, sizeof(char**)*nnames);
247  for (i = 0; i < nnames; i++)
248  {
249  res->elementSetNames[i] = nmem_strdup(nmem, argv[i+1]);
250  }
251  res->num_elementSetNames = nnames;
252  }
253  else if (!strcmp(argv[0], "defaultvariantsetid"))
254  {
255  if (argc != 2)
256  {
257  yaz_log(YLOG_WARN, "%s:%d: Bad # of args for %s",
258  file, lineno, argv[0]);
259  continue;
260  }
261  if (!(res->defaultVariantSetId =
262  odr_getoidbystr_nmem(nmem, argv[1])))
263  {
264  yaz_log(YLOG_WARN, "%s:%d: Bad defaultvariantsetid",
265  file, lineno);
266  continue;
267  }
268  }
269  else if (!strcmp(argv[0], "defaulttagtype"))
270  {
271  if (argc != 2)
272  {
273  yaz_log(YLOG_WARN, "%s:%d: Bad # of args for %s",
274  file, lineno, argv[0]);
275  continue;
276  }
277  res->defaultTagType = nmem_intdup(nmem, atoi(argv[1]));
278  }
279  else if (!strcmp(argv[0], "defaultvariantrequest"))
280  {
281  if (!(res->defaultVariantRequest =
282  read_variant(argc-1, argv+1, nmem, file, lineno)))
283  {
284  yaz_log(YLOG_WARN, "%s:%d: Bad defaultvariantrequest",
285  file, lineno);
286  continue;
287  }
288  }
289  else if (!strcmp(argv[0], "simpleelement"))
290  {
291  Z_ElementRequest *er;
292  Z_SimpleElement *se;
293  Z_ETagPath *tp;
294  char *path = argv[1];
295  char *ep;
296  int num, i = 0;
297 
298  if (!res->elements)
299  res->elements = (Z_ElementRequest **)
300  nmem_malloc(nmem, size_esn = 24*sizeof(er));
301  else if (res->num_elements >= (int) (size_esn/sizeof(er)))
302  {
303  Z_ElementRequest **oe = res->elements;
304  size_esn *= 2;
305  res->elements = (Z_ElementRequest **)
306  nmem_malloc (nmem, size_esn*sizeof(er));
307  memcpy (res->elements, oe, size_esn/2);
308  }
309  if (argc < 2)
310  {
311  yaz_log(YLOG_WARN, "%s:%d: Bad # of args for %s",
312  file, lineno, argv[0]);
313  continue;
314  }
315 
316  res->elements[res->num_elements++] = er =
317  (Z_ElementRequest *)nmem_malloc(nmem, sizeof(*er));
318  er->which = Z_ERequest_simpleElement;
319  er->u.simpleElement = se = (Z_SimpleElement *)
320  nmem_malloc(nmem, sizeof(*se));
321  se->variantRequest = 0;
322  se->path = tp = (Z_ETagPath *)nmem_malloc(nmem, sizeof(*tp));
323  tp->num_tags = 0;
324  /*
325  * Parse the element selector.
326  */
327  for (num = 1, ep = path; (ep = strchr(ep, '/')); num++, ep++)
328  ;
329  tp->tags = (Z_ETagUnit **)
330  nmem_malloc(nmem, sizeof(Z_ETagUnit*)*num);
331 
332  for ((ep = strchr(path, '/')) ; path ;
333  (void)((path = ep) && (ep = strchr(path, '/'))))
334  {
335  Z_ETagUnit *tagunit;
336  if (ep)
337  ep++;
338 
339  assert(i<num);
340  tagunit = read_tagunit(path, nmem, file, lineno);
341  if (!tagunit)
342  {
343  yaz_log (YLOG_WARN, "%s%d: Bad tag unit at %s",
344  file, lineno, path);
345  break;
346  }
347  tp->tags[tp->num_tags++] = tagunit;
348  }
349 
350  if (argc > 2 && !strcmp(argv[2], "variant"))
351  se->variantRequest=
352  read_variant(argc-3, argv+3, nmem, file, lineno);
353  }
354  else
355  yaz_log(YLOG_WARN, "%s:%d: Unknown directive '%s'",
356  file, lineno, argv[0]);
357  fclose (f);
358  return res;
359 }
360 /*
361  * Local variables:
362  * c-basic-offset: 4
363  * c-file-style: "Stroustrup"
364  * indent-tabs-mode: nil
365  * End:
366  * vim: shiftwidth=4 tabstop=8 expandtab
367  */
368 
static Z_ETagUnit * read_tagunit(char *buf, NMEM nmem, const char *file, int lineno)
Definition: d1_espec.c:131
Z_Espec1 * data1_read_espec1(data1_handle dh, const char *file)
Definition: d1_espec.c:213
static Z_Occurrences * read_occurrences(char *occ, NMEM nmem, const char *file, int lineno)
Definition: d1_espec.c:85
static Z_Variant * read_variant(int argc, char **argv, NMEM nmem, const char *file, int lineno)
Definition: d1_espec.c:34
FILE * data1_path_fopen(data1_handle dh, const char *file, const char *mode)
Definition: d1_handle.c:147
NMEM data1_nmem_get(data1_handle dh)
Definition: d1_handle.c:66
#define d1_isdigit(c)
Definition: data1.h:32