ref: ce4a8027322c53b2832f221e2956c90dcd65fd1a
dir: /libxpath/dat.c/
#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; }