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