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