ref: 4e09200f7e4bf8791c9c720922734e0759206b72
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", "AND", "OR", "INDEX", "EQ", "NEQ", "LT", "GT", "LE", "GE", nil }; char* type2str(int type) { if (type >= NEND) return nil; if (type < 0) return nil; return typestrings[type]; } Name *firstname; Name *lastname; Node *firstnode; Node *lastnode; Func *firstfunc; Func *lastfunc; Mbuf *firstmbuf; Mbuf *lastmbuf; Node *rootchain; 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; } 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* addcondcnode(int type, Node *a, Node *b) { Node *n; n = gennode(); n->type = type; n->anode = a; n->bnode = b; return n; } Node* addnode(Name *name, int type, Node *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, Node *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 debugindent(int level) { while (level--) fprint(2, "\t"); } static void debugprintceq(Node *c, int level) { debugindent(level); switch (c->type) { case Neq: fprint(2, " EQ\n"); break; case Nneq: fprint(2, " NEQ\n"); break; case Nlt: fprint(2, " LT\n"); break; case Ngt: fprint(2, " GT\n"); break; case Nle: fprint(2, " LE\n"); break; case Nge: fprint(2, " GE\n"); break; } if (c->anode && c->bnode) { debugindent(level); fprint(2, " A: nodes\n"); debugprintnodes(c->anode, level+1); debugindent(level); fprint(2, " B: nodes\n"); debugprintnodes(c->bnode, level+1); return; } } static void debugprintcond(Node *c, int level) { if (!c) return; debugindent(level); fprint(2, " Cond:\n"); switch (c->type) { case Nand: debugprintcond(c->anode, level+1); debugindent(level); fprint(2, " AND\n"); debugprintcond(c->bnode, level+1); break; case Nor: debugprintcond(c->anode, level+1); debugindent(level); fprint(2, " OR\n"); debugprintcond(c->bnode, level+1); break; case Nindex: debugindent(level); fprint(2, " Index: %d\n", c->number); break; case Nattribute: debugindent(level); fprint(2, " Attr: %s == %s\n", c->anode->name->name, c->bnode && c->bnode->name ? c->bnode->name->name : nil); break; case Neq: case Nneq: case Nlt: case Ngt: case Nle: case Nge: debugprintceq(c, level); break; } } void debugprintfunc(Func *f, int level) { if (!f) return; debugindent(level); fprint(2, " Func: %s %p\n", f->name->name, f->f); } void debugprintnodes(Node *node, int level) { Node *n; for (n = node ? node : rootchain; n; n = n->chain) { debugindent(level); fprint(2, "Node: %p\n", n); debugindent(level); fprint(2, " type: %s\n", type2str(n->type)); if (n->type >= Nand) { debugprintcond(n, level); continue; } switch (n->type) { case Nnumber: debugindent(level); fprint(2, " number: %d\n", n->number); break; default: debugindent(level); fprint(2, " name: %s\n", n->name ? n->name->name : "<root>"); break; } debugprintcond(n->cond, level); debugprintfunc(n->func, level); } } static void reset(void) { 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 (f = firstfunc; f;) { 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* findroot(void) { Node *n, *m; /* find unlinked node */ for (n = firstnode; n;) { for (m = firstnode; m; m = m->next) { if (n == m) { continue; } if (m->chain == n) { n = m; break; } if (m->cond == n) { n = m; break; } if (m->anode == n) { n = m; break; } if (m->bnode == n) { n = m; break; } } if (!m) { /* if no node links to n, n is root */ return n; } /* if m is valid, n == m. Proceed with new n. */ } return nil; } Node* parsexpath(char *s) { reset(); setinputpath(s); if (!yyparse()) { /* if successful */ rootchain = findroot(); return rootchain; } 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; }