data1 part of zebra
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 22 Oct 2002 12:51:08 +0000 (12:51 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 22 Oct 2002 12:51:08 +0000 (12:51 +0000)
72 files changed:
CHANGELOG
Makefile.am
configure.in
data1/Makefile.am [new file with mode: 0644]
data1/d1_absyn.c [new file with mode: 0644]
data1/d1_attset.c [new file with mode: 0644]
data1/d1_doespec.c [new file with mode: 0644]
data1/d1_espec.c [new file with mode: 0644]
data1/d1_expout.c [new file with mode: 0644]
data1/d1_grs.c [new file with mode: 0644]
data1/d1_handle.c [new file with mode: 0644]
data1/d1_if.c [new file with mode: 0644]
data1/d1_map.c [new file with mode: 0644]
data1/d1_marc.c [new file with mode: 0644]
data1/d1_prtree.c [new file with mode: 0644]
data1/d1_read.c [new file with mode: 0644]
data1/d1_soif.c [new file with mode: 0644]
data1/d1_sumout.c [new file with mode: 0644]
data1/d1_sutrs.c [new file with mode: 0644]
data1/d1_tagset.c [new file with mode: 0644]
data1/d1_varset.c [new file with mode: 0644]
data1/d1_write.c [new file with mode: 0644]
include/Makefile.am
include/d1_attset.h [new file with mode: 0644]
include/d1_map.h [new file with mode: 0644]
include/data1.h [new file with mode: 0644]
include/recctrl.h
index/Makefile.am
index/extract.c
index/index.h
index/main.c
index/zinfo.h
index/zserver.c
recctrl/grsread.h
recctrl/xmlread.c
tab/Makefile [new file with mode: 0644]
tab/Makefile.am
tab/Makefile.in [new file with mode: 0644]
tab/bib1.att [new file with mode: 0644]
tab/dan1.att [new file with mode: 0644]
tab/danmarc.abs [new file with mode: 0644]
tab/danmarc.mar [new file with mode: 0644]
tab/explain.abs [new file with mode: 0644]
tab/explain.att [new file with mode: 0644]
tab/explain.tag [new file with mode: 0644]
tab/generic.tag [new file with mode: 0644]
tab/gils-a.est [new file with mode: 0644]
tab/gils-b.est [new file with mode: 0644]
tab/gils-f.est [new file with mode: 0644]
tab/gils-g.est [new file with mode: 0644]
tab/gils-summary.map [new file with mode: 0644]
tab/gils-usmarc.map [new file with mode: 0644]
tab/gils-variant.est [new file with mode: 0644]
tab/gils.abs [new file with mode: 0644]
tab/gils.att [new file with mode: 0644]
tab/gils.tag [new file with mode: 0644]
tab/meta-b.est [new file with mode: 0644]
tab/meta-usmarc.map [new file with mode: 0644]
tab/meta.abs [new file with mode: 0644]
tab/meta.tag [new file with mode: 0644]
tab/summary.abs [new file with mode: 0644]
tab/summary.tag [new file with mode: 0644]
tab/tagsetg.tag [new file with mode: 0644]
tab/tagsetm.tag [new file with mode: 0644]
tab/usmarc-b.est [new file with mode: 0644]
tab/usmarc.abs [new file with mode: 0644]
tab/usmarc.mar [new file with mode: 0644]
tab/usmarc.tag [new file with mode: 0644]
tab/var1.var [new file with mode: 0644]
tab/wais-b.est [new file with mode: 0644]
tab/wais-variant.est [new file with mode: 0644]
tab/wais.abs [new file with mode: 0644]

index db7c3d9..19f7e4a 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,6 @@
 
+Move data1 to Zebra (used to be part of YAZ).
+
 --- 1.3.3 2002/10/05
 
 Fix character encoding of scan response terms.
index d9ba944..3e772ba 100644 (file)
@@ -1,10 +1,11 @@
-## $Id: Makefile.am,v 1.7 2002-09-25 09:50:20 adam Exp $
+## $Id: Makefile.am,v 1.8 2002-10-22 12:51:08 adam Exp $
 
 AUTOMAKE_OPTIONS=foreign
 
 EXTRA_DIST= README CHANGELOG 
 
-SUBDIRS=util bfile dfa dict isams isamb isamc isam rset recctrl tab index test include doc
+SUBDIRS=util bfile dfa dict isams isamb isamc isam rset data1 \
+ recctrl tab index test include doc
 
 SPEC_FILE=$(PACKAGE).spec
 
index 94845a9..297d885 100644 (file)
@@ -1,5 +1,5 @@
 dnl Zebra, Index Data Aps, 1995-2002
-dnl $Id: configure.in,v 1.50 2002-09-25 09:50:20 adam Exp $
+dnl $Id: configure.in,v 1.51 2002-10-22 12:51:08 adam Exp $
 dnl
 AC_INIT(include/zebraver.h)
 AM_INIT_AUTOMAKE(idzebra,1.3.3)
@@ -244,6 +244,7 @@ AC_OUTPUT([
   isamc/Makefile
   isam/Makefile
   rset/Makefile
+  data1/Makefile
   recctrl/Makefile
   index/Makefile
   include/Makefile
diff --git a/data1/Makefile.am b/data1/Makefile.am
new file mode 100644 (file)
index 0000000..aabd6c0
--- /dev/null
@@ -0,0 +1,10 @@
+## $Id: Makefile.am,v 1.1 2002-10-22 12:53:33 adam Exp $
+
+noinst_LIBRARIES=libdata1.a
+
+libdata1_a_SOURCES = d1_handle.c d1_read.c d1_attset.c d1_tagset.c d1_absyn.c \
+  d1_grs.c d1_sutrs.c d1_varset.c d1_espec.c d1_doespec.c d1_map.c d1_marc.c \
+  d1_write.c d1_expout.c d1_sumout.c d1_soif.c d1_prtree.c d1_if.c
+
+AM_CPPFLAGS=-I$(top_srcdir)/include $(YAZINC)
+
diff --git a/data1/d1_absyn.c b/data1/d1_absyn.c
new file mode 100644 (file)
index 0000000..6427202
--- /dev/null
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_absyn.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <yaz/oid.h>
+#include <yaz/log.h>
+#include <data1.h>
+
+#define D1_MAX_NESTING  128
+
+struct data1_absyn_cache_info 
+{
+    char *name;
+    data1_absyn *absyn;
+    data1_absyn_cache next;
+};
+
+struct data1_attset_cache_info 
+{
+    char *name;
+    data1_attset *attset;
+    data1_attset_cache next;
+};
+
+data1_absyn *data1_absyn_search (data1_handle dh, const char *name)
+{
+    data1_absyn_cache p = *data1_absyn_cache_get (dh);
+
+    while (p)
+    {
+       if (!strcmp (name, p->name))
+           return p->absyn;
+       p = p->next;
+    }
+    return NULL;
+}
+
+void data1_absyn_trav (data1_handle dh, void *handle,
+                      void (*fh)(data1_handle dh, void *h, data1_absyn *a))
+{
+    data1_absyn_cache p = *data1_absyn_cache_get (dh);
+
+    while (p)
+    {
+       (*fh)(dh, handle, p->absyn);
+       p = p->next;
+    }
+}
+
+data1_absyn *data1_absyn_add (data1_handle dh, const char *name)
+{
+    char fname[512];
+    NMEM mem = data1_nmem_get (dh);
+
+    data1_absyn_cache p = (data1_absyn_cache)nmem_malloc (mem, sizeof(*p));
+    data1_absyn_cache *pp = data1_absyn_cache_get (dh);
+
+    sprintf(fname, "%s.abs", name);
+    p->absyn = data1_read_absyn (dh, fname, 0);
+    p->name = nmem_strdup (mem, name);
+    p->next = *pp;
+    *pp = p;
+    return p->absyn;
+}
+
+data1_absyn *data1_get_absyn (data1_handle dh, const char *name)
+{
+    data1_absyn *absyn;
+
+    if (!(absyn = data1_absyn_search (dh, name)))
+       absyn = data1_absyn_add (dh, name);
+    return absyn;
+}
+
+data1_attset *data1_attset_search_name (data1_handle dh, const char *name)
+{
+    data1_attset_cache p = *data1_attset_cache_get (dh);
+
+    while (p)
+    {
+       if (!strcmp (name, p->name))
+           return p->attset;
+       p = p->next;
+    }
+    return NULL;
+}
+
+data1_attset *data1_attset_search_id (data1_handle dh, int id)
+{
+    data1_attset_cache p = *data1_attset_cache_get (dh);
+
+    while (p)
+    {
+       if (id == p->attset->reference)
+           return p->attset;
+       p = p->next;
+    }
+    return NULL;
+}
+
+data1_attset *data1_attset_add (data1_handle dh, const char *name)
+{
+    char fname[512], aname[512];
+    NMEM mem = data1_nmem_get (dh);
+    data1_attset *attset;
+
+    strcpy (aname, name);
+    sprintf(fname, "%s.att", name);
+    attset = data1_read_attset (dh, fname);
+    if (!attset)
+    {
+       char *cp;
+       attset = data1_read_attset (dh, name);
+       if (attset && (cp = strrchr (aname, '.')))
+           *cp = '\0';
+    }
+    if (!attset)
+       yaz_log (LOG_WARN|LOG_ERRNO, "Couldn't load attribute set %s", name);
+    else
+    {
+       data1_attset_cache p = (data1_attset_cache)
+           nmem_malloc (mem, sizeof(*p));
+       data1_attset_cache *pp = data1_attset_cache_get (dh);
+       
+       attset->name = p->name = nmem_strdup (mem, aname);
+       p->attset = attset;
+       p->next = *pp;
+       *pp = p;
+    }
+    return attset;
+}
+
+data1_attset *data1_get_attset (data1_handle dh, const char *name)
+{
+    data1_attset *attset;
+
+    if (!(attset = data1_attset_search_name (dh, name)))
+       attset = data1_attset_add (dh, name);
+    return attset;
+}
+
+data1_esetname *data1_getesetbyname(data1_handle dh, data1_absyn *a,
+                                   const char *name)
+{
+    data1_esetname *r;
+
+    for (r = a->esetnames; r; r = r->next)
+       if (!data1_matchstr(r->name, name))
+           return r;
+    return 0;
+}
+
+data1_element *data1_getelementbytagname (data1_handle dh, data1_absyn *abs,
+                                         data1_element *parent,
+                                         const char *tagname)
+{
+    data1_element *r;
+
+    /* It's now possible to have a data1 tree with no abstract syntax */
+    if ( !abs )
+        return 0;
+
+    if (!parent)
+        r = abs->main_elements;
+    else
+       r = parent->children;
+
+    for (; r; r = r->next)
+    {
+       data1_name *n;
+
+       for (n = r->tag->names; n; n = n->next)
+           if (!data1_matchstr(tagname, n->name))
+               return r;
+    }
+    return 0;
+}
+
+data1_element *data1_getelementbyname (data1_handle dh, data1_absyn *absyn,
+                                      const char *name)
+{
+    data1_element *r;
+
+    /* It's now possible to have a data1 tree with no abstract syntax */
+    if ( !absyn )
+        return 0;
+    for (r = absyn->main_elements; r; r = r->next)
+       if (!data1_matchstr(r->name, name))
+           return r;
+    return 0;
+}
+
+
+void fix_element_ref (data1_handle dh, data1_absyn *absyn, data1_element *e)
+{
+    /* It's now possible to have a data1 tree with no abstract syntax */
+    if ( !absyn )
+        return;
+
+    for (; e; e = e->next)
+    {
+       if (!e->sub_name)
+       {
+           if (e->children)
+               fix_element_ref (dh, absyn, e->children);
+       }
+       else
+       {
+           data1_sub_elements *sub_e = absyn->sub_elements;
+           while (sub_e && strcmp (e->sub_name, sub_e->name))
+               sub_e = sub_e->next;
+           if (sub_e)
+               e->children = sub_e->elements;
+           else
+               yaz_log (LOG_WARN, "Unresolved reference to sub-elements %s",
+                     e->sub_name);
+       }
+    }
+}
+
+
+static int parse_termlists (data1_handle dh, data1_termlist ***tpp,
+                           char *p, const char *file, int lineno,
+                           const char *element_name, data1_absyn *res)
+{
+    data1_termlist **tp = *tpp;
+    do
+    {
+       char attname[512], structure[512];
+       char *source;
+       int r;
+       
+       if (!(r = sscanf(p, "%511[^:,]:%511[^,]", attname,
+                        structure)))
+       {
+           yaz_log(LOG_WARN,
+                   "%s:%d: Syntax error in termlistspec '%s'",
+                   file, lineno, p);
+           return -1;
+       }
+       if (*attname == '!')
+           strcpy(attname, element_name);
+       *tp = (data1_termlist *)
+           nmem_malloc(data1_nmem_get(dh), sizeof(**tp));
+       (*tp)->next = 0;
+       if (!((*tp)->att = data1_getattbyname(dh, res->attset,
+                                             attname)))
+       {
+           yaz_log(LOG_WARN,
+                   "%s:%d: Couldn't find att '%s' in attset",
+                   file, lineno, attname);
+           return -1;
+       }
+       if (r == 2 && (source = strchr(structure, ':')))
+           *source++ = '\0';   /* cut off structure .. */
+       else
+           source = "data";    /* ok: default is leaf data */
+       (*tp)->source = (char *)
+           nmem_strdup (data1_nmem_get (dh), source);
+       
+       if (r < 2) /* is the structure qualified? */
+           (*tp)->structure = "w";
+       else 
+           (*tp)->structure = (char *)
+               nmem_strdup (data1_nmem_get (dh), structure);
+       tp = &(*tp)->next;
+    }
+    while ((p = strchr(p, ',')) && *(++p));
+    *tpp = tp;
+    return 0;
+}
+
+data1_absyn *data1_read_absyn (data1_handle dh, const char *file,
+                               int file_must_exist)
+{
+    data1_sub_elements *cur_elements = NULL;
+    data1_absyn *res = 0;
+    FILE *f;
+    data1_element **ppl[D1_MAX_NESTING];
+    data1_esetname **esetpp;
+    data1_maptab **maptabp;
+    data1_marctab **marcp;
+    data1_termlist *all = 0;
+    data1_attset_child **attset_childp;
+    data1_tagset **tagset_childp;
+    int level = 0;
+    int lineno = 0;
+    int argc;
+    char *argv[50], line[512];
+
+    if (!(f = data1_path_fopen(dh, file, "r")))
+    {
+       yaz_log(LOG_WARN|LOG_ERRNO, "Couldn't open %s", file);
+        if (file_must_exist)
+            return 0;
+    }
+    
+    res = (data1_absyn *) nmem_malloc(data1_nmem_get(dh), sizeof(*res));
+    res->name = 0;
+    res->reference = VAL_NONE;
+    res->tagset = 0;
+    res->encoding = 0;
+    res->enable_xpath_indexing = (f ? 0 : 1);
+    tagset_childp = &res->tagset;
+
+    res->attset = data1_empty_attset (dh);
+    attset_childp =  &res->attset->children;
+
+    res->varset = 0;
+    res->esetnames = 0;
+    esetpp = &res->esetnames;
+    res->maptabs = 0;
+    maptabp = &res->maptabs;
+    res->marc = 0;
+    marcp = &res->marc;
+
+    res->sub_elements = NULL;
+    res->main_elements = NULL;
+    
+    while (f && (argc = readconf_line(f, &lineno, line, 512, argv, 50)))
+    {
+       char *cmd = *argv;
+       if (!strcmp(cmd, "elm") || !strcmp(cmd, "element"))
+       {
+           data1_element *new_element;
+           int i;
+           char *p, *sub_p, *path, *name, *termlists;
+           int type, value;
+           data1_termlist **tp;
+
+           if (argc < 4)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to elm", file, lineno);
+               continue;
+           }
+           path = argv[1];
+           name = argv[2];
+           termlists = argv[3];
+
+           if (!cur_elements)
+           {
+                cur_elements = (data1_sub_elements *)
+                   nmem_malloc(data1_nmem_get(dh), sizeof(*cur_elements));
+               cur_elements->next = res->sub_elements;
+               cur_elements->elements = NULL;
+               cur_elements->name = "main";
+               res->sub_elements = cur_elements;
+               
+               level = 0;
+               ppl[level] = &cur_elements->elements;
+            }
+           p = path;
+           for (i = 1;; i++)
+           {
+               char *e;
+
+               if ((e = strchr(p, '/')))
+                   p = e+1;
+               else
+                   break;
+           }
+           if (i > level+1)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad level increase", file, lineno);
+               fclose(f);
+               return 0;
+           }
+           level = i;
+           new_element = *ppl[level-1] = (data1_element *)
+               nmem_malloc(data1_nmem_get(dh), sizeof(*new_element));
+           new_element->next = new_element->children = 0;
+           new_element->tag = 0;
+           new_element->termlists = 0;
+           new_element->sub_name = 0;
+           
+           tp = &new_element->termlists;
+           ppl[level-1] = &new_element->next;
+           ppl[level] = &new_element->children;
+           
+           /* consider subtree (if any) ... */
+           if ((sub_p = strchr (p, ':')) && sub_p[1])
+           {
+               *sub_p++ = '\0';
+               new_element->sub_name =
+                   nmem_strdup (data1_nmem_get(dh), sub_p);            
+           }
+           /* well-defined tag */
+           if (sscanf(p, "(%d,%d)", &type, &value) == 2)
+           {
+               if (!res->tagset)
+               {
+                   yaz_log(LOG_WARN, "%s:%d: No tagset loaded", file, lineno);
+                   fclose(f);
+                   return 0;
+               }
+               if (!(new_element->tag = data1_gettagbynum (dh, res->tagset,
+                                                           type, value)))
+               {
+                   yaz_log(LOG_WARN, "%s:%d: Couldn't find tag %s in tagset",
+                        file, lineno, p);
+                   fclose(f);
+                   return 0;
+               }
+           }
+           /* private tag */
+           else if (*p)
+           {
+               data1_tag *nt =
+                   new_element->tag = (data1_tag *)
+                   nmem_malloc(data1_nmem_get (dh),
+                               sizeof(*new_element->tag));
+               nt->which = DATA1T_string;
+               nt->value.string = nmem_strdup(data1_nmem_get (dh), p);
+               nt->names = (data1_name *)
+                   nmem_malloc(data1_nmem_get(dh), 
+                               sizeof(*new_element->tag->names));
+               nt->names->name = nt->value.string;
+               nt->names->next = 0;
+               nt->kind = DATA1K_string;
+               nt->next = 0;
+               nt->tagset = 0;
+           }
+           else
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad element", file, lineno);
+               fclose(f);
+               return 0;
+           }
+           /* parse termList definitions */
+           p = termlists;
+           if (*p != '-')
+           {
+               assert (res->attset);
+               
+               if (parse_termlists (dh, &tp, p, file, lineno, name, res))
+               {
+                   fclose (f);
+                   return 0;
+               }
+               *tp = all; /* append any ALL entries to the list */
+           }
+           new_element->name = nmem_strdup(data1_nmem_get (dh), name);
+       }
+       else if (!strcmp(cmd, "section"))
+       {
+           char *name;
+           
+           if (argc < 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to section",
+                    file, lineno);
+               continue;
+           }
+           name = argv[1];
+           
+            cur_elements = (data1_sub_elements *)
+               nmem_malloc(data1_nmem_get(dh), sizeof(*cur_elements));
+           cur_elements->next = res->sub_elements;
+           cur_elements->elements = NULL;
+           cur_elements->name = nmem_strdup (data1_nmem_get(dh), name);
+           res->sub_elements = cur_elements;
+           
+           level = 0;
+           ppl[level] = &cur_elements->elements;
+       }
+        else if (!strcmp(cmd, "xpath"))
+        {
+            if (argc != 2)
+            {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to 'xpath' directive",
+                    file, lineno);
+               continue;
+            }
+            if (!strcmp(argv[1], "enable"))
+                res->enable_xpath_indexing = 1;
+            else if (!strcmp (argv[1], "disable"))
+                res->enable_xpath_indexing = 0;
+            else
+            {
+               yaz_log(LOG_WARN, "%s:%d: Expecting disable/enable "
+                        "after 'xpath' directive", file, lineno);
+            }
+        }
+       else if (!strcmp(cmd, "all"))
+       {
+           data1_termlist **tp = &all;
+           if (all)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Too many 'all' directives - ignored",
+                    file, lineno);
+               continue;
+           }
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to 'all' directive",
+                    file, lineno);
+               continue;
+           }
+           if (parse_termlists (dh, &tp, argv[1], file, lineno, 0, res))
+           {
+               fclose (f);
+               return 0;
+           }
+       }
+       else if (!strcmp(cmd, "name"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to name directive",
+                    file, lineno);
+               continue;
+           }
+           res->name = nmem_strdup(data1_nmem_get(dh), argv[1]);
+       }
+       else if (!strcmp(cmd, "reference"))
+       {
+           char *name;
+           
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to reference",
+                    file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if ((res->reference = oid_getvalbyname(name)) == VAL_NONE)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Unknown tagset ref '%s'", 
+                    file, lineno, name);
+               continue;
+           }
+       }
+       else if (!strcmp(cmd, "attset"))
+       {
+           char *name;
+           data1_attset *attset;
+           
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to attset",
+                    file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if (!(attset = data1_get_attset (dh, name)))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Couldn't find attset  %s",
+                    file, lineno, name);
+               continue;
+           }
+           *attset_childp = (data1_attset_child *)
+               nmem_malloc (data1_nmem_get(dh), sizeof(**attset_childp));
+           (*attset_childp)->child = attset;
+           (*attset_childp)->next = 0;
+           attset_childp = &(*attset_childp)->next;
+       }
+       else if (!strcmp(cmd, "tagset"))
+       {
+           char *name;
+           int type = 0;
+           if (argc < 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to tagset",
+                    file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if (argc == 3)
+               type = atoi(argv[2]);
+           *tagset_childp = data1_read_tagset (dh, name, type);
+           if (!(*tagset_childp))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Couldn't load tagset %s",
+                    file, lineno, name);
+               continue;
+           }
+           tagset_childp = &(*tagset_childp)->next;
+       }
+       else if (!strcmp(cmd, "varset"))
+       {
+           char *name;
+
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args in varset",
+                    file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if (!(res->varset = data1_read_varset (dh, name)))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Couldn't load Varset %s",
+                    file, lineno, name);
+               continue;
+           }
+       }
+       else if (!strcmp(cmd, "esetname"))
+       {
+           char *name, *fname;
+
+           if (argc != 3)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args in esetname",
+                    file, lineno);
+               continue;
+           }
+           name = argv[1];
+           fname = argv[2];
+           
+           *esetpp = (data1_esetname *)
+               nmem_malloc(data1_nmem_get(dh), sizeof(**esetpp));
+           (*esetpp)->name = nmem_strdup(data1_nmem_get(dh), name);
+           (*esetpp)->next = 0;
+           if (*fname == '@')
+               (*esetpp)->spec = 0;
+           else if (!((*esetpp)->spec = data1_read_espec1 (dh, fname)))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Espec-1 read failed for %s",
+                    file, lineno, fname);
+               continue;
+           }
+           esetpp = &(*esetpp)->next;
+       }
+       else if (!strcmp(cmd, "maptab"))
+       {
+           char *name;
+           
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args for maptab",
+                     file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if (!(*maptabp = data1_read_maptab (dh, name)))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Couldn't load maptab %s",
+                     file, lineno, name);
+               continue;
+           }
+           maptabp = &(*maptabp)->next;
+       }
+       else if (!strcmp(cmd, "marc"))
+       {
+           char *name;
+           
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # or args for marc",
+                    file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if (!(*marcp = data1_read_marctab (dh, name)))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Couldn't read marctab %s",
+                     file, lineno, name);
+               continue;
+           }
+           marcp = &(*marcp)->next;
+       }
+       else if (!strcmp(cmd, "encoding"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # or args for encoding",
+                    file, lineno);
+               continue;
+           }
+            res->encoding = nmem_strdup (data1_nmem_get(dh), argv[1]);
+       }
+       else
+       {
+           yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'", file, 
+                    lineno, cmd);
+           continue;
+       }
+    }
+    if (f)
+        fclose(f);
+    
+    for (cur_elements = res->sub_elements; cur_elements;
+        cur_elements = cur_elements->next)
+    {
+       if (!strcmp (cur_elements->name, "main"))
+           res->main_elements = cur_elements->elements;
+       fix_element_ref (dh, res, cur_elements->elements);
+    }
+    yaz_log (LOG_DEBUG, "%s: data1_read_absyn end", file);
+    return res;
+}
diff --git a/data1/d1_attset.c b/data1/d1_attset.c
new file mode 100644 (file)
index 0000000..568027f
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 1995-1999, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: d1_attset.c,v $
+ * Revision 1.1  2002-10-22 12:53:33  adam
+ * data1 part of zebra
+ *
+ * Revision 1.15  2002/04/04 20:49:46  adam
+ * New functions yaz_is_abspath, yaz_path_fopen_base
+ *
+ * Revision 1.14  1999/11/30 13:47:12  adam
+ * Improved installation. Moved header files to include/yaz.
+ *
+ * Revision 1.13  1999/10/21 12:06:29  adam
+ * Retrieval module no longer uses ctype.h - functions.
+ *
+ * Revision 1.12  1999/08/27 09:40:32  adam
+ * Renamed logf function to yaz_log. Removed VC++ project files.
+ *
+ * Revision 1.11  1998/10/14 13:31:56  adam
+ * Bug fix. Bug introduced by previous commit.
+ *
+ * Revision 1.10  1998/10/13 16:09:48  adam
+ * Added support for arbitrary OID's for tagsets, schemas and attribute sets.
+ * Added support for multiple attribute set references and tagset references
+ * from an abstract syntax file.
+ * Fixed many bad logs-calls in routines that read the various
+ * specifications regarding data1 (*.abs,*.att,...) and made the messages
+ * consistent whenever possible.
+ * Added extra 'lineno' argument to function readconf_line.
+ *
+ * Revision 1.9  1998/05/18 13:07:03  adam
+ * Changed the way attribute sets are handled by the retriaval module.
+ * Extended Explain conversion / schema.
+ * Modified server and client to work with ASN.1 compiled protocol handlers.
+ *
+ * Revision 1.8  1998/02/11 11:53:35  adam
+ * Changed code so that it compiles as C++.
+ *
+ * Revision 1.7  1997/09/17 12:10:34  adam
+ * YAZ version 1.4.
+ *
+ * Revision 1.6  1997/09/05 09:50:56  adam
+ * Removed global data1_tabpath - uses data1_get_tabpath() instead.
+ *
+ * Revision 1.5  1996/05/09 07:27:43  quinn
+ * Multiple local attributes values supported.
+ *
+ * Revision 1.4  1996/02/21  15:23:36  quinn
+ * Reversed fclose and return;
+ *
+ * Revision 1.3  1995/12/13  17:14:26  quinn
+ * *** empty log message ***
+ *
+ * Revision 1.2  1995/11/01  16:34:55  quinn
+ * Making data1 look for tables in data1_tabpath
+ *
+ * Revision 1.1  1995/11/01  11:56:07  quinn
+ * Added Retrieval (data management) functions en masse.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include <yaz/log.h>
+#include <d1_attset.h>
+#include <data1.h>
+
+data1_att *data1_getattbyname(data1_handle dh, data1_attset *s, char *name)
+{
+    data1_att *r;
+    data1_attset_child *c;
+    
+    /* scan local set */
+    for (r = s->atts; r; r = r->next)
+       if (!data1_matchstr(r->name, name))
+           return r;
+    for (c = s->children; c; c = c->next)
+    {
+       assert (c->child);
+       /* scan included sets */
+       if ((r = data1_getattbyname (dh, c->child, name)))
+           return r;
+    }
+    return 0;
+}
+
+data1_attset *data1_empty_attset(data1_handle dh)
+{
+    NMEM mem = data1_nmem_get (dh);
+    data1_attset *res = (data1_attset*) nmem_malloc(mem,sizeof(*res));
+
+    res->name = 0;
+    res->reference = VAL_NONE;
+    res->atts = 0;
+    res->children = 0;
+    res->next = 0;
+    return res;
+}
+
+data1_attset *data1_read_attset(data1_handle dh, const char *file)
+{
+    data1_attset *res = 0;
+    data1_attset_child **childp;
+    data1_att **attp;
+    FILE *f;
+    NMEM mem = data1_nmem_get (dh);
+    int lineno = 0;
+    int argc;
+    char *argv[50], line[512];
+
+    if (!(f = data1_path_fopen(dh, file, "r")))
+       return NULL;
+    res = data1_empty_attset (dh);
+
+    childp = &res->children;
+    attp = &res->atts;
+
+    while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
+    {
+       char *cmd = argv[0];
+       if (!strcmp(cmd, "att"))
+       {
+           int num;
+           char *name;
+           data1_att *t;
+           data1_local_attribute *locals;
+           
+           if (argc < 3)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to att", file, lineno);
+               continue;
+           }
+           num = atoi (argv[1]);
+           name = argv[2];
+           
+           if (argc == 3) /* no local attributes given */
+           {
+               locals = (data1_local_attribute *)
+                   nmem_malloc(mem, sizeof(*locals));
+               locals->local = num;
+               locals->next = 0;
+           }
+           else /* parse the string "local{,local}" */
+           {
+               char *p = argv[3];
+               data1_local_attribute **ap = &locals;
+               do
+               {
+                   *ap = (data1_local_attribute *)
+                       nmem_malloc(mem, sizeof(**ap));
+                   (*ap)->local = atoi(p);
+                   (*ap)->next = 0;
+                   ap = &(*ap)->next;
+               }
+               while ((p = strchr(p, ',')) && *(++p));
+           }
+           t = *attp = (data1_att *)nmem_malloc(mem, sizeof(*t));
+           t->parent = res;
+           t->name = nmem_strdup(mem, name);
+           t->value = num;
+           t->locals = locals;
+           t->next = 0;
+           attp = &t->next;
+       }
+       else if (!strcmp(cmd, "name"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to name", file, lineno);
+               continue;
+           }
+       }
+       else if (!strcmp(cmd, "reference"))
+       {
+           char *name;
+
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to reference",
+                       file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if ((res->reference = oid_getvalbyname(name)) == VAL_NONE)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Unknown reference oid '%s'",
+                       file, lineno, name);
+               fclose(f);
+               return 0;
+           }
+       }
+       else if (!strcmp(cmd, "ordinal"))
+       {
+           yaz_log (LOG_WARN, "%s:%d: Directive ordinal ignored",
+                    file, lineno);
+       }
+       else if (!strcmp(cmd, "include"))
+       {
+           char *name;
+           data1_attset *attset;
+
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args to include",
+                       file, lineno);
+               continue;
+           }
+           name = argv[1];
+
+           if (!(attset = data1_get_attset (dh, name)))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Include of attset %s failed",
+                       file, lineno, name);
+               continue;
+               
+           }
+           *childp = (data1_attset_child *)
+               nmem_malloc (mem, sizeof(**childp));
+           (*childp)->child = attset;
+           (*childp)->next = 0;
+           childp = &(*childp)->next;
+       }
+       else
+       {
+           yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'",
+                   file, lineno, cmd);
+       }
+    }
+    fclose(f);
+    return res;
+}
diff --git a/data1/d1_doespec.c b/data1/d1_doespec.c
new file mode 100644 (file)
index 0000000..b809fa3
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_doespec.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <assert.h>
+
+#include <yaz/oid.h>
+#include <yaz/log.h>
+#include <yaz/proto.h>
+#include <data1.h>
+
+static int match_children(data1_handle dh, data1_node *n,
+                         Z_Espec1 *e, int i, Z_ETagUnit **t,
+    int num);
+
+static int match_children_wildpath(data1_handle dh, data1_node *n,
+                                  Z_Espec1 *e, int i,
+                                  Z_ETagUnit **t, int num)
+{
+    return 0;
+}
+
+/*
+ * Locate a specific triple within a variant.
+ * set is the set to look for, universal set is the set that applies to a
+ * triple with an unknown set.
+ */
+static Z_Triple *find_triple(Z_Variant *var, oid_value universalset,
+    oid_value set, int zclass, int type)
+{
+    int i;
+    oident *defaultsetent = oid_getentbyoid(var->globalVariantSetId);
+    oid_value defaultset = defaultsetent ? defaultsetent->value :
+       universalset;
+
+    for (i = 0; i < var->num_triples; i++)
+    {
+       oident *cursetent =
+           oid_getentbyoid(var->triples[i]->variantSetId);
+       oid_value curset = cursetent ? cursetent->value : defaultset;
+
+       if (set == curset &&
+           *var->triples[i]->zclass == zclass &&
+           *var->triples[i]->type == type)
+           return var->triples[i];
+    }
+    return 0;
+}
+
+static void mark_subtree(data1_node *n, int make_variantlist, int no_data,
+    int get_bytes, Z_Variant *vreq)
+{
+    data1_node *c;
+
+#if 1
+    if (n->which == DATA1N_tag)
+#else
+    if (n->which == DATA1N_tag && (!n->child || n->child->which != DATA1N_tag))
+    /*
+     * This seems to cause multi-level elements to fall out when only a
+     * top-level elementRequest has been given... Problem is, I can't figure
+     * out what it was supposed to ACHIEVE.... delete when code has been
+     * verified.
+     */
+#endif
+    {
+       n->u.tag.node_selected = 1;
+       n->u.tag.make_variantlist = make_variantlist;
+       n->u.tag.no_data_requested = no_data;
+       n->u.tag.get_bytes = get_bytes;
+    }
+
+    for (c = n->child; c; c = c->next)
+    {
+       if (c->which == DATA1N_tag && (!n->child ||
+           n->child->which != DATA1N_tag))
+       {
+           c->u.tag.node_selected = 1;
+           c->u.tag.make_variantlist = make_variantlist;
+           c->u.tag.no_data_requested = no_data;
+           c->u.tag.get_bytes = get_bytes;
+       }
+       mark_subtree(c, make_variantlist, no_data, get_bytes, vreq);
+    }
+}
+
+
+static void match_triple (data1_handle dh, Z_Variant *vreq,
+                         oid_value defsetval,
+                         oid_value var1, data1_node *n)
+{
+    data1_node **c;
+
+    if (!(n = n->child))
+        return;
+    if (n->which != DATA1N_variant)
+       return;
+    c = &n->child;
+    while (*c)
+    {
+       int remove_flag = 0;
+       Z_Triple *r;
+       
+       assert ((*c)->which == DATA1N_variant);
+       
+       if ((*c)->u.variant.type->zclass->zclass == 4 &&
+           (*c)->u.variant.type->type == 1)
+       {
+           if ((r = find_triple(vreq, defsetval, var1, 4, 1)) &&
+               (r->which == Z_Triple_internationalString))
+           {
+               const char *string_value =
+                   r->value.internationalString;
+               if (strcmp ((*c)->u.variant.value, string_value))
+                   remove_flag = 1;
+           }
+       }
+       if (remove_flag)
+       {
+           data1_free_tree (dh, *c);
+           *c = (*c)->next;
+       }
+       else
+       {
+           match_triple (dh, vreq, defsetval, var1, *c);
+           c = &(*c)->next;
+       }
+    }
+}
+                               
+static int match_children_here (data1_handle dh, data1_node *n,
+                               Z_Espec1 *e, int i,
+                               Z_ETagUnit **t, int num)
+{
+    int counter = 0, hits = 0;
+    data1_node *c;
+    Z_ETagUnit *tp = *t;
+    Z_Occurrences *occur;
+
+    for (c = n->child; c ; c = c->next)
+    {
+       data1_tag *tag = 0;
+
+       if (c->which != DATA1N_tag)
+            continue;
+
+       if (tp->which == Z_ETagUnit_specificTag)
+       {
+           Z_SpecificTag *want = tp->u.specificTag;
+           occur = want->occurrences;
+           if (c->u.tag.element)
+               tag = c->u.tag.element->tag;
+           if (*want->tagType != ((tag && tag->tagset) ? tag->tagset->type :
+               3))
+               continue;
+           if (want->tagValue->which == Z_StringOrNumeric_numeric)
+           {
+               if (!tag || tag->which != DATA1T_numeric)
+                   continue;
+               if (*want->tagValue->u.numeric != tag->value.numeric)
+                   continue;
+           }
+           else
+           {
+               assert(want->tagValue->which == Z_StringOrNumeric_string);
+               if (tag && tag->which != DATA1T_string)
+                   continue;
+               if (data1_matchstr(want->tagValue->u.string,
+                   tag ? tag->value.string : c->u.tag.tag))
+                   continue;
+           }
+       }
+       else
+           occur = tp->u.wildThing;
+
+       /*
+        * Ok, so we have a matching tag. Are we within occurrences-range?
+        */
+       counter++;
+       if (occur && occur->which == Z_Occurrences_last)
+       {
+           yaz_log(LOG_WARN, "Can't do occurrences=last (yet)");
+           return 0;
+       }
+       if (!occur || occur->which == Z_Occurrences_all ||
+           (occur->which == Z_Occurrences_values && counter >=
+           *occur->u.values->start))
+       {
+           if (match_children(dh, c, e, i, t + 1, num - 1))
+           {
+               c->u.tag.node_selected = 1;
+               /*
+                * Consider the variant specification if this is a complete
+                * match.
+                */
+               if (num == 1)
+               {
+                   int show_variantlist = 0;
+                   int no_data = 0;
+                   int get_bytes = -1;
+
+                   Z_Variant *vreq =
+                       e->elements[i]->u.simpleElement->variantRequest;
+                   oident *defset = oid_getentbyoid(e->defaultVariantSetId);
+                   oid_value defsetval = defset ? defset->value : VAL_NONE;
+                   oid_value var1 = oid_getvalbyname("Variant-1");
+
+                   if (!vreq)
+                       vreq = e->defaultVariantRequest;
+
+                   if (vreq)
+                   {
+                       Z_Triple *r;
+
+                       /*
+                        * 6,5: meta-data requested, variant list.
+                        */
+                       if (find_triple(vreq, defsetval, var1, 6, 5))
+                           show_variantlist = 1;
+                       /*
+                        * 9,1: Miscellaneous, no data requested.
+                        */
+                       if (find_triple(vreq, defsetval, var1, 9, 1))
+                           no_data = 1;
+
+                       /* howmuch */
+                       if ((r = find_triple(vreq, defsetval, var1, 5, 5)))
+                           if (r->which == Z_Triple_integer)
+                               get_bytes = *r->value.integer;
+
+                       if (!show_variantlist)
+                           match_triple (dh, vreq, defsetval, var1, c);
+                   }
+                   mark_subtree(c, show_variantlist, no_data, get_bytes, vreq);
+               }
+               hits++;
+               /*
+                * have we looked at enough children?
+                */
+               if (!occur || (occur->which == Z_Occurrences_values &&
+                   (!occur->u.values->howMany ||
+                   counter - *occur->u.values->start >=
+                   *occur->u.values->howMany - 1)))
+                   return hits;
+           }
+       }
+    }
+    return hits;
+}
+
+static int match_children(data1_handle dh, data1_node *n, Z_Espec1 *e,
+                         int i, Z_ETagUnit **t, int num)
+{
+    int res;
+
+    if (!num)
+       return 1;
+    switch (t[0]->which)
+    {
+    case Z_ETagUnit_wildThing:
+    case Z_ETagUnit_specificTag:
+        res = match_children_here(dh, n, e, i, t, num); break;
+    case Z_ETagUnit_wildPath:
+        res = match_children_wildpath(dh, n, e, i, t, num); break;
+    default:
+        abort();
+    }
+    return res;
+}
+
+int data1_doespec1 (data1_handle dh, data1_node *n, Z_Espec1 *e)
+{
+    int i;
+
+    n = data1_get_root_tag (dh, n);
+    if (n && n->which == DATA1N_tag)
+        n->u.tag.node_selected = 1;
+    
+    for (i = 0; i < e->num_elements; i++)
+    {
+        if (e->elements[i]->which != Z_ERequest_simpleElement)
+            return 100;
+        match_children(dh, n, e, i,
+                       e->elements[i]->u.simpleElement->path->tags,
+                       e->elements[i]->u.simpleElement->path->num_tags);
+    }
+    return 0;
+}
diff --git a/data1/d1_espec.c b/data1/d1_espec.c
new file mode 100644 (file)
index 0000000..18ce961
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_espec.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include <yaz/odr.h>
+#include <yaz/proto.h>
+#include <yaz/log.h>
+#include <data1.h>
+
+static Z_Variant *read_variant(int argc, char **argv, NMEM nmem,
+                              const char *file, int lineno)
+{
+    Z_Variant *r = (Z_Variant *)nmem_malloc(nmem, sizeof(*r));
+    oident var1;
+    int i;
+    int oid[OID_SIZE];
+
+    var1.proto = PROTO_Z3950;
+    var1.oclass = CLASS_VARSET;
+    var1.value = VAL_VAR1;
+    r->globalVariantSetId = odr_oiddup_nmem(nmem, oid_ent_to_oid(&var1, oid));
+
+    if (argc)
+       r->triples = (Z_Triple **)nmem_malloc(nmem, sizeof(Z_Triple*) * argc);
+    else
+       r->triples = 0;
+    r->num_triples = argc;
+    for (i = 0; i < argc; i++)
+    {
+       int zclass, type;
+       char value[512];
+       Z_Triple *t;
+
+       if (sscanf(argv[i], "(%d,%d,%511[^)])", &zclass, &type, value) < 3)
+       {
+           yaz_log(LOG_WARN, "%s:%d: Syntax error in variant component '%s'",
+                   file, lineno, argv[i]);
+           return 0;
+       }
+       t = r->triples[i] = (Z_Triple *)nmem_malloc(nmem, sizeof(Z_Triple));
+       t->variantSetId = 0;
+       t->zclass = (int *)nmem_malloc(nmem, sizeof(int));
+       *t->zclass = zclass;
+       t->type = (int *)nmem_malloc(nmem, sizeof(int));
+       *t->type = type;
+       /*
+        * This is wrong.. we gotta look up the correct type for the
+        * variant, I guess... damn this stuff.
+        */
+       if (*value == '@')
+       {
+           t->which = Z_Triple_null;
+           t->value.null = odr_nullval();
+       }
+       else if (d1_isdigit(*value))
+       {
+           t->which = Z_Triple_integer;
+           t->value.integer = (int *)
+               nmem_malloc(nmem, sizeof(*t->value.integer));
+           *t->value.integer = atoi(value);
+       }
+       else
+       {
+           t->which = Z_Triple_internationalString;
+           t->value.internationalString = (char *)
+               nmem_malloc(nmem, strlen(value)+1);
+           strcpy(t->value.internationalString, value);
+       }
+    }
+    return r;
+}
+
+static Z_Occurrences *read_occurrences(char *occ, NMEM nmem,
+                                      const char *file, int lineno)
+{
+    Z_Occurrences *op = (Z_Occurrences *)nmem_malloc(nmem, sizeof(*op));
+    char *p;
+    
+    if (!occ)
+    {
+       op->which = Z_Occurrences_values;
+       op->u.values = (Z_OccurValues *)
+           nmem_malloc(nmem, sizeof(Z_OccurValues));
+       op->u.values->start = (int *)nmem_malloc(nmem, sizeof(int));
+       *op->u.values->start = 1;
+       op->u.values->howMany = 0;
+    }
+    else if (!strcmp(occ, "all"))
+    {
+       op->which = Z_Occurrences_all;
+       op->u.all = odr_nullval();
+    }
+    else if (!strcmp(occ, "last"))
+    {
+       op->which = Z_Occurrences_last;
+       op->u.all = odr_nullval();
+    }
+    else
+    {
+       Z_OccurValues *ov = (Z_OccurValues *)nmem_malloc(nmem, sizeof(*ov));
+    
+       if (!d1_isdigit(*occ))
+       {
+           yaz_log(LOG_WARN, "%s:%d: Bad occurrences-spec %s",
+                   file, lineno, occ);
+           return 0;
+       }
+       op->which = Z_Occurrences_values;
+       op->u.values = ov;
+       ov->start = (int *)nmem_malloc(nmem, sizeof(*ov->start));
+       *ov->start = atoi(occ);
+       if ((p = strchr(occ, '+')))
+       {
+           ov->howMany = (int *)nmem_malloc(nmem, sizeof(*ov->howMany));
+           *ov->howMany = atoi(p + 1);
+       }
+       else
+           ov->howMany = 0;
+    }
+    return op;
+}
+
+
+static Z_ETagUnit *read_tagunit(char *buf, NMEM nmem,
+                               const char *file, int lineno)
+{
+    Z_ETagUnit *u = (Z_ETagUnit *)nmem_malloc(nmem, sizeof(*u));
+    int terms;
+    int type;
+    char value[512], occ[512];
+    
+    if (*buf == '*')
+    {
+       u->which = Z_ETagUnit_wildPath;
+       u->u.wildPath = odr_nullval();
+    }
+    else if (*buf == '?')
+    {
+       u->which = Z_ETagUnit_wildThing;
+       if (buf[1] == ':')
+           u->u.wildThing = read_occurrences(buf+2, nmem, file, lineno);
+       else
+           u->u.wildThing = read_occurrences(0, nmem, file, lineno);
+    }
+    else if ((terms = sscanf(buf, "(%d,%511[^)]):%511[a-zA-Z0-9+]",
+                             &type, value, occ)) >= 2)
+    {
+       int numval;
+       Z_SpecificTag *t;
+       char *valp = value;
+       int force_string = 0;
+       
+       if (*valp == '\'')
+       {
+           valp++;
+           force_string = 1;
+       }
+       u->which = Z_ETagUnit_specificTag;
+       u->u.specificTag = t = (Z_SpecificTag *)nmem_malloc(nmem, sizeof(*t));
+       t->tagType = (int *)nmem_malloc(nmem, sizeof(*t->tagType));
+       *t->tagType = type;
+       t->tagValue = (Z_StringOrNumeric *)
+           nmem_malloc(nmem, sizeof(*t->tagValue));
+       if (!force_string && (numval = atoi(valp)))
+       {
+           t->tagValue->which = Z_StringOrNumeric_numeric;
+           t->tagValue->u.numeric = (int *)nmem_malloc(nmem, sizeof(int));
+           *t->tagValue->u.numeric = numval;
+       }
+       else
+       {
+           t->tagValue->which = Z_StringOrNumeric_string;
+           t->tagValue->u.string = (char *)nmem_malloc(nmem, strlen(valp)+1);
+           strcpy(t->tagValue->u.string, valp);
+       }
+       if (terms > 2) /* an occurrences-spec exists */
+           t->occurrences = read_occurrences(occ, nmem, file, lineno);
+       else
+           t->occurrences = 0;
+    }
+    return u;
+}
+
+/*
+ * Read an element-set specification from a file.
+ * NOTE: If !o, memory is allocated directly from the heap by nmem_malloc().
+ */
+Z_Espec1 *data1_read_espec1 (data1_handle dh, const char *file)
+{
+    FILE *f;
+    NMEM nmem = data1_nmem_get (dh);
+    int lineno = 0;
+    int argc, size_esn = 0;
+    char *argv[50], line[512];
+    Z_Espec1 *res = (Z_Espec1 *)nmem_malloc(nmem, sizeof(*res));
+    
+    if (!(f = data1_path_fopen(dh, file, "r")))
+    {
+       yaz_log(LOG_WARN|LOG_ERRNO, "%s", file);
+       return 0;
+    }
+    
+    res->num_elementSetNames = 0;
+    res->elementSetNames = 0;
+    res->defaultVariantSetId = 0;
+    res->defaultVariantRequest = 0;
+    res->defaultTagType = 0;
+    res->num_elements = 0;
+    res->elements = 0;
+    
+    while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
+       if (!strcmp(argv[0], "elementsetnames"))
+       {
+           int nnames = argc-1, i;
+           
+           if (!nnames)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Empty elementsetnames directive",
+                       file, lineno);
+               continue;
+           }
+           
+           res->elementSetNames =
+               (char **)nmem_malloc(nmem, sizeof(char**)*nnames);
+           for (i = 0; i < nnames; i++)
+           {
+               res->elementSetNames[i] = (char *)
+                   nmem_malloc(nmem, strlen(argv[i+1])+1);
+               strcpy(res->elementSetNames[i], argv[i+1]);
+           }
+           res->num_elementSetNames = nnames;
+       }
+       else if (!strcmp(argv[0], "defaultvariantsetid"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args for %s",
+                       file, lineno, argv[0]);
+               continue;
+           }
+           if (!(res->defaultVariantSetId =
+                 odr_getoidbystr_nmem(nmem, argv[1])))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad defaultvariantsetid",
+                       file, lineno);
+               continue;
+           }
+       }
+       else if (!strcmp(argv[0], "defaulttagtype"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args for %s",
+                       file, lineno, argv[0]);
+               continue;
+           }
+           res->defaultTagType = (int *)nmem_malloc(nmem, sizeof(int));
+           *res->defaultTagType = atoi(argv[1]);
+       }
+       else if (!strcmp(argv[0], "defaultvariantrequest"))
+       {
+           if (!(res->defaultVariantRequest =
+                 read_variant(argc-1, argv+1, nmem, file, lineno)))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad defaultvariantrequest",
+                       file, lineno);
+               continue;
+           }
+       }
+       else if (!strcmp(argv[0], "simpleelement"))
+       {
+           Z_ElementRequest *er;
+           Z_SimpleElement *se;
+           Z_ETagPath *tp;
+           char *path = argv[1];
+           char *ep;
+           int num, i = 0;
+           
+           if (!res->elements)
+               res->elements = (Z_ElementRequest **)
+                   nmem_malloc(nmem, size_esn = 24*sizeof(er));
+           else if (res->num_elements >= (int) (size_esn/sizeof(er)))
+           {
+               Z_ElementRequest **oe = res->elements;
+               size_esn *= 2;
+               res->elements = (Z_ElementRequest **)
+                   nmem_malloc (nmem, size_esn*sizeof(er));
+               memcpy (res->elements, oe, size_esn/2);
+           }
+           if (argc < 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args for %s",
+                       file, lineno, argv[0]);
+               continue;
+           }
+           
+           res->elements[res->num_elements++] = er =
+               (Z_ElementRequest *)nmem_malloc(nmem, sizeof(*er));
+           er->which = Z_ERequest_simpleElement;
+           er->u.simpleElement = se = (Z_SimpleElement *)
+               nmem_malloc(nmem, sizeof(*se));
+           se->variantRequest = 0;
+           se->path = tp = (Z_ETagPath *)nmem_malloc(nmem, sizeof(*tp));
+           tp->num_tags = 0;
+           /*
+            * Parse the element selector.
+            */
+           for (num = 1, ep = path; (ep = strchr(ep, '/')); num++, ep++)
+               ;
+           tp->tags = (Z_ETagUnit **)
+               nmem_malloc(nmem, sizeof(Z_ETagUnit*)*num);
+           
+           for ((ep = strchr(path, '/')) ; path ;
+                (void)((path = ep) && (ep = strchr(path, '/'))))
+           {
+               Z_ETagUnit *tagunit;
+               if (ep)
+                   ep++;
+               
+               assert(i<num);
+               tagunit = read_tagunit(path, nmem, file, lineno);
+               if (!tagunit)
+               {
+                   yaz_log (LOG_WARN, "%s%d: Bad tag unit at %s",
+                            file, lineno, path);
+                   break;
+               }
+               tp->tags[tp->num_tags++] = tagunit;
+           }
+           
+           if (argc > 2 && !strcmp(argv[2], "variant"))
+               se->variantRequest=
+                   read_variant(argc-3, argv+3, nmem, file, lineno);
+       }
+       else
+           yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'",
+                   file, lineno, argv[0]);
+    fclose (f);
+    return res;
+}
diff --git a/data1/d1_expout.c b/data1/d1_expout.c
new file mode 100644 (file)
index 0000000..bad04a7
--- /dev/null
@@ -0,0 +1,1463 @@
+/*
+ * Copyright (c) 1995-1999, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: d1_expout.c,v $
+ * Revision 1.1  2002-10-22 12:53:33  adam
+ * data1 part of zebra
+ *
+ * Revision 1.17  1999/11/30 13:47:12  adam
+ * Improved installation. Moved header files to include/yaz.
+ *
+ * Revision 1.16  1999/08/27 09:40:32  adam
+ * Renamed logf function to yaz_log. Removed VC++ project files.
+ *
+ * Revision 1.15  1998/09/28 12:44:40  adam
+ * Fixed bug in f_integer.
+ *
+ * Revision 1.14  1998/06/08 14:26:41  adam
+ * Fixed bug in f_queryTypeDetails.
+ *
+ * Revision 1.13  1998/06/05 08:58:48  adam
+ * Fixed un-initialised var in f_rpnCapabilities.
+ *
+ * Revision 1.12  1998/05/18 13:07:04  adam
+ * Changed the way attribute sets are handled by the retriaval module.
+ * Extended Explain conversion / schema.
+ * Modified server and client to work with ASN.1 compiled protocol handlers.
+ *
+ * Revision 1.11  1998/04/02 08:27:37  adam
+ * Minor change in definition of Z_TargetInfo. Furhter work on Explain
+ * schema - added AttributeDetails.
+ *
+ * Revision 1.10  1998/03/31 15:13:20  adam
+ * Development towards compiled ASN.1.
+ *
+ * Revision 1.9  1998/03/05 08:07:58  adam
+ * Make data1 to EXPLAIN ignore local tags in root.
+ *
+ * Revision 1.8  1998/02/11 11:53:35  adam
+ * Changed code so that it compiles as C++.
+ *
+ * Revision 1.7  1997/12/09 16:18:16  adam
+ * Work on EXPLAIN schema. First implementation of sub-schema facility
+ * in the *.abs files.
+ *
+ * Revision 1.6  1997/11/24 11:33:56  adam
+ * Using function odr_nullval() instead of global ODR_NULLVAL when
+ * appropriate.
+ *
+ * Revision 1.5  1997/11/19 10:30:06  adam
+ * More explain work.
+ *
+ * Revision 1.4  1997/11/18 09:51:08  adam
+ * Removed element num_children from data1_node. Minor changes in
+ * data1 to Explain.
+ *
+ * Revision 1.3  1997/09/17 12:10:36  adam
+ * YAZ version 1.4.
+ *
+ * Revision 1.2  1995/12/14 16:28:30  quinn
+ * More explain stuff.
+ *
+ * Revision 1.1  1995/12/14  11:09:51  quinn
+ * Work on Explain
+ *
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <yaz/log.h>
+#include <yaz/proto.h>
+#include <data1.h>
+
+typedef struct {
+    data1_handle dh;
+    ODR o;
+    int select;
+
+    bool_t *false_value;
+    bool_t *true_value;
+} ExpHandle;
+
+static int is_numeric_tag (ExpHandle *eh, data1_node *c)
+{
+    if (!c || c->which != DATA1N_tag)
+       return 0;
+    if (!c->u.tag.element)
+    {
+       yaz_log(LOG_WARN, "Tag %s is local", c->u.tag.tag);
+       return 0;
+    }
+    if (c->u.tag.element->tag->which != DATA1T_numeric)
+    {
+       yaz_log(LOG_WARN, "Tag %s is not numeric", c->u.tag.tag);
+       return 0;
+    }
+    if (eh->select && !c->u.tag.node_selected)
+       return 0;
+    return c->u.tag.element->tag->value.numeric;
+}
+
+static int is_data_tag (ExpHandle *eh, data1_node *c)
+{
+    if (!c || c->which != DATA1N_data)
+       return 0;
+    if (eh->select && !c->u.tag.node_selected)
+       return 0;
+    return 1;
+}
+
+static int *f_integer(ExpHandle *eh, data1_node *c)
+{
+    int *r;
+    char intbuf[64];
+
+    c = c->child;
+    if (!is_data_tag (eh, c) || c->u.data.len > 63)
+       return 0;
+    r = (int *)odr_malloc(eh->o, sizeof(*r));
+    sprintf(intbuf, "%.*s", c->u.data.len, c->u.data.data);
+    *r = atoi(intbuf);
+    return r;
+}
+
+static char *f_string(ExpHandle *eh, data1_node *c)
+{
+    char *r;
+
+    c = c->child;
+    if (!is_data_tag (eh, c))
+       return 0;
+    r = (char *)odr_malloc(eh->o, c->u.data.len+1);
+    memcpy(r, c->u.data.data, c->u.data.len);
+    r[c->u.data.len] = '\0';
+    return r;
+}
+
+static bool_t *f_bool(ExpHandle *eh, data1_node *c)
+{
+    bool_t *tf;
+    char intbuf[64];
+
+    c = c->child;
+    if (!is_data_tag (eh, c) || c->u.data.len > 63)
+       return 0;
+    tf = (int *)odr_malloc (eh->o, sizeof(*tf));
+    sprintf(intbuf, "%.*s", c->u.data.len, c->u.data.data);
+    *tf = atoi(intbuf);
+    return tf;
+}
+
+static Odr_oid *f_oid(ExpHandle *eh, data1_node *c, oid_class oclass)
+{
+    char oidstr[64];
+    int oid_this[20];
+    oid_value value_for_this;
+
+    c = c->child;
+    if (!is_data_tag (eh, c) || c->u.data.len > 63)
+       return 0;
+    sprintf(oidstr, "%.*s", c->u.data.len, c->u.data.data);
+    value_for_this = oid_getvalbyname(oidstr);
+    if (value_for_this == VAL_NONE)
+    {
+       Odr_oid *oid = odr_getoidbystr(eh->o, oidstr);
+       assert (oid);
+       return oid;
+    }
+    else
+    {
+       struct oident ident;
+
+       ident.oclass = oclass;
+       ident.proto = PROTO_Z3950;
+       ident.value = value_for_this;
+       
+       oid_ent_to_oid (&ident, oid_this);
+    }
+    return odr_oiddup (eh->o, oid_this);
+}
+
+static Z_IntUnit *f_intunit(ExpHandle *eh, data1_node *c)
+{
+    /* fix */
+    return 0;
+}
+
+static Z_HumanString *f_humstring(ExpHandle *eh, data1_node *c)
+{
+    Z_HumanString *r;
+    Z_HumanStringUnit *u;
+
+    c = c->child;
+    if (!is_data_tag (eh, c))
+       return 0;
+    r = (Z_HumanString *)odr_malloc(eh->o, sizeof(*r));
+    r->num_strings = 1;
+    r->strings = (Z_HumanStringUnit **)odr_malloc(eh->o, sizeof(Z_HumanStringUnit*));
+    r->strings[0] = u = (Z_HumanStringUnit *)odr_malloc(eh->o, sizeof(*u));
+    u->language = 0;
+    u->text = (char *)odr_malloc(eh->o, c->u.data.len+1);
+    memcpy(u->text, c->u.data.data, c->u.data.len);
+    u->text[c->u.data.len] = '\0';
+    return r;
+}
+
+static Z_CommonInfo *f_commonInfo(ExpHandle *eh, data1_node *n)
+{
+    Z_CommonInfo *res = (Z_CommonInfo *)odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->dateAdded = 0;
+    res->dateChanged = 0;
+    res->expiry = 0;
+    res->humanStringLanguage = 0;
+    res->otherInfo = 0;
+
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+           case 601: res->dateAdded = f_string(eh, c); break;
+           case 602: res->dateChanged = f_string(eh, c); break;
+           case 603: res->expiry = f_string(eh, c); break;
+           case 604: res->humanStringLanguage = f_string(eh, c); break;
+       }
+    }
+    return res;
+}
+
+Odr_oid **f_oid_seq (ExpHandle *eh, data1_node *n, int *num, oid_class oclass)
+{
+    Odr_oid **res;
+    data1_node *c;
+    int i;
+
+    *num = 0;
+    for (c = n->child ; c; c = c->next)
+       if (is_numeric_tag (eh, c) == 1000)
+           ++(*num);
+    if (!*num)
+       return NULL;
+    res = (int **)odr_malloc (eh->o, sizeof(*res) * (*num));
+    for (c = n->child, i = 0 ; c; c = c->next)
+       if (is_numeric_tag (eh, c) == 1000)
+           res[i++] = f_oid (eh, c, oclass);
+    return res;
+}
+    
+char **f_string_seq (ExpHandle *eh, data1_node *n, int *num)
+{
+    char **res;
+    data1_node *c;
+    int i;
+
+    *num = 0;
+    for (c = n->child ; c; c = c->next)
+    {
+       if (is_numeric_tag (eh, c) != 1001)
+           continue;
+       ++(*num);
+    }
+    if (!*num)
+       return NULL;
+    res = (char **)odr_malloc (eh->o, sizeof(*res) * (*num));
+    for (c = n->child, i = 0 ; c; c = c->next)
+    {
+       if (is_numeric_tag (eh, c) != 1001)
+           continue;
+       res[i++] = f_string (eh, c);
+    }
+    return res;
+}
+
+Z_ProximitySupport *f_proximitySupport (ExpHandle *eh, data1_node *n)
+{
+    Z_ProximitySupport *res = (Z_ProximitySupport *)
+       odr_malloc (eh->o, sizeof(*res));
+    res->anySupport = eh->false_value;
+    res->num_unitsSupported = 0;
+    res->unitsSupported = 0;
+    return res;
+}
+
+Z_RpnCapabilities *f_rpnCapabilities (ExpHandle *eh, data1_node *n)
+{
+    Z_RpnCapabilities *res = (Z_RpnCapabilities *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->num_operators = 0;
+    res->operators = NULL;
+    res->resultSetAsOperandSupported = eh->false_value;
+    res->restrictionOperandSupported = eh->false_value;
+    res->proximity = NULL;
+
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag(eh, c))
+       {
+       case 550:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 551)
+                   continue;
+               (res->num_operators)++;
+           }
+           if (res->num_operators)
+               res->operators = (int **)
+                   odr_malloc (eh->o, res->num_operators
+                               * sizeof(*res->operators));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 551)
+                   continue;
+               res->operators[i++] = f_integer (eh, n);
+           }
+           break;
+       case 552:
+           res->resultSetAsOperandSupported = f_bool (eh, c);
+           break;
+       case 553:
+           res->restrictionOperandSupported = f_bool (eh, c);
+           break;
+       case 554:
+           res->proximity = f_proximitySupport (eh, c);
+           break;
+       }
+    }
+    return res;
+}
+
+Z_QueryTypeDetails *f_queryTypeDetails (ExpHandle *eh, data1_node *n)
+{
+    Z_QueryTypeDetails *res = (Z_QueryTypeDetails *)
+       odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->which = Z_QueryTypeDetails_rpn;
+    res->u.rpn = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag(eh, c))
+       {
+       case 519:
+           res->which = Z_QueryTypeDetails_rpn;
+           res->u.rpn = f_rpnCapabilities (eh, c);
+           break;
+       case 520:
+           break;
+       case 521:
+           break;
+       }
+    }
+    return res;
+}
+
+static Z_AccessInfo *f_accessInfo(ExpHandle *eh, data1_node *n)
+{
+    Z_AccessInfo *res = (Z_AccessInfo *)odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->num_queryTypesSupported = 0;
+    res->queryTypesSupported = 0;
+    res->num_diagnosticsSets = 0;
+    res->diagnosticsSets = 0;
+    res->num_attributeSetIds = 0;
+    res->attributeSetIds = 0;
+    res->num_schemas = 0;
+    res->schemas = 0;
+    res->num_recordSyntaxes = 0;
+    res->recordSyntaxes = 0;
+    res->num_resourceChallenges = 0;
+    res->resourceChallenges = 0;
+    res->restrictedAccess = 0;
+    res->costInfo = 0;
+    res->num_variantSets = 0;
+    res->variantSets = 0;
+    res->num_elementSetNames = 0;
+    res->elementSetNames = 0;
+    res->num_unitSystems = 0;
+    res->unitSystems = 0;
+
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag (eh, c))
+       {
+       case 501:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 518)
+                   continue;
+               (res->num_queryTypesSupported)++;
+           }
+           if (res->num_queryTypesSupported)
+               res->queryTypesSupported =
+                   (Z_QueryTypeDetails **)
+                   odr_malloc (eh->o, res->num_queryTypesSupported
+                               * sizeof(*res->queryTypesSupported));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 518)
+                   continue;
+               res->queryTypesSupported[i++] = f_queryTypeDetails (eh, n);
+           }
+           break;
+       case 503:
+           res->diagnosticsSets =
+               f_oid_seq(eh, c, &res->num_diagnosticsSets, CLASS_DIAGSET);
+           break;
+       case 505:
+           res->attributeSetIds =
+               f_oid_seq(eh, c, &res->num_attributeSetIds, CLASS_ATTSET);
+           break;
+       case 507:
+           res->schemas =
+               f_oid_seq(eh, c, &res->num_schemas, CLASS_SCHEMA);
+           break;
+       case 509:
+           res->recordSyntaxes =
+               f_oid_seq (eh, c, &res->num_recordSyntaxes, CLASS_RECSYN);
+           break;
+       case 511:
+           res->resourceChallenges =
+               f_oid_seq (eh, c, &res->num_resourceChallenges, CLASS_RESFORM);
+           break;
+       case 513: res->restrictedAccess = NULL; break; /* fix */
+       case 514: res->costInfo = NULL; break; /* fix */
+       case 515:
+           res->variantSets =
+               f_oid_seq (eh, c, &res->num_variantSets, CLASS_VARSET);
+           break;
+       case 516:
+           res->elementSetNames =
+               f_string_seq (eh, c, &res->num_elementSetNames);
+           break;
+       case 517:
+           res->unitSystems = f_string_seq (eh, c, &res->num_unitSystems);
+           break;
+       }
+    }
+    return res;
+}
+
+static int *f_recordCount(ExpHandle *eh, data1_node *c, int *which)
+{
+    int *r= (int *)odr_malloc(eh->o, sizeof(*r));
+    int *wp = which;
+    char intbuf[64];
+
+    c = c->child;
+    if (!is_numeric_tag (eh, c))
+       return 0;
+    if (c->u.tag.element->tag->value.numeric == 210)
+       *wp = Z_DatabaseInfo_actualNumber;
+    else if (c->u.tag.element->tag->value.numeric == 211)
+       *wp = Z_DatabaseInfo_approxNumber;
+    else
+       return 0;
+    if (!c->child || c->child->which != DATA1N_data)
+       return 0;
+    sprintf(intbuf, "%.*s", c->child->u.data.len, c->child->u.data.data);
+    *r = atoi(intbuf);
+    return r;
+}
+
+static Z_ContactInfo *f_contactInfo(ExpHandle *eh, data1_node *n)
+{
+    Z_ContactInfo *res = (Z_ContactInfo *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+    
+    res->name = 0;
+    res->description = 0;
+    res->address = 0;
+    res->email = 0;
+    res->phone = 0;
+    
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 102: res->name = f_string (eh, c); break;
+       case 113: res->description = f_humstring (eh, c); break;
+       case 127: res->address = f_humstring (eh, c); break;
+       case 128: res->email = f_string (eh, c); break;
+       case 129: res->phone = f_string (eh, c); break;
+       }
+    }
+    return res;
+}
+
+static Z_DatabaseList *f_databaseList(ExpHandle *eh, data1_node *n)
+{
+    data1_node *c;
+    Z_DatabaseList *res;
+    int i = 0;
+    
+    for (c = n->child; c; c = c->next)
+    {
+       if (!is_numeric_tag (eh, c) != 102) 
+           continue;
+       ++i;
+    }
+    if (!i)
+       return NULL;
+
+    res = (Z_DatabaseList *)odr_malloc (eh->o, sizeof(*res));
+    
+    res->num_databases = i;
+    res->databases = (char **)odr_malloc (eh->o, sizeof(*res->databases) * i);
+    i = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       if (!is_numeric_tag (eh, c) != 102)
+           continue;
+       res->databases[i++] = f_string (eh, c);
+    }
+    return res;
+}
+
+static Z_NetworkAddressIA *f_networkAddressIA(ExpHandle *eh, data1_node *n)
+{
+    Z_NetworkAddressIA *res = (Z_NetworkAddressIA *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+    
+    res->hostAddress = 0;
+    res->port = 0;
+
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 121: res->hostAddress = f_string (eh, c); break;
+       case 122: res->port = f_integer (eh, c); break;
+       }
+    }
+    return res;
+}
+
+static Z_NetworkAddressOther *f_networkAddressOther(ExpHandle *eh,
+                                                   data1_node *n)
+{
+    Z_NetworkAddressOther *res = (Z_NetworkAddressOther *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->type = 0;
+    res->address = 0;
+
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 124: res->type = f_string (eh, c); break;
+       case 121: res->address = f_string (eh, c); break;
+       }
+    }
+    return res;
+}
+
+static Z_NetworkAddress **f_networkAddresses(ExpHandle *eh, data1_node *n, 
+                                            int *num)
+{
+    Z_NetworkAddress **res = NULL;
+    data1_node *c;
+    int i = 0;
+    
+    *num = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 120:
+       case 123:
+           (*num)++;
+           break;
+       }
+    }
+
+    if (*num)
+       res = (Z_NetworkAddress **) odr_malloc (eh->o, sizeof(*res) * (*num));
+                                              
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 120:
+           res[i] = (Z_NetworkAddress *) odr_malloc (eh->o, sizeof(**res));
+           res[i]->which = Z_NetworkAddress_iA;
+           res[i]->u.internetAddress = f_networkAddressIA(eh, c);
+           i++;
+           break;
+       case 123:
+           res[i] = (Z_NetworkAddress *) odr_malloc (eh->o, sizeof(**res));
+           res[i]->which = Z_NetworkAddress_other;
+           res[i]->u.other = f_networkAddressOther(eh, c);
+           i++;
+           break;
+       }
+    }
+    return res;
+}
+
+static Z_CategoryInfo *f_categoryInfo(ExpHandle *eh, data1_node *n)
+{
+    Z_CategoryInfo *res = (Z_CategoryInfo *)odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->category = 0;
+    res->originalCategory = 0;
+    res->description = 0;
+    res->asn1Module = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 102: res->category = f_string(eh, c); break;
+       case 302: res->originalCategory = f_string(eh, c); break;
+       case 113: res->description = f_humstring(eh, c); break;
+       case 303: res->asn1Module = f_string (eh, c); break;
+       }
+    }
+    return res;
+}
+
+static Z_CategoryList *f_categoryList(ExpHandle *eh, data1_node *n)
+{
+    Z_CategoryList *res = (Z_CategoryList *)odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->commonInfo = 0;
+    res->num_categories = 0;
+    res->categories = NULL;
+
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+
+       switch (is_numeric_tag (eh, c))
+       {
+       case 600: res->commonInfo = f_commonInfo(eh, c); break;
+       case 300:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 301)
+                   continue;
+               (res->num_categories)++;
+           }
+           if (res->num_categories)
+               res->categories =
+                   (Z_CategoryInfo **)odr_malloc (eh->o, res->num_categories 
+                                                  * sizeof(*res->categories));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 301)
+                   continue;
+               res->categories[i++] = f_categoryInfo (eh, n);
+           }
+           break;
+       }
+    }
+    assert (res->num_categories && res->categories);
+    return res;
+}
+
+static Z_TargetInfo *f_targetInfo(ExpHandle *eh, data1_node *n)
+{
+    Z_TargetInfo *res = (Z_TargetInfo *)odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->commonInfo = 0;
+    res->name = 0;
+    res->recentNews = 0;
+    res->icon = 0;
+    res->namedResultSets = 0;
+    res->multipleDBsearch = 0;
+    res->maxResultSets = 0;
+    res->maxResultSize = 0;
+    res->maxTerms = 0;
+    res->timeoutInterval = 0;
+    res->welcomeMessage = 0;
+    res->contactInfo = 0;
+    res->description = 0;
+    res->num_nicknames = 0;
+    res->nicknames = 0;
+    res->usageRest = 0;
+    res->paymentAddr = 0;
+    res->hours = 0;
+    res->num_dbCombinations = 0;
+    res->dbCombinations = 0;
+    res->num_addresses = 0;
+    res->addresses = 0;
+    res->num_languages = 0;
+    res->languages = NULL;
+    res->commonAccessInfo = 0;
+    
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+
+       switch (is_numeric_tag (eh, c))
+       {
+       case 600: res->commonInfo = f_commonInfo(eh, c); break;
+       case 102: res->name = f_string(eh, c); break;
+       case 103: res->recentNews = f_humstring(eh, c); break;
+       case 104: res->icon = NULL; break; /* fix */
+       case 105: res->namedResultSets = f_bool(eh, c); break;
+       case 106: res->multipleDBsearch = f_bool(eh, c); break;
+       case 107: res->maxResultSets = f_integer(eh, c); break;
+       case 108: res->maxResultSize = f_integer(eh, c); break;
+       case 109: res->maxTerms = f_integer(eh, c); break;
+       case 110: res->timeoutInterval = f_intunit(eh, c); break;
+       case 111: res->welcomeMessage = f_humstring(eh, c); break;
+       case 112: res->contactInfo = f_contactInfo(eh, c); break;
+       case 113: res->description = f_humstring(eh, c); break;
+       case 114: 
+           res->num_nicknames = 0;
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 102)
+                   continue;
+               (res->num_nicknames)++;
+           }
+           if (res->num_nicknames)
+               res->nicknames =
+                   (char **)odr_malloc (eh->o, res->num_nicknames 
+                               * sizeof(*res->nicknames));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 102)
+                   continue;
+               res->nicknames[i++] = f_string (eh, n);
+           }
+           break;
+       case 115: res->usageRest = f_humstring(eh, c); break;
+       case 116: res->paymentAddr = f_humstring(eh, c); break;
+       case 117: res->hours = f_humstring(eh, c); break;
+       case 118:
+           res->num_dbCombinations = 0;
+           for (n = c->child; n; n = n->next)
+           {
+               if (!is_numeric_tag(eh, n) != 605)
+                   continue;
+               (res->num_dbCombinations)++;
+           }
+           if (res->num_dbCombinations)
+               res->dbCombinations =
+                   (Z_DatabaseList **)odr_malloc (eh->o, res->num_dbCombinations
+                               * sizeof(*res->dbCombinations));
+           for (n = c->child; n; n = n->next)
+           {
+               if (!is_numeric_tag(eh, n) != 605)
+                   continue;
+               res->dbCombinations[i++] = f_databaseList (eh, n);
+           }
+           break;
+       case 119: 
+           res->addresses =
+               f_networkAddresses (eh, c, &res->num_addresses);
+           break;
+       case 125:
+           res->num_languages = 0;
+           for (n = c->child; n; n = n->next)
+           {
+               if (!is_numeric_tag(eh, n) != 126)
+                   continue;
+               (res->num_languages)++;
+           }
+           if (res->num_languages)
+               res->languages = (char **)
+                   odr_malloc (eh->o, res->num_languages *
+                               sizeof(*res->languages));
+           for (n = c->child; n; n = n->next)
+           {
+               if (!is_numeric_tag(eh, n) != 126)
+                   continue;
+               res->languages[i++] = f_string (eh, n);
+           }
+           break;
+       case 500: res->commonAccessInfo = f_accessInfo(eh, c); break;
+       }
+    }
+    if (!res->namedResultSets)
+       res->namedResultSets = eh->false_value;
+    if (!res->multipleDBsearch)
+       res->multipleDBsearch = eh->false_value;
+    return res;
+}
+
+static Z_DatabaseInfo *f_databaseInfo(ExpHandle *eh, data1_node *n)
+{
+    Z_DatabaseInfo *res = (Z_DatabaseInfo *)odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->commonInfo = 0;
+    res->name = 0;
+    res->explainDatabase = 0;
+    res->num_nicknames = 0;
+    res->nicknames = 0;
+    res->icon = 0;
+    res->userFee = 0;
+    res->available = 0;
+    res->titleString = 0;
+    res->num_keywords = 0;
+    res->keywords = 0;
+    res->description = 0;
+    res->associatedDbs = 0;
+    res->subDbs = 0;
+    res->disclaimers = 0;
+    res->news = 0;
+    res->u.actualNumber = 0;
+    res->defaultOrder = 0;
+    res->avRecordSize = 0;
+    res->maxRecordSize = 0;
+    res->hours = 0;
+    res->bestTime = 0;
+    res->lastUpdate = 0;
+    res->updateInterval = 0;
+    res->coverage = 0;
+    res->proprietary = 0;
+    res->copyrightText = 0;
+    res->copyrightNotice = 0;
+    res->producerContactInfo = 0;
+    res->supplierContactInfo = 0;
+    res->submissionContactInfo = 0;
+    res->accessInfo = 0;
+    
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+
+       switch (is_numeric_tag (eh, c))
+       {
+       case 600: res->commonInfo = f_commonInfo(eh, c); break;
+       case 102: res->name = f_string(eh, c); break;
+       case 226: res->explainDatabase = odr_nullval(); break;
+       case 114:
+           res->num_nicknames = 0;
+           for (n = c->child; n; n = n->next)
+           {
+               if (!is_numeric_tag(eh, n) ||
+                   n->u.tag.element->tag->value.numeric != 102)
+                   continue;
+               (res->num_nicknames)++;
+           }
+           if (res->num_nicknames)
+               res->nicknames =
+                   (char **)odr_malloc (eh->o, res->num_nicknames 
+                               * sizeof(*res->nicknames));
+           for (n = c->child; n; n = n->next)
+           {
+               if (!is_numeric_tag(eh, n) ||
+                   n->u.tag.element->tag->value.numeric != 102)
+                   continue;
+               res->nicknames[i++] = f_string (eh, n);
+           }
+           break;
+       case 104: res->icon = 0; break;      /* fix */
+       case 201: res->userFee = f_bool(eh, c); break;
+       case 202: res->available = f_bool(eh, c); break;
+       case 203: res->titleString = f_humstring(eh, c); break;
+       case 227:
+           res->num_keywords = 0;
+           for (n = c->child; n; n = n->next)
+           {
+               if (!is_numeric_tag(eh, n) != 1000)
+                   continue;
+               (res->num_keywords)++;
+           }
+           if (res->num_keywords)
+               res->keywords =
+                   (Z_HumanString **)odr_malloc (eh->o, res->num_keywords 
+                               * sizeof(*res->keywords));
+           for (n = c->child; n; n = n->next)
+           {
+               if (!is_numeric_tag(eh, n) != 1000)
+                   continue;
+               res->keywords[i++] = f_humstring (eh, n);
+           }
+           break;
+       case 113: res->description = f_humstring(eh, c); break;
+       case 205:
+           res->associatedDbs = f_databaseList (eh, c);
+           break;
+       case 206:
+           res->subDbs = f_databaseList (eh, c);
+           break;
+       case 207: res->disclaimers = f_humstring(eh, c); break;
+       case 103: res->news = f_humstring(eh, c); break;
+       case 209: res->u.actualNumber =
+                     f_recordCount(eh, c, &res->which); break;
+       case 212: res->defaultOrder = f_humstring(eh, c); break;
+       case 213: res->avRecordSize = f_integer(eh, c); break;
+       case 214: res->maxRecordSize = f_integer(eh, c); break;
+       case 215: res->hours = f_humstring(eh, c); break;
+       case 216: res->bestTime = f_humstring(eh, c); break;
+       case 217: res->lastUpdate = f_string(eh, c); break;
+       case 218: res->updateInterval = f_intunit(eh, c); break;
+       case 219: res->coverage = f_humstring(eh, c); break;
+       case 220: res->proprietary = f_bool(eh, c); break;
+       case 221: res->copyrightText = f_humstring(eh, c); break;
+       case 222: res->copyrightNotice = f_humstring(eh, c); break;
+       case 223: res->producerContactInfo = f_contactInfo(eh, c); break;
+       case 224: res->supplierContactInfo = f_contactInfo(eh, c); break;
+       case 225: res->submissionContactInfo = f_contactInfo(eh, c); break;
+       case 500: res->accessInfo = f_accessInfo(eh, c); break;
+       }
+    }
+    if (!res->userFee)
+       res->userFee = eh->false_value;
+    if (!res->available)
+       res->available = eh->true_value;
+    return res;
+}
+
+Z_StringOrNumeric *f_stringOrNumeric (ExpHandle *eh, data1_node *n)
+{
+    Z_StringOrNumeric *res = (Z_StringOrNumeric *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 1001:
+           res->which = Z_StringOrNumeric_string;
+           res->u.string = f_string (eh, c);
+           break;
+       case 1002:
+           res->which = Z_StringOrNumeric_numeric;
+           res->u.numeric = f_integer (eh, c);
+           break;
+       }
+    }
+    return res;
+}
+
+Z_AttributeDescription *f_attributeDescription (
+    ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeDescription *res = (Z_AttributeDescription *)
+       odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+    int i = 0;
+       
+    res->name = 0;
+    res->description = 0;
+    res->attributeValue = 0;
+    res->num_equivalentAttributes = 0;
+    res->equivalentAttributes = 0;
+
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 102: res->name = f_string (eh, c); break;
+       case 113: res->description = f_humstring (eh, c); break;
+       case 710: res->attributeValue = f_stringOrNumeric (eh, c); break;
+       case 752: (res->num_equivalentAttributes++); break;
+       }
+    }
+    if (res->num_equivalentAttributes)
+       res->equivalentAttributes = (Z_StringOrNumeric **)
+           odr_malloc (eh->o, sizeof(*res->equivalentAttributes) *
+                       res->num_equivalentAttributes);
+    for (c = n->child; c; c = c->next)
+       if (is_numeric_tag (eh, c) == 752)
+           res->equivalentAttributes[i++] = f_stringOrNumeric (eh, c);
+    return res;
+}
+
+Z_AttributeType *f_attributeType (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeType *res = (Z_AttributeType *)
+       odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->name = 0;
+    res->description = 0;
+    res->attributeType = 0;
+    res->num_attributeValues = 0;
+    res->attributeValues = 0;
+
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag (eh, c))
+       {
+       case 102: res->name = f_string (eh, c); break;
+       case 113: res->description = f_humstring (eh, c); break;
+       case 704: res->attributeType = f_integer (eh, c); break;
+       case 708:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 709)
+                   continue;
+               (res->num_attributeValues)++;
+           }
+           if (res->num_attributeValues)
+               res->attributeValues = (Z_AttributeDescription **)
+                   odr_malloc (eh->o, res->num_attributeValues
+                               * sizeof(*res->attributeValues));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 709)
+                   continue;
+               res->attributeValues[i++] = f_attributeDescription (eh, n);
+           }
+           break;
+       }
+    }
+    return res;
+}
+
+Z_AttributeSetInfo *f_attributeSetInfo (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeSetInfo *res = (Z_AttributeSetInfo *)
+       odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->commonInfo = 0;
+    res->attributeSet = 0;
+    res->name = 0;
+    res->num_attributes = 0;
+    res->attributes = 0;
+    res->description = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag (eh, c))
+       {
+       case 600: res->commonInfo = f_commonInfo (eh, c); break;
+       case 1000: res->attributeSet = f_oid (eh, c, CLASS_ATTSET); break;
+       case 102: res->name = f_string (eh, c); break;
+       case 750:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 751)
+                   continue;
+               (res->num_attributes)++;
+           }
+           if (res->num_attributes)
+               res->attributes = (Z_AttributeType **)
+                   odr_malloc (eh->o, res->num_attributes
+                               * sizeof(*res->attributes));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 751)
+                   continue;
+               res->attributes[i++] = f_attributeType (eh, n);
+           }
+           break;
+       case 113: res->description = f_humstring (eh, c); break;
+       }
+    }
+    return res;
+}
+
+Z_OmittedAttributeInterpretation *f_omittedAttributeInterpretation (
+    ExpHandle *eh, data1_node *n)
+{
+    Z_OmittedAttributeInterpretation *res = (Z_OmittedAttributeInterpretation*)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->defaultValue = 0;
+    res->defaultDescription = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 706:
+           res->defaultValue = f_stringOrNumeric (eh, c);
+           break;
+       case 113:
+           res->defaultDescription = f_humstring(eh, c);
+           break;
+       }
+    }
+    return res;
+}
+
+Z_AttributeValue *f_attributeValue (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeValue *res = (Z_AttributeValue *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->value = 0;
+    res->description = 0;
+    res->num_subAttributes = 0;
+    res->subAttributes = 0;
+    res->num_superAttributes = 0;
+    res->superAttributes = 0;
+    res->partialSupport = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag (eh, c))
+       {
+       case 710:
+           res->value = f_stringOrNumeric (eh, c);  break;
+       case 113:
+           res->description = f_humstring (eh, c); break;
+       case 712:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 713)
+                   continue;
+               (res->num_subAttributes)++;
+           }
+           if (res->num_subAttributes)
+               res->subAttributes =
+                   (Z_StringOrNumeric **)
+                   odr_malloc (eh->o, res->num_subAttributes
+                               * sizeof(*res->subAttributes));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 713)
+                   continue;
+               res->subAttributes[i++] = f_stringOrNumeric (eh, n);
+           }
+           break;
+       case 714:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 715)
+                   continue;
+               (res->num_superAttributes)++;
+           }
+           if (res->num_superAttributes)
+               res->superAttributes =
+                   (Z_StringOrNumeric **)
+                   odr_malloc (eh->o, res->num_superAttributes
+                               * sizeof(*res->superAttributes));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 715)
+                   continue;
+               res->superAttributes[i++] = f_stringOrNumeric (eh, n);
+           }
+           break;
+       case 711:
+           res->partialSupport = odr_nullval ();
+           break;
+       }
+    }
+    return res;
+}
+
+Z_AttributeTypeDetails *f_attributeTypeDetails (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeTypeDetails *res = (Z_AttributeTypeDetails *)
+       odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+    res->attributeType = 0;
+    res->defaultIfOmitted = 0;
+    res->num_attributeValues = 0;
+    res->attributeValues = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag (eh, c))
+       {
+       case 704: res->attributeType = f_integer (eh, c); break;
+       case 705:
+           res->defaultIfOmitted = f_omittedAttributeInterpretation (eh, c);
+           break;
+       case 708:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 709)
+                   continue;
+               (res->num_attributeValues)++;
+           }
+           if (res->num_attributeValues)
+               res->attributeValues =
+                   (Z_AttributeValue **)
+                   odr_malloc (eh->o, res->num_attributeValues
+                               * sizeof(*res->attributeValues));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 709)
+                   continue;
+               res->attributeValues[i++] = f_attributeValue (eh, n);
+           }
+           break;
+       }
+    }
+    return res;
+}
+
+Z_AttributeSetDetails *f_attributeSetDetails (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeSetDetails *res = (Z_AttributeSetDetails *)
+       odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+    
+    res->attributeSet = 0;
+    res->num_attributesByType = 0;
+    res->attributesByType = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag (eh, c))
+       {
+       case 1000: res->attributeSet = f_oid(eh, c, CLASS_ATTSET); break;
+       case 702:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 703)
+                   continue;
+               (res->num_attributesByType)++;
+           }
+           if (res->num_attributesByType)
+               res->attributesByType =
+                   (Z_AttributeTypeDetails **)
+                   odr_malloc (eh->o, res->num_attributesByType
+                               * sizeof(*res->attributesByType));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 703)
+                   continue;
+               res->attributesByType[i++] = f_attributeTypeDetails (eh, n);
+           }
+           break;
+       }
+    }
+    return res;
+}
+
+Z_AttributeValueList *f_attributeValueList (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeValueList *res = (Z_AttributeValueList *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+    int i = 0;
+
+    res->num_attributes = 0;
+    res->attributes = 0;
+    for (c = n->child; c; c = c->next)
+       if (is_numeric_tag (eh, c) == 710)
+           (res->num_attributes)++;
+    if (res->num_attributes)
+    {
+       res->attributes = (Z_StringOrNumeric **)
+           odr_malloc (eh->o, res->num_attributes * sizeof(*res->attributes));
+    }
+    for (c = n->child; c; c = c->next)
+       if (is_numeric_tag(eh, c) == 710)
+           res->attributes[i++] = f_stringOrNumeric (eh, c);
+    return res;
+}
+
+Z_AttributeOccurrence *f_attributeOccurrence (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeOccurrence *res = (Z_AttributeOccurrence *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->attributeSet = 0;
+    res->attributeType = 0;
+    res->mustBeSupplied = 0;
+    res->which = Z_AttributeOcc_any_or_none;
+    res->attributeValues.any_or_none = odr_nullval ();
+
+    for (c = n->child; c; c = c->next)
+    {
+       switch (is_numeric_tag (eh, c))
+       {
+       case 1000:
+           res->attributeSet = f_oid (eh, c, CLASS_ATTSET); break;
+       case 704:
+           res->attributeType = f_integer (eh, c); break;
+       case 720:
+           res->mustBeSupplied = odr_nullval (); break;
+       case 721:
+           res->which = Z_AttributeOcc_any_or_none;
+           res->attributeValues.any_or_none = odr_nullval ();
+           break;
+       case 722:
+           res->which = Z_AttributeOcc_specific;
+           res->attributeValues.specific = f_attributeValueList (eh, c);
+           break;
+       }
+    }
+    return res;
+}
+
+Z_AttributeCombination *f_attributeCombination (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeCombination *res = (Z_AttributeCombination *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+    int i = 0;
+
+    res->num_occurrences = 0;
+    res->occurrences = 0;
+    for (c = n->child; c; c = c->next)
+       if (is_numeric_tag (eh, c) == 719)
+           (res->num_occurrences)++;
+    if (res->num_occurrences)
+    {
+       res->occurrences = (Z_AttributeOccurrence **)
+           odr_malloc (eh->o, res->num_occurrences * sizeof(*res->occurrences));
+    }
+    for (c = n->child; c; c = c->next)
+       if (is_numeric_tag(eh, c) == 719)
+           res->occurrences[i++] = f_attributeOccurrence (eh, c);
+    assert (res->num_occurrences);
+    return res;
+}
+
+Z_AttributeCombinations *f_attributeCombinations (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeCombinations *res = (Z_AttributeCombinations *)
+       odr_malloc (eh->o, sizeof(*res));
+    data1_node *c;
+    res->defaultAttributeSet = 0;
+    res->num_legalCombinations = 0;
+    res->legalCombinations = 0;
+
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag (eh, c))
+       {
+       case 1000:
+           res->defaultAttributeSet = f_oid (eh, c, CLASS_ATTSET);
+           break;
+       case 717:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 718)
+                   continue;
+               (res->num_legalCombinations)++;
+           }
+           if (res->num_legalCombinations)
+               res->legalCombinations =
+                   (Z_AttributeCombination **)
+                   odr_malloc (eh->o, res->num_legalCombinations
+                               * sizeof(*res->legalCombinations));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 718)
+                   continue;
+               res->legalCombinations[i++] = f_attributeCombination (eh, n);
+           }
+           break;
+       }
+    }
+    assert (res->num_legalCombinations);
+    return res;
+}
+
+Z_AttributeDetails *f_attributeDetails (ExpHandle *eh, data1_node *n)
+{
+    Z_AttributeDetails *res = (Z_AttributeDetails *)
+       odr_malloc(eh->o, sizeof(*res));
+    data1_node *c;
+
+    res->commonInfo = 0;
+    res->databaseName = 0;
+    res->num_attributesBySet = 0;
+    res->attributesBySet = NULL;
+    res->attributeCombinations = NULL;
+
+    for (c = n->child; c; c = c->next)
+    {
+       int i = 0;
+       switch (is_numeric_tag (eh, c))
+       {
+       case 600: res->commonInfo = f_commonInfo(eh, c); break;
+       case 102: res->databaseName = f_string (eh, c); break;
+       case 700:
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 701)
+                   continue;
+               (res->num_attributesBySet)++;
+           }
+           if (res->num_attributesBySet)
+               res->attributesBySet =
+                   (Z_AttributeSetDetails **)
+                   odr_malloc (eh->o, res->num_attributesBySet
+                               * sizeof(*res->attributesBySet));
+           for (n = c->child; n; n = n->next)
+           {
+               if (is_numeric_tag(eh, n) != 701)
+                   continue;
+               res->attributesBySet[i++] = f_attributeSetDetails (eh, n);
+           }
+           break;
+       case 716:
+           res->attributeCombinations = f_attributeCombinations (eh, c);
+           break;
+       }
+    }
+    return res;
+}
+
+Z_ExplainRecord *data1_nodetoexplain (data1_handle dh, data1_node *n,
+                                     int select, ODR o)
+{
+    ExpHandle eh;
+    Z_ExplainRecord *res = (Z_ExplainRecord *)odr_malloc(o, sizeof(*res));
+
+    eh.dh = dh;
+    eh.select = select;
+    eh.o = o;
+    eh.false_value = (int *)odr_malloc(eh.o, sizeof(eh.false_value));
+    *eh.false_value = 0;
+    eh.true_value = (int *)odr_malloc(eh.o, sizeof(eh.true_value));
+    *eh.true_value = 1;
+
+    assert(n->which == DATA1N_root);
+    if (strcmp(n->u.root.type, "explain"))
+    {
+       yaz_log(LOG_WARN, "Attempt to convert a non-Explain record");
+       return 0;
+    }
+    for (n = n->child; n; n = n->next)
+    {
+       switch (is_numeric_tag (&eh, n))
+       {
+       case 1:
+           res->which = Z_Explain_categoryList;
+           if (!(res->u.categoryList = f_categoryList(&eh, n)))
+               return 0;
+           return res;     
+       case 2:
+           res->which = Z_Explain_targetInfo;
+           if (!(res->u.targetInfo = f_targetInfo(&eh, n)))
+               return 0;
+           return res;
+       case 3:
+           res->which = Z_Explain_databaseInfo;
+           if (!(res->u.databaseInfo = f_databaseInfo(&eh, n)))
+               return 0;
+           return res;
+       case 7:
+           res->which = Z_Explain_attributeSetInfo;
+           if (!(res->u.attributeSetInfo = f_attributeSetInfo(&eh, n)))
+               return 0;
+           return res;     
+       case 10:
+           res->which = Z_Explain_attributeDetails;
+           if (!(res->u.attributeDetails = f_attributeDetails(&eh, n)))
+               return 0;
+           return res;
+       }
+    }
+    yaz_log(LOG_WARN, "No category in Explain record");
+    return 0;
+}
diff --git a/data1/d1_grs.c b/data1/d1_grs.c
new file mode 100644 (file)
index 0000000..8343063
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_grs.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ *
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <yaz/proto.h>
+#include <yaz/log.h>
+#include <data1.h>
+
+#define D1_VARIANTARRAY 20 /* fixed max length on sup'd variant-list. Lazy me */
+
+static Z_ElementMetaData *get_ElementMetaData(ODR o)
+{
+    Z_ElementMetaData *r = (Z_ElementMetaData *)odr_malloc(o, sizeof(*r));
+
+    r->seriesOrder = 0;
+    r->usageRight = 0;
+    r->num_hits = 0;
+    r->hits = 0;
+    r->displayName = 0;
+    r->num_supportedVariants = 0;
+    r->supportedVariants = 0;
+    r->message = 0;
+    r->elementDescriptor = 0;
+    r->surrogateFor = 0;
+    r->surrogateElement = 0;
+    r->other = 0;
+
+    return r;
+}
+
+/*
+ * N should point to the *last* (leaf) triple in a sequence. Construct a variant
+ * from each of the triples beginning (ending) with 'n', up to the
+ * nearest parent tag. num should equal the number of triples in the
+ * sequence.
+ */
+static Z_Variant *make_variant(data1_node *n, int num, ODR o)
+{
+    Z_Variant *v = (Z_Variant *)odr_malloc(o, sizeof(*v));
+    data1_node *p;
+
+    v->globalVariantSetId = 0;
+    v->num_triples = num;
+    v->triples = (Z_Triple **)odr_malloc(o, sizeof(Z_Triple*) * num);
+
+    /*
+     * cycle back up through the tree of variants
+     * (traversing exactly 'level' variants).
+     */
+    for (p = n, num--; p && num >= 0; p = p->parent, num--)
+    {
+       Z_Triple *t;
+
+       assert(p->which == DATA1N_variant);
+       t = v->triples[num] = (Z_Triple *)odr_malloc(o, sizeof(*t));
+       t->variantSetId = 0;
+       t->zclass = (int *)odr_malloc(o, sizeof(int));
+       *t->zclass = p->u.variant.type->zclass->zclass;
+       t->type = (int *)odr_malloc(o, sizeof(int));
+       *t->type = p->u.variant.type->type;
+
+       switch (p->u.variant.type->datatype)
+       {
+           case DATA1K_string:
+               t->which = Z_Triple_internationalString;
+               t->value.internationalString =
+                    odr_strdup(o, p->u.variant.value);
+               break;
+           default:
+               yaz_log(LOG_WARN, "Unable to handle value for variant %s",
+                       p->u.variant.type->name);
+               return 0;
+       }
+    }
+    return v;
+}
+
+/*
+ * Traverse the variant children of n, constructing a supportedVariant list.
+ */
+static int traverse_triples(data1_node *n, int level, Z_ElementMetaData *m,
+    ODR o)
+{
+    data1_node *c;
+    
+    for (c = n->child; c; c = c->next)
+       if (c->which == DATA1N_data && level)
+       {
+           if (!m->supportedVariants)
+               m->supportedVariants = (Z_Variant **)odr_malloc(o, sizeof(Z_Variant*) *
+                   D1_VARIANTARRAY);
+           else if (m->num_supportedVariants >= D1_VARIANTARRAY)
+           {
+               yaz_log(LOG_WARN, "Too many variants (D1_VARIANTARRAY==%d)",
+                       D1_VARIANTARRAY);
+               return -1;
+           }
+
+           if (!(m->supportedVariants[m->num_supportedVariants++] =
+               make_variant(n, level, o)))
+               return -1;
+       }
+       else if (c->which == DATA1N_variant)
+           if (traverse_triples(c, level+1, m, o) < 0)
+               return -1;
+    return 0;
+}
+
+/*
+ * Locate some data under this node. This routine should handle variants
+ * prettily.
+ */
+static char *get_data(data1_node *n, int *len)
+{
+    char *r;
+    data1_node *np = 0;
+
+    while (n)
+    {
+        if (n->which == DATA1N_data)
+        {
+            int i;
+            *len = n->u.data.len;
+
+            for (i = 0; i<*len; i++)
+                if (!d1_isspace(n->u.data.data[i]))
+                    break;
+            while (*len && d1_isspace(n->u.data.data[*len - 1]))
+                (*len)--;
+            *len = *len - i;
+            if (*len > 0)
+                return n->u.data.data + i;
+        }
+        if (n->which == DATA1N_tag)
+            np = n->child;
+        n = n->next;
+        if (!n)
+        {
+            n = np;
+            np = 0;
+        }
+    }
+    r = "";
+    *len = strlen(r);
+    return r;
+}
+
+static Z_ElementData *nodetoelementdata(data1_handle dh, data1_node *n,
+                                       int select, int leaf,
+                                       ODR o, int *len)
+{
+    Z_ElementData *res = (Z_ElementData *)odr_malloc(o, sizeof(*res));
+
+    if (!n)
+    {
+       res->which = Z_ElementData_elementNotThere;
+       res->u.elementNotThere = odr_nullval();
+    }
+    else if (n->which == DATA1N_data && leaf)
+    {
+       char str[64], *cp;
+       int toget = n->u.data.len;
+
+        cp = get_data (n, &toget);
+
+       switch (n->u.data.what)
+       {
+        case DATA1I_num:
+            res->which = Z_ElementData_numeric;
+            res->u.numeric = (int *)odr_malloc(o, sizeof(int));
+            *res->u.numeric = atoi_n (cp, toget);
+            *len += 4;
+            break;
+        case DATA1I_text:
+        case DATA1I_xmltext:
+            res->which = Z_ElementData_string;
+            res->u.string = (char *)odr_malloc(o, toget+1);
+            if (toget)
+                memcpy(res->u.string, cp, toget);
+            res->u.string[toget] = '\0';
+            *len += toget;
+            break;
+        case DATA1I_oid:
+            res->which = Z_ElementData_oid;
+            if (toget > 63)
+                toget = 63;
+            memcpy (str, cp, toget);
+            str[toget] = '\0';
+            res->u.oid = odr_getoidbystr(o, str);
+            *len += oid_oidlen(res->u.oid) * sizeof(int);
+            break;
+        default:
+            yaz_log(LOG_WARN, "Can't handle datatype.");
+            return 0;
+       }
+    }
+    else
+    {
+       res->which = Z_ElementData_subtree;
+       if (!(res->u.subtree = data1_nodetogr (dh, n->parent, select, o, len)))
+           return 0;
+    }
+    return res;
+}
+
+static int is_empty_data (data1_node *n)
+{
+    if (n && n->which == DATA1N_data && (n->u.data.what == DATA1I_text
+                               || n->u.data.what == DATA1I_xmltext))
+    {
+        int i = n->u.data.len;
+        
+        while (i > 0 && strchr("\n ", n->u.data.data[i-1]))
+            i--;
+        if (i == 0)
+            return 1;
+    }
+    return 0;
+}
+
+
+static Z_TaggedElement *nodetotaggedelement(data1_handle dh, data1_node *n,
+                                           int select, ODR o,
+                                           int *len)
+{
+    Z_TaggedElement *res = (Z_TaggedElement *)odr_malloc(o, sizeof(*res));
+    data1_tag *tag = 0;
+    data1_node *data;
+    int leaf = 0;
+
+    if (n->which == DATA1N_tag)
+    {
+       if (n->u.tag.element)
+           tag = n->u.tag.element->tag;
+       data = n->child;
+
+        /* skip empty data children */
+        while (is_empty_data(data))
+            data = data->next;
+        if (!data)
+            data = n->child;
+        else
+        {   /* got one. see if this is the only non-empty one */
+            data1_node *sub = data->next;
+            while (sub && is_empty_data(sub))
+                sub = sub->next;
+            if (!sub)
+                leaf = 1;  /* all empty. 'data' is the only child */
+        }
+    }
+    /*
+     * If we're a data element at this point, we need to insert a
+     * wellKnown tag to wrap us up.
+     */
+    else if (n->which == DATA1N_data || n->which == DATA1N_variant)
+    {
+       if (n->root->u.root.absyn &&
+            !(tag = data1_gettagbyname (dh, n->root->u.root.absyn->tagset,
+                                       "wellKnown")))
+       {
+           yaz_log(LOG_WARN, "Unable to locate tag for 'wellKnown'");
+           return 0;
+       }
+       data = n;
+       leaf = 1;
+        if (is_empty_data(data))
+            return 0;
+    }
+    else
+    {
+       yaz_log(LOG_WARN, "Bad data.");
+       return 0;
+    }
+
+    res->tagType = (int *)odr_malloc(o, sizeof(int));
+    *res->tagType = (tag && tag->tagset) ? tag->tagset->type : 3;
+    res->tagValue = (Z_StringOrNumeric *)odr_malloc(o, sizeof(Z_StringOrNumeric));
+    if (tag && tag->which == DATA1T_numeric)
+    {
+       res->tagValue->which = Z_StringOrNumeric_numeric;
+       res->tagValue->u.numeric = (int *)odr_malloc(o, sizeof(int));
+       *res->tagValue->u.numeric = tag->value.numeric;
+    }
+    else
+    {
+       char *tagstr;
+
+       if (n->which == DATA1N_tag)      
+           tagstr = n->u.tag.tag;       /* tag at node */
+       else if (tag)                    
+           tagstr = tag->value.string;  /* no take from well-known */
+       else
+            return 0;
+       res->tagValue->which = Z_StringOrNumeric_string;
+       res->tagValue->u.string = odr_strdup(o, tagstr);
+    }
+    res->tagOccurrence = 0;
+    res->appliedVariant = 0;
+    res->metaData = 0;
+    if (n->which == DATA1N_variant || (data && data->which ==
+       DATA1N_variant && data->next == NULL))
+    {
+       int nvars = 0;
+
+       res->metaData = get_ElementMetaData(o);
+       if (n->which == DATA1N_tag && n->u.tag.make_variantlist)
+           if (traverse_triples(data, 0, res->metaData, o) < 0)
+               return 0;
+       while (data && data->which == DATA1N_variant)
+       {
+           nvars++;
+           data = data->child;
+       }
+       if (n->which != DATA1N_tag || !n->u.tag.no_data_requested)
+           res->appliedVariant = make_variant(data->parent, nvars-1, o);
+    }
+    if (n->which == DATA1N_tag && n->u.tag.no_data_requested)
+    {
+       res->content = (Z_ElementData *)odr_malloc(o, sizeof(*res->content));
+       res->content->which = Z_ElementData_noDataRequested;
+       res->content->u.noDataRequested = odr_nullval();
+    }
+    else if (!(res->content = nodetoelementdata (dh, data, select, leaf,
+                                                o, len)))
+       return 0;
+    *len += 10;
+    return res;
+}
+
+Z_GenericRecord *data1_nodetogr(data1_handle dh, data1_node *n,
+                               int select, ODR o, int *len)
+{
+    Z_GenericRecord *res = (Z_GenericRecord *)odr_malloc(o, sizeof(*res));
+    data1_node *c;
+    int num_children = 0;
+
+    if (n->which == DATA1N_root)
+        n = data1_get_root_tag (dh, n);
+        
+    for (c = n->child; c; c = c->next)
+       num_children++;
+
+    res->elements = (Z_TaggedElement **)
+        odr_malloc(o, sizeof(Z_TaggedElement *) * num_children);
+    res->num_elements = 0;
+    for (c = n->child; c; c = c->next)
+    {
+       if (c->which == DATA1N_tag && select && !c->u.tag.node_selected)
+           continue;
+       if ((res->elements[res->num_elements] =
+             nodetotaggedelement (dh, c, select, o, len)))
+           res->num_elements++;
+    }
+    return res;
+}
diff --git a/data1/d1_handle.c b/data1/d1_handle.c
new file mode 100644 (file)
index 0000000..7a37eac
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ *
+ * $Id: d1_handle.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <yaz/log.h>
+#include <data1.h>
+
+struct data1_handle_info {
+    WRBUF wrbuf;
+    char *tab_path;
+    char *tab_root;
+
+    char *read_buf;
+    int read_len;
+
+    data1_absyn_cache absyn_cache;
+    data1_attset_cache attset_cache;
+
+    char *map_buf;
+    int map_len;
+
+    NMEM mem;
+    int flags;
+};
+
+data1_handle data1_create (void)
+{
+    return data1_createx(0);
+}
+
+data1_handle data1_createx (int flags)
+{
+    data1_handle p = (data1_handle)xmalloc (sizeof(*p));
+    if (!p)
+       return NULL;
+    p->tab_path = NULL;
+    p->tab_root = NULL;
+    p->wrbuf = wrbuf_alloc();
+    p->read_buf = NULL;
+    p->read_len = 0;
+    p->map_buf = NULL;
+    p->map_len = 0;
+    p->absyn_cache = NULL;
+    p->attset_cache = NULL;
+    p->mem = nmem_create ();
+    p->flags = flags;
+    return p;
+}
+
+NMEM data1_nmem_get (data1_handle dh)
+{
+    return dh->mem;
+}
+
+data1_absyn_cache *data1_absyn_cache_get (data1_handle dh)
+{
+    return &dh->absyn_cache;
+}
+
+data1_attset_cache *data1_attset_cache_get (data1_handle dh)
+{
+    return &dh->attset_cache;
+}
+
+void data1_destroy (data1_handle dh)
+{
+    if (!dh)
+       return;
+    wrbuf_free (dh->wrbuf, 1);
+    if (dh->tab_path)
+       xfree (dh->tab_path);
+    if (dh->tab_root)
+       xfree (dh->tab_root);
+    if (dh->read_buf)
+       xfree (dh->read_buf);
+    if (dh->map_buf)
+        xfree (dh->map_buf);
+    nmem_destroy (dh->mem);
+    
+    xfree (dh);
+}
+
+WRBUF data1_get_wrbuf (data1_handle dp)
+{
+    return dp->wrbuf;
+}
+
+char **data1_get_read_buf (data1_handle dp, int **lenp)
+{
+    *lenp = &dp->read_len;
+    yaz_log (LOG_DEBUG, "data1_get_read_buf lenp=%u", **lenp);
+    return &dp->read_buf;
+}
+
+char **data1_get_map_buf (data1_handle dp, int **lenp)
+{
+    *lenp = &dp->map_len;
+    yaz_log (LOG_DEBUG, "data1_get_map_buf lenp=%u", **lenp);
+    return &dp->map_buf;
+}
+
+void data1_set_tabpath (data1_handle dp, const char *p)
+{
+    xfree (dp->tab_path);
+    dp->tab_path = NULL;
+    if (p)
+        dp->tab_path = xstrdup (p);
+}
+
+void data1_set_tabroot (data1_handle dp, const char *p)
+{
+    xfree (dp->tab_root);
+    dp->tab_root = NULL;
+    if (p)
+        dp->tab_root = xstrdup (p);
+}
+
+const char *data1_get_tabpath (data1_handle dp)
+{
+    return dp->tab_path;
+}
+
+const char *data1_get_tabroot (data1_handle dp)
+{
+    return dp->tab_root;
+}
+
+FILE *data1_path_fopen (data1_handle dh, const char *file, const char *mode)
+{
+    const char *path = data1_get_tabpath(dh);
+    const char *root = data1_get_tabroot(dh);
+    return yaz_fopen (path, file, "r", root);
+}
+
+int data1_is_xmlmode(data1_handle dh)
+{
+    return dh->flags & DATA1_FLAG_XML;
+}
diff --git a/data1/d1_if.c b/data1/d1_if.c
new file mode 100644 (file)
index 0000000..1fe5a7d
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ *
+ * d1_if.c : A simple interface for extracting strings from data1_node
+ *           tree structures
+ *
+ * $Id: d1_if.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <data1.h>
+#include <yaz/log.h>
+
+#include <string.h>
+
+
+/*
+ * Search for a token in the supplied string up to the supplied list of stop characters or EOL
+ * At the end, return the character causing the break and fill pTokenBuffer with the token string so far
+ * After the scan, *pPosInBuffer will point to the next character after the one causing the break and
+ *                 pTokenBuffer will contain the actual token
+ */
+char data1_ScanNextToken(char* pBuffer,
+                         char** pPosInBuffer,
+                         char* pBreakChars,
+                         char* pWhitespaceChars,
+                         char* pTokenBuffer)
+{
+    char* pBuff = pTokenBuffer;
+    *pBuff = '\0';
+
+    while ( **pPosInBuffer )
+    {
+        if ( strchr(pBreakChars,**pPosInBuffer) != NULL )
+        {
+            /* Current character is a break character */
+            *pBuff++ = '\0';
+            return *((*pPosInBuffer)++);
+        }
+        else
+        {
+            if ( strchr(pWhitespaceChars, **pPosInBuffer) != NULL )
+                (*pPosInBuffer)++;
+            else
+                *pBuff++ = *((*pPosInBuffer)++);
+        }
+    }
+
+    *pBuff++ = *((*pPosInBuffer)++);
+    return(**pPosInBuffer);
+}
+
+/* 
+ * Attempt to find a string value given the specified tagpath
+ * 
+ * Need to make this safe by passing in a buffer..... 
+ *
+ */
+char *data1_getNodeValue(data1_node* node, char* pTagPath)
+{
+    data1_node* n = NULL;
+
+    n = data1_LookupNode(node, pTagPath );
+
+    if ( n )
+    {
+        /* n should be a tag node with some data under it.... */
+        if ( n->child )
+        {
+            if ( n->child->which == DATA1N_data )
+            {
+                return n->child->u.data.data;
+            }
+            else
+            {
+                yaz_log(LOG_WARN,"Attempting to lookup data for tagpath: Child node is not a data node");
+            }
+        }
+        else
+        {
+            yaz_log(LOG_WARN,"Found a node matching the tagpath, but it has no child data nodes");
+        }
+    }
+    else
+    {
+        yaz_log(LOG_WARN,"Unable to lookup a node on the specified tag path");
+    }
+
+    return "";
+}
+
+
+/* Max length of a tag */
+#define MAX_TAG_SIZE 50
+
+/* 
+ * data1_LookupNode : Try and find a node as specified by a tagpath
+ */
+data1_node *data1_LookupNode(data1_node* node, char* pTagPath)
+{
+    /* Node matching the pattern in the tagpath */
+    data1_node* matched_node = NULL;
+
+    /* Current Child node as we search for nodes matching the pattern in the tagpath */
+    data1_node* current_child = node->child;
+
+    /* Current position in string */
+    char* pCurrCharInPath = pTagPath;
+
+    /* Work buffer */
+    char Buffer[MAX_TAG_SIZE];
+
+    /* The tag type of this node */
+    int iTagType = 0;
+
+    /* for non string tags, the tag value */
+    int iTagValue = 0;
+
+    /* for string tags, the tag value */
+    char StringTagVal[MAX_TAG_SIZE];
+
+    /* Which occurence of that tag under this node */
+    int iOccurences=0;
+
+    /* Character causing a break */
+    char sepchr = '\0';
+    Buffer[0] = '\0';
+    StringTagVal[0] = '\0';
+
+    sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ",[(."," ", Buffer);
+
+    if ( sepchr == '[' )
+    {
+        /* Next component in node value is [ TagType, TagVal, TagOccurence ] */
+        sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ","," ", Buffer);
+        iTagType = atoi(Buffer);
+
+        /* Occurence is optional... */
+        sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ",]."," ", Buffer);
+
+        if ( iTagType == 3 )
+            strcpy(StringTagVal,Buffer);
+        else
+            iTagValue = atoi(Buffer);
+
+        /* If sepchar was a ',' there should be an instance */
+        if ( sepchr == ',' )
+        {
+            sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "]."," ", Buffer);
+            iOccurences = atoi(Buffer);
+        }
+
+        if ( sepchr == ']' )
+        {
+            /* See if we can scan the . for the next component or the end of the line... */
+            sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "."," ", Buffer);
+        }
+        else
+        {
+            yaz_log(LOG_FATAL,"Node does not end with a ]");
+            /* Fatal Error */
+            return(NULL);
+        }
+    }
+    else
+    {
+        /* We have a TagName so Read up to ( or . or EOL */
+        iTagType = 3;
+        strcpy(StringTagVal,Buffer);
+
+        if ( sepchr == '(' )
+        {
+            /* Read the occurence */
+            sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ")"," ", Buffer);
+            iOccurences = atoi(Buffer);
+
+            /* See if we can find the . at the end of this clause */
+            sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "."," ", Buffer);
+        }
+        
+    }
+
+    yaz_log(LOG_DEBUG,"search node for child like [%d,%d,%s,%d]",iTagType,iTagValue,StringTagVal,iOccurences);
+    
+
+    /* OK.. We have extracted tagtype, Value and Occurence, see if we can find a node */
+    /* Under the current parent matching that description                             */
+
+    while ( ( current_child ) && ( matched_node == NULL ) )
+    {
+        if ( current_child->which == DATA1N_tag )
+        {
+            if ( iTagType == 3 )
+            {
+                if ( ( current_child->u.tag.element == NULL ) &&
+                     ( strcmp(current_child->u.tag.tag, StringTagVal) == 0 ) )
+                {
+                    if ( iOccurences )
+                    {
+                        /* Everything matched, but not yet found the
+                           right occurence of the given tag */
+                        iOccurences--;
+                    }
+                    else
+                    {
+                        /* We have matched a string tag... Is there more to
+                           process? */
+                        matched_node = current_child;
+                    }
+                }
+            }
+            else /* Attempt to match real element */
+            {
+                yaz_log(LOG_WARN,"Non string tag matching not yet implemented");
+            }
+        }
+        current_child = current_child->next;
+    }
+
+
+    /* If there is more... Continue */
+    if ( ( sepchr == '.' ) && ( matched_node ) )
+    {
+        return data1_LookupNode(matched_node, pCurrCharInPath);
+    }
+    else
+    {
+        return matched_node;
+    }
+}
+
+/**
+
+data1_CountOccurences
+
+Count the number of occurences of the last instance on a tagpath.
+
+@param data1_node* node : The root of the tree we wish to look for occurences in
+@param const char* pTagPath : The tagpath we want to count the occurences of... 
+
+*/
+int data1_CountOccurences(data1_node* node, char* pTagPath)
+{
+    int iRetVal = 0;
+    data1_node* n = NULL;
+    data1_node* pParent = NULL;
+
+    n = data1_LookupNode(node, pTagPath );
+
+
+    if ( ( n ) &&
+         ( n->which == DATA1N_tag ) &&
+         ( n->parent ) )
+    {
+        data1_node* current_child;
+        pParent = n->parent;
+
+        for ( current_child = pParent->child;
+              current_child;
+              current_child = current_child->next )
+        {
+            if ( current_child->which == DATA1N_tag )
+            {
+                if ( current_child->u.tag.element == NULL )
+                {
+                    if ( ( n->u.tag.tag ) &&
+                         ( current_child->u.tag.tag ) &&
+                         ( strcmp(current_child->u.tag.tag, n->u.tag.tag) == 0 ) )
+                    {
+                        iRetVal++;
+                    }
+                }
+                else if ( current_child->u.tag.element == n->u.tag.element )
+                {
+                    /* Hmmm... Is the above right for non string tags???? */
+                    iRetVal++;
+                }
+            }
+        }
+    }
+
+    return iRetVal;
+}
diff --git a/data1/d1_map.c b/data1/d1_map.c
new file mode 100644 (file)
index 0000000..8cd3bc9
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_map.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <yaz/oid.h>
+#include <yaz/log.h>
+#include <yaz/readconf.h>
+#include <yaz/tpath.h>
+#include <data1.h>
+#include <d1_map.h>
+
+data1_maptab *data1_read_maptab (data1_handle dh, const char *file)
+{
+    NMEM mem = data1_nmem_get (dh);
+    data1_maptab *res = (data1_maptab *)nmem_malloc(mem, sizeof(*res));
+    FILE *f;
+    int lineno = 0;
+    int argc;
+    char *argv[50], line[512];
+    data1_mapunit **mapp;
+    int local_numeric = 0;
+
+    if (!(f = data1_path_fopen(dh, file, "r")))
+    {
+       yaz_log(LOG_WARN|LOG_ERRNO, "%s", file);
+       return 0;
+    }
+
+    res->name = 0;
+    res->target_absyn_ref = VAL_NONE;
+    res->map = 0;
+    mapp = &res->map;
+    res->next = 0;
+
+    while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
+       if (!strcmp(argv[0], "targetref"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args for targetref",
+                       file, lineno);
+               continue;
+           }
+           if ((res->target_absyn_ref = oid_getvalbyname(argv[1]))
+               == VAL_NONE)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Unknown reference '%s'",
+                       file, lineno, argv[1]);
+               continue;
+           }
+       }
+       else if (!strcmp(argv[0], "targetname"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args for targetname",
+                       file, lineno);
+               continue;
+           }
+           res->target_absyn_name =
+               (char *)nmem_malloc(mem, strlen(argv[1])+1);
+           strcpy(res->target_absyn_name, argv[1]);
+       }
+       else if (!yaz_matchstr(argv[0], "localnumeric"))
+           local_numeric = 1;
+       else if (!strcmp(argv[0], "name"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args for name", file, lineno);
+               continue;
+           }
+           res->name = (char *)nmem_malloc(mem, strlen(argv[1])+1);
+           strcpy(res->name, argv[1]);
+       }
+       else if (!strcmp(argv[0], "map"))
+       {
+           data1_maptag **mtp;
+           char *ep, *path = argv[2];
+
+           if (argc < 3)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # of args for map",
+                       file, lineno);
+               continue;
+           }
+           *mapp = (data1_mapunit *)nmem_malloc(mem, sizeof(**mapp));
+           (*mapp)->next = 0;
+           if (argc > 3 && !data1_matchstr(argv[3], "nodata"))
+               (*mapp)->no_data = 1;
+           else
+               (*mapp)->no_data = 0;
+           (*mapp)->source_element_name =
+               (char *)nmem_malloc(mem, strlen(argv[1])+1);
+           strcpy((*mapp)->source_element_name, argv[1]);
+           mtp = &(*mapp)->target_path;
+           if (*path == '/')
+               path++;
+           for (ep = strchr(path, '/'); path; (void)((path = ep) &&
+               (ep = strchr(path, '/'))))
+           {
+               int type, np;
+               char valstr[512], parm[512];
+
+               if (ep)
+                   ep++;
+               if ((np = sscanf(path, "(%d,%511[^)]):%511[^/]", &type, valstr,
+                   parm)) < 2)
+               {
+                   yaz_log(LOG_WARN, "%s:%d: Syntax error in map "
+                           "directive: %s", file, lineno, argv[2]);
+                   fclose(f);
+                   return 0;
+               }
+               *mtp = (data1_maptag *)nmem_malloc(mem, sizeof(**mtp));
+               (*mtp)->next = 0;
+               (*mtp)->type = type;
+               if (np > 2 && !data1_matchstr(parm, "new"))
+                   (*mtp)->new_field = 1;
+               else
+                   (*mtp)->new_field = 0;
+               if ((type != 3 || local_numeric) && d1_isdigit(*valstr))
+                {
+                   (*mtp)->which = D1_MAPTAG_numeric;
+                   (*mtp)->value.numeric = atoi(valstr);
+               }
+               else
+               {
+                   (*mtp)->which = D1_MAPTAG_string;
+                   (*mtp)->value.string =
+                       (char *)nmem_malloc(mem, strlen(valstr)+1);
+                   strcpy((*mtp)->value.string, valstr);
+               }
+               mtp = &(*mtp)->next;
+           }
+           mapp = &(*mapp)->next;
+       }
+       else 
+           yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'",
+                   file, lineno, argv[0]);
+
+    fclose(f);
+    return res;
+}
+
+/*
+ * Locate node with given elementname.
+ * NOTE: This is stupid - we don't find repeats this way.
+ */
+static data1_node *find_node(data1_node *p, char *elementname)
+{
+    data1_node *c, *r;
+
+    for (c = p->child; c; c = c->next)
+       if (c->which == DATA1N_tag && c->u.tag.element &&
+           !data1_matchstr(c->u.tag.element->name, elementname))
+           return c;
+       else if ((r = find_node(c, elementname)))
+           return r;
+    return 0;
+}
+
+/*
+ * See if the node n is equivalent to the tag t.
+ */
+static int tagmatch(data1_node *n, data1_maptag *t)
+{
+    if (n->which != DATA1N_tag)
+       return 0;
+    if (n->u.tag.element)
+    {
+       if (n->u.tag.element->tag->tagset)
+       {
+           if (n->u.tag.element->tag->tagset->type != t->type)
+               return 0;
+       }
+       else if (t->type != 3)
+           return 0;
+       if (n->u.tag.element->tag->which == DATA1T_numeric)
+       {
+           if (t->which != D1_MAPTAG_numeric)
+               return 0;
+           if (n->u.tag.element->tag->value.numeric != t->value.numeric)
+               return 0;
+       }
+       else
+       {
+           if (t->which != D1_MAPTAG_string)
+               return 0;
+           if (data1_matchstr(n->u.tag.element->tag->value.string,
+               t->value.string))
+               return 0;
+       }
+    }
+    else /* local tag */
+    {
+       char str[10];
+
+       if (t->type != 3)
+           return 0;
+       if (t->which == D1_MAPTAG_numeric)
+           sprintf(str, "%d", t->value.numeric);
+       else
+           strcpy(str, t->value.string);
+       if (data1_matchstr(n->u.tag.tag, str))
+           return 0;
+    }
+    return 1;
+}
+
+static data1_node *dup_child (data1_handle dh, data1_node *n,
+                              data1_node **last, NMEM mem,
+                              data1_node *parent)
+{
+    data1_node *first = 0;
+    data1_node **m = &first;
+
+    for (; n; n = n->next)
+    {
+        *last = *m = (data1_node *) nmem_malloc (mem, sizeof(**m));
+        memcpy (*m, n, sizeof(**m));
+        
+        (*m)->parent = parent;
+        (*m)->root = parent->root;
+        (*m)->child = dup_child(dh, n->child, &(*m)->last_child, mem, *m);
+        m = &(*m)->next;
+    }
+    *m = 0;
+    return first;
+}
+
+static int map_children(data1_handle dh, data1_node *n, data1_maptab *map,
+                       data1_node *res, NMEM mem)
+{
+    data1_node *c;
+    data1_mapunit *m;
+    /*
+     * locate each source element in turn.
+     */
+    for (c = n->child; c; c = c->next)
+       if (c->which == DATA1N_tag && c->u.tag.element)
+       {
+           for (m = map->map; m; m = m->next)
+           {
+               if (!data1_matchstr(m->source_element_name,
+                   c->u.tag.element->name))
+               {
+                   data1_node *pn = res;
+                   data1_node *cur = pn->last_child;
+                   data1_maptag *mt;
+
+                   /*
+                    * process the target path specification.
+                    */
+                   for (mt = m->target_path; mt; mt = mt->next)
+                   {
+                       if (!cur || mt->new_field || !tagmatch(cur, mt))
+                       {
+                           cur = data1_mk_node2 (dh, mem, DATA1N_tag, pn);
+                           cur->u.tag.tag = mt->value.string;
+                       }
+                       
+                       if (mt->next)
+                           pn = cur;
+                       else if (!m->no_data)
+                       {
+                            cur->child =
+                                dup_child (dh, c->child,
+                                           &cur->last_child, mem, cur);
+                       }
+                   }
+               }
+           }
+           if (map_children(dh, c, map, res, mem) < 0)
+               return -1;
+       }
+    return 0;
+}
+
+/*
+ * Create a (possibly lossy) copy of the given record based on the
+ * table. The new copy will refer back to the data of the original record,
+ * which should not be discarded during the lifetime of the copy.
+ */
+data1_node *data1_map_record (data1_handle dh, data1_node *n,
+                             data1_maptab *map, NMEM m)
+{
+    data1_node *res1, *res = data1_mk_node2 (dh, m, DATA1N_root, 0);
+
+    res->which = DATA1N_root;
+    res->u.root.type = map->target_absyn_name;
+    if (!(res->u.root.absyn = data1_get_absyn(dh, map->target_absyn_name)))
+    {
+       yaz_log(LOG_WARN, "%s: Failed to load target absyn '%s'",
+               map->name, map->target_absyn_name);
+    }
+    if (data1_is_xmlmode(dh))
+    {
+        n = n->child;
+        if (!n)
+            return 0;
+        res1 = data1_mk_tag (dh, m, map->target_absyn_name, 0, res);
+    }
+    else
+        res1 = res;
+
+    if (map_children(dh, n, map, res1, m) < 0)
+    {
+       data1_free_tree(dh, res);
+       return 0;
+    }
+    return res;
+}
+
diff --git a/data1/d1_marc.c b/data1/d1_marc.c
new file mode 100644 (file)
index 0000000..5bd1e2c
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_marc.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <yaz/oid.h>
+#include <yaz/log.h>
+#include <yaz/marcdisp.h>
+#include <yaz/readconf.h>
+#include <yaz/xmalloc.h>
+#include <yaz/tpath.h>
+#include <data1.h>
+
+data1_marctab *data1_read_marctab (data1_handle dh, const char *file)
+{
+    FILE *f;
+    NMEM mem = data1_nmem_get (dh);
+    data1_marctab *res = (data1_marctab *)nmem_malloc(mem, sizeof(*res));
+    char line[512], *argv[50];
+    int lineno = 0;
+    int argc;
+    
+    if (!(f = data1_path_fopen(dh, file, "r")))
+    {
+       yaz_log(LOG_WARN|LOG_ERRNO, "%s", file);
+       return 0;
+    }
+
+    res->name = 0;
+    res->reference = VAL_NONE;
+    res->next = 0;
+    res->length_data_entry = 4;
+    res->length_starting = 5;
+    res->length_implementation = 0;
+    strcpy(res->future_use, "4");
+
+    strcpy(res->record_status, "n");
+    strcpy(res->implementation_codes, "    ");
+    res->indicator_length = 2;
+    res->identifier_length = 2;
+    res->force_indicator_length = -1;
+    res->force_identifier_length = -1;
+    strcpy(res->user_systems, "z  ");
+    
+    while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
+       if (!strcmp(*argv, "name"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d:Missing arg for %s", file, lineno,
+                       *argv);
+               continue;
+           }
+           res->name = nmem_strdup(mem, argv[1]);
+       }
+       else if (!strcmp(*argv, "reference"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno,
+                       *argv);
+               continue;
+           }
+           if ((res->reference = oid_getvalbyname(argv[1])) == VAL_NONE)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Unknown tagset reference '%s'",
+                       file, lineno, argv[1]);
+               continue;
+           }
+       }
+       else if (!strcmp(*argv, "length-data-entry"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno,
+                       *argv);
+               continue;
+           }
+           res->length_data_entry = atoi(argv[1]);
+       }
+       else if (!strcmp(*argv, "length-starting"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno,
+                       *argv);
+               continue;
+           }
+           res->length_starting = atoi(argv[1]);
+       }
+       else if (!strcmp(*argv, "length-implementation"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno,
+                       *argv);
+               continue;
+           }
+           res->length_implementation = atoi(argv[1]);
+       }
+       else if (!strcmp(*argv, "future-use"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno,
+                       *argv);
+               continue;
+           }
+           strncpy(res->future_use, argv[1], 2);
+       }
+       else if (!strcmp(*argv, "force-indicator-length"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno,
+                       *argv);
+               continue;
+           }
+           res->force_indicator_length = atoi(argv[1]);
+       }
+       else if (!strcmp(*argv, "force-identifier-length"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno,
+                       *argv);
+               continue;
+           }
+           res->force_identifier_length = atoi(argv[1]);
+       }
+       else
+           yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'", file, lineno,
+                   *argv);
+
+    fclose(f);
+    return res;
+}
+
+
+/*
+ * Locate some data under this node. This routine should handle variants
+ * prettily.
+ */
+static char *get_data(data1_node *n, int *len)
+{
+    char *r;
+
+    while (n)
+    {
+        if (n->which == DATA1N_data)
+        {
+            int i;
+            *len = n->u.data.len;
+
+            for (i = 0; i<*len; i++)
+                if (!d1_isspace(n->u.data.data[i]))
+                    break;
+            while (*len && d1_isspace(n->u.data.data[*len - 1]))
+                (*len)--;
+            *len = *len - i;
+            if (*len > 0)
+                return n->u.data.data + i;
+        }
+        if (n->which == DATA1N_tag)
+            n = n->child;
+       else if (n->which == DATA1N_data)
+            n = n->next;
+       else
+            break;     
+    }
+    r = "";
+    *len = strlen(r);
+    return r;
+}
+
+static void memint (char *p, int val, int len)
+{
+    char buf[10];
+
+    if (len == 1)
+        *p = val + '0';
+    else
+    {
+        sprintf (buf, "%08d", val);
+        memcpy (p, buf+8-len, len);
+    }
+}
+
+static int is_indicator (data1_marctab *p, data1_node *subf)
+{
+#if 1
+    if (p->indicator_length != 2 ||
+       (subf && subf->which == DATA1N_tag && strlen(subf->u.tag.tag) == 2))
+       return 1;
+#else
+    if (subf && subf->which == DATA1N_tag && subf->child->which == DATA1N_tag)
+       return 1;
+#endif
+    return 0;
+}
+
+static int nodetomarc(data1_handle dh,
+                     data1_marctab *p, data1_node *n, int selected,
+                      char **buf, int *size)
+{
+    int len = 26;
+    int dlen;
+    int base_address = 25;
+    int entry_p, data_p;
+    char *op;
+    data1_node *field, *subf;
+
+    yaz_log (LOG_DEBUG, "nodetomarc");
+
+    for (field = n->child; field; field = field->next)
+    {
+        int is00X = 0;
+
+       if (field->which != DATA1N_tag)
+       {
+           yaz_log(LOG_WARN, "Malformed field composition for marc output.");
+           return -1;
+       }
+       if (selected && !field->u.tag.node_selected)
+           continue;
+
+       subf = field->child;
+        if (!subf)
+            continue;
+
+        len += 4 + p->length_data_entry + p->length_starting
+            + p->length_implementation;
+        base_address += 3 + p->length_data_entry + p->length_starting
+            + p->length_implementation;
+
+       if (subf->which == DATA1N_data)
+            is00X = 1;
+       if (!data1_is_xmlmode(dh))
+        {
+            if (subf->which == DATA1N_tag && !strcmp(subf->u.tag.tag, "@"))
+                is00X = 1;
+        }
+            
+       
+        if (!is00X)
+            len += p->indicator_length;  
+       /*  we'll allow no indicator if length is not 2 */
+       if (is_indicator (p, subf))
+           subf = subf->child;
+
+        for (; subf; subf = subf->next)
+        {
+            if (!is00X)
+                len += p->identifier_length;
+           get_data(subf, &dlen);
+            len += dlen;
+        }
+    }
+
+    if (!*buf)
+       *buf = (char *)xmalloc(*size = len);
+    else if (*size <= len)
+       *buf = (char *)xrealloc(*buf, *size = len);
+       
+    op = *buf;
+    memint (op, len, 5);
+    memcpy (op+5, p->record_status, 1);
+    memcpy (op+6, p->implementation_codes, 4);
+    memint (op+10, p->indicator_length, 1);
+    memint (op+11, p->identifier_length, 1);
+    memint (op+12, base_address, 5);
+    memcpy (op+17, p->user_systems, 3);
+    memint (op+20, p->length_data_entry, 1);
+    memint (op+21, p->length_starting, 1);
+    memint (op+22, p->length_implementation, 1);
+    memcpy (op+23, p->future_use, 1);
+    
+    entry_p = 24;
+    data_p = base_address;
+
+    for (field = n->child; field; field = field->next)
+    {
+        int is00X = 0;
+
+        int data_0 = data_p;
+       char *indicator_data = "    ";
+       if (selected && !field->u.tag.node_selected)
+           continue;
+
+       subf = field->child;
+        if (!subf)
+            continue;
+
+        if (subf->which == DATA1N_data)
+            is00X = 1;
+       if (!data1_is_xmlmode(dh))
+        {
+            if (subf->which == DATA1N_tag && !strcmp(subf->u.tag.tag, "@"))
+                is00X = 1;
+        }
+
+       if (is_indicator (p, subf))
+       {
+            indicator_data = subf->u.tag.tag;
+           subf = subf->child;
+       }
+        if (!is00X)
+        {
+            memcpy (op + data_p, indicator_data, p->indicator_length);
+            data_p += p->indicator_length;
+        }
+        for (; subf; subf = subf->next)
+        {
+           char *data;
+
+            if (!is00X)
+            {
+                const char *identifier = "a";
+                if (subf->which != DATA1N_tag)
+                    yaz_log(LOG_WARN, "Malformed fields for marc output.");
+                else
+                    identifier = subf->u.tag.tag;
+                op[data_p] = ISO2709_IDFS;
+                memcpy (op + data_p+1, identifier, p->identifier_length-1);
+                data_p += p->identifier_length;
+            }
+           data = get_data(subf, &dlen);
+            memcpy (op + data_p, data, dlen);
+            data_p += dlen;
+        }
+        op[data_p++] = ISO2709_FS;
+
+        memcpy (op + entry_p, field->u.tag.tag, 3);
+        entry_p += 3;
+        memint (op + entry_p, data_p - data_0, p->length_data_entry);
+        entry_p += p->length_data_entry;
+        memint (op + entry_p, data_0 - base_address, p->length_starting);
+        entry_p += p->length_starting;
+        entry_p += p->length_implementation;
+    }
+    op[entry_p++] = ISO2709_FS;
+    assert (entry_p == base_address);
+    op[data_p++] = ISO2709_RS;
+    assert (data_p == len);
+    return len;
+}
+
+char *data1_nodetomarc(data1_handle dh, data1_marctab *p, data1_node *n,
+                      int selected, int *len)
+{
+    int *size;
+    char **buf = data1_get_map_buf (dh, &size);
+
+    n = data1_get_root_tag (dh, n);
+    if (!n)
+        return 0;
+    *len = nodetomarc(dh, p, n, selected, buf, size);
+    return *buf;
+}
diff --git a/data1/d1_prtree.c b/data1/d1_prtree.c
new file mode 100644 (file)
index 0000000..0b46e8b
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_prtree.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <yaz/log.h>
+#include <data1.h>
+
+static void pr_string (FILE *out, const char *str, int len)
+{
+    int i;
+    for (i = 0; i<len; i++)
+    {
+       int c = str[i];
+       if (c < 32 || c >126)
+           fprintf (out, "\\x%02x", c & 255);
+       else
+           fputc (c, out);
+    }
+}
+
+static void pr_tree (data1_handle dh, data1_node *n, FILE *out, int level)
+{
+    fprintf (out, "%*s", level, "");
+    switch (n->which)
+    {
+    case DATA1N_root:
+        fprintf (out, "root abstract syntax=%s\n", n->u.root.type);
+        break;
+    case DATA1N_tag:
+       fprintf (out, "tag type=%s sel=%d\n", n->u.tag.tag,
+                 n->u.tag.node_selected);
+        if (n->u.tag.attributes)
+        {
+            data1_xattr *xattr = n->u.tag.attributes;
+            fprintf (out, "%*s attr", level, "");
+            for (; xattr; xattr = xattr->next)
+                fprintf (out, " %s=%s ", xattr->name, xattr->value);
+            fprintf (out, "\n");
+        }
+       break;
+    case DATA1N_data:
+    case DATA1N_comment:
+        if (n->which == DATA1N_data)
+            fprintf (out, "data type=");
+        else
+            fprintf (out, "comment type=");
+       switch (n->u.data.what)
+       {
+       case DATA1I_inctxt:
+           fprintf (out, "inctxt\n");
+           break;
+       case DATA1I_incbin:
+           fprintf (out, "incbin\n");
+           break;
+       case DATA1I_text:
+           fprintf (out, "text '");
+           pr_string (out, n->u.data.data, n->u.data.len);
+           fprintf (out, "'\n");
+           break;
+       case DATA1I_num:
+           fprintf (out, "num '");
+           pr_string (out, n->u.data.data, n->u.data.len);
+           fprintf (out, "'\n");
+           break;
+       case DATA1I_oid:
+           fprintf (out, "oid '");
+           pr_string (out, n->u.data.data, n->u.data.len);
+           fprintf (out, "'\n");
+           break;
+       case DATA1I_xmltext:
+           fprintf (out, "xml text '");
+           pr_string (out, n->u.data.data, n->u.data.len);
+           fprintf (out, "'\n");
+            break;
+       default:
+           fprintf (out, "unknown(%d)\n", n->u.data.what);
+           break;
+       }
+       break;
+    case DATA1N_preprocess:
+       fprintf (out, "preprocess target=%s\n", n->u.preprocess.target);
+        if (n->u.preprocess.attributes)
+        {
+            data1_xattr *xattr = n->u.preprocess.attributes;
+            fprintf (out, "%*s attr", level, "");
+            for (; xattr; xattr = xattr->next)
+                fprintf (out, " %s=%s ", xattr->name, xattr->value);
+            fprintf (out, "\n");
+        }
+       break;
+    case DATA1N_variant:
+       fprintf (out, "variant\n");
+#if 0
+       if (n->u.variant.type->name)
+           fprintf (out, " class=%s type=%d value=%s\n",
+                    n->u.variant.type->name, n->u.variant.type->type,
+                    n->u.variant.value);
+#endif
+       break;
+    default:
+       fprintf (out, "unknown(%d)\n", n->which);
+    }
+    if (n->child)
+       pr_tree (dh, n->child, out, level+4);
+    if (n->next)
+       pr_tree (dh, n->next, out, level);
+}
+
+
+void data1_pr_tree (data1_handle dh, data1_node *n, FILE *out)
+{
+    pr_tree (dh, n, out, 0);
+}
diff --git a/data1/d1_read.c b/data1/d1_read.c
new file mode 100644 (file)
index 0000000..6597220
--- /dev/null
@@ -0,0 +1,1092 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_read.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <yaz/xmalloc.h>
+#include <yaz/yaz-util.h>
+#include <yaz/log.h>
+#include <data1.h>
+
+data1_node *data1_get_root_tag (data1_handle dh, data1_node *n)
+{
+    if (!n)
+        return 0;
+    if (data1_is_xmlmode(dh))
+    {
+        n = n->child;
+        while (n && n->which != DATA1N_tag)
+            n = n->next;
+    }
+    return n;
+}
+        
+/*
+ * get the tag which is the immediate parent of this node (this may mean
+ * traversing intermediate things like variants and stuff.
+ */
+data1_node *get_parent_tag (data1_handle dh, data1_node *n)
+{
+    if (data1_is_xmlmode(dh))
+    {
+        for (; n && n->which != DATA1N_root; n = n->parent)
+            if (n->which == DATA1N_tag && n->parent &&
+                n->parent->which != DATA1N_root)
+                return n;
+    }
+    else
+    {
+        for (; n && n->which != DATA1N_root; n = n->parent)
+            if (n->which == DATA1N_tag)
+                return n;
+    }
+    return 0;
+}
+
+data1_node *data1_mk_node (data1_handle dh, NMEM m)
+{
+    return data1_mk_node2 (dh, m, DATA1N_root, 0);
+}
+
+data1_node *data1_mk_node_type (data1_handle dh, NMEM m, int type)
+{
+    return data1_mk_node2 (dh, m, type, 0);
+}
+
+static void data1_init_node (data1_handle dh, data1_node *r, int type)
+{
+    r->which = type;
+    switch(type)
+    {
+    case DATA1N_tag:
+       r->u.tag.tag = 0;
+       r->u.tag.element = 0;
+       r->u.tag.no_data_requested = 0;
+       r->u.tag.node_selected = 0;
+       r->u.tag.make_variantlist = 0;
+       r->u.tag.get_bytes = -1;
+       r->u.tag.attributes = 0;
+       break;
+    case DATA1N_root:
+       r->u.root.type = 0;
+       r->u.root.absyn = 0;
+       break;
+    case DATA1N_data:
+       r->u.data.data = 0;
+       r->u.data.len = 0;
+       r->u.data.what = 0;
+       r->u.data.formatted_text = 0;
+        break;
+    case DATA1N_comment:
+       r->u.data.data = 0;
+       r->u.data.len = 0;
+       r->u.data.what = 0;
+       r->u.data.formatted_text = 1;
+        break;
+    case DATA1N_variant:
+        r->u.variant.type = 0;
+        r->u.variant.value = 0;
+       break;
+    case DATA1N_preprocess:
+        r->u.preprocess.target = 0;
+        r->u.preprocess.attributes = 0;
+        break;
+    default:
+       logf (LOG_WARN, "data_mk_node_type. bad type = %d\n", type);
+    }
+}
+
+data1_node *data1_append_node (data1_handle dh, NMEM m, int type,
+                               data1_node *parent)
+{
+    data1_node *r = (data1_node *)nmem_malloc(m, sizeof(*r));
+    r->next = r->child = r->last_child = 0;
+    r->destroy = 0;
+    
+    if (!parent)
+        r->root = r;
+    else
+    {
+        r->root = parent->root;
+        r->parent = parent;
+        if (!parent->child)
+            parent->child = parent->last_child = r;
+        else
+            parent->last_child->next = r;
+        parent->last_child = r;
+    }
+    data1_init_node(dh, r, type);
+    return r;
+}
+
+data1_node *data1_mk_node2 (data1_handle dh, NMEM m, int type,
+                            data1_node *parent)
+{
+    return data1_append_node (dh, m, type, parent);
+}
+
+data1_node *data1_insert_node (data1_handle dh, NMEM m, int type,
+                               data1_node *parent)
+{
+    data1_node *r = (data1_node *)nmem_malloc(m, sizeof(*r));
+    r->next = r->child = r->last_child = 0;
+    r->destroy = 0;
+    
+    if (!parent)
+        r->root = r;
+    else
+    {
+        r->root = parent->root;
+        r->parent = parent;
+        if (!parent->child)
+            parent->last_child = r;
+        else
+            r->next = parent->child;
+        parent->child = r;
+    }
+    data1_init_node(dh, r, type);
+    return r;
+}
+
+void data1_free_tree (data1_handle dh, data1_node *t)
+{
+    data1_node *p = t->child, *pn;
+
+    while (p)
+    {
+       pn = p->next;
+       data1_free_tree (dh, p);
+       p = pn;
+    }
+    if (t->destroy)
+       (*t->destroy)(t);
+}
+
+data1_node *data1_mk_root (data1_handle dh, NMEM nmem, const char *name)
+{
+    data1_absyn *absyn = data1_get_absyn (dh, name);
+    data1_node *res;
+    if (!absyn)
+    {
+        yaz_log(LOG_WARN, "Unable to acquire abstract syntax " "for '%s'",
+                name); 
+        /* It's now OK for a record not to have an absyn */
+    }
+    res = data1_mk_node2 (dh, nmem, DATA1N_root, 0);
+    res->u.root.type = data1_insert_string (dh, res, nmem, name);
+    res->u.root.absyn = absyn;
+    return res;
+}
+
+void data1_set_root(data1_handle dh, data1_node *res,
+                    NMEM nmem, const char *name)
+{
+    data1_absyn *absyn = data1_get_absyn (dh, name);
+
+    res->u.root.type = data1_insert_string (dh, res, nmem, name);
+    res->u.root.absyn = absyn;
+}
+
+data1_node *data1_mk_preprocess (data1_handle dh, NMEM nmem,
+                                 const char *target,
+                                 const char **attr, data1_node *at)
+{
+    return data1_mk_preprocess_n (dh, nmem, target, strlen(target),
+                                  attr, at);
+}
+
+data1_node *data1_mk_preprocess_n (data1_handle dh, NMEM nmem,
+                                   const char *target, size_t len,
+                                   const char **attr, data1_node *at)
+{
+    data1_xattr **p;
+    data1_node *res = data1_mk_node2 (dh, nmem, DATA1N_preprocess, at);
+    res->u.preprocess.target = data1_insert_string_n (dh, res, nmem,
+                                                      target, len);
+    
+    p = &res->u.preprocess.attributes;
+    while (attr && *attr)
+    {
+        *p = (data1_xattr*) nmem_malloc (nmem, sizeof(**p));
+        (*p)->name = nmem_strdup (nmem, *attr++);
+        (*p)->value = nmem_strdup (nmem, *attr++);
+        (*p)->what = DATA1I_text;
+
+        p = &(*p)->next;
+    }
+    *p = 0;
+    return res;
+}
+
+data1_node *data1_mk_tag_n (data1_handle dh, NMEM nmem, 
+                            const char *tag, size_t len, const char **attr,
+                            data1_node *at)
+{
+    data1_node *partag = get_parent_tag(dh, at);
+    data1_node *res = data1_mk_node2 (dh, nmem, DATA1N_tag, at);
+    data1_xattr **p;
+    data1_element *e = 0;
+    
+    res->u.tag.tag = data1_insert_string_n (dh, res, nmem, tag, len);
+    
+    if (!partag)  /* top tag? */
+        e  = data1_getelementbytagname (dh, at->root->u.root.absyn,
+                                        0 /* index as local */,
+                                        res->u.tag.tag);
+    else
+    {
+        /* only set element for known tags */
+        e = partag->u.tag.element;
+        if (e)
+            e = data1_getelementbytagname (dh, at->root->u.root.absyn,
+                                           e, res->u.tag.tag);
+    }
+    res->u.tag.element = e;
+    p = &res->u.tag.attributes;
+    while (attr && *attr)
+    {
+        *p = (data1_xattr*) nmem_malloc (nmem, sizeof(**p));
+        (*p)->name = nmem_strdup (nmem, *attr++);
+        (*p)->value = nmem_strdup (nmem, *attr++);
+        (*p)->what = DATA1I_text;
+        p = &(*p)->next;
+    }
+    *p = 0;
+    return res;
+}
+
+void data1_tag_add_attr (data1_handle dh, NMEM nmem,
+                         data1_node *res, const char **attr)
+{
+    data1_xattr **p;
+
+    if (res->which != DATA1N_tag)
+        return;
+
+    p = &res->u.tag.attributes;
+    while (*p)
+        p = &(*p)->next;
+
+    while (attr && *attr)
+    {
+        *p = (data1_xattr*) nmem_malloc (nmem, sizeof(**p));
+        (*p)->name = nmem_strdup (nmem, *attr++);
+        (*p)->value = nmem_strdup (nmem, *attr++);
+        (*p)->what = DATA1I_text;
+        p = &(*p)->next;
+    }
+    *p = 0;
+}
+
+data1_node *data1_mk_tag (data1_handle dh, NMEM nmem,
+                          const char *tag, const char **attr, data1_node *at) 
+{
+    return data1_mk_tag_n (dh, nmem, tag, strlen(tag), attr, at);
+}
+
+data1_node *data1_search_tag (data1_handle dh, data1_node *n,
+                              const char *tag)
+{
+    if (*tag == '/')
+    {
+        n = data1_get_root_tag (dh, n);
+        if (n)
+            n = n->child;
+        tag++;
+    }
+    for (; n; n = n->next)
+       if (n->which == DATA1N_tag && n->u.tag.tag &&
+           !yaz_matchstr (tag, n->u.tag.tag))
+       {
+           return n;
+       }
+    return 0;
+}
+
+data1_node *data1_mk_tag_uni (data1_handle dh, NMEM nmem, 
+                              const char *tag, data1_node *at)
+{
+    data1_node *node = data1_search_tag (dh, at->child, tag);
+    if (!node)
+       node = data1_mk_tag (dh, nmem, tag, 0 /* attr */, at);
+    else
+        node->child = node->last_child = 0;
+    return node;
+}
+
+data1_node *data1_mk_text_n (data1_handle dh, NMEM mem,
+                             const char *buf, size_t len, data1_node *parent)
+{
+    data1_node *res = data1_mk_node2 (dh, mem, DATA1N_data, parent);
+    res->u.data.what = DATA1I_text;
+    res->u.data.len = len;
+    
+    res->u.data.data = data1_insert_string_n (dh, res, mem, buf, len);
+    return res;
+}
+
+data1_node *data1_mk_text_nf (data1_handle dh, NMEM mem,
+                              const char *buf, size_t len, data1_node *parent)
+{
+    data1_node *res = data1_mk_text_n (dh, mem, buf, len, parent);
+    res->u.data.formatted_text = 1;
+    return res;
+}
+
+data1_node *data1_mk_text (data1_handle dh, NMEM mem,
+                           const char *buf, data1_node *parent)
+{
+    return data1_mk_text_n (dh, mem, buf, strlen(buf), parent);
+}
+
+data1_node *data1_mk_comment_n (data1_handle dh, NMEM mem,
+                                const char *buf, size_t len,
+                                data1_node *parent)
+{
+    data1_node *res = data1_mk_node2 (dh, mem, DATA1N_comment, parent);
+    res->u.data.what = DATA1I_text;
+    res->u.data.len = len;
+    
+    res->u.data.data = data1_insert_string_n (dh, res, mem, buf, len);
+    return res;
+}
+
+data1_node *data1_mk_comment (data1_handle dh, NMEM mem,
+                              const char *buf, data1_node *parent)
+{
+    return data1_mk_comment_n (dh, mem, buf, strlen(buf), parent);
+}
+
+char *data1_insert_string_n (data1_handle dh, data1_node *res,
+                             NMEM m, const char *str, size_t len)
+{
+    char *b;
+    if (len >= DATA1_LOCALDATA)
+        b = (char *) nmem_malloc (m, len+1);
+    else
+        b = res->lbuf;
+    memcpy (b, str, len);
+    b[len] = 0;
+    return b;
+}
+
+char *data1_insert_string (data1_handle dh, data1_node *res,
+                           NMEM m, const char *str)
+{
+    return data1_insert_string_n (dh, res, m, str, strlen(str));
+}
+
+static data1_node *data1_add_insert_taggeddata(data1_handle dh,
+                                               data1_node *at,
+                                               const char *tagname, NMEM m,
+                                               int local_allowed,
+                                              int insert_mode)
+{
+    data1_node *root = at->root;
+    data1_node *partag = get_parent_tag (dh, at);
+    data1_element *e = NULL;
+    data1_node *datn = 0;
+    data1_node *tagn = 0;
+
+    if (!partag)
+        e = data1_getelementbytagname (dh, root->u.root.absyn, 0, tagname);
+    else 
+    {
+       e = partag->u.tag.element;
+        if (e)
+            e = data1_getelementbytagname (dh, root->u.root.absyn, e, tagname);
+    }
+    if (local_allowed || e)
+    {
+        if (insert_mode)
+            tagn = data1_insert_node (dh, m, DATA1N_tag, at);
+        else
+            tagn = data1_append_node (dh, m, DATA1N_tag, at);
+        tagn->u.tag.tag = data1_insert_string (dh, tagn, m, tagname);
+        tagn->u.tag.element = e;
+        datn = data1_mk_node2 (dh, m, DATA1N_data, tagn);
+    }
+    return datn;
+}
+
+data1_node *data1_mk_tag_data(data1_handle dh, data1_node *at,
+                              const char *tagname, NMEM m)
+{
+    return data1_add_insert_taggeddata (dh, at, tagname, m, 1, 0);
+}
+
+
+/*
+ * Insert a tagged node into the record root as first child of the node at
+ * which should be root or tag itself). Returns pointer to the data node,
+ * which can then be modified.
+ */
+data1_node *data1_mk_tag_data_wd(data1_handle dh, data1_node *at,
+                                 const char *tagname, NMEM m)
+{
+    return data1_add_insert_taggeddata (dh, at, tagname, m, 0, 1);
+}
+
+data1_node *data1_insert_taggeddata (data1_handle dh, data1_node *root,
+                                     data1_node *at, const char *tagname,
+                                     NMEM m)
+{
+    return data1_add_insert_taggeddata (dh, at, tagname, m, 0, 1);
+}
+
+data1_node *data1_add_taggeddata (data1_handle dh, data1_node *root,
+                                  data1_node *at, const char *tagname,
+                                  NMEM m)
+{
+    return data1_add_insert_taggeddata (dh, at, tagname, m, 1, 0);
+}
+
+data1_node *data1_mk_tag_data_int (data1_handle dh, data1_node *at,
+                                   const char *tag, int num,
+                                   NMEM nmem)
+{
+    data1_node *node_data;
+    
+    node_data = data1_mk_tag_data (dh, at, tag, nmem);
+    if (!node_data)
+       return 0;
+    node_data->u.data.what = DATA1I_num;
+    node_data->u.data.data = node_data->lbuf;
+    sprintf (node_data->u.data.data, "%d", num);
+    node_data->u.data.len = strlen (node_data->u.data.data);
+    return node_data;
+}
+
+data1_node *data1_mk_tag_data_oid (data1_handle dh, data1_node *at,
+                                   const char *tag, Odr_oid *oid,
+                                   NMEM nmem)
+{
+    data1_node *node_data;
+    char str[128], *p = str;
+    Odr_oid *ii;
+    
+    node_data = data1_mk_tag_data (dh, at, tag, nmem);
+    if (!node_data)
+       return 0;
+    
+    for (ii = oid; *ii >= 0; ii++)
+    {
+       if (ii != oid)
+           *p++ = '.';
+       sprintf (p, "%d", *ii);
+       p += strlen (p);
+    }
+    node_data->u.data.what = DATA1I_oid;
+    node_data->u.data.len = strlen (str);
+    node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
+    return node_data;
+}
+
+
+data1_node *data1_mk_tag_data_text (data1_handle dh, data1_node *at,
+                                    const char *tag, const char *str,
+                                    NMEM nmem)
+{
+    data1_node *node_data;
+    
+    node_data = data1_mk_tag_data (dh, at, tag, nmem);
+    if (!node_data)
+       return 0;
+    node_data->u.data.what = DATA1I_text;
+    node_data->u.data.len = strlen (str);
+    node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
+    return node_data;
+}
+
+
+data1_node *data1_mk_tag_data_text_uni (data1_handle dh, data1_node *at,
+                                        const char *tag, const char *str,
+                                        NMEM nmem)
+{
+    data1_node *node = data1_search_tag (dh, at->child, tag);
+    if (!node)
+        return data1_mk_tag_data_text (dh, at, tag, str, nmem);
+    else
+    {
+       data1_node *node_data = node->child;
+       node_data->u.data.what = DATA1I_text;
+       node_data->u.data.len = strlen (str);
+       node_data->u.data.data = data1_insert_string (dh, node_data,
+                                                     nmem, str);
+        node_data->child = node_data->last_child = 0;
+       return node_data;
+    }
+}
+
+static int ampr (int (*get_byte)(void *fh), void *fh, int *amp)
+{
+#if 1
+    int c = (*get_byte)(fh);
+    *amp = 0;
+    return c;
+#else
+    int c = (*get_byte)(fh);
+    *amp = 0;
+    if (c == '&')
+    {
+        char ent[20];
+        int i = 0;
+       
+        while (1)
+        {
+            c = (*get_byte)(fh);
+            if (c == ';')
+            {
+                ent[i] = 0;
+                
+                c = ' ';
+                if (!strcmp (ent, "quot"))
+                    c = '"';
+                if (!strcmp (ent, "apos"))
+                    c = '\'';
+                if (!strcmp (ent, "gt"))
+                    c = '>';
+                if (!strcmp (ent, "lt"))
+                    c = '<';
+                if (!strcmp (ent, "amp"))
+                    c = '&';
+                *amp = 1;
+                break;
+            }
+            else if (c == 0 || d1_isspace(c))
+                break;
+            if (i < 19)
+                ent[i++] = c;
+        }
+    }
+    return c;
+#endif
+}
+
+data1_xattr *data1_read_xattr (data1_handle dh, NMEM m,
+                              int (*get_byte)(void *fh), void *fh,
+                              WRBUF wrbuf, int *ch, int *amp)
+{
+    data1_xattr *p_first = 0;
+    data1_xattr **pp = &p_first;
+    int c = *ch;
+    for (;;)
+    {
+       data1_xattr *p;
+       int len;
+       while (*amp || (c && d1_isspace(c)))
+           c = ampr (get_byte, fh, amp);
+       if (*amp == 0 && (c == 0 || c == '>' || c == '/'))
+           break;
+       *pp = p = (data1_xattr *) nmem_malloc (m, sizeof(*p));
+       p->next = 0;
+       pp = &p->next;
+       p->value = 0;
+        p->what = DATA1I_xmltext;
+       
+       wrbuf_rewind(wrbuf);
+       while (c && c != '=' && c != '>' && c != '/' && !d1_isspace(c))
+       {
+           wrbuf_putc (wrbuf, c);
+           c = ampr (get_byte, fh, amp);
+       }
+       wrbuf_putc (wrbuf, '\0');
+       len = wrbuf_len(wrbuf);
+       p->name = (char*) nmem_malloc (m, len);
+       strcpy (p->name, wrbuf_buf(wrbuf));
+       if (c == '=')
+       {
+           c = ampr (get_byte, fh, amp);
+           if (*amp == 0 && c == '"')
+           {
+               c = ampr (get_byte, fh, amp);   
+               wrbuf_rewind(wrbuf);
+               while (*amp || (c && c != '"'))
+               {
+                   wrbuf_putc (wrbuf, c);
+                   c = ampr (get_byte, fh, amp);
+               }
+               if (c)
+                   c = ampr (get_byte, fh, amp);
+           }
+           else if (*amp == 0 && c == '\'')
+           {
+               c = ampr (get_byte, fh, amp);   
+               wrbuf_rewind(wrbuf);
+               while (*amp || (c && c != '\''))
+               {
+                   wrbuf_putc (wrbuf, c);
+                   c = ampr (get_byte, fh, amp);
+               }
+               if (c)
+                   c = ampr (get_byte, fh, amp);
+           }
+           else
+           {
+               wrbuf_rewind(wrbuf);
+               while (*amp || (c && c != '>' && c != '/'))
+               {
+                   wrbuf_putc (wrbuf, c);
+                   c = ampr (get_byte, fh, amp);
+               }
+            }
+           wrbuf_putc (wrbuf, '\0');
+           len = wrbuf_len(wrbuf);
+           p->value = (char*) nmem_malloc (m, len);
+           strcpy (p->value, wrbuf_buf(wrbuf));
+       }
+    }
+    *ch = c;
+    return p_first;
+}
+
+/*
+ * Ugh. Sometimes functions just grow and grow on you. This one reads a
+ * 'node' and its children.
+ */
+data1_node *data1_read_nodex (data1_handle dh, NMEM m,
+                             int (*get_byte)(void *fh), void *fh, WRBUF wrbuf)
+{
+    data1_node *d1_stack[256];
+    data1_node *res;
+    int c, amp;
+    int level = 0;
+    int line = 1;
+
+    d1_stack[level] = 0;
+    c = ampr (get_byte, fh, &amp);
+    while (c != '\0')
+    {
+       data1_node *parent = level ? d1_stack[level-1] : 0;
+
+       if (amp == 0 && c == '<') /* beginning of tag */
+       {
+           data1_xattr *xattr;
+
+           char tag[64];
+           char args[256];
+           int null_tag = 0;
+           int end_tag = 0;
+           size_t i = 0;
+
+           c = ampr (get_byte, fh, &amp);
+           if (amp == 0 && c == '/')
+           {
+               end_tag = 1;
+               c = ampr (get_byte, fh, &amp);
+           }
+           else if (amp == 0 && c == '!')
+           {
+                int c0, amp0;
+              
+                wrbuf_rewind(wrbuf);
+                
+                c0 = ampr (get_byte, fh, &amp0);
+                if (amp0 == 0 && c0 == '\0')
+                    break;
+                c = ampr (get_byte, fh, &amp);
+                
+                if (amp0 == 0 && c0 == '-' && amp == 0 && c == '-')
+                {
+                    /* COMMENT: <!-- ... --> */
+                    int no_dash = 0;
+                    
+                    c = ampr (get_byte, fh, &amp);
+                    while (amp || c)
+                    {
+                        if (amp == 0 && c == '-')
+                            no_dash++;
+                        else if (amp == 0 && c == '>' && no_dash >= 2)
+                        {
+                            if (level > 0)
+                                d1_stack[level] = 
+                                    data1_mk_comment_n (
+                                        dh, m,
+                                        wrbuf_buf(wrbuf), wrbuf_len(wrbuf)-2,
+                                        d1_stack[level-1]);
+                            c = ampr (get_byte, fh, &amp); /* skip > */
+                            break;
+                        }
+                        else
+                            no_dash = 0;
+                        wrbuf_putc (wrbuf, c);
+                        c = ampr (get_byte, fh, &amp);
+                    }
+                    continue;
+                }
+                else
+                {   /* DIRECTIVE: <! .. > */
+       
+                   int blevel = 0;
+                    while (amp || c)
+                    {
+                        if (amp == 0 && c == '>' && blevel == 0)
+                        {
+                            c = ampr (get_byte, fh, &amp);
+                           break;
+                        }
+                       if (amp == 0 && c == '[')
+                           blevel++;
+                       if (amp == 0 && c == ']' && blevel > 0)
+                           blevel--;
+                        c = ampr (get_byte, fh, &amp);
+                    }
+                    continue;
+                }
+           }
+           while (amp || (c && c != '>' && c != '/' && !d1_isspace(c)))
+           {
+               if (i < (sizeof(tag)-1))
+                   tag[i++] = c;
+               c = ampr (get_byte, fh, &amp);
+           }
+           tag[i] = '\0';
+           xattr = data1_read_xattr (dh, m, get_byte, fh, wrbuf, &c, &amp);
+           args[0] = '\0';
+           if (amp == 0 && c == '/')
+           {    /* <tag attrs/> or <tag/> */
+               null_tag = 1;
+               c = ampr (get_byte, fh, &amp);
+           }
+           if (amp || c != '>')
+           {
+               yaz_log(LOG_WARN, "d1: %d: Malformed tag", line);
+               return 0;
+           }
+           else
+               c = ampr (get_byte, fh, &amp);
+
+           /* End tag? */
+           if (end_tag)       
+           {
+               if (*tag == '\0')
+                   --level;        /* </> */
+               else
+               {                   /* </tag> */
+                   int i = level;
+                   while (i > 0)
+                   {
+                       parent = d1_stack[--i];
+                       if ((parent->which == DATA1N_root &&
+                            !strcmp(tag, parent->u.root.type)) ||
+                           (parent->which == DATA1N_tag &&
+                            !strcmp(tag, parent->u.tag.tag)))
+                       {
+                           level = i;
+                           break;
+                       }
+                   }
+                   if (i != level)
+                   {
+                       yaz_log (LOG_WARN, "%d: no begin tag for %s",
+                                line, tag);
+                       break;
+                   }
+               }
+                if (data1_is_xmlmode(dh))
+                {
+                    if (level <= 1)
+                        return d1_stack[0];
+                }
+                else
+                {
+                    if (level <= 0)
+                        return d1_stack[0];
+                }
+               continue;
+           }   
+           else if (!strcmp(tag, "var"))
+           {
+               char tclass[DATA1_MAX_SYMBOL], type[DATA1_MAX_SYMBOL];
+               data1_vartype *tp;
+               int val_offset;
+               
+               if (sscanf(args, "%s %s %n", tclass, type, &val_offset) != 2)
+               {
+                   yaz_log(LOG_WARN, "Malformed variant triple at '%s'", tag);
+                   continue;
+               }
+               if (!(tp =
+                     data1_getvartypebyct(dh,
+                                          parent->root->u.root.absyn->varset,
+                                          tclass, type)))
+                   continue;
+               /*
+                * If we're the first variant in this group, create a parent 
+                * variant, and insert it before the current variant.
+                */
+               if (parent->which != DATA1N_variant)
+               {
+                   res = data1_mk_node2 (dh, m, DATA1N_variant, parent);
+               }
+               else
+               {
+                   /*
+                    * now determine if one of our ancestor triples is of
+                    * same type. If so, we break here.
+                    */
+                   int i;
+                   for (i = level-1; d1_stack[i]->which==DATA1N_variant; --i)
+                       if (d1_stack[i]->u.variant.type == tp)
+                       {
+                           level = i;
+                           break;
+                       }
+                   res = data1_mk_node2 (dh, m, DATA1N_variant, parent);
+                   res->u.variant.type = tp;
+                   res->u.variant.value =
+                       data1_insert_string (dh, res, m, args + val_offset);
+               }
+           }
+           else 
+            {
+                
+                /* tag .. acquire our element in the abstract syntax */
+                if (level == 0)
+                {
+                    parent = data1_mk_root (dh, m, tag);
+                    res = d1_stack[level] = parent;
+
+                    if (data1_is_xmlmode(dh))
+                    {
+                        level++;
+                        res = data1_mk_tag (dh, m, tag, 0 /* attr */, parent);
+                        res->u.tag.attributes = xattr;
+                    }
+                }
+                else
+                {
+                    res = data1_mk_tag (dh, m, tag, 0 /* attr */, parent);
+                    res->u.tag.attributes = xattr;
+                }
+            }
+           d1_stack[level] = res;
+           d1_stack[level+1] = 0;
+           if (level < 250 && !null_tag)
+               ++level;
+       }
+       else /* != '<'... this is a body of text */
+       {
+           int len;
+           
+           if (level == 0)
+           {
+               c = ampr (get_byte, fh, &amp);
+               continue;
+           }
+           res = data1_mk_node2 (dh, m, DATA1N_data, parent);
+           res->u.data.what = DATA1I_xmltext;
+           res->u.data.formatted_text = 0;
+           d1_stack[level] = res;
+           
+           wrbuf_rewind(wrbuf);
+
+           while (amp || (c && c != '<'))
+           {
+               wrbuf_putc (wrbuf, c);
+               c = ampr (get_byte, fh, &amp);
+           }
+           len = wrbuf_len(wrbuf);
+
+           /* use local buffer of nmem if too large */
+           if (len >= DATA1_LOCALDATA)
+               res->u.data.data = (char*) nmem_malloc (m, len);
+           else
+               res->u.data.data = res->lbuf;
+       
+            if (len)
+                memcpy (res->u.data.data, wrbuf_buf(wrbuf), len);
+            else
+                res->u.data.data = 0;
+            res->u.data.len = len;
+       }
+    }
+    return 0;
+}
+
+int getc_mem (void *fh)
+{
+    const char **p = (const char **) fh;
+    if (**p)
+       return *(*p)++;
+    return 0;
+}
+
+data1_node *data1_read_node (data1_handle dh, const char **buf, NMEM m)
+{
+    WRBUF wrbuf = wrbuf_alloc();
+    data1_node *node;
+
+    node = data1_read_nodex(dh, m, getc_mem, (void *) (buf), wrbuf);
+    wrbuf_free (wrbuf, 1);
+    return node;
+}
+
+/*
+ * Read a record in the native syntax.
+ */
+data1_node *data1_read_record(data1_handle dh,
+                             int (*rf)(void *, char *, size_t), void *fh,
+                              NMEM m)
+{
+    int *size;
+    char **buf = data1_get_read_buf (dh, &size);
+    const char *bp;
+    int rd = 0, res;
+    
+    if (!*buf)
+       *buf = (char *)xmalloc(*size = 4096);
+    
+    for (;;)
+    {
+       if (rd + 2048 >= *size && !(*buf =(char *)xrealloc(*buf, *size *= 2)))
+           abort();
+       if ((res = (*rf)(fh, *buf + rd, 2048)) <= 0)
+       {
+           if (!res)
+           {
+               bp = *buf;
+               (*buf)[rd] = '\0';
+               return data1_read_node(dh, &bp, m);
+           }
+           else
+               return 0;
+       }
+       rd += res;
+    }
+}
+
+data1_node *data1_read_sgml (data1_handle dh, NMEM m, const char *buf)
+{
+    const char *bp = buf;
+    return data1_read_node (dh, &bp, m);
+}
+
+
+static int conv_item (NMEM m, yaz_iconv_t t, 
+                      WRBUF wrbuf, char *inbuf, size_t inlen)
+{
+    wrbuf_rewind (wrbuf);
+    if (wrbuf->size < 10)
+        wrbuf_grow (wrbuf, 10);
+    for (;;)
+    {
+        char *outbuf = wrbuf->buf + wrbuf->pos;
+        size_t outlen = wrbuf->size - wrbuf->pos;
+        if (yaz_iconv (t, &inbuf, &inlen, &outbuf, &outlen) ==
+            (size_t)(-1) && yaz_iconv_error(t) != YAZ_ICONV_E2BIG)
+        {
+            /* bad data. stop and skip conversion entirely */
+            return -1;
+        }
+        else if (inlen == 0)
+        {   /* finished converting */
+            wrbuf->pos = wrbuf->size - outlen;
+            break;
+        }
+        else
+        {
+            /* buffer too small: make sure we expand buffer */
+            wrbuf->pos = wrbuf->size - outlen;
+            wrbuf_grow(wrbuf, 20);
+        }
+    }
+    return 0;
+}
+
+static void data1_iconv_s (data1_handle dh, NMEM m, data1_node *n,
+                           yaz_iconv_t t, WRBUF wrbuf, const char *tocode)
+{
+    for (; n; n = n->next)
+    {
+        switch (n->which)
+        {
+        case DATA1N_data:
+        case DATA1N_comment:
+            if (conv_item (m, t, wrbuf, n->u.data.data, n->u.data.len) == 0)
+            {
+                n->u.data.data =
+                    data1_insert_string_n (dh, n, m, wrbuf->buf,
+                                           wrbuf->pos);
+                n->u.data.len = wrbuf->pos;
+            }
+            break;
+        case DATA1N_tag:
+            if (conv_item (m, t, wrbuf, n->u.tag.tag, strlen(n->u.tag.tag))
+                == 0)
+            {
+                n->u.tag.tag =
+                    data1_insert_string_n (dh, n, m, 
+                                           wrbuf->buf, wrbuf->pos);
+            }
+            if (n->u.tag.attributes)
+            {
+                data1_xattr *p;
+                for (p = n->u.tag.attributes; p; p = p->next)
+                {
+                    if (p->value &&
+                        conv_item(m, t, wrbuf, p->value, strlen(p->value))
+                        == 0)
+                    {
+                        wrbuf_puts (wrbuf, "");
+                        p->value = nmem_strdup (m, wrbuf->buf);
+                    }
+                }
+            }
+            break;
+        case DATA1N_preprocess:
+            if (strcmp(n->u.preprocess.target, "xml") == 0)
+            {
+                data1_xattr *p = n->u.preprocess.attributes;
+                for (; p; p = p->next)
+                    if (strcmp (p->name, "encoding") == 0)
+                        p->value = nmem_strdup (m, tocode);
+            }
+            break;
+        }
+        data1_iconv_s (dh, m, n->child, t, wrbuf, tocode);
+    }
+}
+
+const char *data1_get_encoding (data1_handle dh, data1_node *n)
+{
+    /* see if we have an xml header that specifies encoding */
+    if (n && n->child && n->child->which == DATA1N_preprocess &&
+        strcmp (n->child->u.preprocess.target, "xml") == 0)
+    {
+        data1_xattr *xp = n->child->u.preprocess.attributes;
+        for (; xp; xp = xp->next)
+            if (!strcmp (xp->name, "encoding") == 0)
+                return xp->value;
+    }
+    /* no encoding in header, so see if "encoding" was specified for abs */
+    if (n && n->which == DATA1N_root &&
+        n->u.root.absyn && n->u.root.absyn->encoding)
+        return n->u.root.absyn->encoding;
+    /* none of above, return a hard coded default */
+    return "ISO-8859-1";
+}
+
+int data1_iconv (data1_handle dh, NMEM m, data1_node *n,
+                  const char *tocode, 
+                  const char *fromcode)
+{
+    if (strcmp (tocode, fromcode))
+    {
+        WRBUF wrbuf = wrbuf_alloc();
+        yaz_iconv_t t = yaz_iconv_open (tocode, fromcode);
+        if (!t)
+            return -1;
+        data1_iconv_s (dh, m, n, t, wrbuf, tocode);
+        yaz_iconv_close (t);
+        wrbuf_free (wrbuf, 1);
+    }
+    return 0;
+}
diff --git a/data1/d1_soif.c b/data1/d1_soif.c
new file mode 100644 (file)
index 0000000..3aaf857
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_soif.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <yaz/wrbuf.h>
+#include <data1.h>
+
+/*
+ * This module generates SOIF (Simple Object Interchange Format) records
+ * from d1-nodes. nested elements are flattened out, depth first, by
+ * concatenating the tag names at each level.
+ */
+
+static int nodetoelement(data1_node *n, int select, char *prefix, WRBUF b)
+{
+    data1_node *c;
+    char tmp[1024];
+
+    for (c = n->child; c; c = c->next)
+    {
+       char *tag;
+
+       if (c->which == DATA1N_tag)
+       {
+           if (select && !c->u.tag.node_selected)
+               continue;
+           if (c->u.tag.element && c->u.tag.element->tag)
+               tag = c->u.tag.element->tag->names->name; /* first name */
+           else
+           tag = c->u.tag.tag; /* local string tag */
+
+           if (*prefix)
+               sprintf(tmp, "%s-%s", prefix, tag);
+           else
+               strcpy(tmp, tag);
+
+           if (nodetoelement(c, select, tmp, b) < 0)
+               return 0;
+       }
+       else if (c->which == DATA1N_data)
+       {
+           char *p = c->u.data.data;
+           int l = c->u.data.len;
+
+           wrbuf_write(b, prefix, strlen(prefix));
+
+           sprintf(tmp, "{%d}:\t", l);
+           wrbuf_write(b, tmp, strlen(tmp));
+           wrbuf_write(b, p, l);
+           wrbuf_putc(b, '\n');
+       }
+    }
+    return 0;
+}
+
+char *data1_nodetosoif (data1_handle dh, data1_node *n, int select, int *len)
+{
+    WRBUF b = data1_get_wrbuf (dh);
+    char buf[128];
+
+    wrbuf_rewind(b);
+    
+    if (n->which != DATA1N_root)
+       return 0;
+    sprintf(buf, "@%s{\n", n->u.root.type);
+    wrbuf_write(b, buf, strlen(buf));
+    if (nodetoelement(n, select, "", b))
+       return 0;
+    wrbuf_write(b, "}\n", 2);
+    *len = wrbuf_len(b);
+    return wrbuf_buf(b);
+}
diff --git a/data1/d1_sumout.c b/data1/d1_sumout.c
new file mode 100644 (file)
index 0000000..a2cb932
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_sumout.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <yaz/log.h>
+#include <yaz/proto.h>
+#include <data1.h>
+
+static int *f_integer(data1_node *c, ODR o)
+{
+    int *r;
+    char intbuf[64];
+
+    if (!c->child || c->child->which != DATA1N_data ||
+       c->child->u.data.len > 63)
+       return 0;
+    r = (int *)odr_malloc(o, sizeof(*r));
+    sprintf(intbuf, "%.*s", 63, c->child->u.data.data);
+    *r = atoi(intbuf);
+    return r;
+}
+
+static char *f_string(data1_node *c, ODR o)
+{
+    char *r;
+
+    if (!c->child || c->child->which != DATA1N_data)
+       return 0;
+    r = (char *)odr_malloc(o, c->child->u.data.len+1);
+    memcpy(r, c->child->u.data.data, c->child->u.data.len);
+    r[c->child->u.data.len] = '\0';
+    return r;
+}
+
+Z_BriefBib *data1_nodetosummary (data1_handle dh, data1_node *n,
+                                int select, ODR o)
+{
+    Z_BriefBib *res = (Z_BriefBib *)odr_malloc(o, sizeof(*res));
+    data1_node *c;
+
+    assert(n->which == DATA1N_root);
+    if (strcmp(n->u.root.type, "summary"))
+    {
+       yaz_log(LOG_WARN, "Attempt to convert a non-summary record");
+       return 0;
+    }
+
+    res->title = "[UNKNOWN]";
+    res->author = 0;
+    res->callNumber = 0;
+    res->recordType = 0;
+    res->bibliographicLevel = 0;
+    res->num_format = 0;
+    res->format = 0;
+    res->publicationPlace = 0;
+    res->publicationDate = 0;
+    res->targetSystemKey = 0;
+    res->satisfyingElement = 0;
+    res->rank = 0;
+    res->documentId = 0;
+    res->abstract = 0;
+    res->otherInfo = 0;
+
+    for (c = n->child; c; c = c->next)
+    {
+       if (c->which != DATA1N_tag || !c->u.tag.element)
+       {
+           yaz_log(LOG_WARN, "Malformed element in Summary record");
+           return 0;
+       }
+       if (select && !c->u.tag.node_selected)
+           continue;
+       switch (c->u.tag.element->tag->value.numeric)
+       {
+           case 0: res->title = f_string(c, o); break;
+           case 1: res->author = f_string(c, o); break;
+           case 2: res->callNumber = f_string(c, o); break;
+           case 3: res->recordType = f_string(c, o); break;
+           case 4: res->bibliographicLevel = f_string(c, o); break;
+           case 5: abort();   /* TODO */
+           case 10: res->publicationPlace = f_string(c, o); break;
+           case 11: res->publicationDate = f_string(c, o); break;
+           case 12: res->targetSystemKey = f_string(c, o); break;
+           case 13: res->satisfyingElement = f_string(c, o); break;
+           case 14: res->rank = f_integer(c, o); break;
+           case 15: res->documentId = f_string(c, o); break;
+           case 16: res->abstract = f_string(c, o); break;
+           case 17: abort(); /* TODO */
+           default:
+               yaz_log(LOG_WARN, "Unknown element in Summary record.");
+       }
+    }
+    return res;
+}
diff --git a/data1/d1_sutrs.c b/data1/d1_sutrs.c
new file mode 100644 (file)
index 0000000..4bd6b54
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_sutrs.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ *
+ */
+
+#include <data1.h>
+
+#define NTOBUF_INDENT   2
+#define NTOBUF_MARGIN 75
+
+static int wordlen(char *b, int i)
+{
+    int l = 0;
+
+    while (i && !d1_isspace(*b))
+       l++, b++, i--;
+    return l;
+}
+
+static int nodetobuf(data1_node *n, int select, WRBUF b, int indent, int col)
+{
+    data1_node *c;
+    char line[1024];
+
+    for (c = n->child; c; c = c->next)
+    {
+       char *tag;
+
+       if (c->which == DATA1N_tag)
+       {
+           if (select && !c->u.tag.node_selected)
+               continue;
+           if (c->u.tag.element && c->u.tag.element->tag)
+               tag = c->u.tag.element->tag->names->name; /* first name */
+           else
+               tag = c->u.tag.tag; /* local string tag */
+           if (data1_matchstr(tag, "wellknown")) /* skip wellknown */
+           {
+               if (col)
+                   wrbuf_putc(b, '\n');
+               sprintf(line, "%*s%s:", indent * NTOBUF_INDENT, "", tag);
+               wrbuf_write(b, line, strlen(line));
+               col = strlen(line);
+           }
+           if (nodetobuf(c, select, b, indent+1, col) < 0)
+               return 0;
+       }
+       else if (c->which == DATA1N_data)
+       {
+           char *p = c->u.data.data;
+           int l = c->u.data.len;
+           int first = 0;
+
+           if ((c->u.data.what == DATA1I_text ||
+               c->u.data.what == DATA1I_xmltext) && c->u.data.formatted_text)
+           {
+               wrbuf_putc(b, '\n');
+               wrbuf_write(b, c->u.data.data, c->u.data.len);
+               sprintf(line, "%*s", indent * NTOBUF_INDENT, "");
+               wrbuf_write(b, line, strlen(line));
+               col = indent * NTOBUF_INDENT;
+           }
+           else if (c->u.data.what == DATA1I_text ||
+                    c->u.data.what == DATA1I_xmltext)
+           {
+               while (l)
+               {
+                   int wlen;
+
+                   while (l && d1_isspace(*p))
+                       p++, l--;
+                   if (!l)
+                       break;
+                   /* break if we'll cross margin and word is not too long */
+                   if (col + (wlen = wordlen(p, l)) > NTOBUF_MARGIN && wlen <
+                       NTOBUF_MARGIN - indent * NTOBUF_INDENT)
+                   {
+                       sprintf(line, "\n%*s", indent * NTOBUF_INDENT, "");
+                       wrbuf_write(b, line, strlen(line));
+                       col = indent * NTOBUF_INDENT;
+                       first = 1;
+                   }
+                   if (!first)
+                   {
+                       wrbuf_putc(b, ' ');
+                       col++;
+                   }
+                   while (l && !d1_isspace(*p))
+                   {
+                       if (col > NTOBUF_MARGIN)
+                       {
+                           wrbuf_putc(b, '=');
+                           wrbuf_putc(b, '\n');
+                           sprintf(line, "%*s", indent * NTOBUF_INDENT, "");
+                           wrbuf_write(b, line, strlen(line));
+                           col = indent * NTOBUF_INDENT;
+                       }
+                       wrbuf_putc(b, *p);
+                       p++;
+                       l--;
+                       col++;
+                   }
+                   first = 0;
+               }
+           }
+           else if (c->u.data.what == DATA1I_num)
+           {
+               wrbuf_putc(b, ' ');
+               wrbuf_write(b, c->u.data.data, c->u.data.len);
+           }
+       }
+    }
+    return 0;
+}
+
+/*
+ * Return area containing SUTRS-formatted data. Ownership of this data
+ * remains in this module, and the buffer is reused on next call. This may
+ * need changing.
+ */
+
+char *data1_nodetobuf (data1_handle dh, data1_node *n, int select, int *len)
+{
+    WRBUF b = data1_get_wrbuf (dh);
+
+    wrbuf_rewind(b);
+    if (nodetobuf(n, select, b, 0, 0))
+       return 0;
+    wrbuf_putc(b, '\n');
+    *len = wrbuf_len(b);
+    return wrbuf_buf(b);
+}
diff --git a/data1/d1_tagset.c b/data1/d1_tagset.c
new file mode 100644 (file)
index 0000000..8b1ada6
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_tagset.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <yaz/log.h>
+#include <data1.h>
+
+/*
+ * We'll probably want to add some sort of hashed index to these lookup-
+ * functions eventually.
+ */
+
+data1_datatype data1_maptype (data1_handle dh, char *t)
+{
+    static struct
+    {
+       char *tname;
+       data1_datatype type;
+    } types[] =
+    {
+       {"structured", DATA1K_structured},
+       {"string", DATA1K_string},
+       {"numeric", DATA1K_numeric},
+       {"oid", DATA1K_oid},
+       {"bool", DATA1K_bool},
+       {"generalizedtime", DATA1K_generalizedtime},
+       {"intunit", DATA1K_intunit},
+       {"int", DATA1K_int},
+       {"octetstring", DATA1K_octetstring},
+       {"null", DATA1K_null},
+       {NULL, (data1_datatype) -1}
+    };
+    int i;
+
+    for (i = 0; types[i].tname; i++)
+       if (!data1_matchstr(types[i].tname, t))
+           return types[i].type;
+    return DATA1K_unknown;
+}
+
+data1_tag *data1_gettagbynum (data1_handle dh, data1_tagset *s,
+                             int type, int value)
+{
+    data1_tag *r;
+    
+    for (; s; s = s->next)
+    {
+       /* scan local set */
+       if (type == s->type)
+           for (r = s->tags; r; r = r->next)
+               if (r->which == DATA1T_numeric && r->value.numeric == value)
+                   return r;
+       /* scan included sets */
+       if (s->children &&
+           (r = data1_gettagbynum (dh, s->children, type, value)))
+           return r;
+    }
+    return 0;
+}
+
+data1_tag *data1_gettagbyname (data1_handle dh, data1_tagset *s,
+                              const char *name)
+{
+    data1_tag *r;
+
+    for (; s; s = s->next)
+    {
+       /* scan local set */
+       for (r = s->tags; r; r = r->next)
+       {
+           data1_name *np;
+
+           for (np = r->names; np; np = np->next)
+               if (!data1_matchstr(np->name, name))
+                   return r;
+       }
+       /* scan included sets */
+       if (s->children && (r = data1_gettagbyname (dh, s->children, name)))
+           return r;
+    }
+    return 0;
+}
+
+data1_tagset *data1_empty_tagset (data1_handle dh)
+{
+    data1_tagset *res =
+       (data1_tagset *) nmem_malloc(data1_nmem_get (dh), sizeof(*res));
+    res->name = 0;
+    res->reference = VAL_NONE;
+    res->tags = 0;
+    res->type = 0;
+    res->children = 0;
+    res->next = 0;
+    return res;
+}
+
+data1_tagset *data1_read_tagset (data1_handle dh, const char *file, int type)
+{
+    NMEM mem = data1_nmem_get (dh);
+    data1_tagset *res = 0;
+    data1_tagset **childp;
+    data1_tag **tagp;
+    FILE *f;
+    int lineno = 0;
+    int argc;
+    char *argv[50], line[512];
+
+    if (!(f = data1_path_fopen(dh, file, "r")))
+    {
+       yaz_log(LOG_WARN|LOG_ERRNO, "%s", file);
+       return 0;
+    }
+    res = data1_empty_tagset (dh);
+    res->type = type;
+    childp = &res->children;
+    tagp = &res->tags;
+
+    while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
+    {
+       char *cmd = *argv;
+       if (!strcmp(cmd, "tag"))
+       {
+           int value;
+           char *names, *type, *nm;
+           data1_tag *rr;
+           data1_name **npp;
+
+           if (argc != 4)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args to tag", file, lineno);
+               continue;
+           }
+           value = atoi(argv[1]);
+           names = argv[2];
+           type = argv[3];
+
+           rr = *tagp = (data1_tag *)nmem_malloc(mem, sizeof(*rr));
+           rr->tagset = res;
+           rr->next = 0;
+           rr->which = DATA1T_numeric;
+           rr->value.numeric = value;
+           /*
+            * how to deal with local numeric tags?
+            */
+
+           if (!(rr->kind = data1_maptype(dh, type)))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Unknown datatype %s",
+                    file, lineno, type);
+               fclose(f);
+               return 0;
+           }
+           
+           /* read namelist */
+           nm = names;
+           npp = &rr->names;
+           do
+           {
+               char *e;
+
+               *npp = (data1_name *)nmem_malloc(mem, sizeof(**npp));
+               if ((e = strchr(nm, '/')))
+                   *(e++) = '\0';
+               (*npp)->name = nmem_strdup(mem, nm);
+               (*npp)->next = 0;
+               npp = &(*npp)->next;
+               nm = e;
+           }
+           while (nm);
+           tagp = &rr->next;
+       }
+       else if (!strcmp(cmd, "name"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args to name", file, lineno);
+               continue;
+           }
+           res->name = nmem_strdup(mem, argv[1]);
+       }
+       else if (!strcmp(cmd, "reference"))
+       {
+           char *name;
+           
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args to reference",
+                       file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if ((res->reference = oid_getvalbyname(name)) == VAL_NONE)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Unknown tagset ref '%s'",
+                       file, lineno, name);
+               continue;
+           }
+       }
+       else if (!strcmp(cmd, "type"))
+       {
+           if (argc != 2)
+           {
+               yaz_log (LOG_WARN, "%s:%d: Bad # args to type", file, lineno);
+               continue;
+           }
+           if (!res->type)
+               res->type = atoi(argv[1]);
+       }
+       else if (!strcmp(cmd, "include"))
+       {
+           char *name;
+           int type = 0;
+
+           if (argc < 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args to include",
+                       file, lineno);
+               continue;
+           }
+           name = argv[1];
+           if (argc == 3)
+               type = atoi(argv[2]);
+           *childp = data1_read_tagset (dh, name, type);
+           if (!(*childp))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Inclusion failed for tagset %s",
+                       file, lineno, name);
+               continue;
+           }
+           childp = &(*childp)->next;
+       }
+       else
+       {
+           yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'",
+                   file, lineno, cmd);
+       }
+    }
+    fclose(f);
+    return res;
+}
diff --git a/data1/d1_varset.c b/data1/d1_varset.c
new file mode 100644 (file)
index 0000000..94f1cfd
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1995-1999, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: d1_varset.c,v $
+ * Revision 1.1  2002-10-22 12:53:33  adam
+ * data1 part of zebra
+ *
+ * Revision 1.11  2002/04/04 20:49:46  adam
+ * New functions yaz_is_abspath, yaz_path_fopen_base
+ *
+ * Revision 1.10  1999/11/30 13:47:12  adam
+ * Improved installation. Moved header files to include/yaz.
+ *
+ * Revision 1.9  1999/08/27 09:40:32  adam
+ * Renamed logf function to yaz_log. Removed VC++ project files.
+ *
+ * Revision 1.8  1998/10/13 16:09:54  adam
+ * Added support for arbitrary OID's for tagsets, schemas and attribute sets.
+ * Added support for multiple attribute set references and tagset references
+ * from an abstract syntax file.
+ * Fixed many bad logs-calls in routines that read the various
+ * specifications regarding data1 (*.abs,*.att,...) and made the messages
+ * consistent whenever possible.
+ * Added extra 'lineno' argument to function readconf_line.
+ *
+ * Revision 1.7  1998/02/11 11:53:35  adam
+ * Changed code so that it compiles as C++.
+ *
+ * Revision 1.6  1997/09/17 12:10:39  adam
+ * YAZ version 1.4.
+ *
+ * Revision 1.5  1997/09/05 09:50:58  adam
+ * Removed global data1_tabpath - uses data1_get_tabpath() instead.
+ *
+ * Revision 1.4  1997/05/14 06:54:04  adam
+ * C++ support.
+ *
+ * Revision 1.3  1995/11/01 16:34:58  quinn
+ * Making data1 look for tables in data1_tabpath
+ *
+ * Revision 1.2  1995/11/01  13:54:50  quinn
+ * Minor adjustments
+ *
+ * Revision 1.1  1995/11/01  11:56:09  quinn
+ * Added Retrieval (data management) functions en masse.
+ *
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <yaz/oid.h>
+#include <yaz/log.h>
+#include <data1.h>
+
+data1_vartype *data1_getvartypebyct (data1_handle dh, data1_varset *set,
+                                    char *zclass, char *type)
+{
+    data1_varclass *c;
+    data1_vartype *t;
+
+    for (c = set->classes; c; c = c->next)
+       if (!data1_matchstr(c->name, zclass))
+       {
+           for (t = c->types; t; t = t->next)
+               if (!data1_matchstr(t->name, type))
+                   return t;
+           yaz_log(LOG_WARN, "Unknown variant type %s in class %s",
+                   type, zclass);
+           return 0;
+       }
+    yaz_log(LOG_WARN, "Unknown variant class %s", zclass);
+    return 0;
+}
+
+data1_varset *data1_read_varset (data1_handle dh, const char *file)
+{
+    NMEM mem = data1_nmem_get (dh);
+    data1_varset *res = (data1_varset *)nmem_malloc(mem, sizeof(*res));
+    data1_varclass **classp = &res->classes, *zclass = 0;
+    data1_vartype **typep = 0;
+    FILE *f;
+    int lineno = 0;
+    int argc;
+    char *argv[50],line[512];
+
+    res->name = 0;
+    res->reference = VAL_NONE;
+    res->classes = 0;
+
+    if (!(f = data1_path_fopen(dh, file, "r")))
+    {
+       yaz_log(LOG_WARN|LOG_ERRNO, "%s", file);
+       return 0;
+    }
+    while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
+       if (!strcmp(argv[0], "class"))
+       {
+           data1_varclass *r;
+           
+           if (argc != 3)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # or args to class",
+                       file, lineno);
+               continue;
+           }
+           *classp = r = zclass = (data1_varclass *)
+               nmem_malloc(mem, sizeof(*r));
+           r->set = res;
+           r->zclass = atoi(argv[1]);
+           r->name = nmem_strdup(mem, argv[2]);
+           r->types = 0;
+           typep = &r->types;
+           r->next = 0;
+           classp = &r->next;
+       }
+       else if (!strcmp(argv[0], "type"))
+       {
+           data1_vartype *r;
+
+           if (!typep)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Directive class must precede type",
+                       file, lineno);
+               continue;
+           }
+           if (argc != 4)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # or args to type",
+                       file, lineno);
+               continue;
+           }
+           *typep = r = (data1_vartype *)nmem_malloc(mem, sizeof(*r));
+           r->name = nmem_strdup(mem, argv[2]);
+           r->zclass = zclass;
+           r->type = atoi(argv[1]);
+           if (!(r->datatype = data1_maptype (dh, argv[3])))
+           {
+               yaz_log(LOG_WARN, "%s:%d: Unknown datatype '%s'",
+                       file, lineno, argv[3]);
+               fclose(f);
+               return 0;
+           }
+           r->next = 0;
+           typep = &r->next;
+       }
+       else if (!strcmp(argv[0], "name"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args for name",
+                       file, lineno);
+               continue;
+           }
+           res->name = nmem_strdup(mem, argv[1]);
+       }
+       else if (!strcmp(argv[0], "reference"))
+       {
+           if (argc != 2)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Bad # args for reference",
+                       file, lineno);
+               continue;
+           }
+           if ((res->reference = oid_getvalbyname(argv[1])) == VAL_NONE)
+           {
+               yaz_log(LOG_WARN, "%s:%d: Unknown reference '%s'",
+                       file, lineno, argv[1]);
+               continue;
+           }
+       }
+       else 
+           yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'",
+                   file, lineno, argv[0]);
+    
+    fclose(f);
+    return res;
+}
diff --git a/data1/d1_write.c b/data1/d1_write.c
new file mode 100644 (file)
index 0000000..587e75d
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ * See the file LICENSE for details.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Id: d1_write.c,v 1.1 2002-10-22 12:53:33 adam Exp $
+ */
+
+#include <string.h>
+
+#include <data1.h>
+#include <yaz/wrbuf.h>
+
+#define IDSGML_MARGIN 75
+
+#define PRETTY_FORMAT 0
+
+static int wordlen(char *b, int max)
+{
+    int l = 0;
+
+    while (l < max && !d1_isspace(*b))
+       l++, b++;
+    return l;
+}
+
+static void indent (WRBUF b, int col)
+{
+    int i;
+    for (i = 0; i<col; i++)
+        wrbuf_putc (b, ' ');
+}
+
+static void wrbuf_write_cdata(WRBUF b, const char *msg, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++)
+    {
+        switch (msg[i])
+        {
+        case '"':
+            wrbuf_puts (b, "&quot;");
+            break;
+        case '\'':
+            wrbuf_puts (b, "&apos;");
+            break;
+        case '>':
+            wrbuf_puts (b, "&gt;");
+            break;
+        case '<':
+            wrbuf_puts (b, "&lt;");
+            break;
+        case '&':
+            wrbuf_puts (b, "&amp;");
+            break;
+        default:
+            wrbuf_putc(b, msg[i]);
+        }
+    }
+}
+
+static void wrbuf_put_cdata(WRBUF b, const char *msg)
+{
+    wrbuf_write_cdata (b, msg, strlen(msg));
+}
+
+static void wrbuf_put_xattr(WRBUF b, data1_xattr *p)
+{
+    for (; p; p = p->next)
+    {
+        wrbuf_putc (b, ' ');
+        if (p->what == DATA1I_xmltext)
+            wrbuf_puts (b, p->name);
+        else
+            wrbuf_put_cdata (b, p->name);
+        if (p->value)
+        {
+            wrbuf_putc (b, '=');
+            wrbuf_putc (b, '"');
+            if (p->what == DATA1I_text)
+                wrbuf_put_cdata (b, p->value);
+            else
+                wrbuf_puts (b, p->value);
+            wrbuf_putc (b, '"');
+        }
+    }
+}
+
+static int nodetoidsgml(data1_node *n, int select, WRBUF b, int col,
+                        int pretty_format)
+{
+    data1_node *c;
+
+    for (c = n->child; c; c = c->next)
+    {
+       char *tag;
+
+        if (c->which == DATA1N_preprocess)
+        {
+            data1_xattr *p;
+
+            if (pretty_format)
+                indent (b, col);
+           wrbuf_puts (b, "<?");
+            wrbuf_put_cdata (b, c->u.preprocess.target);
+            wrbuf_put_xattr (b, c->u.preprocess.attributes);
+            if (c->child)
+                wrbuf_puts(b, " ");
+            if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2,
+                             pretty_format) < 0)
+                return -1;
+            wrbuf_puts (b, "?>\n");
+        }
+        else if (c->which == DATA1N_tag)
+       {
+           if (select && !c->u.tag.node_selected)
+               continue;
+            tag = c->u.tag.tag;
+           if (!data1_matchstr(tag, "wellknown")) /* skip wellknown */
+           {
+               if (nodetoidsgml(c, select, b, col, pretty_format) < 0)
+                   return -1;
+           }
+           else
+           {
+               data1_xattr *p;
+
+                if (pretty_format)
+                    indent (b, col);
+               wrbuf_puts (b, "<");    
+               wrbuf_put_cdata (b, tag);
+                wrbuf_put_xattr (b, c->u.tag.attributes);
+               wrbuf_puts(b, ">");
+                if (pretty_format)
+                    wrbuf_puts(b, "\n");
+               if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2,
+                                 pretty_format) < 0)
+                   return -1;
+                if (pretty_format)
+                    indent (b, col);
+               wrbuf_puts(b, "</");
+               wrbuf_put_cdata(b, tag);
+               wrbuf_puts(b, ">");
+                if (pretty_format)
+                    wrbuf_puts (b, "\n");
+           }
+       }
+       else if (c->which == DATA1N_data || c->which == DATA1N_comment)
+       {
+           char *p = c->u.data.data;
+           int l = c->u.data.len;
+           int first = 1;
+           int lcol = col;
+
+            if (pretty_format && !c->u.data.formatted_text)
+                indent (b, col);
+            if (c->which == DATA1N_comment)
+                wrbuf_puts (b, "<!--");
+           switch (c->u.data.what)
+           {
+            case DATA1I_xmltext:
+               wrbuf_write(b, c->u.data.data, c->u.data.len);
+                break;
+           case DATA1I_text:
+                if (!pretty_format || c->u.data.formatted_text)
+                {
+                    wrbuf_write_cdata (b, p, l);
+                }
+                else
+                {
+                    while (l)
+                    {
+                        int wlen;
+                        
+                        while (l && d1_isspace(*p))
+                            p++, l--;
+                        if (!l)
+                            break;
+                        /* break if we cross margin and word is not too long */
+                        if (lcol + (wlen = wordlen(p, l)) > IDSGML_MARGIN &&
+                            wlen < IDSGML_MARGIN)
+                        {
+                            wrbuf_puts (b, "\n");
+                            indent (b, col);
+                            lcol = col;
+                            first = 1;
+                        }
+                        if (!first)
+                        {
+                            wrbuf_putc(b, ' ');
+                            lcol++;
+                        }
+                        while (l && !d1_isspace(*p))
+                        {
+                            wrbuf_putc(b, *p);
+                            p++;
+                            l--;
+                            lcol++;
+                        }
+                        first = 0;
+                    }
+                    wrbuf_puts(b, "\n");
+                }
+               break;
+           case DATA1I_num:
+               wrbuf_write_cdata(b, c->u.data.data, c->u.data.len);
+                if (pretty_format)
+                    wrbuf_puts(b, "\n");
+               break;
+           case DATA1I_oid:
+               wrbuf_write_cdata(b, c->u.data.data, c->u.data.len);
+                if (pretty_format)
+                    wrbuf_puts(b, "\n");
+           }
+            if (c->which == DATA1N_comment)
+            {
+                wrbuf_puts(b, "-->");
+                if (pretty_format)
+                    wrbuf_puts(b, "\n");
+            }
+       }
+    }
+    return 0;
+}
+
+char *data1_nodetoidsgml (data1_handle dh, data1_node *n, int select, int *len)
+{
+    WRBUF b = data1_get_wrbuf (dh);
+    
+    wrbuf_rewind(b);
+    
+    if (!data1_is_xmlmode (dh))
+    {
+        wrbuf_puts (b, "<");
+        wrbuf_puts (b, n->u.root.type);
+        wrbuf_puts (b, ">\n");
+    }
+    if (nodetoidsgml(n, select, b, 0, 0 /* no pretty format */))
+       return 0;
+    if (!data1_is_xmlmode (dh))
+    {
+        wrbuf_puts (b, "</");
+        wrbuf_puts (b, n->u.root.type);
+        wrbuf_puts (b, ">\n");
+    }
+    *len = wrbuf_len(b);
+    return wrbuf_buf(b);
+}
index a753b84..2d36402 100644 (file)
@@ -1,6 +1,6 @@
 
