Added Retrieval (data management) functions en masse.
[yaz-moved-to-github.git] / retrieval / d1_absyn.c
1 /*
2  * Copyright (c) 1995, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: d1_absyn.c,v $
7  * Revision 1.1  1995-11-01 11:56:06  quinn
8  * Added Retrieval (data management) functions en masse.
9  *
10  *
11  */
12
13 #include <ctype.h>
14 #include <stdio.h>
15 #include <assert.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include <xmalloc.h>
20 #include <oid.h>
21 #include <log.h>
22
23 #include "data1.h"
24
25 #define D1_MAX_NESTING  128
26 #define DATA1_MAX_SYNTAXES 30 /* max no of syntaxes to handle in one session */
27
28 static struct /* cache of abstract syntaxes */
29 {
30     char *name;
31     data1_absyn *absyn;
32 } syntaxes[DATA1_MAX_SYNTAXES] = {{0,0}};
33
34 data1_absyn *data1_get_absyn(char *name)
35 {
36     char fname[512];
37     int i;
38
39     for (i = 0; syntaxes[i].name; i++)
40         if (!strcmp(name, syntaxes[i].name))
41             return syntaxes[i].absyn;
42
43     if (i >= DATA1_MAX_SYNTAXES - 1)
44     {
45         logf(LOG_WARN, "Too many abstract syntaxes loaded");
46         return 0;
47     }
48     sprintf(fname, "%s.abs", name);
49     if (!(syntaxes[i].absyn = data1_read_absyn(fname)))
50         return 0;
51     if (!(syntaxes[i].name = xmalloc(strlen(name)+1)))
52         abort();
53     strcpy(syntaxes[i].name, name);
54     syntaxes[i+1].name = 0;
55     return syntaxes[i].absyn;
56 }
57
58 data1_esetname *data1_getesetbyname(data1_absyn *a, char *name)
59 {
60     data1_esetname *r;
61
62     for (r = a->esetnames; r; r = r->next)
63         if (!data1_matchstr(r->name, name))
64             return r;
65     return 0;
66 }
67
68 data1_element *data1_getelementbytagname(data1_absyn *abs,
69     data1_element *parent, char *tagname)
70 {
71     data1_element *r;
72
73     if (!parent)
74         r = abs->elements;
75     else
76         r = parent->children;
77     for (; r; r = r->next)
78     {
79         data1_name *n;
80
81         for (n = r->tag->names; n; n = n->next)
82             if (!data1_matchstr(tagname, n->name))
83                 return r;
84     }
85     return 0;
86 }
87
88 data1_element *data1_getelementbyname(data1_absyn *absyn, char *name)
89 {
90     data1_element *r;
91
92     for (r = absyn->elements; r; r = r->next)
93         if (!data1_matchstr(r->name, name))
94             return r;
95     return 0;
96 }
97
98 data1_absyn *data1_read_absyn(char *file)
99 {
100     char line[512], *r, cmd[512], args[512];
101     data1_absyn *res = 0;
102     FILE *f;
103     data1_element **ppl[D1_MAX_NESTING];
104     data1_esetname **esetpp;
105     data1_maptab **maptabp;
106     data1_marctab **marcp;
107     int level = 0;
108
109     if (!(f = fopen(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->reference = VAL_NONE;
119     res->tagset = 0;
120     res->attset = 0;
121     res->varset = 0;
122     res->esetnames = 0;
123     res->maptabs = 0;
124     maptabp = &res->maptabs;
125     res->marc = 0;
126     marcp = &res->marc;
127     res->elements = 0;
128     ppl[0] = &res->elements;
129     esetpp = &res->esetnames;
130
131     for (;;)
132     {
133         while ((r = fgets(line, 512, f)))
134         {
135             while (*r && isspace(*r))
136                 r++;
137             if (*r && *r != '#')
138                 break;
139         }
140         if (!r)
141         {
142             fclose(f);
143             return res;
144         }
145         if (sscanf(r, "%s %[^\n]", cmd, args) < 2)
146             *args = '\0';
147         if (!strcmp(cmd, "elm"))
148         {
149             data1_element *new;
150             int i;
151             char path[512], name[512], att[512], *p;
152             int type, value;
153
154             if (sscanf(args, "%s %s %s", path, name, att) < 3)
155             {
156                 logf(LOG_WARN, "Bad # of args to elm in %s: '%s'", 
157                     file, args);
158                 fclose(f);
159                 return 0;
160             }
161             p = path;
162             for (i = 0;; i++)
163             {
164                 char *e;
165
166                 if ((e = strchr(p, '/')))
167                     p = e+1;
168                 else
169                     break;
170             }
171             if (i > level + 1)
172             {
173                 logf(LOG_WARN, "Bad level inc in %s in '%'", file, args);
174                 fclose(f);
175                 return 0;
176             }
177             level = i;
178             if (!(new = *ppl[level] = xmalloc(sizeof(*new))))
179                 abort;
180             new ->next = new->children = 0;
181             ppl[level] = &new->next;
182             ppl[level+1] = &new->children;
183
184             if (sscanf(p, "(%d,%d)", &type, &value) < 2)
185             {
186                 logf(LOG_WARN, "Malformed element '%s' in %s", p, file);
187                 fclose(f);
188                 return 0;
189             }
190             if (!res->tagset)
191             {
192                 logf(LOG_WARN, "No tagset loaded in %s", file);
193                 fclose(f);
194                 return 0;
195             }
196             if (!(new->tag = data1_gettagbynum(res->tagset, type, value)))
197             {
198                 logf(LOG_WARN, "Couldn't find tag %s in tagset in %s",
199                     p, file);
200                 fclose(f);
201                 return 0;
202             }
203             if (*att == '!')
204                 strcpy(att, name);
205             if (*att == '-')
206                 new->att = 0;
207             else
208             {
209                 if (!res->attset)
210                 {
211                     logf(LOG_WARN, "No attset loaded in %s", file);
212                     fclose(f);
213                     return 0;
214                 }
215                 if (!(new->att = data1_getattbyname(res->attset, att)))
216                 {
217                     logf(LOG_WARN, "Couldn't find att '%s' in attset", att);
218                     fclose(f);
219                     return 0;
220                 }
221             }
222             if (!(new->name = xmalloc(strlen(name)+1)))
223                 abort();
224             strcpy(new->name, name);
225         }
226         else if (!strcmp(cmd, "name"))
227         {
228             char name[512];
229
230             if (!sscanf(args, "%s", name))
231             {
232                 logf(LOG_WARN, "%s malformed name directive in %s", file);
233                 fclose(f);
234                 return 0;
235             }
236             if (!(res->name = xmalloc(strlen(args)+1)))
237                 abort();
238             strcpy(res->name, name);
239         }
240         else if (!strcmp(cmd, "reference"))
241         {
242             char name[512];
243
244             if (!sscanf(args, "%s", name))
245             {
246                 logf(LOG_WARN, "%s malformed reference directive in %s", file);
247                 fclose(f);
248                 return 0;
249             }
250             if ((res->reference = oid_getvalbyname(name)) == VAL_NONE)
251             {
252                 logf(LOG_WARN, "Unknown tagset ref '%s' in %s", name, file);
253                 fclose(f);
254                 return 0;
255             }
256         }
257         else if (!strcmp(cmd, "attset"))
258         {
259             char name[512];
260
261             if (!sscanf(args, "%s", name))
262             {
263                 logf(LOG_WARN, "%s malformed attset directive in %s", file);
264                 fclose(f);
265                 return 0;
266             }
267             if (!(res->attset = data1_read_attset(name)))
268             {
269                 logf(LOG_WARN, "Attset failed in %s", file);
270                 fclose(f);
271                 return 0;
272             }
273         }
274         else if (!strcmp(cmd, "tagset"))
275         {
276             char name[512];
277
278             if (!sscanf(args, "%s", name))
279             {
280                 logf(LOG_WARN, "%s malformed tagset directive in %s", file);
281                 fclose(f);
282                 return 0;
283             }
284             if (!(res->tagset = data1_read_tagset(name)))
285             {
286                 logf(LOG_WARN, "Tagset failed in %s", file);
287                 fclose(f);
288                 return 0;
289             }
290         }
291         else if (!strcmp(cmd, "varset"))
292         {
293             char name[512];
294
295             if (!sscanf(args, "%s", name))
296             {
297                 logf(LOG_WARN, "%s malformed varset directive in %s", file);
298                 fclose(f);
299                 return 0;
300             }
301             if (!(res->varset = data1_read_varset(name)))
302             {
303                 logf(LOG_WARN, "Varset failed in %s", file);
304                 fclose(f);
305                 return 0;
306             }
307         }
308         else if (!strcmp(cmd, "esetname"))
309         {
310             char name[512], fname[512];
311
312             if (sscanf(args, "%s %s", name, fname) != 2)
313             {
314                 logf(LOG_WARN, "%s: Two arg's required for esetname directive");
315                 fclose(f);
316                 return 0;
317             }
318             *esetpp = xmalloc(sizeof(**esetpp));
319             (*esetpp)->name = xmalloc(strlen(name)+1);
320             strcpy((*esetpp)->name, name);
321             if (*fname == '@')
322                 (*esetpp)->spec = 0;
323             else if (!((*esetpp)->spec = data1_read_espec1(fname, 0)))
324             {
325                 logf(LOG_WARN, "%s: Espec-1 read failed", file);
326                 fclose(f);
327                 return 0;
328             }
329             (*esetpp)->next = 0;
330             esetpp = &(*esetpp)->next;
331         }
332         else if (!strcmp(cmd, "maptab"))
333         {
334             char name[512];
335
336             if (sscanf(args, "%s", name) != 1)
337             {
338                 logf(LOG_WARN, "%s: One argument required for maptab directive",
339                     file);
340                 continue;
341             }
342             if (!(*maptabp = data1_read_maptab(name)))
343             {
344                 logf(LOG_WARN, "%s: Failed to read maptab.");
345                 continue;
346             }
347             maptabp = &(*maptabp)->next;
348         }
349         else if (!strcmp(cmd, "marc"))
350         {
351             char name[512];
352
353             if (sscanf(args, "%s", name) != 1)
354             {
355                 logf(LOG_WARN, "%s: One argument required for marc directive",
356                     file);
357                 continue;
358             }
359             if (!(*marcp = data1_read_marctab(name)))
360             {
361                 logf(LOG_WARN, "%s: Failed to read marctab.");
362                 continue;
363             }
364             marcp = &(*marcp)->next;
365         }
366         else
367         {
368             logf(LOG_WARN, "Unknown directive '%s' in %s", cmd, file);
369             fclose(f);
370             return 0;
371         }
372     }
373 }