shithub: xml-9atom

ref: ce4a8027322c53b2832f221e2956c90dcd65fd1a
dir: /libxpath/dat.c/

View raw version
#include <u.h>
#include <libc.h>
#include <xml.h>
#include <xpath.h>
#include "dat.h"

char *typestrings[] = {
	"root",
	"string",
	"number",
	"child",
	"attribute",
	"function",
	"descendant-or-self",
	nil
};

char*
type2str(int type)
{
	if (type >= NEND)
		return nil;
	if (type < 0)
		return nil;
	return typestrings[type];
}

Name *firstname;
Name *lastname;
Cond *firstcond;
Cond *lastcond;
Node *firstnode;
Node *lastnode;
Func *firstfunc;
Func *lastfunc;
Mbuf *firstmbuf;
Mbuf *lastmbuf;

Name*
findname(char *n)
{
	Name *nm;
	
	if (!n)
		return nil;
	
	for (nm = firstname; nm; nm = nm->next)
		if (nm->name && strcmp(nm->name, n) == 0)
			return nm;
	return nil;
}

Name*
addname(char *n)
{
	Name *nm;
	int quoted, l;
	
	quoted = 0;
	if (*n == '\'') {
		quoted = 1;
		n++;
		l = strlen(n);
		n[l-1] = 0;
	}
	
	if (!firstname) {
		firstname = mallocz(sizeof(Name), 1);
		firstname->name = strdup(n);
		firstname->quoted = quoted;
		lastname = firstname;
		return firstname;
	}
	
	nm = findname(n);
	if (nm)
		return nm;
	
	lastname->next = mallocz(sizeof(Name), 1);
	lastname = lastname->next;
	lastname->name = strdup(n);
	lastname->quoted = quoted;
	return lastname;
}

Cond*
genaddcond(void)
{
	if (!firstcond) {
		firstcond = mallocz(sizeof(Cond), 1);
		lastcond = firstcond;
		return firstcond;
	}
	
	lastcond->next = mallocz(sizeof(Cond), 1);
	lastcond = lastcond->next;
	return lastcond;
}

Cond*
addcondb(int type, Cond *A, Cond *B)
{
	Cond *c;
	c = genaddcond();
	c->type = type;
	c->a = A;
	c->b = B;
	return c;
}

Cond*
addcondi(int index)
{
	Cond *c;
	c = genaddcond();
	c->type = CTindex;
	c->index = index;
	return c;
}

Cond*
addcondattr(Name *attr, Name *value)
{
	Cond *c;
	c = genaddcond();
	c->type = CTattr;
	c->attr = attr;
	c->value = value;
	return c;
}

Cond*
addcondhasattr(Name *attr)
{
	Cond *c;
	c = genaddcond();
	c->type = CThasattr;
	c->attr = attr;
	return c;
}

Cond*
addcondcnode(int type, Node *a, Node *b)
{
	Cond *c;
	c = genaddcond();
	c->type = type;
	c->anode = a;
	c->bnode = b;
	return c;
}

static Node*
gennode(void)
{
	if (!firstnode) {
		firstnode = mallocz(sizeof(Node), 1);
		lastnode = firstnode;
		return firstnode;
	}
	lastnode->next = mallocz(sizeof(Node), 1);
	lastnode = lastnode->next;
	return lastnode;
}

Node*
addnode(Name *name, int type, Cond *cond)
{
	Node *n;
	n = gennode();
	
	if (name && name->quoted)
		type = Nstring;
	
	n->name = name;
	n->type = type;
	n->cond = cond;
	
	switch (type) {
	case Nfunction:
		n->func = findfunc(name);
		break;
	}
	return n;
}

Node*
addnoden(int number, Cond *cond)
{
	Node *n;
	n = gennode();
	
	n->type = Nnumber;
	n->number = number;
	n->cond = cond;
	return n;
}

Node*
chainnode(Node *base, Node *new)
{
	Node *o;
	o = base;
	while (base->chain)
		base = base->chain;
	base->chain = new;
	return o;
}

Func*
findfunc(Name *name)
{
	Func *f;
	for (f = firstfunc; f; f = f->next)
		if (f->name == name)
			return f;
	return nil;
}

