+/*
+ * Copyright (c) 1995, the EUROPAGATE consortium (see below).
+ *
+ * The EUROPAGATE consortium members are:
+ *
+ * University College Dublin
+ * Danmarks Teknologiske Videnscenter
+ * An Chomhairle Leabharlanna
+ * Consejo Superior de Investigaciones Cientificas
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation, in whole or in part, for any purpose, is hereby granted,
+ * provided that:
+ *
+ * 1. This copyright and permission notice appear in all copies of the
+ * software and its documentation. Notices of copyright or attribution
+ * which appear at the beginning of any file must remain unchanged.
+ *
+ * 2. The names of EUROPAGATE or the project partners may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * 3. Users of this software (implementors and gateway operators) agree to
+ * inform the EUROPAGATE consortium of their use of the software. This
+ * information will be used to evaluate the EUROPAGATE project and the
+ * software, and to plan further developments. The consortium may use
+ * the information in later publications.
+ *
+ * 4. Users of this software agree to make their best efforts, when
+ * documenting their use of the software, to acknowledge the EUROPAGATE
+ * consortium, and the role played by the software in their work.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE
+ * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
+ * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
+ * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND
+ * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
/* CCL - lexical analysis
* Europagate, 1995
*
- * $Log: ccltoken.c,v $
- * Revision 1.2 1995-09-27 15:02:44 quinn
- * Modified function heads & prototypes.
+ * $Id: ccltoken.c,v 1.19 2002-06-06 12:54:24 adam Exp $
+ *
+ * Old Europagate Log:
+ *
+ * Revision 1.10 1995/07/11 12:28:31 adam
+ * New function: ccl_token_simple (split into simple tokens) and
+ * ccl_token_del (delete tokens).
+ *
+ * Revision 1.9 1995/05/16 09:39:28 adam
+ * LICENSE.
*
- * Revision 1.1 1995/04/10 10:28:22 quinn
- * Added copy of CCL.
+ * Revision 1.8 1995/05/11 14:03:57 adam
+ * Changes in the reading of qualifier(s). New function: ccl_qual_fitem.
+ * New variable ccl_case_sensitive, which controls whether reserved
+ * words and field names are case sensitive or not.
+ *
+ * Revision 1.7 1995/04/19 12:11:24 adam
+ * Minor change.
+ *
+ * Revision 1.6 1995/04/17 09:31:48 adam
+ * Improved handling of qualifiers. Aliases or reserved words.
*
* Revision 1.5 1995/02/23 08:32:00 adam
* Changed header.
*
*/
-#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <assert.h>
-#include <ccl.h>
+#include <yaz/ccl.h>
-static int strin (const char *s, const char *cset)
+/*
+ * token_cmp: Compare token with keyword(s)
+ * kw: Keyword list. Each keyword is separated by space.
+ * token: CCL token.
+ * return: 1 if token string matches one of the keywords in list;
+ * 0 otherwise.
+ */
+static int token_cmp (CCL_parser cclp, const char *kw, struct ccl_token *token)
{
- while (*cset)
+ const char *cp1 = kw;
+ const char *cp2;
+ const char *aliases;
+ int case_sensitive = cclp->ccl_case_sensitive;
+
+ aliases = ccl_qual_search_special(cclp->bibset, "case");
+ if (aliases)
+ case_sensitive = atoi(aliases);
+ if (!kw)
+ return 0;
+ while ((cp2 = strchr (cp1, ' ')))
{
- if (*cset++ == *s)
- return 1;
+ if (token->len == (size_t) (cp2-cp1))
+ {
+ if (case_sensitive)
+ {
+ if (!memcmp (cp1, token->name, token->len))
+ return 1;
+ }
+ else
+ {
+ if (!ccl_memicmp (cp1, token->name, token->len))
+ return 1;
+ }
+ }
+ cp1 = cp2+1;
+ }
+ if (case_sensitive)
+ return token->len == strlen(cp1)
+ && !memcmp (cp1, token->name, token->len);
+ return token->len == strlen(cp1) &&
+ !ccl_memicmp (cp1, token->name, token->len);
+}
+
+/*
+ * ccl_token_simple: tokenize CCL raw tokens
+ */
+struct ccl_token *ccl_token_simple (const char *command)
+{
+ const char *cp = command;
+ struct ccl_token *first = NULL;
+ struct ccl_token *last = NULL;
+
+ while (1)
+ {
+ while (*cp && strchr (" \t\r\n", *cp))
+ {
+ cp++;
+ continue;
+ }
+ if (!first)
+ {
+ first = last = (struct ccl_token *)xmalloc (sizeof (*first));
+ ccl_assert (first);
+ last->prev = NULL;
+ }
+ else
+ {
+ last->next = (struct ccl_token *)xmalloc (sizeof(*first));
+ ccl_assert (last->next);
+ last->next->prev = last;
+ last = last->next;
+ }
+ last->next = NULL;
+ last->name = cp;
+ last->len = 1;
+ switch (*cp++)
+ {
+ case '\0':
+ last->kind = CCL_TOK_EOL;
+ return first;
+ case '\"':
+ last->kind = CCL_TOK_TERM;
+ last->name = cp;
+ last->len = 0;
+ while (*cp && *cp != '\"')
+ {
+ cp++;
+ ++ last->len;
+ }
+ if (*cp == '\"')
+ cp++;
+ break;
+ default:
+ while (*cp && !strchr (" \t\n\r", *cp))
+ {
+ cp++;
+ ++ last->len;
+ }
+ last->kind = CCL_TOK_TERM;
+ }
}
- return 0;
+ return first;
}
-const char *ccl_token_and = "and";
-const char *ccl_token_or = "or";
-const char *ccl_token_not = "not";
-const char *ccl_token_set = "set";
-struct ccl_token MDF *ccl_tokenize (const char *command)
+/*
+ * ccl_tokenize: tokenize CCL command string.
+ * return: CCL token list.
+ */
+struct ccl_token *ccl_parser_tokenize (CCL_parser cclp, const char *command)
{
+ const char *aliases;
const char *cp = command;
struct ccl_token *first = NULL;
struct ccl_token *last = NULL;
while (1)
{
- while (*cp && strin (cp, " \t\r\n"))
+ while (*cp && strchr (" \t\r\n", *cp))
{
cp++;
continue;
}
if (!first)
{
- first = last = malloc (sizeof (*first));
- assert (first);
+ first = last = (struct ccl_token *)xmalloc (sizeof (*first));
+ ccl_assert (first);
last->prev = NULL;
}
else
{
- last->next = malloc (sizeof(*first));
- assert (last->next);
+ last->next = (struct ccl_token *)xmalloc (sizeof(*first));
+ ccl_assert (last->next);
last->next->prev = last;
last = last->next;
}
else
last->kind = CCL_TOK_REL;
break;
- case '-':
- last->kind = CCL_TOK_MINUS;
- break;
case '\"':
last->kind = CCL_TOK_TERM;
last->name = cp;
cp++;
break;
default:
- while (*cp && !strin (cp, "(),%!><=- \t\n\r"))
+ if (!strchr ("(),%!><=- \t\n\r", cp[-1]))
{
- cp++;
- ++ last->len;
+ while (*cp && !strchr ("(),%!><=- \t\n\r", *cp))
+ {
+ cp++;
+ ++ last->len;
+ }
}
- if (strlen (ccl_token_and)==last->len &&
- !memcmp (ccl_token_and, last->name, last->len))
- last->kind = CCL_TOK_AND;
- else if (strlen (ccl_token_or)==last->len &&
- !memcmp (ccl_token_or, last->name, last->len))
- last->kind = CCL_TOK_OR;
- else if (strlen (ccl_token_not)==last->len &&
- !memcmp (ccl_token_not, last->name, last->len))
- last->kind = CCL_TOK_NOT;
- else if (strlen (ccl_token_set)==last->len &&
- !memcmp (ccl_token_set, last->name, last->len))
- last->kind = CCL_TOK_SET;
- else
- last->kind = CCL_TOK_TERM;
+ last->kind = CCL_TOK_TERM;
+
+ aliases = ccl_qual_search_special(cclp->bibset, "and");
+ if (!aliases)
+ aliases = cclp->ccl_token_and;
+ if (token_cmp (cclp, aliases, last))
+ last->kind = CCL_TOK_AND;
+
+ aliases = ccl_qual_search_special(cclp->bibset, "or");
+ if (!aliases)
+ aliases = cclp->ccl_token_or;
+ if (token_cmp (cclp, aliases, last))
+ last->kind = CCL_TOK_OR;
+
+ aliases = ccl_qual_search_special(cclp->bibset, "not");
+ if (!aliases)
+ aliases = cclp->ccl_token_not;
+ if (token_cmp (cclp, aliases, last))
+ last->kind = CCL_TOK_NOT;
+
+ aliases = ccl_qual_search_special(cclp->bibset, "set");
+ if (!aliases)
+ aliases = cclp->ccl_token_set;
+
+ if (token_cmp (cclp, aliases, last))
+ last->kind = CCL_TOK_SET;
}
}
return first;
}
+
+struct ccl_token *ccl_tokenize (const char *command)
+{
+ CCL_parser cclp = ccl_parser_create ();
+ struct ccl_token *list;
+
+ list = ccl_parser_tokenize (cclp, command);
+
+ ccl_parser_destroy (cclp);
+ return list;
+}
+
+/*
+ * ccl_token_del: delete CCL tokens
+ */
+void ccl_token_del (struct ccl_token *list)
+{
+ struct ccl_token *list1;
+
+ while (list)
+ {
+ list1 = list->next;
+ xfree (list);
+ list = list1;
+ }
+}
+
+char *ccl_strdup (const char *str)
+{
+ int len = strlen(str);
+ char *p = (char*) xmalloc (len+1);
+ strcpy (p, str);
+ return p;
+}
+
+CCL_parser ccl_parser_create (void)
+{
+ CCL_parser p = (CCL_parser)xmalloc (sizeof(*p));
+ if (!p)
+ return p;
+ p->look_token = NULL;
+ p->error_code = 0;
+ p->error_pos = NULL;
+ p->bibset = NULL;
+
+ p->ccl_token_and = ccl_strdup("and");
+ p->ccl_token_or = ccl_strdup("or");
+ p->ccl_token_not = ccl_strdup("not andnot");
+ p->ccl_token_set = ccl_strdup("set");
+ p->ccl_case_sensitive = 1;
+
+ return p;
+}
+
+void ccl_parser_destroy (CCL_parser p)
+{
+ if (!p)
+ return;
+ xfree (p->ccl_token_and);
+ xfree (p->ccl_token_or);
+ xfree (p->ccl_token_not);
+ xfree (p->ccl_token_set);
+ xfree (p);
+}
+
+void ccl_parser_set_op_and (CCL_parser p, const char *op)
+{
+ if (p && op)
+ {
+ if (p->ccl_token_and)
+ xfree (p->ccl_token_and);
+ p->ccl_token_and = ccl_strdup (op);
+ }
+}
+
+void ccl_parser_set_op_or (CCL_parser p, const char *op)
+{
+ if (p && op)
+ {
+ if (p->ccl_token_or)
+ xfree (p->ccl_token_or);
+ p->ccl_token_or = ccl_strdup (op);
+ }
+}
+void ccl_parser_set_op_not (CCL_parser p, const char *op)
+{
+ if (p && op)
+ {
+ if (p->ccl_token_not)
+ xfree (p->ccl_token_not);
+ p->ccl_token_not = ccl_strdup (op);
+ }
+}
+void ccl_parser_set_op_set (CCL_parser p, const char *op)
+{
+ if (p && op)
+ {
+ if (p->ccl_token_set)
+ xfree (p->ccl_token_set);
+ p->ccl_token_set = ccl_strdup (op);
+ }
+}
+
+void ccl_parser_set_case (CCL_parser p, int case_sensitivity_flag)
+{
+ if (p)
+ p->ccl_case_sensitive = case_sensitivity_flag;
+}