#include #include #include #include "util.h" #include "trie.h" #include "query.h" void printexpr(Texpr* e) { int i; switch(e->op){ case Ttag: print("%s", e->tag); break; case Tand: case Tor: printexpr(e->tagls[0]); for(i = 1; i < e->arity; i++){ if(e->op == Tand) print(" "); else print(" : "); printexpr(e->tagls[i]); } break; default: sysfatal("bad op"); } } void printexprval(Texpr* e) { int i; if(e->rval->nv != 0){ print("%llx", e->rval->v[0]); for(i = 1; i < e->rval->nv; i++) print(" %llx", e->rval->v[i]); print("\n"); } } char* smprintexprval(Texpr* e) { int i; static char buf[64*1024]; char* s; s = buf; *s = 0; if(e->rval->nv != 0){ s = seprint(s, buf+sizeof(buf), "%llx", e->rval->v[0]); for(i = 1; i < e->rval->nv; i++) s = seprint(s, buf+sizeof(buf), " %llx", e->rval->v[i]); seprint(s, buf+sizeof(buf), "\n"); } return estrdup(buf); } static void addtagl(Texpr* e, Texpr* tl) { assert(e->op == Tor || e->op == Tand); if((e->arity%Incr) == 0) e->tagls = erealloc(e->tagls, (e->arity+Incr)*sizeof(Texpr)); e->tagls[e->arity++] = tl; } static Texpr* parsetag(int ntoks, char* toks[], int* pos) { Texpr* e; if(*pos == ntoks) return nil; if(strcmp(toks[*pos], ":") == 0) sysfatal("tag expected"); e = emallocz(sizeof(Texpr), 1); e->op = Ttag; e->tag = estrdup(toks[*pos]); (*pos)++; return e; } static Texpr* parsetagl(int ntoks, char* toks[], int* pos) { Texpr* re; Texpr* e; if(*pos == ntoks) return nil; re = emallocz(sizeof(Texpr), 1); re->op = Tand; if(strcmp(toks[*pos], ":") == 0) sysfatal("tag expected"); do { e = parsetag(ntoks, toks, pos); addtagl(re, e); } while(*pos < ntoks && strcmp(toks[*pos],":") != 0); return re; } Texpr* parseexpr(int ntoks, char* toks[], int* pos) { Texpr* e; Texpr* re; e = parsetagl(ntoks, toks, pos); if(e == nil) return nil; if(*pos == ntoks) return e; re = emallocz(sizeof(Texpr), 1); re->op = Tor; addtagl(re, e); while(*pos < ntoks){ if(strcmp(toks[*pos], ":") != 0) sysfatal("':' expected"); (*pos)++; e = parsetagl(ntoks, toks, pos); if(e == nil) sysfatal("tag list expected"); addtagl(re, e); } return re; } static Vals* newvals(void) { Vals* vals; vals = emallocz(sizeof(*vals), 1); return vals; } static Vals* dupvals(Vals* vals) { Vals* nv; nv = newvals(); *nv = *vals; nv->v = emallocz(nv->av*sizeof(uvlong), 0); memmove(nv->v, vals->v, nv->nv*sizeof(uvlong)); return nv; } static void addvals(Vals* vals, Trie* t) { int i; free(vals->v); vals->av = t->nvals+t->nsvals+Incr; vals->nv = t->nvals+t->nsvals; vals->v = emallocz(vals->av*sizeof(uvlong), 0); if(t->nvals) memmove(vals->v, t->vals, t->nvals*sizeof(uvlong)); for(i = 0; i < t->nsvals; i++) vals->v[t->nvals+i] = (uvlong)t->svals[i]; } static void delvals(Vals* vals) { vals->nv = 0; } static void freevals(Vals* vals) { if(vals){ free(vals->v); free(vals); } } static int hasval(Vals* vals, uvlong v) { int i; for(i = 0; i < vals->nv; i++) if(vals->v[i] == v) break; return i < vals->nv; } static void addval(Vals* vals, uvlong v) { if(hasval(vals, v)) return; if(vals->nv == vals->av){ vals->av += Incr; vals->v = erealloc(vals->v, vals->av*sizeof(uvlong)); } vals->v[vals->nv++] = v; } static void delval(Vals* vals, uvlong v) { int i; int nv; nv = vals->nv; for(i = 0; i < nv; i++) if(vals->v[i] == v){ vals->v[i] = vals->v[nv-1]; vals->nv--; break; } } void evalexpr(Trie* t, Texpr* e) { int i, j; Trie* tt; Texpr* ie; for(i = 0; i < e->arity; i++) evalexpr(t, e->tagls[i]); switch(e->op){ case Ttag: e->rval = newvals(); tt = trieget(t, e->tag); if(tt != nil) addvals(e->rval, tt); break; case Tand: e->rval = dupvals(e->tagls[0]->rval); for(i = 1; i < e->arity; i++){ ie = e->tagls[i]; for(j = 0; j < e->rval->nv;) if(!hasval(ie->rval, e->rval->v[j])) delval(e->rval, e->rval->v[j]); else j++; } break; case Tor: e->rval = dupvals(e->tagls[0]->rval); for(i = 1; i < e->arity; i++){ ie = e->tagls[i]; for(j = 0; j < ie->rval->nv; j++) addval(e->rval, ie->rval->v[j]); } break; default: sysfatal("evalexpr: bad op %d", e->op); } } void freeexpr(Texpr* e) { int i; if(e == nil) return; switch(e->op){ case Ttag: free(e->tag); break; case Tand: case Tor: for(i = 1; i < e->arity; i++) freeexpr(e->tagls[i]); break; default: sysfatal("bad op"); } freevals(e->rval); free(e); }