forsyth20121205-174063a80cc13 years agoHistory
180 lines · 2.9 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h" #include <interp.h> #include "draw.h" enum{	Qdir,	Qtkevents}; staticDirtab tkdirtab[]={	{".",	{Qdir,0,QTDIR},	0,	0500},	{"tkevents",		{Qtkevents, 0},		0,	0600},}; static struct {	QLock	l;	Queue*	eq;	Ref	inuse;} tkevents; static voidtkwiretapper(void *top, char *cmd, char *result, void *image, Rectangle *rp){	Block *b;	int n;	char *s, *e; 	n = 12;	if(cmd != nil)		n += strlen(cmd)+2+1;	if(result != nil)		n += strlen(result)+2+1;	if(image != nil)		n += 12;	if(rp != nil)		n += 4*20;	n++;	b = allocb(n);	if(b != nil){		s = (char*)b->wp;		e = s+n;		s += snprint(s, e-s, "%p", top);		if(cmd != nil){			*s++ = ' ';			*s++ = '[';			n = strlen(cmd);			memmove(s, cmd, n);			s += n;			*s++ = ']';		}		/* ignore result for now */		if(image != nil)			s += snprint(s, e-s, " %p", image);		if(rp != nil)			s += snprint(s, e-s, " %d %d %d %d", rp->min.x, rp->min.y, rp->max.x, rp->max.y);		*s++ = '\n';		b->wp = (uchar*)s;		release();		qlock(&tkevents.l);		if(waserror()){			qunlock(&tkevents.l);			acquire();			return;		}		if(tkevents.eq != nil)			qbwrite(tkevents.eq, b);		poperror();		qunlock(&tkevents.l);		acquire();	}} void	(*tkwiretap)(void*, char*, char*, void*, Rectangle*); static Chan*tkattach(char* spec){	return devattach(L'τ', spec);} static Walkqid*tkwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, tkdirtab, nelem(tkdirtab), devgen);} static inttkstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, tkdirtab, nelem(tkdirtab), devgen);} static Chan*tkopen(Chan* c, int omode){	if(c->qid.type & QTDIR)		return devopen(c, omode, tkdirtab, nelem(tkdirtab), devgen);	switch((ulong)c->qid.path){	case Qtkevents:		c = devopen(c, omode, tkdirtab, nelem(tkdirtab), devgen);		qlock(&tkevents.l);		if(incref(&tkevents.inuse) != 1){			qunlock(&tkevents.l);			error(Einuse);		}		if(tkevents.eq == nil)			tkevents.eq = qopen(256*1024, 0, nil, nil);		else			qreopen(tkevents.eq);		tkwiretap = tkwiretapper;		qunlock(&tkevents.l);		break;	}	return c;} static voidtkclose(Chan* c){	if(c->qid.type & QTDIR || (c->flag & COPEN) == 0)		return;	qlock(&tkevents.l);	if(decref(&tkevents.inuse) == 0){		tkwiretap = nil;		qclose(tkevents.eq);	}	qunlock(&tkevents.l);} static longtkread(Chan* c, void* a, long n, vlong offset){	USED(offset);	switch((ulong)c->qid.path){	case Qdir:		return devdirread(c, a, n, tkdirtab, nelem(tkdirtab), devgen);	case Qtkevents:		return qread(tkevents.eq, a, n);	default:		n=0;		break;	}	return n;} static longtkwrite(Chan*, void*, long, vlong){	error(Ebadusefd);	return 0;} Dev tkdevtab = {	L'τ',	"tk", 	devreset,	devinit,	devshutdown,	tkattach,	tkwalk,	tkstat,	tkopen,	devcreate,	tkclose,	tkread,	devbread,	tkwrite,	devbwrite,	devremove,	devwstat,};