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