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