1 /* $Id: d1_absyn.c,v 1.2 2002-10-22 13:19:50 adam Exp $
2 Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
5 This file is part of the Zebra server.
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra. If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
32 #define D1_MAX_NESTING 128
34 struct data1_absyn_cache_info
38 data1_absyn_cache next;
41 struct data1_attset_cache_info
45 data1_attset_cache next;
48 data1_absyn *data1_absyn_search (data1_handle dh, const char *name)
50 data1_absyn_cache p = *data1_absyn_cache_get (dh);
54 if (!strcmp (name, p->name))
61 void data1_absyn_trav (data1_handle dh, void *handle,
62 void (*fh)(data1_handle dh, void *h, data1_absyn *a))
64 data1_absyn_cache p = *data1_absyn_cache_get (dh);
68 (*fh)(dh, handle, p->absyn);
73 data1_absyn *data1_absyn_add (data1_handle dh, const char *name)
76 NMEM mem = data1_nmem_get (dh);
78 data1_absyn_cache p = (data1_absyn_cache)nmem_malloc (mem, sizeof(*p));
79 data1_absyn_cache *pp = data1_absyn_cache_get (dh);
81 sprintf(fname, "%s.abs", name);
82 p->absyn = data1_read_absyn (dh, fname, 0);
83 p->name = nmem_strdup (mem, name);
89 data1_absyn *data1_get_absyn (data1_handle dh, const char *name)
93 if (!(absyn = data1_absyn_search (dh, name)))
94 absyn = data1_absyn_add (dh, name);
98 data1_attset *data1_attset_search_name (data1_handle dh, const char *name)
100 data1_attset_cache p = *data1_attset_cache_get (dh);
104 if (!strcmp (name, p->name))
111 data1_attset *data1_attset_search_id (data1_handle dh, int id)
113 data1_attset_cache p = *data1_attset_cache_get (dh);
117 if (id == p->attset->reference)
124 data1_attset *data1_attset_add (data1_handle dh, const char *name)
126 char fname[512], aname[512];
127 NMEM mem = data1_nmem_get (dh);
128 data1_attset *attset;
130 strcpy (aname, name);
131 sprintf(fname, "%s.att", name);
132 attset = data1_read_attset (dh, fname);
136 attset = data1_read_attset (dh, name);
137 if (attset && (cp = strrchr (aname, '.')))
141 yaz_log (LOG_WARN|LOG_ERRNO, "Couldn't load attribute set %s", name);
144 data1_attset_cache p = (data1_attset_cache)
145 nmem_malloc (mem, sizeof(*p));
146 data1_attset_cache *pp = data1_attset_cache_get (dh);
148 attset->name = p->name = nmem_strdup (mem, aname);
156 data1_attset *data1_get_attset (data1_handle dh, const char *name)
158 data1_attset *attset;
160 if (!(attset = data1_attset_search_name (dh, name)))
161 attset = data1_attset_add (dh, name);
165 data1_esetname *data1_getesetbyname(data1_handle dh, data1_absyn *a,
170 for (r = a->esetnames; r; r = r->next)
171 if (!data1_matchstr(r->name, name))
176 data1_element *data1_getelementbytagname (data1_handle dh, data1_absyn *abs,
177 data1_element *parent,
182 /* It's now possible to have a data1 tree with no abstract syntax */
187 r = abs->main_elements;
189 r = parent->children;
191 for (; r; r = r->next)
195 for (n = r->tag->names; n; n = n->next)
196 if (!data1_matchstr(tagname, n->name))
202 data1_element *data1_getelementbyname (data1_handle dh, data1_absyn *absyn,
207 /* It's now possible to have a data1 tree with no abstract syntax */
210 for (r = absyn->main_elements; r; r = r->next)
211 if (!data1_matchstr(r->name, name))
217 void fix_element_ref (data1_handle dh, data1_absyn *absyn, data1_element *e)
219 /* It's now possible to have a data1 tree with no abstract syntax */
223 for (; e; e = e->next)
228 fix_element_ref (dh, absyn, e->children);
232 data1_sub_elements *sub_e = absyn->sub_elements;
233 while (sub_e && strcmp (e->sub_name, sub_e->name))
236 e->children = sub_e->elements;
238 yaz_log (LOG_WARN, "Unresolved reference to sub-elements %s",
245 static int parse_termlists (data1_handle dh, data1_termlist ***tpp,
246 char *p, const char *file, int lineno,
247 const char *element_name, data1_absyn *res)
249 data1_termlist **tp = *tpp;
252 char attname[512], structure[512];
256 if (!(r = sscanf(p, "%511[^:,]:%511[^,]", attname,
260 "%s:%d: Syntax error in termlistspec '%s'",
265 strcpy(attname, element_name);
266 *tp = (data1_termlist *)
267 nmem_malloc(data1_nmem_get(dh), sizeof(**tp));
269 if (!((*tp)->att = data1_getattbyname(dh, res->attset,
273 "%s:%d: Couldn't find att '%s' in attset",
274 file, lineno, attname);
277 if (r == 2 && (source = strchr(structure, ':')))
278 *source++ = '\0'; /* cut off structure .. */
280 source = "data"; /* ok: default is leaf data */
281 (*tp)->source = (char *)
282 nmem_strdup (data1_nmem_get (dh), source);
284 if (r < 2) /* is the structure qualified? */
285 (*tp)->structure = "w";
287 (*tp)->structure = (char *)
288 nmem_strdup (data1_nmem_get (dh), structure);
291 while ((p = strchr(p, ',')) && *(++p));
296 data1_absyn *data1_read_absyn (data1_handle dh, const char *file,
299 data1_sub_elements *cur_elements = NULL;
300 data1_absyn *res = 0;
302 data1_element **ppl[D1_MAX_NESTING];
303 data1_esetname **esetpp;
304 data1_maptab **maptabp;
305 data1_marctab **marcp;
306 data1_termlist *all = 0;
307 data1_attset_child **attset_childp;
308 data1_tagset **tagset_childp;
312 char *argv[50], line[512];
314 if (!(f = data1_path_fopen(dh, file, "r")))
316 yaz_log(LOG_WARN|LOG_ERRNO, "Couldn't open %s", file);
321 res = (data1_absyn *) nmem_malloc(data1_nmem_get(dh), sizeof(*res));
323 res->reference = VAL_NONE;
326 res->enable_xpath_indexing = (f ? 0 : 1);
327 tagset_childp = &res->tagset;
329 res->attset = data1_empty_attset (dh);
330 attset_childp = &res->attset->children;
334 esetpp = &res->esetnames;
336 maptabp = &res->maptabs;
340 res->sub_elements = NULL;
341 res->main_elements = NULL;
343 while (f && (argc = readconf_line(f, &lineno, line, 512, argv, 50)))
346 if (!strcmp(cmd, "elm") || !strcmp(cmd, "element"))
348 data1_element *new_element;
350 char *p, *sub_p, *path, *name, *termlists;
356 yaz_log(LOG_WARN, "%s:%d: Bad # of args to elm", file, lineno);
365 cur_elements = (data1_sub_elements *)
366 nmem_malloc(data1_nmem_get(dh), sizeof(*cur_elements));
367 cur_elements->next = res->sub_elements;
368 cur_elements->elements = NULL;
369 cur_elements->name = "main";
370 res->sub_elements = cur_elements;
373 ppl[level] = &cur_elements->elements;
380 if ((e = strchr(p, '/')))
387 yaz_log(LOG_WARN, "%s:%d: Bad level increase", file, lineno);
392 new_element = *ppl[level-1] = (data1_element *)
393 nmem_malloc(data1_nmem_get(dh), sizeof(*new_element));
394 new_element->next = new_element->children = 0;
395 new_element->tag = 0;
396 new_element->termlists = 0;
397 new_element->sub_name = 0;
399 tp = &new_element->termlists;
400 ppl[level-1] = &new_element->next;
401 ppl[level] = &new_element->children;
403 /* consider subtree (if any) ... */
404 if ((sub_p = strchr (p, ':')) && sub_p[1])
407 new_element->sub_name =
408 nmem_strdup (data1_nmem_get(dh), sub_p);
410 /* well-defined tag */
411 if (sscanf(p, "(%d,%d)", &type, &value) == 2)
415 yaz_log(LOG_WARN, "%s:%d: No tagset loaded", file, lineno);
419 if (!(new_element->tag = data1_gettagbynum (dh, res->tagset,
422 yaz_log(LOG_WARN, "%s:%d: Couldn't find tag %s in tagset",
432 new_element->tag = (data1_tag *)
433 nmem_malloc(data1_nmem_get (dh),
434 sizeof(*new_element->tag));
435 nt->which = DATA1T_string;
436 nt->value.string = nmem_strdup(data1_nmem_get (dh), p);
437 nt->names = (data1_name *)
438 nmem_malloc(data1_nmem_get(dh),
439 sizeof(*new_element->tag->names));
440 nt->names->name = nt->value.string;
442 nt->kind = DATA1K_string;
448 yaz_log(LOG_WARN, "%s:%d: Bad element", file, lineno);
452 /* parse termList definitions */
456 assert (res->attset);
458 if (parse_termlists (dh, &tp, p, file, lineno, name, res))
463 *tp = all; /* append any ALL entries to the list */
465 new_element->name = nmem_strdup(data1_nmem_get (dh), name);
467 else if (!strcmp(cmd, "section"))
473 yaz_log(LOG_WARN, "%s:%d: Bad # of args to section",
479 cur_elements = (data1_sub_elements *)
480 nmem_malloc(data1_nmem_get(dh), sizeof(*cur_elements));
481 cur_elements->next = res->sub_elements;
482 cur_elements->elements = NULL;
483 cur_elements->name = nmem_strdup (data1_nmem_get(dh), name);
484 res->sub_elements = cur_elements;
487 ppl[level] = &cur_elements->elements;
489 else if (!strcmp(cmd, "xpath"))
493 yaz_log(LOG_WARN, "%s:%d: Bad # of args to 'xpath' directive",
497 if (!strcmp(argv[1], "enable"))
498 res->enable_xpath_indexing = 1;
499 else if (!strcmp (argv[1], "disable"))
500 res->enable_xpath_indexing = 0;
503 yaz_log(LOG_WARN, "%s:%d: Expecting disable/enable "
504 "after 'xpath' directive", file, lineno);
507 else if (!strcmp(cmd, "all"))
509 data1_termlist **tp = &all;
512 yaz_log(LOG_WARN, "%s:%d: Too many 'all' directives - ignored",
518 yaz_log(LOG_WARN, "%s:%d: Bad # of args to 'all' directive",
522 if (parse_termlists (dh, &tp, argv[1], file, lineno, 0, res))
528 else if (!strcmp(cmd, "name"))
532 yaz_log(LOG_WARN, "%s:%d: Bad # of args to name directive",
536 res->name = nmem_strdup(data1_nmem_get(dh), argv[1]);
538 else if (!strcmp(cmd, "reference"))
544 yaz_log(LOG_WARN, "%s:%d: Bad # of args to reference",
549 if ((res->reference = oid_getvalbyname(name)) == VAL_NONE)
551 yaz_log(LOG_WARN, "%s:%d: Unknown tagset ref '%s'",
556 else if (!strcmp(cmd, "attset"))
559 data1_attset *attset;
563 yaz_log(LOG_WARN, "%s:%d: Bad # of args to attset",
568 if (!(attset = data1_get_attset (dh, name)))
570 yaz_log(LOG_WARN, "%s:%d: Couldn't find attset %s",
574 *attset_childp = (data1_attset_child *)
575 nmem_malloc (data1_nmem_get(dh), sizeof(**attset_childp));
576 (*attset_childp)->child = attset;
577 (*attset_childp)->next = 0;
578 attset_childp = &(*attset_childp)->next;
580 else if (!strcmp(cmd, "tagset"))
586 yaz_log(LOG_WARN, "%s:%d: Bad # of args to tagset",
592 type = atoi(argv[2]);
593 *tagset_childp = data1_read_tagset (dh, name, type);
594 if (!(*tagset_childp))
596 yaz_log(LOG_WARN, "%s:%d: Couldn't load tagset %s",
600 tagset_childp = &(*tagset_childp)->next;
602 else if (!strcmp(cmd, "varset"))
608 yaz_log(LOG_WARN, "%s:%d: Bad # of args in varset",
613 if (!(res->varset = data1_read_varset (dh, name)))
615 yaz_log(LOG_WARN, "%s:%d: Couldn't load Varset %s",
620 else if (!strcmp(cmd, "esetname"))
626 yaz_log(LOG_WARN, "%s:%d: Bad # of args in esetname",
633 *esetpp = (data1_esetname *)
634 nmem_malloc(data1_nmem_get(dh), sizeof(**esetpp));
635 (*esetpp)->name = nmem_strdup(data1_nmem_get(dh), name);
639 else if (!((*esetpp)->spec = data1_read_espec1 (dh, fname)))
641 yaz_log(LOG_WARN, "%s:%d: Espec-1 read failed for %s",
642 file, lineno, fname);
645 esetpp = &(*esetpp)->next;
647 else if (!strcmp(cmd, "maptab"))
653 yaz_log(LOG_WARN, "%s:%d: Bad # of args for maptab",
658 if (!(*maptabp = data1_read_maptab (dh, name)))
660 yaz_log(LOG_WARN, "%s:%d: Couldn't load maptab %s",
664 maptabp = &(*maptabp)->next;
666 else if (!strcmp(cmd, "marc"))
672 yaz_log(LOG_WARN, "%s:%d: Bad # or args for marc",
677 if (!(*marcp = data1_read_marctab (dh, name)))
679 yaz_log(LOG_WARN, "%s:%d: Couldn't read marctab %s",
683 marcp = &(*marcp)->next;
685 else if (!strcmp(cmd, "encoding"))
689 yaz_log(LOG_WARN, "%s:%d: Bad # or args for encoding",
693 res->encoding = nmem_strdup (data1_nmem_get(dh), argv[1]);
697 yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'", file,
705 for (cur_elements = res->sub_elements; cur_elements;
706 cur_elements = cur_elements->next)
708 if (!strcmp (cur_elements->name, "main"))
709 res->main_elements = cur_elements->elements;
710 fix_element_ref (dh, res, cur_elements->elements);
712 yaz_log (LOG_DEBUG, "%s: data1_read_absyn end", file);