Doxygen frindly comments. Minor simplications.
[yaz-moved-to-github.git] / src / cclqual.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 cclqual.c
46  * \brief Implements CCL qualifier utilities
47  */
48 /* CCL qualifiers
49  * Europagate, 1995
50  *
51  * $Id: cclqual.c,v 1.7 2007-04-26 22:11:32 adam Exp $
52  *
53  * Old Europagate Log:
54  *
55  * Revision 1.9  1995/05/16  09:39:27  adam
56  * LICENSE.
57  *
58  * Revision 1.8  1995/05/11  14:03:57  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.7  1995/04/17  09:31:46  adam
64  * Improved handling of qualifiers. Aliases or reserved words.
65  *
66  * Revision 1.6  1995/02/23  08:32:00  adam
67  * Changed header.
68  *
69  * Revision 1.4  1995/02/14  19:55:12  adam
70  * Header files ccl.h/cclp.h are gone! They have been merged an
71  * moved to ../include/ccl.h.
72  * Node kind(s) in ccl_rpn_node have changed names.
73  *
74  * Revision 1.3  1995/02/14  16:20:56  adam
75  * Qualifiers are read from a file now.
76  *
77  * Revision 1.2  1995/02/14  10:25:56  adam
78  * The constructions 'qualifier rel term ...' implemented.
79  *
80  * Revision 1.1  1995/02/13  15:15:07  adam
81  * Added handling of qualifiers. Not finished yet.
82  *
83  */
84
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <string.h>
88
89 #include "cclp.h"
90
91 /** CCL Qualifier */
92 struct ccl_qualifier {
93     char *name;
94     int no_sub;
95     struct ccl_qualifier **sub;
96     struct ccl_rpn_attr *attr_list;
97     struct ccl_qualifier *next;
98 };
99
100
101 /** Definition of CCL_bibset pointer */
102 struct ccl_qualifiers {
103     struct ccl_qualifier *list;
104     struct ccl_qualifier_special *special;
105 };
106
107
108 /** CCL Qualifier special */
109 struct ccl_qualifier_special {
110     char *name;
111     char *value;
112     struct ccl_qualifier_special *next;
113 };
114
115
116 static struct ccl_qualifier *ccl_qual_lookup(CCL_bibset b,
117                                              const char *n, size_t len)
118 {
119     struct ccl_qualifier *q;
120     for (q = b->list; q; q = q->next)
121         if (len == strlen(q->name) && !memcmp(q->name, n, len))
122             break;
123     return q;
124 }
125
126 /** \brief specifies special qualifier
127     \param bibset Bibset
128     \param n name of special (without leading @)
129     \param v value of special
130 */
131 void ccl_qual_add_special(CCL_bibset bibset, const char *n, const char *v)
132 {
133     struct ccl_qualifier_special *p;
134     const char *pe;
135
136     for (p = bibset->special; p && strcmp(p->name, n); p = p->next)
137         ;
138     if (p)
139         xfree(p->value);
140     else
141     {
142         p = (struct ccl_qualifier_special *) xmalloc(sizeof(*p));
143         p->name = xstrdup(n);
144         p->value = 0;
145         p->next = bibset->special;
146         bibset->special = p;
147     }
148     while (strchr(" \t", *v))
149         ++v;
150     for (pe = v + strlen(v); pe != v; --pe)
151         if (!strchr(" \n\r\t", pe[-1]))
152             break;
153     p->value = (char*) xmalloc(pe - v + 1);
154     if (pe - v)
155         memcpy(p->value, v, pe - v);
156     p->value[pe - v] = '\0';
157 }
158
159 static int next_token(const char **cpp, const char **dst)
160 {
161     int len = 0;
162     const char *cp = *cpp;
163     while (*cp && strchr(" \r\n\t\f", *cp))
164         cp++;
165     if (dst)
166         *dst = cp;
167     len = 0;
168     while (*cp && !strchr(" \r\n\t\f", *cp))
169     {
170         cp++;
171         len++;
172     }
173     *cpp = cp;
174     return len;
175 }
176
177 /** \brief adds specifies qualifier aliases
178     
179     \param b bibset
180     \param n qualifier name
181     \param names list of qualifier aliases
182 */
183 void ccl_qual_add_combi(CCL_bibset b, const char *n, const char *names)
184 {
185     const char *cp, *cp1;
186     int i, len;
187     struct ccl_qualifier *q;
188     for (q = b->list; q && strcmp(q->name, n); q = q->next)
189         ;
190     if (q)
191         return ;
192     q = (struct ccl_qualifier *) xmalloc(sizeof(*q));
193     q->name = xstrdup(n);
194     q->attr_list = 0;
195     q->next = b->list;
196     b->list = q;
197     
198     cp = names;
199     for (i = 0; next_token(&cp, 0); i++)
200         ;
201     q->no_sub = i;
202     q->sub = (struct ccl_qualifier **) xmalloc(sizeof(*q->sub) *
203                                               (1+q->no_sub));
204     cp = names;
205     for (i = 0; (len = next_token(&cp, &cp1)); i++)
206     {
207         q->sub[i] = ccl_qual_lookup(b, cp1, len);
208     }
209 }
210
211 /** \brief adds specifies attributes for qualifier
212     
213     \param b bibset
214     \param name qualifier name
215     \param no number of attribute type+value pairs
216     \param type_ar attributes type of size no
217     \param value_ar attribute value of size no
218     \param svalue_ar attribute string values ([i] only used  if != NULL)
219     \param attsets attribute sets of size no
220 */
221
222 void ccl_qual_add_set(CCL_bibset b, const char *name, int no,
223                        int *type_ar, int *value_ar, char **svalue_ar,
224                        char **attsets)
225 {
226     struct ccl_qualifier *q;
227     struct ccl_rpn_attr **attrp;
228
229     ccl_assert(b);
230     for (q = b->list; q; q = q->next)
231         if (!strcmp(name, q->name))
232             break;
233     if (!q)
234     {
235         q = (struct ccl_qualifier *)xmalloc(sizeof(*q));
236         ccl_assert(q);
237         
238         q->next = b->list;
239         b->list = q;
240         
241         q->name = xstrdup(name);
242         q->attr_list = 0;
243
244         q->no_sub = 0;
245         q->sub = 0;
246     }
247     attrp = &q->attr_list;
248     while (*attrp)
249         attrp = &(*attrp)->next;
250     while (--no >= 0)
251     {
252         struct ccl_rpn_attr *attr;
253
254         attr = (struct ccl_rpn_attr *)xmalloc(sizeof(*attr));
255         ccl_assert(attr);
256         attr->set = *attsets++;
257         attr->type = *type_ar++;
258         if (*svalue_ar)
259         {
260             attr->kind = CCL_RPN_ATTR_STRING;
261             attr->value.str = *svalue_ar;
262         }
263         else
264         {
265             attr->kind = CCL_RPN_ATTR_NUMERIC;
266             attr->value.numeric = *value_ar;
267         }
268         svalue_ar++;
269         value_ar++;
270         *attrp = attr;
271         attrp = &attr->next;
272     }
273     *attrp = NULL;
274 }
275
276 /** \brief creates Bibset
277     \returns bibset
278  */
279 CCL_bibset ccl_qual_mk(void)
280 {
281     CCL_bibset b = (CCL_bibset)xmalloc(sizeof(*b));
282     ccl_assert(b);
283     b->list = NULL;     
284     b->special = NULL;
285     return b;
286 }
287
288 /** \brief destroys Bibset
289     \param b pointer to Bibset
290     
291     *b will be set to NULL.
292  */
293 void ccl_qual_rm(CCL_bibset *b)
294 {
295     struct ccl_qualifier *q, *q1;
296     struct ccl_qualifier_special *sp, *sp1;
297
298     if (!*b)
299         return;
300     for (q = (*b)->list; q; q = q1)
301     {
302         struct ccl_rpn_attr *attr, *attr1;
303
304         for (attr = q->attr_list; attr; attr = attr1)
305         {
306             attr1 = attr->next;
307             if (attr->set)
308                 xfree(attr->set);
309             if (attr->kind == CCL_RPN_ATTR_STRING)
310                 xfree(attr->value.str);
311             xfree(attr);
312         }
313         q1 = q->next;
314         xfree(q->name);
315         if (q->sub)
316             xfree(q->sub);
317         xfree(q);
318     }
319     for (sp = (*b)->special; sp; sp = sp1)
320     {
321         sp1 = sp->next;
322         xfree(sp->name);
323         xfree(sp->value);
324         xfree(sp);
325     }
326     xfree(*b);
327     *b = NULL;
328 }
329
330 /** \brief searches for qualifier attributes
331     \param cclp CCL parser
332     \param name qualifier name to for search (length given by len)
333     \param len length of name
334     \param seq attribute index (0=first, 1=second, ..)
335     \returns attribute or NULL if none is found
336 */
337 struct ccl_rpn_attr *ccl_qual_search(CCL_parser cclp, const char *name, 
338                                      size_t len, int seq)
339 {
340     struct ccl_qualifier *q;
341     const char *aliases;
342     int case_sensitive = cclp->ccl_case_sensitive;
343
344     ccl_assert(cclp);
345     if (!cclp->bibset)
346         return NULL;
347
348     aliases = ccl_qual_search_special(cclp->bibset, "case");
349     if (aliases)
350         case_sensitive = atoi(aliases);
351
352     for (q = cclp->bibset->list; q; q = q->next)
353         if (strlen(q->name) == len)
354         {
355             if (case_sensitive)
356             {
357                 if (!memcmp(name, q->name, len))
358                     break;
359             }
360             else
361             {
362                 if (!ccl_memicmp(name, q->name, len))
363                     break;
364             }
365         }
366     if (q)
367     {
368         if (q->attr_list && seq == 0)
369             return q->attr_list;
370         if (seq < q->no_sub && q->sub[seq])
371         {
372             return q->sub[seq]->attr_list;
373         }
374     }
375     return 0;
376 }
377
378 const char *ccl_qual_search_special(CCL_bibset b, const char *name)
379 {
380     struct ccl_qualifier_special *q;
381     if (!b)
382         return 0;
383     for (q = b->special; q && strcmp(q->name, name); q = q->next)
384         ;
385     if (q)
386         return q->value;
387     return 0;
388 }
389 /*
390  * Local variables:
391  * c-basic-offset: 4
392  * indent-tabs-mode: nil
393  * End:
394  * vim: shiftwidth=4 tabstop=8 expandtab
395  */
396