Use oid_class rather than int for OID class.
[yaz-moved-to-github.git] / src / cclqfile.c
1 /*
2  * Copyright (c) 1995, the EUROPAGATE consortium (see below).
3  *
4  * The EUROPAGATE consortium members are:
5  *
6  *    University College Dublin
7  *    Danmarks Teknologiske Videnscenter
8  *    An Chomhairle Leabharlanna
9  *    Consejo Superior de Investigaciones Cientificas
10  *
11  * Permission to use, copy, modify, distribute, and sell this software and
12  * its documentation, in whole or in part, for any purpose, is hereby granted,
13  * provided that:
14  *
15  * 1. This copyright and permission notice appear in all copies of the
16  * software and its documentation. Notices of copyright or attribution
17  * which appear at the beginning of any file must remain unchanged.
18  *
19  * 2. The names of EUROPAGATE or the project partners may not be used to
20  * endorse or promote products derived from this software without specific
21  * prior written permission.
22  *
23  * 3. Users of this software (implementors and gateway operators) agree to
24  * inform the EUROPAGATE consortium of their use of the software. This
25  * information will be used to evaluate the EUROPAGATE project and the
26  * software, and to plan further developments. The consortium may use
27  * the information in later publications.
28  * 
29  * 4. Users of this software agree to make their best efforts, when
30  * documenting their use of the software, to acknowledge the EUROPAGATE
31  * consortium, and the role played by the software in their work.
32  *
33  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
34  * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
35  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
36  * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE
37  * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
38  * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
39  * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND
40  * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
41  * USE OR PERFORMANCE OF THIS SOFTWARE.
42  *
43  */
44 /** 
45  * \file cclqfile.c
46  * \brief Implements parsing of CCL qualifier specs in files
47  */
48 /* CCL qualifiers
49  * Europagate, 1995
50  *
51  * $Id: cclqfile.c,v 1.11 2007-04-30 19:55:40 adam Exp $
52  *
53  * Old Europagate Log:
54  *
55  * Revision 1.3  1995/05/16  09:39:26  adam
56  * LICENSE.
57  *
58  * Revision 1.2  1995/05/11  14:03:56  adam
59  * Changes in the reading of qualifier(s). New function: ccl_qual_fitem.
60  * New variable ccl_case_sensitive, which controls whether reserved
61  * words and field names are case sensitive or not.
62  *
63  * Revision 1.1  1995/04/17  09:31:45  adam
64  * Improved handling of qualifiers. Aliases or reserved words.
65  *
66  */
67
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71
72 #include <yaz/tokenizer.h>
73 #include <yaz/ccl.h>
74 #include <yaz/log.h>
75
76 #define MAX_QUAL 128
77
78 int ccl_qual_field2(CCL_bibset bibset, const char *cp, const char *qual_name,
79                     const char **addinfo)
80 {
81     yaz_tok_cfg_t yt = yaz_tok_cfg_create();
82
83     int type_ar[MAX_QUAL];
84     int value_ar[MAX_QUAL];
85     char *svalue_ar[MAX_QUAL];
86     char *attsets[MAX_QUAL];
87     int pair_no = 0;
88     char *type_str = 0;
89     int t;
90     yaz_tok_parse_t tp;
91
92     yaz_tok_cfg_single_tokens(yt, ",=");
93
94     tp = yaz_tok_parse_buf(yt, cp);
95
96     yaz_tok_cfg_destroy(yt);
97     *addinfo = 0;
98     
99     t = yaz_tok_move(tp);
100     while (t == YAZ_TOK_STRING)
101     {
102         /* we don't know what lead is yet */
103         char *lead_str = xstrdup(yaz_tok_parse_string(tp));
104         const char *value_str = 0;
105         int type = 0, value = 0; /* indicates attribute value UNSET  */
106
107         t = yaz_tok_move(tp);
108         if (t == ',')
109         {
110             /* full attribute spec: set, type = value */
111             /* lead is attribute set */
112             attsets[pair_no] = lead_str;
113             t = yaz_tok_move(tp);
114             if (t != YAZ_TOK_STRING)
115             {
116                 *addinfo = "token expected";
117                 goto out;
118             }
119             xfree(type_str);
120             type_str = xstrdup(yaz_tok_parse_string(tp));
121             if (yaz_tok_move(tp) != '=')
122             {
123                 *addinfo = "= expected";
124                 goto out;
125             }
126         }
127         else if (t == '=')
128         {
129             /* lead is attribute type */
130             /* attribute set omitted: type = value */
131             attsets[pair_no] = 0;
132             xfree(type_str);
133             type_str = lead_str;
134         }
135         else
136         {
137             /* lead is first of a list of qualifier aliaeses */
138             /* qualifier alias: q1 q2 ... */
139             char *qlist[10];
140             int i = 0;
141
142             qlist[i++] = lead_str;
143
144             while ((t=yaz_tok_move(tp)) == YAZ_TOK_STRING)
145             {
146                 if (i < sizeof(qlist)/sizeof(*qlist)-1)
147                     qlist[i++] = xstrdup(yaz_tok_parse_string(tp));
148             }
149             qlist[i] = 0;
150             yaz_tok_parse_destroy(tp);
151             ccl_qual_add_combi (bibset, qual_name, (const char **) qlist);
152             for (i = 0; qlist[i]; i++)
153                 xfree(qlist[i]);
154             return 0;
155         }
156         while (1) /* comma separated attribute value list */
157         {
158             t = yaz_tok_move(tp);
159             /* must have a value now */
160             if (t != YAZ_TOK_STRING)
161             {
162                 *addinfo = "value token expected";
163                 goto out;
164             }
165             value_str = yaz_tok_parse_string(tp);
166             
167             if (sscanf(type_str, "%d", &type) == 1)
168                 ;
169             else if (strlen(type_str) != 1)
170             {
171                 *addinfo = "bad attribute type";
172                 goto out;
173             }
174             else
175             {
176                 switch (*type_str)
177                 {
178                 case 'u':
179                 case 'U':
180                     type = CCL_BIB1_USE;
181                     break;
182                 case 'r':
183                 case 'R':
184                     type = CCL_BIB1_REL;
185                     if (!ccl_stricmp (value_str, "o"))
186                         value = CCL_BIB1_REL_ORDER;
187                     else if (!ccl_stricmp (value_str, "r"))
188                         value = CCL_BIB1_REL_PORDER;
189                     break;                
190                 case 'p':
191                 case 'P':
192                     type = CCL_BIB1_POS;
193                     break;
194                 case 's':
195                 case 'S':
196                     type = CCL_BIB1_STR;
197                     if (!ccl_stricmp (value_str, "pw"))
198                         value = CCL_BIB1_STR_WP;
199                     if (!ccl_stricmp (value_str, "al"))
200                         value = CCL_BIB1_STR_AND_LIST;
201                     if (!ccl_stricmp (value_str, "ol"))
202                         value = CCL_BIB1_STR_OR_LIST;
203                     break;                
204                 case 't':
205                 case 'T':
206                     type = CCL_BIB1_TRU;
207                     if (!ccl_stricmp (value_str, "l"))
208                         value = CCL_BIB1_TRU_CAN_LEFT;
209                     else if (!ccl_stricmp (value_str, "r"))
210                         value = CCL_BIB1_TRU_CAN_RIGHT;
211                     else if (!ccl_stricmp (value_str, "b"))
212                         value = CCL_BIB1_TRU_CAN_BOTH;
213                     else if (!ccl_stricmp (value_str, "n"))
214                         value = CCL_BIB1_TRU_CAN_NONE;
215                     break;                
216                 case 'c':
217                 case 'C':
218                     type = CCL_BIB1_COM;
219                     break;
220                 }
221             }
222             if (type == 0)
223             {
224                 /* type was not set in switch above */
225                 *addinfo = "bad attribute type";
226                 goto out;
227             }
228             type_ar[pair_no] = type;
229             if (value)
230             {
231                 value_ar[pair_no] = value;
232                 svalue_ar[pair_no] = 0;
233             }
234             else if (*value_str >= '0' && *value_str <= '9')
235             {
236                 value_ar[pair_no] = atoi (value_str);
237                 svalue_ar[pair_no] = 0;
238             }
239             else
240             {
241                 value_ar[pair_no] = 0;
242                 svalue_ar[pair_no] = xstrdup(value_str);
243             }
244             pair_no++;
245             if (pair_no == MAX_QUAL)
246             {
247                 *addinfo = "too many attribute values";
248                 goto out;
249             }
250             t = yaz_tok_move(tp);
251             if (t != ',')
252                 break;
253             attsets[pair_no] = attsets[pair_no-1];
254         }
255     }
256  out:
257     xfree(type_str);
258     type_str = 0;
259
260     yaz_tok_parse_destroy(tp);
261
262     if (*addinfo)
263     {
264         int i;
265         for (i = 0; i<pair_no; i++)
266         {
267             xfree(attsets[i]);
268             xfree(svalue_ar[i]);
269         }
270         return -1;
271     }
272     ccl_qual_add_set(bibset, qual_name, pair_no, type_ar, value_ar, svalue_ar,
273                      attsets);
274     return 0;
275 }
276
277 void ccl_qual_field(CCL_bibset bibset, const char *cp, const char *qual_name)
278 {
279     const char *addinfo;
280     ccl_qual_field2(bibset, cp, qual_name, &addinfo);
281     if (addinfo)
282         yaz_log(YLOG_WARN, "ccl_qual_field2 fail: %s", addinfo);
283 }
284
285 void ccl_qual_fitem (CCL_bibset bibset, const char *cp, const char *qual_name)
286 {
287     if (*qual_name == '@')
288         ccl_qual_add_special(bibset, qual_name+1, cp);
289     else
290         ccl_qual_field(bibset, cp, qual_name);
291 }
292
293 void ccl_qual_buf(CCL_bibset bibset, const char *buf)
294 {
295     const char *cp1 = buf;
296     char line[256];
297     while (1)
298     {
299         const char *cp2 = cp1;
300         int len;
301         while (*cp2 && !strchr("\r\n", *cp2))
302             cp2++;
303         len = cp2 - cp1;
304         if (len > 0)
305         {
306             if (len >= (sizeof(line)-1))
307                 len = sizeof(line)-1;
308             memcpy(line, cp1, len);
309             line[len] = '\0';
310             ccl_qual_line(bibset, line);
311         }
312         if (!*cp2)
313             break;
314         cp1 = cp2+1;
315     }
316 }
317
318 void ccl_qual_line(CCL_bibset bibset, char *line)
319 {
320     int  no_scan = 0;
321     char qual_name[128];
322     char *cp1, *cp = line;
323     
324     if (*cp == '#')
325         return;        /* ignore lines starting with # */
326     if (sscanf (cp, "%100s%n", qual_name, &no_scan) < 1)
327         return;        /* also ignore empty lines */
328     cp += no_scan;
329     cp1 = strchr(cp, '#');
330     if (cp1)
331         *cp1 = '\0';
332     ccl_qual_fitem (bibset, cp, qual_name);
333 }
334
335 /*
336  * ccl_qual_file: Read bibset definition from file.
337  * bibset:  Bibset
338  * inf:     FILE pointer.
339  *
340  * Each line format is:
341  *  <name> <t>=<v> <t>=<v> ....
342  *  Where <name> is name of qualifier;
343  *  <t>=<v> is a attribute definition pair where <t> is one of: 
344  *     u(use), r(relation), p(position), t(truncation), c(completeness) 
345  *     or plain integer.
346  *  <v> is an integer or special pseudo-value.
347  */
348 void ccl_qual_file (CCL_bibset bibset, FILE *inf)
349 {
350     char line[256];
351
352     while (fgets (line, 255, inf))
353         ccl_qual_line(bibset, line);
354 }
355
356 int ccl_qual_fname (CCL_bibset bibset, const char *fname)
357 {
358     FILE *inf;
359     inf = fopen (fname, "r");
360     if (!inf)
361         return -1;
362     ccl_qual_file (bibset, inf);
363     fclose (inf);
364     return 0;
365 }
366 /*
367  * Local variables:
368  * c-basic-offset: 4
369  * indent-tabs-mode: nil
370  * End:
371  * vim: shiftwidth=4 tabstop=8 expandtab
372  */
373