Plan 9 from Bell Labs’s /usr/web/sources/contrib/nemo/root/sys/src/cmd/tags/query.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <bio.h>
#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);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.