-noinst_HEADERS = bfile.h bset.h charmap.h dfa.h dict.h direntz.h isam.h \
- isamc.h isamd.h isams.h mfile.h passwddb.h recctrl.h res.h rsbool.h rset.h \
- rsisam.h rsisamc.h rsisams.h rsisamd.h rsm_or.h rsnull.h rstemp.h set.h \
- sortidx.h str.h zebra-lock.h zebramap.h zebrautl.h zebraver.h isamb.h \
- rsbetween.h rsisamb.h
+noinst_HEADERS = bfile.h bset.h charmap.h d1_attset.h d1_map.h \
+data1.h dfa.h dict.h direntz.h isamb.h isamc.h isamd.h isamg.h isam.h \
+isams.h mfile.h passwddb.h recctrl.h res.h rsbetween.h rsbool.h rset.h \
+rsisamb.h rsisamc.h rsisamd.h rsisam.h rsisams.h rsm_or.h rsnull.h \
+rstemp.h set.h sortidx.h str.h zebra-lock.h zebramap.h zebrautl.h zebraver.h
diff --git a/include/d1_attset.h b/include/d1_attset.h
new file mode 100644 (file)
index 0000000..dfafdd9
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1995-2000, Index Data.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation, in whole or in part, for any purpose, is hereby granted,
+ * provided that:
+ *
+ * 1. This copyright and permission notice appear in all copies of the
+ * software and its documentation. Notices of copyright or attribution
+ * which appear at the beginning of any file must remain unchanged.
+ *
+ * 2. The names of Index Data or the individual authors may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ * IN NO EVENT SHALL INDEX DATA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR
+ * NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef D1_ATTSET_H
+#define D1_ATTSET_H
+
+#include <yaz/oid.h>
+
+YAZ_BEGIN_CDECL
+
+/*
+ * This structure describes a attset, perhaps made up by inclusion
+ * (supersetting) of other attribute sets. When indexing and searching,
+ * we perform a normalisation, where we associate a given tag with
+ * the set that originally defined it, rather than the superset. This
+ * allows the most flexible access. Eg, the tags common to GILS and BIB-1
+ * should be searchable by both names.
+ */
+
+struct data1_attset;
+
+typedef struct data1_local_attribute
+{
+    int local;
+    struct data1_local_attribute *next;
+} data1_local_attribute;
+
+typedef struct data1_attset data1_attset;    
+typedef struct data1_att data1_att;
+typedef struct data1_attset_child data1_attset_child;
+
+struct data1_att
+{
+    data1_attset *parent;          /* attribute set */
+    char *name;                    /* symbolic name of this attribute */
+    int value;                     /* attribute value */
+    data1_local_attribute *locals; /* local index values */
+    data1_att *next;
+};
+
+struct data1_attset_child {
+    data1_attset *child;
+    data1_attset_child *next;
+};
+
+struct data1_attset
+{
+    char *name;          /* symbolic name */
+    oid_value reference;   /* external ID of attset */
+    data1_att *atts;          /* attributes */
+    data1_attset_child *children;  /* included attset */
+    data1_attset *next;       /* next in cache */
+};
+
+typedef struct data1_handle_info *data1_handle;
+
+YAZ_EXPORT data1_att *data1_getattbyname(data1_handle dh, data1_attset *s,
+                                        char *name);
+YAZ_EXPORT data1_attset *data1_read_attset(data1_handle dh, const char *file);
+
+YAZ_EXPORT data1_attset *data1_empty_attset(data1_handle dh);
+
+YAZ_END_CDECL
+
+#endif
diff --git a/include/d1_map.h b/include/d1_map.h
new file mode 100644 (file)
index 0000000..bfd3567
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1995-2000, Index Data.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation, in whole or in part, for any purpose, is hereby granted,
+ * provided that:
+ *
+ * 1. This copyright and permission notice appear in all copies of the
+ * software and its documentation. Notices of copyright or attribution
+ * which appear at the beginning of any file must remain unchanged.
+ *
+ * 2. The names of Index Data or the individual authors may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ * IN NO EVENT SHALL INDEX DATA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR
+ * NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef D1_MAP_H
+#define D1_MAP_H
+
+YAZ_BEGIN_CDECL
+
+typedef struct data1_maptag
+{
+    int new_field;
+    int type;
+#define D1_MAPTAG_numeric 1
+#define D1_MAPTAG_string 2
+    int which;
+    union
+    {
+       int numeric;
+       char *string;
+    } value;
+    struct data1_maptag *next;
+} data1_maptag;
+
+typedef struct data1_mapunit
+{
+    int no_data;
+    char *source_element_name;
+    data1_maptag *target_path;
+    struct data1_mapunit *next;
+} data1_mapunit;
+
+typedef struct data1_maptab
+{
+    char *name;
+    oid_value target_absyn_ref;
+    char *target_absyn_name;
+    data1_mapunit *map;
+    struct data1_maptab *next;
+} data1_maptab;
+
+YAZ_END_CDECL
+
+#endif
diff --git a/include/data1.h b/include/data1.h
new file mode 100644 (file)
index 0000000..98cf8cb
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 1995-2002, Index Data.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation, in whole or in part, for any purpose, is hereby granted,
+ * provided that:
+ *
+ * 1. This copyright and permission notice appear in all copies of the
+ * software and its documentation. Notices of copyright or attribution
+ * which appear at the beginning of any file must remain unchanged.
+ *
+ * 2. The names of Index Data or the individual authors may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ * IN NO EVENT SHALL INDEX DATA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR
+ * NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * $Id: data1.h,v 1.1 2002-10-22 12:51:08 adam Exp $
+ */
+
+#ifndef DATA1_H
+#define DATA1_H
+
+#include <stdio.h>
+
+#include <yaz/nmem.h>
+#include <yaz/oid.h>
+#include <yaz/proto.h>
+
+#include <d1_attset.h>
+#include <d1_map.h>
+#include <yaz/yaz-util.h>
+#include <yaz/wrbuf.h>
+
+#define d1_isspace(c) strchr(" \r\n\t\f", c)
+#define d1_isdigit(c) ((c) <= '9' && (c) >= '0')
+
+YAZ_BEGIN_CDECL
+
+#define data1_matchstr(s1, s2) yaz_matchstr(s1, s2)
+
+#define DATA1_MAX_SYMBOL 31
+
+typedef struct data1_name
+{
+    char *name;
+    struct data1_name *next;
+} data1_name;
+
+typedef struct data1_absyn_cache_info *data1_absyn_cache;
+typedef struct data1_attset_cache_info *data1_attset_cache;
+
+typedef enum data1_datatype
+{
+    DATA1K_unknown,
+    DATA1K_structured,
+    DATA1K_string,
+    DATA1K_numeric,
+    DATA1K_bool,
+    DATA1K_oid,
+    DATA1K_generalizedtime,
+    DATA1K_intunit,
+    DATA1K_int,
+    DATA1K_octetstring,
+    DATA1K_null
+} data1_datatype;
+
+typedef struct data1_marctab
+{
+    char *name;
+    oid_value reference;
+
+    char record_status[2];
+    char implementation_codes[5];
+    int  indicator_length;
+    int  identifier_length;
+    char user_systems[4];
+
+    int  length_data_entry;
+    int  length_starting;
+    int  length_implementation;
+    char future_use[2];
+
+    int  force_indicator_length;
+    int  force_identifier_length;
+    struct data1_marctab *next;
+} data1_marctab;
+
+typedef struct data1_esetname
+{
+    char *name;
+    Z_Espec1 *spec;
+    struct data1_esetname *next;
+} data1_esetname;
+
+/*
+ * Variant set definitions.
+ */
+
+typedef struct data1_vartype
+{
+    char *name;
+    struct data1_varclass *zclass;
+    int type;
+    data1_datatype datatype;
+    struct data1_vartype *next;
+} data1_vartype;
+
+typedef struct data1_varclass
+{
+    char *name;
+    struct data1_varset *set;
+    int zclass;
+    data1_vartype *types;
+    struct data1_varclass *next;
+} data1_varclass;
+
+typedef struct data1_varset
+{
+    char *name;
+    oid_value reference;
+    data1_varclass *classes;
+} data1_varset;
+
+/*
+ * Tagset definitions
+ */
+
+struct data1_tagset;
+
+typedef struct data1_tag
+{
+    data1_name *names;
+#define DATA1T_numeric 1
+#define DATA1T_string 2
+    int which;
+    union
+    {
+       int numeric;
+       char *string;
+    } value;
+    data1_datatype kind;
+
+    struct data1_tagset *tagset;
+    struct data1_tag *next;
+} data1_tag;
+
+typedef struct data1_tagset data1_tagset;
+
+struct data1_tagset
+{
+    int type;                        /* type of tagset in current context */
+    char *name;                      /* symbolic name */
+    oid_value reference;
+    data1_tag *tags;                 /* tags defined by this set */
+    data1_tagset *children;          /* children */
+    data1_tagset *next;              /* sibling */
+};
+
+typedef struct data1_termlist
+{
+    data1_att *att;
+    char *structure;
+    char *source;
+    struct data1_termlist *next;
+} data1_termlist;
+
+/*
+ * abstract syntax specification
+ */
+
+typedef struct data1_element
+{
+    char *name;
+    data1_tag *tag;
+    data1_termlist *termlists;
+    char *sub_name;
+    struct data1_element *children;
+    struct data1_element *next;
+} data1_element;
+
+typedef struct data1_sub_elements {
+    char *name;
+    struct data1_sub_elements *next;
+    data1_element *elements;
+} data1_sub_elements;
+
+typedef struct data1_xattr {
+    char *name;
+    char *value;
+    struct data1_xattr *next;
+    unsigned short what;  /* DATA1I_text, .. see data1_node.u.data */
+} data1_xattr;
+
+typedef struct data1_absyn
+{
+    char *name;
+    oid_value reference;
+    data1_tagset *tagset;
+    data1_attset *attset;
+    data1_varset *varset;
+    data1_esetname *esetnames;
+    data1_maptab *maptabs;
+    data1_marctab *marc;
+    data1_sub_elements *sub_elements;
+    data1_element *main_elements;
+    char *encoding;
+    int  enable_xpath_indexing;
+} data1_absyn;
+
+/*
+ * record data node (tag/data/variant)
+ */
+
+typedef struct data1_node
+{
+    /* the root of a record (containing global data) */
+#define DATA1N_root 1 
+    /* a tag */
+#define DATA1N_tag  2       
+    /* some data under a leaf tag or variant */
+#define DATA1N_data 3
+    /* variant specification (a triple, actually) */
+#define DATA1N_variant 4
+    /* comment (same as data) */
+#define DATA1N_comment 5
+    /* preprocessing instruction */
+#define DATA1N_preprocess 6
+    int which;
+    union
+    {
+       struct
+       {
+           char *type;
+           data1_absyn *absyn;  /* abstract syntax for this type */
+       } root;
+
+       struct 
+       {
+           char *tag;
+           data1_element *element;
+           int no_data_requested;
+           int get_bytes;
+           unsigned node_selected : 1;
+           unsigned make_variantlist : 1;
+            data1_xattr *attributes;
+       } tag;
+
+       struct
+       {
+           char *data;      /* filename or data */
+           int len;
+            /* text inclusion */
+#define DATA1I_inctxt 1
+            /* binary data inclusion */
+#define DATA1I_incbin 2
+        /* text data */
+#define DATA1I_text 3 
+            /* numerical data */
+#define DATA1I_num 4
+            /* object identifier */
+#define DATA1I_oid 5
+            /* XML text */
+#define DATA1I_xmltext 6
+            unsigned what:7;
+           unsigned formatted_text : 1;   /* newlines are significant */
+       } data;
+
+       struct
+       {
+           data1_vartype *type;
+           char *value;
+       } variant;
+
+        struct
+        {
+            char *target;
+            data1_xattr *attributes;
+        } preprocess;
+    } u;
+
+    void (*destroy)(struct data1_node *n);
+#define DATA1_LOCALDATA 12
+    char lbuf[DATA1_LOCALDATA]; /* small buffer for local data */
+    struct data1_node *next;
+    struct data1_node *child;
+    struct data1_node *last_child;
+    struct data1_node *parent;
+    struct data1_node *root;
+} data1_node;
+
+YAZ_EXPORT data1_handle data1_create (void);
+
+#define DATA1_FLAG_XML  1
+YAZ_EXPORT data1_handle data1_createx (int flags);
+
+YAZ_EXPORT void data1_destroy(data1_handle dh);
+YAZ_EXPORT data1_node *get_parent_tag(data1_handle dh, data1_node *n);
+YAZ_EXPORT data1_node *data1_read_node(data1_handle dh, const char **buf,
+                                      NMEM m);
+YAZ_EXPORT data1_node *data1_read_nodex (data1_handle dh, NMEM m,
+                                        int (*get_byte)(void *fh), void *fh,
+                                        WRBUF wrbuf);
+YAZ_EXPORT data1_node *data1_read_record(data1_handle dh, 
+                                        int (*rf)(void *, char *, size_t),
+                                        void *fh, NMEM m);
+YAZ_EXPORT data1_absyn *data1_read_absyn(data1_handle dh, const char *file,
+                                         int file_must_exist);
+YAZ_EXPORT data1_tag *data1_gettagbynum(data1_handle dh,
+                                       data1_tagset *s,
+                                       int type, int value);
+YAZ_EXPORT data1_tagset *data1_empty_tagset (data1_handle dh);
+YAZ_EXPORT data1_tagset *data1_read_tagset(data1_handle dh, 
+                                          const char *file,
+                                          int type);
+YAZ_EXPORT data1_element *data1_getelementbytagname(data1_handle dh, 
+                                                   data1_absyn *abs,
+                                                   data1_element *parent,
+                                                   const char *tagname);
+YAZ_EXPORT Z_GenericRecord *data1_nodetogr(data1_handle dh, data1_node *n,
+                                          int select, ODR o,
+                                          int *len);
+YAZ_EXPORT data1_tag *data1_gettagbyname(data1_handle dh, data1_tagset *s,
+                                        const char *name);
+YAZ_EXPORT void data1_free_tree(data1_handle dh, data1_node *t);
+YAZ_EXPORT char *data1_nodetobuf(data1_handle dh, data1_node *n,
+                                int select, int *len);
+YAZ_EXPORT data1_node *data1_mk_tag_data_wd(data1_handle dh,
+                                            data1_node *at,
+                                            const char *tagname, NMEM m);
+YAZ_EXPORT data1_node *data1_mk_tag_data(data1_handle dh, data1_node *at,
+                                         const char *tagname, NMEM m);
+YAZ_EXPORT data1_datatype data1_maptype(data1_handle dh, char *t);
+YAZ_EXPORT data1_varset *data1_read_varset(data1_handle dh, const char *file);
+YAZ_EXPORT data1_vartype *data1_getvartypebyct(data1_handle dh,
+                                              data1_varset *set,
+                                              char *zclass, char *type);
+YAZ_EXPORT Z_Espec1 *data1_read_espec1(data1_handle dh, const char *file);
+YAZ_EXPORT int data1_doespec1(data1_handle dh, data1_node *n, Z_Espec1 *e);
+YAZ_EXPORT data1_esetname *data1_getesetbyname(data1_handle dh, 
+                                              data1_absyn *a,
+                                              const char *name);
+YAZ_EXPORT data1_element *data1_getelementbyname(data1_handle dh,
+                                                data1_absyn *absyn,
+                                                const char *name);
+YAZ_EXPORT data1_node *data1_mk_node2(data1_handle dh, NMEM m,
+                                      int type, data1_node *parent);
+
+YAZ_EXPORT data1_node *data1_mk_tag (data1_handle dh, NMEM nmem, 
+                                     const char *tag, const char **attr,
+                                     data1_node *at);
+YAZ_EXPORT data1_node *data1_mk_tag_n (data1_handle dh, NMEM nmem,
+                                       const char *tag, size_t len,
+                                       const char **attr,
+                                       data1_node *at);
+YAZ_EXPORT void data1_tag_add_attr (data1_handle dh, NMEM nmem,
+                                    data1_node *res, const char **attr);
+
+YAZ_EXPORT data1_node *data1_mk_text_n (data1_handle dh, NMEM mem,
+                                        const char *buf, size_t len,
+                                        data1_node *parent);
+YAZ_EXPORT data1_node *data1_mk_text_nf (data1_handle dh, NMEM mem,
+                                         const char *buf, size_t len,
+                                         data1_node *parent);
+YAZ_EXPORT data1_node *data1_mk_text (data1_handle dh, NMEM mem,
+                                      const char *buf, data1_node *parent);
+
+YAZ_EXPORT data1_node *data1_mk_comment_n (data1_handle dh, NMEM mem,
+                                           const char *buf, size_t len,
+                                           data1_node *parent);
+
+YAZ_EXPORT data1_node *data1_mk_comment (data1_handle dh, NMEM mem,
+                                         const char *buf, data1_node *parent);
+
+YAZ_EXPORT data1_node *data1_mk_preprocess_n (data1_handle dh, NMEM nmem,
+                                              const char *target, size_t len,
+                                              const char **attr,
+                                              data1_node *at);
+
+YAZ_EXPORT data1_node *data1_mk_preprocess (data1_handle dh, NMEM nmem,
+                                            const char *target,
+                                            const char **attr,
+                                            data1_node *at);
+
+YAZ_EXPORT data1_node *data1_mk_root (data1_handle dh, NMEM nmem,
+                                      const char *name);
+YAZ_EXPORT void data1_set_root(data1_handle dh, data1_node *res,
+                               NMEM nmem, const char *name);
+
+YAZ_EXPORT data1_node *data1_mk_tag_data_int (data1_handle dh, data1_node *at,
+                                              const char *tag, int num,
+                                              NMEM nmem);
+YAZ_EXPORT data1_node *data1_mk_tag_data_oid (data1_handle dh, data1_node *at,
+                                              const char *tag, Odr_oid *oid,
+                                              NMEM nmem);
+YAZ_EXPORT data1_node *data1_mk_tag_data_text (data1_handle dh, data1_node *at,
+                                               const char *tag,
+                                               const char *str,
+                                               NMEM nmem);
+YAZ_EXPORT data1_node *data1_mk_tag_data_text_uni (data1_handle dh,
+                                                   data1_node *at,
+                                                   const char *tag,
+                                                   const char *str,
+                                                   NMEM nmem);
+
+YAZ_EXPORT data1_absyn *data1_get_absyn (data1_handle dh, const char *name);
+
+YAZ_EXPORT data1_node *data1_search_tag (data1_handle dh, data1_node *n,
+                                         const char *tag);
+YAZ_EXPORT data1_node *data1_mk_tag_uni (data1_handle dh, NMEM nmem, 
+                                         const char *tag, data1_node *at);
+YAZ_EXPORT data1_attset *data1_get_attset (data1_handle dh, const char *name);
+YAZ_EXPORT data1_maptab *data1_read_maptab(data1_handle dh, const char *file);
+YAZ_EXPORT data1_node *data1_map_record(data1_handle dh, data1_node *n,
+                                       data1_maptab *map, NMEM m);
+YAZ_EXPORT data1_marctab *data1_read_marctab (data1_handle dh,
+                                             const char *file);
+YAZ_EXPORT char *data1_nodetomarc(data1_handle dh, data1_marctab *p,
+                                 data1_node *n, int selected, int *len);
+YAZ_EXPORT char *data1_nodetoidsgml(data1_handle dh, data1_node *n,
+                                   int select, int *len);
+YAZ_EXPORT Z_ExplainRecord *data1_nodetoexplain(data1_handle dh,
+                                               data1_node *n, int select,
+                                               ODR o);
+YAZ_EXPORT Z_BriefBib *data1_nodetosummary(data1_handle dh, 
+                                          data1_node *n, int select,
+                                          ODR o);
+YAZ_EXPORT char *data1_nodetosoif(data1_handle dh, data1_node *n, int select,
+                                 int *len);
+YAZ_EXPORT void data1_set_tabpath(data1_handle dh, const char *path);
+YAZ_EXPORT void data1_set_tabroot (data1_handle dp, const char *p);
+YAZ_EXPORT const char *data1_get_tabpath(data1_handle dh);
+YAZ_EXPORT const char *data1_get_tabroot(data1_handle dh);
+
+YAZ_EXPORT WRBUF data1_get_wrbuf (data1_handle dp);
+YAZ_EXPORT char **data1_get_read_buf (data1_handle dp, int **lenp);
+YAZ_EXPORT char **data1_get_map_buf (data1_handle dp, int **lenp);
+YAZ_EXPORT data1_absyn_cache *data1_absyn_cache_get (data1_handle dh);
+YAZ_EXPORT data1_attset_cache *data1_attset_cache_get (data1_handle dh);
+YAZ_EXPORT NMEM data1_nmem_get (data1_handle dh);
+YAZ_EXPORT void data1_pr_tree (data1_handle dh, data1_node *n, FILE *out);
+YAZ_EXPORT char *data1_insert_string (data1_handle dh, data1_node *res,
+                                     NMEM m, const char *str);
+YAZ_EXPORT char *data1_insert_string_n (data1_handle dh, data1_node *res,
+                                        NMEM m, const char *str, size_t len);
+YAZ_EXPORT data1_node *data1_read_sgml (data1_handle dh, NMEM m,
+                                       const char *buf);
+YAZ_EXPORT data1_node *data1_read_xml (data1_handle dh,
+                                       int (*rf)(void *, char *, size_t),
+                                       void *fh, NMEM m);
+YAZ_EXPORT void data1_absyn_trav (data1_handle dh, void *handle,
+                                 void (*fh)(data1_handle dh,
+                                            void *h, data1_absyn *a));
+
+YAZ_EXPORT data1_attset *data1_attset_search_id (data1_handle dh, int id);
+
+YAZ_EXPORT char *data1_getNodeValue(data1_node* node, char* pTagPath);
+YAZ_EXPORT data1_node *data1_LookupNode(data1_node* node, char* pTagPath);
+YAZ_EXPORT int data1_CountOccurences(data1_node* node, char* pTagPath);
+
+YAZ_EXPORT FILE *data1_path_fopen (data1_handle dh, const char *file,
+                                   const char *mode);
+
+/* obsolete functions ... */
+
+YAZ_EXPORT data1_node *data1_mk_node (data1_handle dh, NMEM m);
+YAZ_EXPORT data1_node *data1_insert_taggeddata (data1_handle dh,
+                                                data1_node *root,
+                                                data1_node *at,
+                                                const char *tagname, NMEM m);
+YAZ_EXPORT data1_node *data1_mk_node_type (data1_handle dh, NMEM m, int type);
+YAZ_EXPORT data1_node *data1_add_taggeddata (data1_handle dh, data1_node *root,
+                                             data1_node *at,
+                                             const char *tagname,
+                                             NMEM m);
+
+YAZ_EXPORT data1_node *data1_get_root_tag (data1_handle dh, data1_node *n);
+
+YAZ_EXPORT int data1_iconv (data1_handle dh, NMEM m, data1_node *n,
+                            const char *tocode, 
+                            const char *fromcode);
+
+YAZ_EXPORT const char *data1_get_encoding (data1_handle dh, data1_node *n);
+
+YAZ_EXPORT int data1_is_xmlmode(data1_handle dh);
+
+YAZ_END_CDECL
+
+#endif
index 8083710..3f345a9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: recctrl.h,v 1.39 2002-08-28 12:47:10 adam Exp $
+/* $Id: recctrl.h,v 1.40 2002-10-22 12:51:08 adam Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -28,7 +28,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <yaz/proto.h>
 #include <yaz/oid.h>
 #include <yaz/odr.h>
-#include <yaz/data1.h>
+#include <data1.h>
 #include <zebramap.h>
 
 #ifdef __cplusplus
index d5a0bb5..623cb93 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am,v 1.14 2002-08-05 14:08:08 adam Exp $
+## $Id: Makefile.am,v 1.15 2002-10-22 12:51:08 adam Exp $
 
 noinst_PROGRAMS = apitest kdump
 
@@ -13,8 +13,8 @@ libzebra_a_SOURCES = dir.c dirs.c trav.c kinput.c kcompare.c \
 libzebra_a_LIBADD = \
  ../rset/librset.a ../dict/libdict.a  ../isams/libisams.a \
  ../isam/libisam.a ../isamc/libisamc.a ../isamb/libisamb.a \
- ../recctrl/librecctrl.a ../bfile/libbfile.a ../dfa/libdfa.a \
- ../util/libutil.a
+ ../recctrl/librecctrl.a ../data1/libdata1.a ../bfile/libbfile.a \
+ ../dfa/libdfa.a ../util/libutil.a
 
 bin_PROGRAMS = zebraidx zebrasrv
 
index e7e8cc6..619fdfd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: extract.c,v 1.125 2002-10-22 09:37:55 heikki Exp $
+/* $Id: extract.c,v 1.126 2002-10-22 12:51:08 adam Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -1632,8 +1632,17 @@ void extract_flushSortKeys (ZebraHandle zh, SYSNO sysno,
     while (sk)
     {
        struct sortKey *sk_next = sk->next;
-       sortIdx_type (sortIdx, sk->attrUse);
-       sortIdx_add (sortIdx, sk->string, sk->length);
+        if (cmd == 1)
+        {
+            /* insert/update: set it */
+            sortIdx_type (sortIdx, sk->attrUse);
+            sortIdx_add (sortIdx, sk->string, sk->length);
+        }
+        else if (cmd == 0)
+        {   /* delete : zero it  */
+            sortIdx_type (sortIdx, sk->attrUse);
+            sortIdx_add (sortIdx, "", 1);
+        }
        xfree (sk->string);
        xfree (sk);
        sk = sk_next;
