Minor fix.
[yaz-moved-to-github.git] / retrieval / d1_tagset.c
1 /*
2  * Copyright (c) 1995-1997, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: d1_tagset.c,v $
7  * Revision 1.8  1998-05-18 13:07:07  adam
8  * Changed the way attribute sets are handled by the retriaval module.
9  * Extended Explain conversion / schema.
10  * Modified server and client to work with ASN.1 compiled protocol handlers.
11  *
12  * Revision 1.7  1998/02/11 11:53:35  adam
13  * Changed code so that it compiles as C++.
14  *
15  * Revision 1.6  1997/09/17 12:10:38  adam
16  * YAZ version 1.4.
17  *
18  * Revision 1.5  1997/09/05 09:50:57  adam
19  * Removed global data1_tabpath - uses data1_get_tabpath() instead.
20  *
21  * Revision 1.4  1995/11/13 09:27:38  quinn
22  * Fiddling with the variant stuff.
23  *
24  * Revision 1.3  1995/11/01  16:34:58  quinn
25  * Making data1 look for tables in data1_tabpath
26  *
27  * Revision 1.2  1995/11/01  13:54:49  quinn
28  * Minor adjustments
29  *
30  * Revision 1.1  1995/11/01  11:56:09  quinn
31  * Added Retrieval (data management) functions en masse.
32  *
33  *
34  */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <ctype.h>
39 #include <string.h>
40
41 #include <log.h>
42 #include <tpath.h>
43
44 #include <data1.h>
45
46 /*
47  * We'll probably want to add some sort of hashed index to these lookup-
48  * functions eventually.
49  */
50
51 data1_datatype data1_maptype (data1_handle dh, char *t)
52 {
53     static struct
54     {
55         char *tname;
56         data1_datatype type;
57     } types[] =
58     {
59         {"structured", DATA1K_structured},
60         {"string", DATA1K_string},
61         {"numeric", DATA1K_numeric},
62         {"oid", DATA1K_oid},
63         {"bool", DATA1K_bool},
64         {"generalizedtime", DATA1K_generalizedtime},
65         {"intunit", DATA1K_intunit},
66         {"int", DATA1K_int},
67         {"octetstring", DATA1K_octetstring},
68         {"null", DATA1K_null},
69         {NULL, (data1_datatype) -1}
70     };
71     int i;
72
73     for (i = 0; types[i].tname; i++)
74         if (!data1_matchstr(types[i].tname, t))
75             return types[i].type;
76     return 0;
77 }
78
79 data1_tag *data1_gettagbynum (data1_handle dh, data1_tagset *s,
80                               int type, int value)
81 {
82     data1_tag *r;
83
84     for (; s; s = s->next)
85     {
86         /* scan local set */
87         if (type == s->type)
88             for (r = s->tags; r; r = r->next)
89                 if (r->which == DATA1T_numeric && r->value.numeric == value)
90                     return r;
91         /* scan included sets */
92         if (s->children && (r = data1_gettagbynum (dh, s->children,
93                                                    type, value)))
94             return r;
95     }
96     return 0;
97 }
98
99 data1_tag *data1_gettagbyname (data1_handle dh, data1_tagset *s, char *name)
100 {
101     data1_tag *r;
102
103     for (; s; s = s->next)
104     {
105         /* scan local set */
106         for (r = s->tags; r; r = r->next)
107         {
108             data1_name *np;
109
110             for (np = r->names; np; np = np->next)
111                 if (!data1_matchstr(np->name, name))
112                     return r;
113         }
114         /* scan included sets */
115         if (s->children && (r = data1_gettagbyname (dh, s->children, name)))
116             return r;
117     }
118     return 0;
119 }
120
121 data1_tagset *data1_read_tagset (data1_handle dh, char *file)
122 {
123     NMEM mem = data1_nmem_get (dh);
124     char line[512], *r, cmd[512], args[512];
125     data1_tagset *res = 0, **childp;
126     data1_tag **tagp;
127     FILE *f;
128
129     if (!(f = yaz_path_fopen(data1_get_tabpath(dh), file, "r")))
130     {
131         logf(LOG_WARN|LOG_ERRNO, "%s", file);
132         return 0;
133     }
134
135     res = (data1_tagset *)nmem_malloc(mem, sizeof(*res));
136     res->name = 0;
137     res->type = 0;
138     res->tags = 0;
139     res->children = 0;
140     res->next = 0;
141     childp = &res->children;
142     tagp = &res->tags;
143
144     for (;;)
145     {
146         while ((r = fgets(line, 512, f)))
147         {
148             while (*r && isspace(*r))
149                 r++;
150             if (*r && *r != '#')
151                 break;
152         }
153         if (!r)
154         {
155             fclose(f);
156             return res;
157         }
158         if (sscanf(r, "%s %[^\n]", cmd, args) < 2)
159             *args = '\0';
160         if (!strcmp(cmd, "tag"))
161         {
162             int value;
163             char names[512], type[512], *nm;
164             data1_tag *rr;
165             data1_name **npp;
166
167             if (sscanf(args, "%d %s %s", &value, names, type) < 3)
168             {
169                 logf(LOG_WARN, "Bad number of parms in '%s' in %s",
170                     args, file);
171                 fclose(f);
172                 return 0;
173             }
174             rr = *tagp = (data1_tag *)nmem_malloc(mem, sizeof(*rr));
175             rr->tagset = res;
176             rr->next = 0;
177             rr->which = DATA1T_numeric;
178             rr->value.numeric = value;
179             /*
180              * how to deal with local numeric tags?
181              */
182
183             if (!(rr->kind = data1_maptype(dh, type)))
184             {
185                 logf(LOG_WARN, "Unknown datatype %s in %s", type, file);
186                 fclose(f);
187                 return 0;
188             }
189             
190             /* read namelist */
191             nm = names;
192             npp = &rr->names;
193             do
194             {
195                 char *e;
196
197                 *npp = (data1_name *)nmem_malloc(mem, sizeof(**npp));
198                 if ((e = strchr(nm, '/')))
199                     *(e++) = '\0';
200                 (*npp)->name = nmem_strdup(mem, nm);
201                 (*npp)->next = 0;
202                 npp = &(*npp)->next;
203                 nm = e;
204             }
205             while (nm);
206             tagp = &rr->next;
207         }
208         else if (!strcmp(cmd, "name"))
209         {
210             char name[512];
211
212             if (!sscanf(args, "%s", name))
213             {
214                 logf(LOG_WARN, "%s malformed name directive in %s", file);
215                 fclose(f);
216                 return 0;
217             }
218             res->name = nmem_strdup(mem, args);
219         }
220         else if (!strcmp(cmd, "reference"))
221         {
222             char name[512];
223
224             if (!sscanf(args, "%s", name))
225             {
226                 logf(LOG_WARN, "%s malformed reference directive in %s", file);
227                 fclose(f);
228                 return 0;
229             }
230             if ((res->reference = oid_getvalbyname(name)) == VAL_NONE)
231             {
232                 logf(LOG_WARN, "Unknown tagset ref '%s' in %s", name, file);
233                 fclose(f);
234                 return 0;
235             }
236         }
237         else if (!strcmp(cmd, "type"))
238         {
239             if (!sscanf(args, "%d", &res->type))
240             {
241                 logf(LOG_WARN, "%s malformed type directive in %s", file);
242                 fclose(f);
243                 return 0;
244             }
245         }
246         else if (!strcmp(cmd, "include"))
247         {
248             char name[512];
249
250             if (!sscanf(args, "%s", name))
251             {
252                 logf(LOG_WARN, "%s malformed reference directive in %s", file);
253                 fclose(f);
254                 return 0;
255             }
256             if (!(*childp = data1_read_tagset (dh, name)))
257             {
258                 logf(LOG_WARN, "Inclusion failed in %s", file);
259                 fclose(f);
260                 return 0;
261             }
262             childp = &(*childp)->next;
263         }
264         else
265         {
266             logf(LOG_WARN, "Unknown directive '%s' in %s", cmd, file);
267             fclose(f);
268             return 0;
269         }
270     }
271 }