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