Remove Emilda section
[idzebra-moved-to-github.git] / data1 / d1_tagset.c
1 /* This file is part of the Zebra server.
2    Copyright (C) 1994-2011 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <yaz/log.h>
28 #include <idzebra/data1.h>
29 #include <yaz/oid_db.h>
30
31 /*
32  * We'll probably want to add some sort of hashed index to these lookup-
33  * functions eventually.
34  */
35
36 data1_datatype data1_maptype (data1_handle dh, char *t)
37 {
38     static struct
39     {
40         char *tname;
41         data1_datatype type;
42     } types[] =
43     {
44         {"structured", DATA1K_structured},
45         {"string", DATA1K_string},
46         {"numeric", DATA1K_numeric},
47         {"oid", DATA1K_oid},
48         {"bool", DATA1K_bool},
49         {"generalizedtime", DATA1K_generalizedtime},
50         {"intunit", DATA1K_intunit},
51         {"int", DATA1K_int},
52         {"octetstring", DATA1K_octetstring},
53         {"null", DATA1K_null},
54         {NULL, (data1_datatype) -1}
55     };
56     int i;
57
58     for (i = 0; types[i].tname; i++)
59         if (!data1_matchstr(types[i].tname, t))
60             return types[i].type;
61     return DATA1K_unknown;
62 }
63
64 data1_tag *data1_gettagbynum (data1_handle dh, data1_tagset *s,
65                               int type, int value)
66 {
67     data1_tag *r;
68     
69     for (; s; s = s->next)
70     {
71         /* scan local set */
72         if (type == s->type)
73             for (r = s->tags; r; r = r->next)
74                 if (r->which == DATA1T_numeric && r->value.numeric == value)
75                     return r;
76         /* scan included sets */
77         if (s->children &&
78             (r = data1_gettagbynum (dh, s->children, type, value)))
79             return r;
80     }
81     return 0;
82 }
83
84 data1_tag *data1_gettagbyname (data1_handle dh, data1_tagset *s,
85                                const char *name)
86 {
87     data1_tag *r;
88
89     for (; s; s = s->next)
90     {
91         /* scan local set */
92         for (r = s->tags; r; r = r->next)
93         {
94             data1_name *np;
95
96             for (np = r->names; np; np = np->next)
97                 if (!data1_matchstr(np->name, name))
98                     return r;
99         }
100         /* scan included sets */
101         if (s->children && (r = data1_gettagbyname (dh, s->children, name)))
102             return r;
103     }
104     return 0;
105 }
106
107 data1_tagset *data1_empty_tagset (data1_handle dh)
108 {
109     data1_tagset *res =
110         (data1_tagset *) nmem_malloc(data1_nmem_get (dh), sizeof(*res));
111     res->name = 0;
112     res->oid = 0;
113     res->tags = 0;
114     res->type = 0;
115     res->children = 0;
116     res->next = 0;
117     return res;
118 }
119
120 data1_tagset *data1_read_tagset (data1_handle dh, const char *file, int type)
121 {
122     NMEM mem = data1_nmem_get (dh);
123     data1_tagset *res = 0;
124     data1_tagset **childp;
125     data1_tag **tagp;
126     FILE *f;
127     int lineno = 0;
128     int argc;
129     char *argv[50], line[512];
130
131     if (!(f = data1_path_fopen(dh, file, "r")))
132     {
133         yaz_log(YLOG_WARN|YLOG_ERRNO, "%s", file);
134         return 0;
135     }
136     res = data1_empty_tagset (dh);
137     res->type = type;
138     childp = &res->children;
139     tagp = &res->tags;
140
141     while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
142     {
143         char *cmd = *argv;
144         if (!strcmp(cmd, "tag"))
145         {
146             int value;
147             char *names, *type, *nm;
148             data1_tag *rr;
149             data1_name **npp;
150
151             if (argc != 4)
152             {
153                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to tag", file, lineno);
154                 continue;
155             }
156             value = atoi(argv[1]);
157             names = argv[2];
158             type = argv[3];
159
160             rr = *tagp = (data1_tag *)nmem_malloc(mem, sizeof(*rr));
161             rr->tagset = res;
162             rr->next = 0;
163             rr->which = DATA1T_numeric;
164             rr->value.numeric = value;
165             /*
166              * how to deal with local numeric tags?
167              */
168
169             if (!(rr->kind = data1_maptype(dh, type)))
170             {
171                 yaz_log(YLOG_WARN, "%s:%d: Unknown datatype %s",
172                      file, lineno, type);
173                 fclose(f);
174                 return 0;
175             }
176             
177             /* read namelist */
178             nm = names;
179             npp = &rr->names;
180             do
181             {
182                 char *e;
183
184                 *npp = (data1_name *)nmem_malloc(mem, sizeof(**npp));
185                 if ((e = strchr(nm, '/')))
186                     *(e++) = '\0';
187                 (*npp)->name = nmem_strdup(mem, nm);
188                 (*npp)->next = 0;
189                 npp = &(*npp)->next;
190                 nm = e;
191             }
192             while (nm);
193             tagp = &rr->next;
194         }
195         else if (!strcmp(cmd, "name"))
196         {
197             if (argc != 2)
198             {
199                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to name", file, lineno);
200                 continue;
201             }
202             res->name = nmem_strdup(mem, argv[1]);
203         }
204         else if (!strcmp(cmd, "reference"))
205         {
206             char *name;
207             
208             if (argc != 2)
209             {
210                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to reference",
211                         file, lineno);
212                 continue;
213             }
214             name = argv[1];
215             res->oid = yaz_string_to_oid_nmem(yaz_oid_std(),
216                                               CLASS_TAGSET, name, mem);
217             if (!res->oid)
218             {
219                 yaz_log(YLOG_WARN, "%s:%d: Unknown tagset ref '%s'",
220                         file, lineno, name);
221                 continue;
222             }
223         }
224         else if (!strcmp(cmd, "type"))
225         {
226             if (argc != 2)
227             {
228                 yaz_log (YLOG_WARN, "%s:%d: Bad # args to type", file, lineno);
229                 continue;
230             }
231             if (!res->type)
232                 res->type = atoi(argv[1]);
233         }
234         else if (!strcmp(cmd, "include"))
235         {
236             char *name;
237             int type = 0;
238
239             if (argc < 2)
240             {
241                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to include",
242                         file, lineno);
243                 continue;
244             }
245             name = argv[1];
246             if (argc == 3)
247                 type = atoi(argv[2]);
248             *childp = data1_read_tagset (dh, name, type);
249             if (!(*childp))
250             {
251                 yaz_log(YLOG_WARN, "%s:%d: Inclusion failed for tagset %s",
252                         file, lineno, name);
253                 continue;
254             }
255             childp = &(*childp)->next;
256         }
257         else
258         {
259             yaz_log(YLOG_WARN, "%s:%d: Unknown directive '%s'",
260                     file, lineno, cmd);
261         }
262     }
263     fclose(f);
264     return res;
265 }
266 /*
267  * Local variables:
268  * c-basic-offset: 4
269  * c-file-style: "Stroustrup"
270  * indent-tabs-mode: nil
271  * End:
272  * vim: shiftwidth=4 tabstop=8 expandtab
273  */
274