Moved stop word support code to separate ccl_stop_words.c and
[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.10 2007-05-01 12:22:11 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 #include <yaz/snprintf.h>
89 #include <yaz/tokenizer.h>
90 #include "cclp.h"
91
92 /** CCL Qualifier */
93 struct ccl_qualifier {
94     char *name;
95     int no_sub;
96     struct ccl_qualifier **sub;
97     struct ccl_rpn_attr *attr_list;
98     struct ccl_qualifier *next;
99 };
100
101
102 /** Definition of CCL_bibset pointer */
103 struct ccl_qualifiers {
104     struct ccl_qualifier *list;
105     struct ccl_qualifier_special *special;
106 };
107
108
109 /** CCL Qualifier special */
110 struct ccl_qualifier_special {
111     char *name;
112     const char **values;
113     struct ccl_qualifier_special *next;
114 };
115
116
117 static struct ccl_qualifier *ccl_qual_lookup(CCL_bibset b,
118                                              const char *n, size_t len)
119 {
120     struct ccl_qualifier *q;
121     for (q = b->list; q; q = q->next)
122         if (len == strlen(q->name) && !memcmp(q->name, n, len))
123             break;
124     return q;
125 }
126
127 void ccl_qual_add_special_ar(CCL_bibset bibset, const char *n,
128                              const char **values)
129 {
130     struct ccl_qualifier_special *p;
131     for (p = bibset->special; p && strcmp(p->name, n); p = p->next)
132         ;
133     if (p)
134     {
135         if (p->values)
136         {
137             int i;
138             for (i = 0; p->values[i]; i++)
139                 xfree((char *) p->values[i]);
140             xfree(p->values);
141         }
142     }
143     else
144     {
145         p = (struct ccl_qualifier_special *) xmalloc(sizeof(*p));
146         p->name = xstrdup(n);
147         p->next = bibset->special;
148         bibset->special = p;
149     }
150     p->values = values;
151 }
152
153 void ccl_qual_add_special(CCL_bibset bibset, const char *n, const char *cp)
154 {
155     size_t no = 2;
156     char **vlist = xmalloc(no * sizeof(*vlist));
157     yaz_tok_cfg_t yt = yaz_tok_cfg_create();
158     int t;
159     int i = 0;
160     
161     yaz_tok_parse_t tp = yaz_tok_parse_buf(yt, cp);
162     
163     yaz_tok_cfg_destroy(yt);
164     
165     t = yaz_tok_move(tp);
166     while (t == YAZ_TOK_STRING)
167     {
168         if (i >= no-1)
169             vlist = xrealloc(vlist, (no = no * 2) * sizeof(*vlist));
170         vlist[i++] = xstrdup(yaz_tok_parse_string(tp));
171         t = yaz_tok_move(tp); 
172     }
173     vlist[i] = 0;
174     ccl_qual_add_special_ar(bibset, n, (const char **) vlist);
175     
176     yaz_tok_parse_destroy(tp);
177 }
178
179
180 /** \brief adds specifies qualifier aliases
181     
182     \param b bibset
183     \param n qualifier name
184     \param names list of qualifier aliases
185 */
186 void ccl_qual_add_combi(CCL_bibset b, const char *n, const char **names)
187 {
188     int i;
189     struct ccl_qualifier *q;
190     for (q = b->list; q && strcmp(q->name, n); q = q->next)
191         ;
192     if (q)
193         return ;
194     q = (struct ccl_qualifier *) xmalloc(sizeof(*q));
195     q->name = xstrdup(n);
196     q->attr_list = 0;
197     q->next = b->list;
198     b->list = q;
199     
200     for (i = 0; names[i]; i++)
201         ;
202     q->no_sub = i;
203     q->sub = (struct ccl_qualifier **)
204         xmalloc(sizeof(*q->sub) * (1+q->no_sub));
205     for (i = 0; names[i]; i++)
206         q->sub[i] = ccl_qual_lookup(b, names[i], strlen(names[i]));
207 }
208
209 /** \brief adds specifies attributes for qualifier
210     
211     \param b bibset
212     \param name qualifier name
213     \param no number of attribute type+value pairs
214     \param type_ar attributes type of size no
215     \param value_ar attribute value of size no
216     \param svalue_ar attribute string values ([i] only used  if != NULL)
217     \param attsets attribute sets of size no
218 */
219
220 void ccl_qual_add_set(CCL_bibset b, const char *name, int no,
221                        int *type_ar, int *value_ar, char **svalue_ar,
222                        char **attsets)
223 {
224     struct ccl_qualifier *q;
225     struct ccl_rpn_attr **attrp;
226
227     ccl_assert(b);
228     for (q = b->list; q; q = q->next)
229         if (!strcmp(name, q->name))
230             break;
231     if (!q)
232     {
233         q = (struct ccl_qualifier *)xmalloc(sizeof(*q));
234         ccl_assert(q);
235         
236         q->next = b->list;
237         b->list = q;
238         
239         q->name = xstrdup(name);
240         q->attr_list = 0;
241
242         q->no_sub = 0;
243         q->sub = 0;
244     }
245     attrp = &q->attr_list;
246     while (*attrp)
247         attrp = &(*attrp)->next;
248     while (--no >= 0)
249     {
250         struct ccl_rpn_attr *attr;
251
252         attr = (struct ccl_rpn_attr *)xmalloc(sizeof(*attr));
253         ccl_assert(attr);
254         attr->set = *attsets++;
255         attr->type = *type_ar++;
256         if (*svalue_ar)
257         {
258             attr->kind = CCL_RPN_ATTR_STRING;
259             attr->value.str = *svalue_ar;
260         }
261         else
262         {
263             attr->kind = CCL_RPN_ATTR_NUMERIC;
264             attr->value.numeric = *value_ar;
265         }
266         svalue_ar++;
267         value_ar++;
268         *attrp = attr;
269         attrp = &attr->next;
270     }
271     *attrp = NULL;
272 }
273
274 /** \brief creates Bibset
275     \returns bibset
276  */
277 CCL_bibset ccl_qual_mk(void)
278 {
279     CCL_bibset b = (CCL_bibset)xmalloc(sizeof(*b));
280     ccl_assert(b);
281     b->list = NULL;     
282     b->special = NULL;
283     return b;
284 }
285
286 /** \brief destroys Bibset
287     \param b pointer to Bibset
288     
289     *b will be set to NULL.
290  */
291 void ccl_qual_rm(CCL_bibset *b)
292 {
293     struct ccl_qualifier *q, *q1;
294     struct ccl_qualifier_special *sp, *sp1;
295
296     if (!*b)
297         return;
298     for (q = (*b)->list; q; q = q1)
299     {
300         struct ccl_rpn_attr *attr, *attr1;
301
302         for (attr = q->attr_list; attr; attr = attr1)
303         {
304             attr1 = attr->next;
305             if (attr->set)
306                 xfree(attr->set);
307             if (attr->kind == CCL_RPN_ATTR_STRING)
308                 xfree(attr->value.str);
309             xfree(attr);
310         }
311         q1 = q->next;
312         xfree(q->name);
313         if (q->sub)
314             xfree(q->sub);
315         xfree(q);
316     }
317     for (sp = (*b)->special; sp; sp = sp1)
318     {
319         sp1 = sp->next;
320         xfree(sp->name);
321         if (sp->values)
322         {
323             int i;
324             for (i = 0; sp->values[i]; i++)
325                 xfree((char*) sp->values[i]);
326             xfree(sp->values);
327         }
328         xfree(sp);
329     }
330     xfree(*b);
331     *b = NULL;
332 }
333
334 ccl_qualifier_t ccl_qual_search(CCL_parser cclp, const char *name, 
335                                 size_t name_len, int seq)
336 {
337     struct ccl_qualifier *q = 0;
338     const char **aliases;
339     int case_sensitive = cclp->ccl_case_sensitive;
340
341     ccl_assert(cclp);
342     if (!cclp->bibset)
343         return 0;
344
345     aliases = ccl_qual_search_special(cclp->bibset, "case");
346     if (aliases)
347         case_sensitive = atoi(aliases[0]);
348
349     for (q = cclp->bibset->list; q; q = q->next)
350         if (strlen(q->name) == name_len)
351         {
352             if (case_sensitive)
353             {
354                 if (!memcmp(name, q->name, name_len))
355                     break;
356             }
357             else
358             {
359                 if (!ccl_memicmp(name, q->name, name_len))
360                     break;
361             }
362         }
363     if (q)
364     {
365         if (q->no_sub)
366         {
367             if (seq < q->no_sub)
368                 q = q->sub[seq];
369             else
370                 q = 0;
371         }
372         else if (seq)
373             q = 0;
374     }
375     return q;
376 }
377
378 struct ccl_rpn_attr *ccl_qual_get_attr(ccl_qualifier_t q)
379 {
380     return q->attr_list;
381 }
382
383 const char *ccl_qual_get_name(ccl_qualifier_t q)
384 {
385     return q->name;
386 }
387
388 const char **ccl_qual_search_special(CCL_bibset b, const char *name)
389 {
390     struct ccl_qualifier_special *q;
391     if (!b)
392         return 0;
393     for (q = b->special; q && strcmp(q->name, name); q = q->next)
394         ;
395     if (q)
396         return q->values;
397     return 0;
398 }
399
400 int ccl_search_stop(CCL_bibset bibset, const char *qname,
401                     const char *src_str, size_t src_len)
402 {
403     const char **slist = 0;
404     if (qname)
405     {
406         char qname_buf[80];
407         yaz_snprintf(qname_buf, sizeof(qname_buf)-1, "stop.%s",
408                      qname);
409         slist = ccl_qual_search_special(bibset, qname_buf);
410     }
411     if (!slist)
412         slist = ccl_qual_search_special(bibset, "stop.*");
413     if (slist)
414     {
415         int i;
416         for (i = 0; slist[i]; i++)
417             if (src_len == strlen(slist[i]) 
418                 && ccl_memicmp(slist[i], src_str, src_len) == 0)
419                 return 1;
420     }
421     return 0;
422 }
423
424 /*
425  * Local variables:
426  * c-basic-offset: 4
427  * indent-tabs-mode: nil
428  * End:
429  * vim: shiftwidth=4 tabstop=8 expandtab
430  */
431