Func*
addfunc(Name *name, void (*f)(XpResult*, Elem*))
{
	Func *func;
	
	func = findfunc(name);
	if (func)
		sysfatal("double registering function: %s", name->name);
	
	if (!firstfunc) {
		firstfunc = mallocz(sizeof(Func), 1);
		firstfunc->name = name;
		firstfunc->f = f;
		lastfunc = firstfunc;
		return firstfunc;
	}
	lastfunc->next = mallocz(sizeof(Func), 1);
	lastfunc = lastfunc->next;
	lastfunc->name = name;
	lastfunc->f = f;
	return lastfunc;
}

static void
debugprintceq(Cond *c)
{
	if (c->anode && c->bnode) {
		fprint(2, "    A: nodes\n");
		debugprintnodes(c->anode);
		fprint(2, "    B: nodes\n");
		debugprintnodes(c->bnode);
		return;
	}
}

static void
debugprintcond(Cond *c)
{
	if (!c)
		return;
	
	fprint(2, "  Cond:\n");
	
	switch (c->type) {
	case CTand:
		debugprintcond(c->a);
		fprint(2, "    AND\n");
		debugprintcond(c->b);
		break;
	case CTor:
		debugprintcond(c->a);
		fprint(2, "    OR\n");
		debugprintcond(c->b);
		break;
	case CTindex:
		fprint(2, "    Index: %d\n", c->index);
		break;
	case CTattr:
		fprint(2, "    Attr: %s == %s\n", c->attr->name, c->value->name);
		break;
	case CThasattr:
		fprint(2, "    Attr: %s\n", c->attr->name);
		break;
	case CTeq:
		debugprintceq(c);
		break;
	}
}

void
debugprintfunc(Func *f)
{
	if (!f)
		return;
	
	fprint(2, "    Func: %s %p\n", f->name->name, f->f);
}

void
debugprintnodes(Node *node)
{
	Node *n;
	
	for (n = node ? node : firstnode; n; n = n->chain) {
		fprint(2, "Node:\n");
		fprint(2, "  type: %s\n", type2str(n->type));
		switch (n->type) {
		case Nnumber:
			fprint(2, "  number: %d\n", n->number);
			break;
		default:
			fprint(2, "  name: %s\n", n->name ? n->name->name : "<root>");
			break;
		}
		debugprintcond(n->cond);
		debugprintfunc(n->func);
	}
}

static void
reset(void)
{
	Cond *c, *oc;
	Node *n, *on;
	Name *nm, *onm;
	Func *f, *of;
	Mbuf *m, *om;
	
	for (nm = firstname; nm;) {
		onm = nm->next;
		free(nm->name);
		free(nm);
		nm = onm;
	}
	firstname = lastname = nil;
	
	for (n = firstnode; n;) {
		on = n->next;
		free(n);
		n = on;
	}
	firstnode = lastnode = nil;
	
	for (c = firstcond; c;) {
		oc = c->next;
		free(c);
		c = oc;
	}
	firstcond = lastcond = nil;
	
	for (f = firstfunc; c;) {
		of = f->next;
		free(f);
		f = of;
	}
	firstfunc = lastfunc = nil;
	
	for (m = firstmbuf; m;) {
		om = m->next;
		free(m->ptr);
		free(m);
		m = om;
	}
	firstmbuf = lastmbuf = nil;
	
	initfuncs();
}

void
regmbuf(void *ptr)
{
	if (!firstmbuf) {
		firstmbuf = mallocz(sizeof(Mbuf), 1);
		firstmbuf->ptr = ptr;
		lastmbuf = firstmbuf;
		return;
	}
	lastmbuf->next = mallocz(sizeof(Mbuf), 1);
	lastmbuf = lastmbuf->next;
	lastmbuf->ptr = ptr;
}

void setinputpath(char*);
int yyparse(void);

Node*
parsexpath(char *s)
{
	reset();
	setinputpath(s);
	if (!yyparse()) /* if successful */
		return firstnode;
	werrstr("syntax error");
	return nil;
}

void
buildsinglestring(XpResult *r, char *s)
{
	r->type = Xstring;
	r->num = r->size = 1;
	r->strings = malloc(sizeof(char*));
	r->strings[0] = s;
}

void
buildsingleelem(XpResult *r, Elem *e)
{
	r->type = Xelem;
	r->num = r->size = 1;
	r->elems = malloc(sizeof(Elem*));
	r->elems[0] = e;
}

void
buildsinglenum(XpResult *r, int n)
{
	r->type = Xnum;
	r->num = r->size = 1;
	r->numbers = malloc(sizeof(int));
	r->numbers[0] = n;
}