index 099e21b..432c757 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: index.h,v 1.88 2002-10-16 09:30:57 heikki Exp $
+/* $Id: index.h,v 1.89 2002-10-22 12:51:08 adam Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -43,7 +43,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <isamd.h>
 #include <isamb.h>
 #define ISAM_DEFAULT "c"
-#include <yaz/data1.h>
+#include <data1.h>
 #include <recctrl.h>
 #include "recindex.h"
 #include "zebraapi.h"
index b86f13b..8cdc106 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.99 2002-10-22 09:37:55 heikki Exp $
+/* $Id: main.c,v 1.100 2002-10-22 12:51:08 adam Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -35,7 +35,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <sys/times.h>
 #endif
 
-#include <yaz/data1.h>
+#include <data1.h>
 #include "zebraapi.h"
 
 char *prog;
index 3e8714c..2f75d5a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: zinfo.h,v 1.14 2002-08-02 19:26:56 adam Exp $
+/* $Id: zinfo.h,v 1.15 2002-10-22 12:51:08 adam Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -24,7 +24,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #ifndef ZINFO_H
 #define ZINFO_H
 
-#include <yaz/data1.h>
+#include <data1.h>
 #include "zebraapi.h"
 #include "recindex.h"
 
index 1b063b2..cfdd3dd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: zserver.c,v 1.99 2002-09-17 21:17:37 adam Exp $
+/* $Id: zserver.c,v 1.100 2002-10-22 12:51:08 adam Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -32,7 +32,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <unistd.h>
 #endif
 
-#include <yaz/data1.h>
+#include <yaz/log.h>
 #include <yaz/ill.h>
 
 #include "zserver.h"
index c7c4ad1..f1ea420 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: grsread.h,v 1.10 2002-08-02 19:26:56 adam Exp $
+/* $Id: grsread.h,v 1.11 2002-10-22 12:51:09 adam Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -25,7 +25,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #ifndef GRSREAD_H
 #define GRSREAD_H
 
-#include <yaz/data1.h>
+#include <data1.h>
 
 #ifdef __cplusplus
 extern "C" {
index 0cb5a75..e39e1b5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: xmlread.c,v 1.5 2002-08-29 09:59:25 adam Exp $
+/* $Id: xmlread.c,v 1.6 2002-10-22 12:51:09 adam Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -36,7 +36,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include <yaz/xmalloc.h>
 #include <yaz/log.h>
-#include <yaz/data1.h>
+#include <data1.h>
 
 #include <expat.h>
 
diff --git a/tab/Makefile b/tab/Makefile
new file mode 100644 (file)
index 0000000..62deffa
--- /dev/null
@@ -0,0 +1,208 @@
+# Generated automatically from Makefile.in by configure.
+# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ..
+prefix = /usr/local
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/idzebra
+pkglibdir = $(libdir)/idzebra
+pkgincludedir = $(includedir)/idzebra
+
+top_builddir = ..
+
+ACLOCAL = aclocal
+AUTOCONF = autoconf
+AUTOMAKE = automake
+AUTOHEADER = autoheader
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+transform = s,x,x,
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = gcc
+CPP = gcc -E
+DSSSL_DIR = /usr/share/sgml/docbook/stylesheet/dsssl/modular
+DTD_DIR = /usr/share/sgml/docbook/dtd/xml/4.1.2
+MAKEINFO = makeinfo
+PACKAGE = idzebra
+RANLIB = ranlib
+TCL_INCLUDE = -I/usr/include/tcl8.3
+TCL_LIB = -L/usr/lib -ltcl8.3${TCL_DBGX} -ldl  -lieee -lm
+VERSION = 1.3.3
+YAZINC = -I/home/adam/proj/yaz/include -DYAZ_POSIX_THREADS=1 -D_REENTRANT
+YAZLALIB = /home/adam/proj/yaz/lib/libyazthread.la /home/adam/proj/yaz/lib/libyaz.la -lpthread
+YAZLIB = -L/home/adam/proj/yaz/lib/.libs -lyazthread -lyaz -lpthread
+YAZVERSION = 1.9.1
+yazconfig = ./../yaz/yaz-config
+
+tabdatadir = $(pkgdatadir)/tab
+tabdata_DATA = bib1.att dan1.att danmarc.abs danmarc.mar default.idx  explain.abs explain.att explain.tag generic.tag gils.abs gils-a.est  gils.att gils-b.est gils-f.est gils-g.est gils-summary.map gils.tag  gils-usmarc.map gils-variant.est hci.flt mail.flt  meta.abs meta-b.est meta.tag meta-usmarc.map news.flt numeric.chr  nwi.flt refer.flt scan.chr sgml.flt soif.flt string.chr summary.abs  summary.tag tagsetg.tag tagsetm.tag urx.chr usmarc.abs usmarc-b.est  usmarc.flt usmarc.mar usmarc.tag var1.var wais.abs wais-b.est  wais-variant.est
+
+
+EXTRA_DIST = $(tabdata_DATA)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES = 
+DATA =  $(tabdata_DATA)
+
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu tab/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+install-tabdataDATA: $(tabdata_DATA)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(tabdatadir)
+       @list='$(tabdata_DATA)'; for p in $$list; do \
+         if test -f $(srcdir)/$$p; then \
+           echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(tabdatadir)/$$p"; \
+           $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(tabdatadir)/$$p; \
+         else if test -f $$p; then \
+           echo " $(INSTALL_DATA) $$p $(DESTDIR)$(tabdatadir)/$$p"; \
+           $(INSTALL_DATA) $$p $(DESTDIR)$(tabdatadir)/$$p; \
+         fi; fi; \
+       done
+
+uninstall-tabdataDATA:
+       @$(NORMAL_UNINSTALL)
+       list='$(tabdata_DATA)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(tabdatadir)/$$p; \
+       done
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = tab
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu tab/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-tabdataDATA
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-tabdataDATA
+uninstall: uninstall-am
+all-am: Makefile $(DATA)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+       $(mkinstalldirs)  $(DESTDIR)$(tabdatadir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: uninstall-tabdataDATA install-tabdataDATA tags distdir info-am \
+info dvi-am dvi check check-am installcheck-am installcheck \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
index ab7baa8..dd538f5 100644 (file)
@@ -1,11 +1,15 @@
-## $Id: Makefile.am,v 1.2 2000-04-05 09:58:12 adam Exp $
+## $Id: Makefile.am,v 1.4 2002-10-22 12:51:09 adam Exp $
 
 tabdatadir = $(pkgdatadir)/tab
+tabdata_DATA = bib1.att dan1.att danmarc.abs danmarc.mar default.idx \
+ explain.abs explain.att explain.tag generic.tag gils.abs gils-a.est \
+ gils.att gils-b.est gils-f.est gils-g.est gils-summary.map gils.tag \
+ gils-usmarc.map gils-variant.est hci.flt mail.flt \
+ meta.abs meta-b.est meta.tag meta-usmarc.map news.flt numeric.chr \
+ nwi.flt refer.flt scan.chr sgml.flt soif.flt string.chr summary.abs \
+ summary.tag tagsetg.tag tagsetm.tag urx.chr usmarc.abs usmarc-b.est \
+ usmarc.flt usmarc.mar usmarc.tag var1.var wais.abs wais-b.est \
+ wais-variant.est
 
-tabdata_DATA = default.idx hci.flt mail.flt news.flt \
- numeric.chr nwi.flt out out,v refer.flt scan.chr sgml.flt soif.flt \
- string.chr urx.chr usmarc.flt
+EXTRA_DIST = $(tabdata_DATA)
 
-EXTRA_DIST = default.idx hci.flt mail.flt news.flt \
- numeric.chr nwi.flt out out,v refer.flt scan.chr sgml.flt soif.flt \
- string.chr urx.chr usmarc.flt
diff --git a/tab/Makefile.in b/tab/Makefile.in
new file mode 100644 (file)
index 0000000..99c22c5
--- /dev/null
@@ -0,0 +1,208 @@
+# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CPP = @CPP@
+DSSSL_DIR = @DSSSL_DIR@
+DTD_DIR = @DTD_DIR@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+TCL_INCLUDE = @TCL_INCLUDE@
+TCL_LIB = @TCL_LIB@
+VERSION = @VERSION@
+YAZINC = @YAZINC@
+YAZLALIB = @YAZLALIB@
+YAZLIB = @YAZLIB@
+YAZVERSION = @YAZVERSION@
+yazconfig = @yazconfig@
+
+tabdatadir = $(pkgdatadir)/tab
+tabdata_DATA = bib1.att dan1.att danmarc.abs danmarc.mar default.idx  explain.abs explain.att explain.tag generic.tag gils.abs gils-a.est  gils.att gils-b.est gils-f.est gils-g.est gils-summary.map gils.tag  gils-usmarc.map gils-variant.est hci.flt mail.flt  meta.abs meta-b.est meta.tag meta-usmarc.map news.flt numeric.chr  nwi.flt refer.flt scan.chr sgml.flt soif.flt string.chr summary.abs  summary.tag tagsetg.tag tagsetm.tag urx.chr usmarc.abs usmarc-b.est  usmarc.flt usmarc.mar usmarc.tag var1.var wais.abs wais-b.est  wais-variant.est
+
+
+EXTRA_DIST = $(tabdata_DATA)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES = 
+DATA =  $(tabdata_DATA)
+
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu tab/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+install-tabdataDATA: $(tabdata_DATA)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(tabdatadir)
+       @list='$(tabdata_DATA)'; for p in $$list; do \
+         if test -f $(srcdir)/$$p; then \
+           echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(tabdatadir)/$$p"; \
+           $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(tabdatadir)/$$p; \
+         else if test -f $$p; then \
+           echo " $(INSTALL_DATA) $$p $(DESTDIR)$(tabdatadir)/$$p"; \
+           $(INSTALL_DATA) $$p $(DESTDIR)$(tabdatadir)/$$p; \
+         fi; fi; \
+       done
+
+uninstall-tabdataDATA:
+       @$(NORMAL_UNINSTALL)
+       list='$(tabdata_DATA)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(tabdatadir)/$$p; \
+       done
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = tab
+
+distdir: $(DISTFILES)
+       here=`cd $(top_builddir) && pwd`; \
+       top_distdir=`cd $(top_distdir) && pwd`; \
+       distdir=`cd $(distdir) && pwd`; \
+       cd $(top_srcdir) \
+         && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu tab/Makefile
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-tabdataDATA
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-tabdataDATA
+uninstall: uninstall-am
+all-am: Makefile $(DATA)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+       $(mkinstalldirs)  $(DESTDIR)$(tabdatadir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: uninstall-tabdataDATA install-tabdataDATA tags distdir info-am \
+info dvi-am dvi check check-am installcheck-am installcheck \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tab/bib1.att b/tab/bib1.att
new file mode 100644 (file)
index 0000000..d90038f
--- /dev/null
@@ -0,0 +1,104 @@
+# $Id: bib1.att,v 1.1 2002-10-22 12:51:09 adam Exp $
+# Bib-1 Attribute Set
+name bib1
+reference Bib-1
+
+att 1               Personal-name
+att 2               Corporate-name
+att 3               Conference-name
+att 4               Title
+att 5               Title-series
+att 6               Title-uniform
+att 7               ISBN
+att 8               ISSN
+att 9               LC-card-number
+att 10              BNB-card-number
+att 11              BGF-number
+att 12              Local-number
+att 13              Dewey-classification
+att 14              UDC-classification
+att 15              Bliss-classification
+att 16              LC-call-number
+att 17              NLM-call-number
+att 18              NAL-call-number
+att 19              MOS-call-number
+att 20              Local-classification
+att 21              Subject-heading
+att 22              Subject-Rameau
+att 23              BDI-index-subject
+att 24              INSPEC-subject
+att 25              MESH-subject
+att 26              PA-subject
+att 27              LC-subject-heading
+att 28              RVM-subject-heading
+att 29              Local-subject-index
+att 30              Date
+att 31              Date-of-publication
+att 32              Date-of-acquisition
+att 33              Title-key
+att 34              Title-collective
+att 35              Title-parallel
+att 36              Title-cover
+att 37              Title-added-title-page
+att 38              Title-caption
+att 39              Title-running
+att 40              Title-spine
+att 41              Title-other-variant
+att 42              Title-former
+att 43              Title-abbreviated
+att 44              Title-expanded
+att 45              Subject-precis
+att 46              Subject-rswk
+att 47              Subject-subdivision
+att 48              Number-natl-biblio
+att 49              Number-legal-deposit
+att 50              Number-govt-pub
+att 51              Number-music-publisher
+att 52              Number-db
+att 53              Number-local-call
+att 54              Code-language
+att 55              Code-geographic
+att 56              Code-institution
+att 57              Name-and-title
+att 58              Name-geographic
+att 59              Place-publication
+att 60              CODEN
+att 61              Microform-generation
+att 62              Abstract
+att 63              Note
+att 1000            Author-title
+att 1001            Record-type
+att 1002            Name
+att 1003            Author
+att 1004            Author-name-personal
+att 1005            Author-name-corporate
+att 1006            Author-name-conference
+att 1007            Identifier-standard
+att 1008            Subject-LC-childrens
+att 1009            Subject-name-personal
+att 1010            Body-of-text
+att 1011            Date/time-added-to-db
+att 1012            Date/time-last-modified
+att 1013            Authority/format-id
+att 1014            Concept-text
+att 1015            Concept-reference
+att 1016            Any                1016,4,1005,62
+att 1017            Server-choice
+att 1018            Publisher
+att 1019            Record-source
+att 1020            Editor
+att 1021            Bib-level
+att 1022            Geographic-class
+att 1023            Indexed-by
+att 1024            Map-scale
+att 1025            Music-key
+att 1026            Related-periodical
+att 1027            Report-number
+att 1028            Stock-number
+att 1030            Thematic-number
+att 1031            Material-type
+att 1032            Doc-id
+att 1033            Host-item
+att 1034            Content-type
+att 1035            Anywhere
+att 1036            Author-Title-Subject
diff --git a/tab/dan1.att b/tab/dan1.att
new file mode 100644 (file)
index 0000000..6a96c1a
--- /dev/null
@@ -0,0 +1,22 @@
+name dan1
+reference 1.2.840.10003.3.15
+att 1         Classification-DK5-alfa-subdivision   # au Alfabetisk underdeling DK-5
+att 2         Subject-controlled                    # ke Kontrollerede emneord
+att 3         Subject-DBC                           # db DBC emneord
+att 4         Subject-DBC-non-fiction               # df DBC-faglitterære emneord
+att 5         Subject-DBC-fiction                   # ds DBC-skønlitterære emneord
+att 6         Subject-DBC-music                     # me DBC-Musikemneord
+att 7         Form-as-subject                       # fm Form betegnelse som emneord 
+att 8         Level-as-subject                      # nb Niveau-emneord
+att 9         Shelf-mark                            # po Opstillingselement
+att 10        Classification-DK5-number             # dk DK5
+att 11        Classification-as-shelf-mark          # ok Klassifikation som opstilling
+att 12        Obsolete-shelf-mark                   # gd Forældet dk-klassemærke
+att 13        Subject-FUI                           # fg FUI-Koder
+att 14        Catalogue-code                        # kk Katalogkode
+att 15        LIX-number                            # ix LIX
+att 16        Music-notation                        # nm Musikalsk notation
+att 17        Item-number                           # nr Numre
+att 18        Local-item-number                     # en Numre på ens materiale
+att 19        Previous-FAUST-code                   # tf Tidligere og lokale faustnumre 
+att 20        Title-host-publication                # lvx Værtspublikationstitel (uden nummer)
diff --git a/tab/danmarc.abs b/tab/danmarc.abs
new file mode 100644 (file)
index 0000000..cf4aed1
--- /dev/null
@@ -0,0 +1,755 @@
+name danmarc
+reference DANmarc
+attset bib1.att
+attset dan1.att
+
+marc danmarc.mar
+
+esetname B @
+esetname F @
+
+elm 10          DanBib-ID-nummer                    -
+elm 10/?        DanBib-ID-nummer                    Item-number
+elm 10/?/a      DanBib-ID-nummer                    Item-number
+elm 10/?/b      Dataproducentens-biblioteksnummer   -
+
+elm 11          ID-nummer-på-hovedmaterialets-post  -
+elm 11/?        ID-nummer-på-hovedmaterialets-post  -
+elm 11/?/a      ID-nummer-på-hovedmaterialets-post  -
+
+elm 14          ID-nummer-på-post-på-højere-niveau  -
+elm 14/?        ID-nummer-på-post-på-højere-niveau  -
+elm 14/?/a      ID-nummer-på-post-på-højere-niveau  -
+elm 14/?/x      ID-nummer-på-post-på-højere-niveau  Item-number
+
+elm 15          ID-nummer-på-post-på-lavere-niveau  -
+elm 15/?        ID-nummer-på-post-på-lavere-niveau  Item-number
+elm 15/?/a      ID-nummer-på-post-på-lavere-niveau  Item-number
+
+elm 16          ID-nummer-på-værtspublikation       -
+elm 16/?        ID-nummer-på-værtspublikation       -
+elm 16/?/a      ID-nummer-på-værtspublikation       -
+
+elm 17          ID-nummer-på-første-udgave          -
+elm 17/?        ID-nummer-på-første-udgave          Item-number,Local-item-number
+elm 17/?/a      ID-nummer-på-første-udgave          Item-number,Local-item-number
+
+elm 18          ID-nummer-på-anden-post-for-samme-materiale          -
+elm 18/?        ID-nummer-på-anden-post-for-samme-materiale          Item-number,Local-item-number
+elm 18/?/a      ID-nummer-på-anden-post-for-samme-materiale          Item-number,Local-item-number
+
+elm 20          Nationalbibliografisk-nummer        -
+elm 20/?        Nationalbibliografisk-nummer        Item-number
+elm 20/?/a      Landekode-for-nationalbibliografi   -
+elm 20/?/b      Nationalbibliografisk-nummer        Item-number
+
+elm 21          ISBN                                -
+elm 21/?        ISBN                                ISBN,Identifier-standard,Item-number
+elm 21/?/a      ISBN                                ISBN,Identifier-standard,Item-number
+elm 21/?/b      Tilføjelse                          -
+elm 21/?/c      Bindtype                            -
+elm 21/?/d      Anskaffelsesvilkår/pris             -
+elm 21/?/n      Bestillingsnummer                   Item-number
+elm 21/?/x      Fejltryk-eller-fejlagtigt-anvendt-ISBN  ISBN,Identifier-standard,Item-number
+
+elm 22          ISSN                                -
+elm 22/?        ISSN                                ISBN,Identifier-standard,Item-number
+elm 22/?/a      ISSN                                ISBN,Identifier-standard,Item-number
+elm 22/?/b      Tilføjelse                          -
+elm 22/?/c      Bindtype                            -
+elm 22/?/d      Anskaffelsesvilkår/pris             -
+elm 22/?/z      Fejlagtigt-tildelt-ISSN             ISBN,Identifier-standard,Item-number
+
+elm 28          ISMN                                -
+elm 28/?        ISMN                                ISBN,Identifier-standard,Item-number
+elm 28/?/a      ISMN                                ISBN,Identifier-standard,Item-number
+elm 28/?/b      Tilføjelse                          -
+elm 28/?/c      Bindtype                            -
+elm 28/?/d      Anskaffelsesvilkår/pris             -
+elm 28/?/n      Bestillingsnummer                   Item-number
+
+elm 30          CODEN                               -
+elm 30/?        CODEN                               CODEN,Item-number
+elm 30/?/a      CODEN                               CODEN,Item-number
+
+elm 32          Kode-for-natio-eller-fagbibliografi -
+elm 32/?        Kode-for-natio-eller-fagbibliografi Catalogue-code
+elm 32/?/a      Kode-for-nationalbibliografi        Catalogue-code
+elm 32/?/x      Kode-for-fagbibliografi             Catalogue-code
+
+#elm 34          Kodede-matematiske-oplysninger      -
+#elm 34/?        Kodede-matematiske-oplysninger      Code-map-scale
+#elm 34/?/a      Målestokstype                       Code-map-scale
+#elm 34/?/b      Konstant-lineær-vandret-målestok    Code-map-scale
+#elm 34/?/d      Koordinater                         Code-map-scale
+#elm 34/?/e      Koordinater                         Code-map-scale
+#elm 34/?/f      Koordinater                         Code-map-scale
+#elm 34/?/g      Koordinater                         Code-map-scale
+
+elm 38          Opstillingskode-for-børnelitteratur -
+elm 38/?        Opstillingskode-for-børnelitteratur -
+elm 38/?/a      Opstillingskode-for-børnelitteratur -
+
+elm 39          Opstillingskode-for-musikoptagelser -
+elm 39/?        Opstillingskode-for-musikoptagelser -
+elm 39/?/a      Opstillingskode-for-musikoptagelser -
+
+elm 41          Sprogkode                           -
+elm 41/?        Sprogkode                           -
+elm 41/?/a      Materialets-sprog                   Code-language
+#elm 41/?/b      Mellemoriginalens-sprog             Code-language-original
+#elm 41/?/c      Originaludgavens-sprog              Code-language-original
+elm 41/?/d      Sprog-i-resuméer                    Code-language
+elm 41/?/e      Sprog-i-mindre-dele-af-materialet   Code-language
+elm 41/?/p      Sprog-i-parallel-tekst              Code-language
+elm 41/?/u      Sprog-i-undertekster-til-film/video Code-language
+
+elm 42          Lix-tal                             -
+elm 42/?        Lix-tal                             -
+elm 42/?/a      Samlet-lix-tal                      LIX-number
+elm 42/?/b      Specifikation-af-lix-tal            -
+
+elm 43          Kode-for-geografisk-område          -
+elm 43/?        Kode-for-geografisk-område          -
+elm 43/?/a      Kode-for-geografisk-område          -
+
+elm 44          Pædagogisk-fagkode                  -
+elm 44/?        Pædagogisk-fagkode                  Subject-FUI
+elm 44/?/a      Kode-for-skoleretning               Subject-FUI
+elm 44/?/b      Kode-for-fag-og-undervisningsmateriale  Subject-FUI
+
+elm 50          LC-klassifikation                   -
+#elm 50/?        LC-klassifikation                   Classification-LC
+elm 50/?        LC-klassifikation                   -
+elm 50/?/a      LC-klassifikation                   -
+elm 50/?/b      Materialenummer                     -
+
+elm 60          NLM-klassifikation                  -
+#elm 60/?        NLM-klassifikation                  Classification-NLM
+elm 60/?        NLM-klassifikation                  -
+elm 60/?/a      NLM-klassifikation                  -
+elm 60/?/b      Materialenummer                     -
+
+elm 70          NAL-klassifikation                  -
+#elm 70/?        NAL-klassifikation                  Classification-NAL
+elm 70/?        NAL-klassifikation                  -
+elm 70/?/a      Materialenummer                     -
+
+elm 79          DB-klassifikation                   -
+elm 79/?        DB-klassifikation                   -
+#elm 79/?        DB-klassifikation                   Classification-DB 
+elm 79/?/a      Systemkode                          -
+
+elm 80          UDK                                 -
+#elm 80/?        UDK                                 Classification-UDC
+elm 80/?        UDK                                 -
+elm 80/?/a      UDK-notation                        -
+
+elm 82          DDC                                 -
+elm 82/?        DDC                                 -
+#elm 82/?        DDC                                 Classification-Dewey
+elm 82/?/a      Basisnummer                         -
+elm 82/?/b      Udgivelse                           -
+elm 82/?/c      DDC-udgave                          -
+
+elm 83          Felt-083                            -
+elm 83/?        Felt-083                            -
+elm 83/?/a      Felt-083                            -
+elm 83/?/b      Felt-083                            -
+
+elm 85          BCM-klassifikation                  -
+elm 85/?        BCM-klassifikation                  -
+#elm 85/?        BCM-klassifikation                  Classification-BCM
+elm 85/?/a      BCM-klassifikation                  -
+elm 85/?/b      BCM-klassifikation                  -
+elm 85/?/c      BCM-klassifikation                  -
+
+elm 87          Lokal-klassifikationsnotation-1     -
+elm 87/?        Lokal-klassifikationsnotation-1     -
+#elm 87/?/a      Lokal-klassifikationsnotation-1     Classification-local
+elm 87/?/b      Lokal-klassifikationsnotation-1     -
+
+elm 88          Lokal-klassifikationsnotation-2     -
+elm 88/?        Lokal-klassifikationsnotation-2     -
+#elm 88/?/a      Lokal-klassifikationsnotation-2     Classification-local
+elm 88/?/b      Lokal-klassifikationsnotation-2     -
+elm 88/?/c      Lokal-klassifikationsnotation-2     -
+elm 88/?/d      Lokal-klassifikationsnotation-2     -
+elm 88/?/e      Lokal-klassifikationsnotation-2     -
+elm 88/?/f      Lokal-klassifikationsnotation-2     -
+elm 88/?/n      Lokal-klassifikationsnotation-2     -
+elm 88/?/p      Lokal-klassifikationsnotation-2     -
+elm 88/?/q      Lokal-klassifikationsnotation-2     -
+elm 88/?/t      Lokal-klassifikationsnotation-2     -
+elm 88/?/u      Lokal-klassifikationsnotation-2     -
+
+elm 89          Lokal-klassifikationsnotation-3     -
+elm 89/?        Lokal-klassifikationsnotation-3     -
+#elm 89/?/a      Lokal-klassifikationsnotation-3     Classification-local
+elm 89/?/b      Lokal-klassifikationsnotation-3     -
+elm 89/?/c      Lokal-klassifikationsnotation-3     -
+
+elm 96          Lokal-opstillingssignatur           -
+elm 96/?        Lokal-opstillingssignatur           -
+elm 96/?/a      Opstilling           -
+elm 96/?/n      Lokal-opstillingssignatur           -
+elm 96/?/z      Lokaliseringskode                   -
+
+elm 100         Personnavn                  -
+elm 100/?       Personnavn                  Personal-name:w,Personal-name:p,Shelf-mark
+#elm 100/?/a     Efternavn/fornavn-alene     Personal-name:w,Personal-name:p,Personal-name-personal:w,Personal-name-personal:p,Shelf-mark
+#elm 100/?/c     Fødselsår                   Personal-name:w,Personal-name:p,Personal-name-personal:w,Personal-name-personal:p,Shelf-mark
+#elm 100/?/f     Tilføjelse                  Personal-name:w,Personal-name:p,Personal-name-personal:w,Personal-name-personal:p,Shelf-mark
+#elm 100/?/h     Fornavn                     Personal-name:w,Personal-name:p,Personal-name-personal:w,Personal-name-personal:p,Shelf-mark
+#elm 100/?/k     Fuldt-udskrevet-fornavn     Personal-name:w,Personal-name:p,Personal-name-personal:w,Personal-name-personal:p,Shelf-mark
+
+elm 110         Korporationsnavn-opstillingselement     -
+elm 110/?       Korporationsnavn-opstillingselement     Personal-name:w,Personal-name:p,Corporate-name:w,Corporate-name:p,Shelf-mark
+#elm 110/?/a     Korporationsnavn                        Personal-name:w,Personal-name:p,Personal-name-corporate:w,Personal-name-corporate:p,Shelf-mark
+#elm 110/?/c     Underkorporation                        Personal-name:w,Personal-name:p,Personal-name-corporate:w,Personal-name-corporate:p,Shelf-mark
+#elm 110/?/e     Tilføjelse                              Personal-name:w,Personal-name:p,Personal-name-corporate:w,Personal-name-corporate:p,Shelf-mark
+#elm 110/?/i     Nummer-på-konference                    Personal-name:w,Personal-name:p,Personal-name-corporate:w,Personal-name-corporate:p,Shelf-mark
+#elm 110/?/j     Sted-for-konference                     Personal-name:w,Personal-name:p,Personal-name-corporate:w,Personal-name-corporate:p,Shelf-mark
+#elm 110/?/k     År-for-konference                       Personal-name:w,Personal-name:p,Personal-name-corporate:w,Personal-name-corporate:p,Shelf-mark
+
+elm 210         Forkortet-nøgletitel                    -
+elm 210/?       Forkortet-nøgletitel                    Title-key,Title,Title:p
+elm 210/?/a     Forkortet-nøgletitel                    Title-key,Title,Title:p
+elm 210/?/b     Forkortet-identificerende-tilføjelse    Title-key,Title,Title:p
+
+elm 222         Nøgletitel                  -
+elm 222/?       Nøgletitel                  Title-key,Title,Title:p
+elm 222/?/a     Nøgletitel                  Title-key,Title,Title:p
+elm 222/?/b     Identificerende-tilføjelse  Title-key,Title,Title:p
+
+elm 239         Uniform-titel/standardtitel-opstillingselement  -
+elm 239/?       Uniform-titel/standardtitel-opstillingselement  Title-uniform,Title,Title:p
+elm 239/?/t     Uniform-titel                                   Title-uniform,Title,Title:p
+elm 239/?/u     Almindeligt-kendt-tilnavn                       Title-uniform,Title,Title:p
+elm 239/?/v     Uddragstitel                                    Title-uniform,Title,Title:p
+elm 239/?/Ø     Uniform-titel/standardtitel-opstillingselement  -
+elm 239/?/ø     Identificerende-tilføjelser                     Title-uniform,Title
+
+elm 240         Uniform-titel-opstillingselement    -
+elm 240/?       Uniform-titel-opstillingselement    Title-uniform,Title,Title:p
+elm 240/?/a     Uniform-titel                       Title-uniform,Title,Title:p
+elm 240/?/j     Andet-identificerende-element       Title-uniform,Title,Title:p
+elm 240/?/r     Sprog-i-oversættelse/version        -
+elm 240/?/u     Udgivelsesår                        -
+elm 240/?/ø     Identificerende-tilføjelser         Title-uniform,Title
+
+elm 241         Originaltitel           -
+elm 241/?       Originaltitel           Title,Title:p
+elm 241/?/a     Originaltitel           Title,Title:p
+elm 241/?/r     Sprog                   -
+
+elm 245         Originaltitel-og-ophavsangivelse            -
+elm 245/?       Originaltitel-og-ophavsangivelse            Title,Title:p
+elm 245/?/A     Originaltitel-og-ophavsangivelse            -
+elm 245/?/G     Originaltitel-og-ophavsangivelse            -
+elm 245/?/a     Titel                                       Title,Title:p
+elm 245/?/b     Rest-af-titel-eller-alternativ-titel        Title,Title:p
+elm 245/?/c     Undertitel-og-anden-titelinformation        Title,Title:p
+elm 245/?/e     Ophavsangivelser-opslag                     -
+elm 245/?/f     Ophavsangivelser                            -
+elm 245/?/g     Numerisk-eller-alfabetisk-betegnelse-for-bind                       Title,Title:p
+elm 245/?/i     Anden-primær/sekundær-ophavsangivelse-kun-i-nationalbibliogafien    -
+elm 245/?/j     Anden-primær/sekundær-ophavsangivelse-ikke-i-nationalbibliogafien   -
+elm 245/?/o     Titel-på-supplement/sektion                  -
+elm 245/?/p     Paralleltitel                               Title-parallel,Title,Title:p
+elm 245/?/s     Parallel-undertitel                         Title-parallel,Title,Title:p
+elm 245/?/u     Markant-undertitel                          Title,Title:p
+elm 245/?/x     Hovedtitel-på-tilføjet-værk-af-andet-ophav  Title,Title:p
+elm 245/?/y     Titel-på-supplement                         Title,Title:p
+elm 245/?/Ø     Originaltitel-og-ophavsangivelse            -
+elm 245/?/æ     Identificerende-ophavsangivelse-til-titel   -
+elm 245/?/ø     Identificerende-tilføjelser-til-titel       -
+
+elm 248         Bindspecifikation                       -
+elm 248/?       Bindspecifikation                       Title
+elm 248/?/a     Bindtitel/supplementstitel              Title,Title:p
+elm 248/?/c     Undertitel-og-anden-titelinformation    Title,Title:p
+elm 248/?/e     Ophavsangivelse                         -
+elm 248/?/g     Bindnummer/supplementsbetegnelse        Title
+elm 248/?/j     Udgivelsesår                            -
+elm 248/?/l     Generel-note                            Note
+elm 248/?/w     Udgavebetegnelse                        -
+
+elm 250         Udgavebetegnelse                        -
+elm 250/?       Udgavebetegnelse                        -
+elm 250/?/a     Udgavebetegnelse                        -
+elm 250/?/b     Kort-udgavebetegnelse/sonderingselement -
+elm 250/?/c     Ophavsangivelse-opslag                  -
+elm 250/?/d     Ophavsangivelse                         -
+elm 250/?/x     Oplagsbetegnelse                        -
+
+elm 255         Nummereringer-og-dateringer   -
+elm 255/?       Nummereringer-og-dateringer   -
+elm 255/?/a     Nummereringer-og-dateringer   -
+
+elm 256         Matematiske-oplysninger-for-kartografiske-materialer    -
+#elm 256/?       Matematiske-oplysninger-for-kartografiske-materialer    Code-map-scale
+#elm 256/?/a     Målestok                                                Code-map-scale
+#elm 256/?/c     Projektion                                              Code-map-scale
+
+elm 260         Publicering/distribution        -
+elm 260/?       Publicering/distribution        -
+elm 260/?/a     Hjemsted-for-forlag             Place-publication
+elm 260/?/b     Navn-på-forlag                  Publisher
+elm 260/?/c     Udgivelsesår                    Date-of-Publication
+elm 260/?/d     Adresse-på-forlag               -
+elm 260/?/e     Funktionsangivelse-på-forlag    -
+elm 260/?/f     Hjemsted-for-distributør        Place-publication
+elm 260/?/g     Navn-på-distributør             -
+elm 260/?/k     Trykkerioplysninger             -
+elm 260/?/p     Navn-på-forlag/distributør-på-andet-sprog/alfabet   publisher
+
+elm 300         Fysisk-beskrivelse                          -
+elm 300/?       Fysisk-beskrivelse                          -
+elm 300/?/D     Fysisk-beskrivelse                          -
+elm 300/?/a     Omfang-uden-specifik-materialebetegnelse    -
+elm 300/?/b     Yderligere-fysisk-beskrivelse               -
+elm 300/?/c     Størrelse                                   -
+elm 300/?/d     Bilag                                       -
+elm 300/?/e     Tekniske-oplysninger                        -
+elm 300/?/l     Spilletid