2 * Copyright (c) 1995-2002, Index Data.
3 * See the file LICENSE for details.
4 * Sebastian Hammer, Adam Dickmeiss
6 * $Id: d1_absyn.c,v 1.33 2002-08-17 07:56:59 adam Exp $
16 #include <yaz/data1.h>
18 #define D1_MAX_NESTING 128
20 struct data1_absyn_cache_info
24 data1_absyn_cache next;
27 struct data1_attset_cache_info
31 data1_attset_cache next;
34 data1_absyn *data1_absyn_search (data1_handle dh, const char *name)
36 data1_absyn_cache p = *data1_absyn_cache_get (dh);
40 if (!strcmp (name, p->name))
47 void data1_absyn_trav (data1_handle dh, void *handle,
48 void (*fh)(data1_handle dh, void *h, data1_absyn *a))
50 data1_absyn_cache p = *data1_absyn_cache_get (dh);
54 (*fh)(dh, handle, p->absyn);
59 data1_absyn *data1_absyn_add (data1_handle dh, const char *name)
62 NMEM mem = data1_nmem_get (dh);
64 data1_absyn_cache p = (data1_absyn_cache)nmem_malloc (mem, sizeof(*p));
65 data1_absyn_cache *pp = data1_absyn_cache_get (dh);
67 sprintf(fname, "%s.abs", name);
68 p->absyn = data1_read_absyn (dh, fname, 0);
69 p->name = nmem_strdup (mem, name);
75 data1_absyn *data1_get_absyn (data1_handle dh, const char *name)
79 if (!(absyn = data1_absyn_search (dh, name)))
80 absyn = data1_absyn_add (dh, name);
84 data1_attset *data1_attset_search_name (data1_handle dh, const char *name)
86 data1_attset_cache p = *data1_attset_cache_get (dh);
90 if (!strcmp (name, p->name))
97 data1_attset *data1_attset_search_id (data1_handle dh, int id)
99 data1_attset_cache p = *data1_attset_cache_get (dh);
103 if (id == p->attset->reference)
110 data1_attset *data1_attset_add (data1_handle dh, const char *name)
112 char fname[512], aname[512];
113 NMEM mem = data1_nmem_get (dh);
114 data1_attset *attset;
116 strcpy (aname, name);
117 sprintf(fname, "%s.att", name);
118 attset = data1_read_attset (dh, fname);
122 attset = data1_read_attset (dh, name);
123 if (attset && (cp = strrchr (aname, '.')))
127 yaz_log (LOG_WARN|LOG_ERRNO, "Couldn't load attribute set %s", name);
130 data1_attset_cache p = (data1_attset_cache)
131 nmem_malloc (mem, sizeof(*p));
132 data1_attset_cache *pp = data1_attset_cache_get (dh);
134 attset->name = p->name = nmem_strdup (mem, aname);
142 data1_attset *data1_get_attset (data1_handle dh, const char *name)
144 data1_attset *attset;
146 if (!(attset = data1_attset_search_name (dh, name)))
147 attset = data1_attset_add (dh, name);
151 data1_esetname *data1_getesetbyname(data1_handle dh, data1_absyn *a,
156 for (r = a->esetnames; r; r = r->next)
157 if (!data1_matchstr(r->name, name))
162 data1_element *data1_getelementbytagname (data1_handle dh, data1_absyn *abs,
163 data1_element *parent,
168 /* It's now possible to have a data1 tree with no abstract syntax */
173 r = abs->main_elements;
175 r = parent->children;
177 for (; r; r = r->next)
181 for (n = r->tag->names; n; n = n->next)
182 if (!data1_matchstr(tagname, n->name))
188 data1_element *data1_getelementbyname (data1_handle dh, data1_absyn *absyn,
193 /* It's now possible to have a data1 tree with no abstract syntax */
196 for (r = absyn->main_elements; r; r = r->next)
197 if (!data1_matchstr(r->name, name))
203 void fix_element_ref (data1_handle dh, data1_absyn *absyn, data1_element *e)
205 /* It's now possible to have a data1 tree with no abstract syntax */
209 for (; e; e = e->next)
214 fix_element_ref (dh, absyn, e->children);
218 data1_sub_elements *sub_e = absyn->sub_elements;
219 while (sub_e && strcmp (e->sub_name, sub_e->name))
222 e->children = sub_e->elements;
224 yaz_log (LOG_WARN, "Unresolved reference to sub-elements %s",
231 static int parse_termlists (data1_handle dh, data1_termlist ***tpp,
232 char *p, const char *file, int lineno,
233 const char *element_name, data1_absyn *res)
235 data1_termlist **tp = *tpp;
238 char attname[512], structure[512];
242 if (!(r = sscanf(p, "%511[^:,]:%511[^,]", attname,
246 "%s:%d: Syntax error in termlistspec '%s'",
251 strcpy(attname, element_name);
252 *tp = (data1_termlist *)
253 nmem_malloc(data1_nmem_get(dh), sizeof(**tp));
255 if (!((*tp)->att = data1_getattbyname(dh, res->attset,
259 "%s:%d: Couldn't find att '%s' in attset",
260 file, lineno, attname);
263 if (r == 2 && (source = strchr(structure, ':')))
264 *source++ = '\0'; /* cut off structure .. */
266 source = "data"; /* ok: default is leaf data */
267 (*tp)->source = (char *)
268 nmem_strdup (data1_nmem_get (dh), source);
270 if (r < 2) /* is the structure qualified? */
271 (*tp)->structure = "w";
273 (*tp)->structure = (char *)
274 nmem_strdup (data1_nmem_get (dh), structure);
277 while ((p = strchr(p, ',')) && *(++p));
282 data1_absyn *data1_read_absyn (data1_handle dh, const char *file,
285 data1_sub_elements *cur_elements = NULL;
286 data1_absyn *res = 0;
288 data1_element **ppl[D1_MAX_NESTING];
289 data1_esetname **esetpp;
290 data1_maptab **maptabp;
291 data1_marctab **marcp;
292 data1_termlist *all = 0;
293 data1_attset_child **attset_childp;
294 data1_tagset **tagset_childp;
298 char *argv[50], line[512];
300 if (!(f = data1_path_fopen(dh, file, "r")))
302 yaz_log(LOG_WARN|LOG_ERRNO, "Couldn't open %s", file);
307 res = (data1_absyn *) nmem_malloc(data1_nmem_get(dh), sizeof(*res));
309 res->reference = VAL_NONE;
312 res->enable_xpath_indexing = (f ? 0 : 1);
313 tagset_childp = &res->tagset;
315 res->attset = data1_empty_attset (dh);
316 attset_childp = &res->attset->children;
320 esetpp = &res->esetnames;
322 maptabp = &res->maptabs;
326 res->sub_elements = NULL;
327 res->main_elements = NULL;
329 while (f && (argc = readconf_line(f, &lineno, line, 512, argv, 50)))
332 if (!strcmp(cmd, "elm"))
334 data1_element *new_element;
336 char *p, *sub_p, *path, *name, *termlists;
342 yaz_log(LOG_WARN, "%s:%d: Bad # of args to elm", file, lineno);
351 cur_elements = (data1_sub_elements *)
352 nmem_malloc(data1_nmem_get(dh), sizeof(*cur_elements));
353 cur_elements->next = res->sub_elements;
354 cur_elements->elements = NULL;
355 cur_elements->name = "main";
356 res->sub_elements = cur_elements;
359 ppl[level] = &cur_elements->elements;
366 if ((e = strchr(p, '/')))
373 yaz_log(LOG_WARN, "%s:%d: Bad level increase", file, lineno);
378 new_element = *ppl[level-1] = (data1_element *)
379 nmem_malloc(data1_nmem_get(dh), sizeof(*new_element));
380 new_element->next = new_element->children = 0;
381 new_element->tag = 0;
382 new_element->termlists = 0;
383 new_element->sub_name = 0;
385 tp = &new_element->termlists;
386 ppl[level-1] = &new_element->next;
387 ppl[level] = &new_element->children;
389 /* consider subtree (if any) ... */
390 if ((sub_p = strchr (p, ':')) && sub_p[1])
393 new_element->sub_name =
394 nmem_strdup (data1_nmem_get(dh), sub_p);
396 /* well-defined tag */
397 if (sscanf(p, "(%d,%d)", &type, &value) == 2)
401 yaz_log(LOG_WARN, "%s:%d: No tagset loaded", file, lineno);
405 if (!(new_element->tag = data1_gettagbynum (dh, res->tagset,
408 yaz_log(LOG_WARN, "%s:%d: Couldn't find tag %s in tagset",
418 new_element->tag = (data1_tag *)
419 nmem_malloc(data1_nmem_get (dh),
420 sizeof(*new_element->tag));
421 nt->which = DATA1T_string;
422 nt->value.string = nmem_strdup(data1_nmem_get (dh), p);
423 nt->names = (data1_name *)
424 nmem_malloc(data1_nmem_get(dh),
425 sizeof(*new_element->tag->names));
426 nt->names->name = nt->value.string;
428 nt->kind = DATA1K_string;
434 yaz_log(LOG_WARN, "%s:%d: Bad element", file, lineno);
438 /* parse termList definitions */
442 assert (res->attset);
444 if (parse_termlists (dh, &tp, p, file, lineno, name, res))
449 *tp = all; /* append any ALL entries to the list */
451 new_element->name = nmem_strdup(data1_nmem_get (dh), name);
453 else if (!strcmp(cmd, "section"))
459 yaz_log(LOG_WARN, "%s:%d: Bad # of args to section",
465 cur_elements = (data1_sub_elements *)
466 nmem_malloc(data1_nmem_get(dh), sizeof(*cur_elements));
467 cur_elements->next = res->sub_elements;
468 cur_elements->elements = NULL;
469 cur_elements->name = nmem_strdup (data1_nmem_get(dh), name);
470 res->sub_elements = cur_elements;
473 ppl[level] = &cur_elements->elements;
475 else if (!strcmp(cmd, "xpath"))
479 yaz_log(LOG_WARN, "%s:%d: Bad # of args to 'xpath' directive",
483 if (!strcmp(argv[1], "enable"))
484 res->enable_xpath_indexing = 1;
485 else if (!strcmp (argv[1], "disable"))
486 res->enable_xpath_indexing = 0;
489 yaz_log(LOG_WARN, "%s:%d: Expecting disable/enable "
490 "after 'xpath' directive", file, lineno);
493 else if (!strcmp(cmd, "all"))
495 data1_termlist **tp = &all;
498 yaz_log(LOG_WARN, "%s:%d: Too many 'all' directives - ignored",
504 yaz_log(LOG_WARN, "%s:%d: Bad # of args to 'all' directive",
508 if (parse_termlists (dh, &tp, argv[1], file, lineno, 0, res))
514 else if (!strcmp(cmd, "name"))
518 yaz_log(LOG_WARN, "%s:%d: Bad # of args to name directive",
522 res->name = nmem_strdup(data1_nmem_get(dh), argv[1]);
524 else if (!strcmp(cmd, "reference"))
530 yaz_log(LOG_WARN, "%s:%d: Bad # of args to reference",
535 if ((res->reference = oid_getvalbyname(name)) == VAL_NONE)
537 yaz_log(LOG_WARN, "%s:%d: Unknown tagset ref '%s'",
542 else if (!strcmp(cmd, "attset"))
545 data1_attset *attset;
549 yaz_log(LOG_WARN, "%s:%d: Bad # of args to attset",
554 if (!(attset = data1_get_attset (dh, name)))
556 yaz_log(LOG_WARN, "%s:%d: Couldn't find attset %s",
560 *attset_childp = (data1_attset_child *)
561 nmem_malloc (data1_nmem_get(dh), sizeof(**attset_childp));
562 (*attset_childp)->child = attset;
563 (*attset_childp)->next = 0;
564 attset_childp = &(*attset_childp)->next;
566 else if (!strcmp(cmd, "tagset"))
572 yaz_log(LOG_WARN, "%s:%d: Bad # of args to tagset",
578 type = atoi(argv[2]);
579 *tagset_childp = data1_read_tagset (dh, name, type);
580 if (!(*tagset_childp))
582 yaz_log(LOG_WARN, "%s:%d: Couldn't load tagset %s",
586 tagset_childp = &(*tagset_childp)->next;
588 else if (!strcmp(cmd, "varset"))
594 yaz_log(LOG_WARN, "%s:%d: Bad # of args in varset",
599 if (!(res->varset = data1_read_varset (dh, name)))
601 yaz_log(LOG_WARN, "%s:%d: Couldn't load Varset %s",
606 else if (!strcmp(cmd, "esetname"))
612 yaz_log(LOG_WARN, "%s:%d: Bad # of args in esetname",
619 *esetpp = (data1_esetname *)
620 nmem_malloc(data1_nmem_get(dh), sizeof(**esetpp));
621 (*esetpp)->name = nmem_strdup(data1_nmem_get(dh), name);
625 else if (!((*esetpp)->spec = data1_read_espec1 (dh, fname)))
627 yaz_log(LOG_WARN, "%s:%d: Espec-1 read failed for %s",
628 file, lineno, fname);
631 esetpp = &(*esetpp)->next;
633 else if (!strcmp(cmd, "maptab"))
639 yaz_log(LOG_WARN, "%s:%d: Bad # of args for maptab",
644 if (!(*maptabp = data1_read_maptab (dh, name)))
646 yaz_log(LOG_WARN, "%s:%d: Couldn't load maptab %s",
650 maptabp = &(*maptabp)->next;
652 else if (!strcmp(cmd, "marc"))
658 yaz_log(LOG_WARN, "%s:%d: Bad # or args for marc",
663 if (!(*marcp = data1_read_marctab (dh, name)))
665 yaz_log(LOG_WARN, "%s:%d: Couldn't read marctab %s",
669 marcp = &(*marcp)->next;
671 else if (!strcmp(cmd, "encoding"))
675 yaz_log(LOG_WARN, "%s:%d: Bad # or args for encoding",
679 res->encoding = nmem_strdup (data1_nmem_get(dh), argv[1]);
683 yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'", file,
691 for (cur_elements = res->sub_elements; cur_elements;
692 cur_elements = cur_elements->next)
694 if (!strcmp (cur_elements->name, "main"))
695 res->main_elements = cur_elements->elements;
696 fix_element_ref (dh, res, cur_elements->elements);
698 yaz_log (LOG_DEBUG, "%s: data1_read_absyn end", file);