/* $Id: xpath.c,v 1.3 2003/03/01 22:45:38 adam Exp $
Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003
Index Data Aps
This file is part of the Zebra server.
Zebra is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with Zebra; see the file LICENSE.zebra. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <yaz/nmem.h>
#include <zebra_xpath.h>
static char *get_xp_part (char **strs, NMEM mem, int *literal)
{
char *cp = *strs;
char *str = 0;
char *res = 0;
*literal = 0;
while (*cp == ' ')
cp++;
str = cp;
if (strchr("()", *cp))
cp++;
else if (strchr("><=", *cp))
{
while (strchr("><=", *cp))
cp++;
}
else if (*cp == '"' || *cp == '\'')
{
int sep = *cp;
str++;
cp++;
while (*cp && *cp != sep)
cp++;
res = nmem_malloc(mem, cp - str + 1);
if ((cp - str))
memcpy (res, str, (cp-str));
res[cp-str] = '\0';
if (*cp)
cp++;
*literal = 1;
}
else
{
while (*cp && !strchr("><=()]\" ", *cp))
cp++;
}
if (!res)
{
res = nmem_malloc(mem, cp - str + 1);
if ((cp - str))
memcpy (res, str, (cp-str));
res[cp-str] = '\0';
}
*strs = cp;
return res;
}
static struct xpath_predicate *get_xpath_boolean(char **pr, NMEM mem,
char **look, int *literal);
static struct xpath_predicate *get_xpath_relation(char **pr, NMEM mem,
char **look, int *literal)
{
struct xpath_predicate *res = 0;
if (!*literal && !strcmp(*look, "("))
{
*look = get_xp_part(pr, mem, literal);
res = get_xpath_boolean(pr, mem, look, literal);
if (!strcmp(*look, ")"))
*look = get_xp_part(pr, mem, literal);
else
res = 0; /* error */
}
else
{
res=nmem_malloc(mem, sizeof(struct xpath_predicate));
res->which = XPATH_PREDICATE_RELATION;
res->u.relation.name = *look;
*look = get_xp_part(pr, mem, literal);
if (*look && !*literal && strchr("><=", **look))
{
res->u.relation.op = *look;
*look = get_xp_part(pr, mem, literal);
if (!*look)
return 0; /* error */
res->u.relation.value = *look;
*look = get_xp_part(pr, mem, literal);
}
else
{
res->u.relation.op = "";
res->u.relation.value = "";
}
}
return res;
}
static struct xpath_predicate *get_xpath_boolean(char **pr, NMEM mem,
char **look, int *literal)
{
struct xpath_predicate *left = 0;
left = get_xpath_relation(pr, mem, look, literal);
if (!left)
return 0;
while (*look && !*literal &&
(!strcmp(*look, "and") || !strcmp(*look, "or") ||
!strcmp(*look, "not")))
{
struct xpath_predicate *res, *right;
res = nmem_malloc(mem, sizeof(struct xpath_predicate));
res->which = XPATH_PREDICATE_BOOLEAN;
res->u.boolean.op = *look;
res->u.boolean.left = left;
*look = get_xp_part(pr, mem, literal); /* skip the boolean name */
right = get_xpath_relation(pr, mem, look, literal);
res->u.boolean.right = right;
left = res;
}
return left;
}
static struct xpath_predicate *get_xpath_predicate(char *predicate, NMEM mem)
{
int literal;
char **pr = &predicate;
char *look = get_xp_part(pr, mem, &literal);
if (!look)
return 0;
return get_xpath_boolean(pr, mem, &look, &literal);
}
int zebra_parse_xpath_str(const char *xpath_string,
struct xpath_location_step *xpath, int max, NMEM mem)
{
const char *cp;
char *a;
int no = 0;
if (!xpath_string || *xpath_string != '/')
return -1;
cp = xpath_string;
while (*cp && no < max)
{
int i = 0;
while (*cp && !strchr("/[",*cp))
{
i++;
cp++;
}
xpath[no].predicate = 0;
xpath[no].part = nmem_malloc (mem, i+1);
if (i)
memcpy (xpath[no].part, cp - i, i);
xpath[no].part[i] = 0;
if (*cp == '[')
{
cp++;
while (*cp == ' ')
cp++;
a = (char *)cp;
xpath[no].predicate = get_xpath_predicate(a, mem);
while(*cp && *cp != ']') {
cp++;
}
if (*cp == ']')
cp++;
} /* end of ] predicate */
no++;
if (*cp != '/')
break;
cp++;
}
/* for debugging .. */
#if 0
dump_xp_steps(xpath, no);
#endif
return no;
}
void dump_xp_predicate (struct xpath_predicate *p)
{
if (p) {
if (p->which == XPATH_PREDICATE_RELATION &&
p->u.relation.name[0]) {
fprintf (stderr, "%s,%s,%s",
p->u.relation.name,
p->u.relation.op,
p->u.relation.value);
} else {
fprintf (stderr, "(");
dump_xp_predicate(p->u.boolean.left);
fprintf (stderr, ") %s (", p->u.boolean.op);
dump_xp_predicate(p->u.boolean.right);
fprintf (stderr, ")");
}
}
}
void dump_xp_steps (struct xpath_location_step *xpath, int no)
{
int i;
for (i=0; i<no; i++) {
fprintf (stderr, "Step %d: %s ",i,xpath[i].part);
dump_xp_predicate(xpath[i].predicate);
fprintf (stderr, "\n");
}
}
syntax highlighted by Code2HTML, v. 0.9.1