shithub: aplenty

ref: 666191d45413d79a7a462998ebfd300e12af6f13
dir: /aplenty.c/

View raw version
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include <bio.h>
#include <json.h>
#include <regexp.h>

QLock lwin;
char *rdir;
vlong caddr;
int debug;

void
hevride(int in, int ev, int out, int addr){
	Biobuf *bev;
	char *b, s[32], k;   /* event buffer, kind */
	long t, n, o; /*       type, length, offset */

	bev = Bfdopen(ev, OREAD);
	while(b = Brdline(bev, '\n')){
		Bseek(bev, Blinelen(bev), 1);
		k = b[0]; b++;
		t = atol(strtok(b, " \n"));
		n = atol(strtok(nil, " \n"));
		o = atol(b = strtok(nil, " \n"));
		for(; *b != '\0'; b++); b++;
		if(debug)
			fprintf(stderr, "ride: %c %ld %ld %ld\n", k, t, n, o);

		qlock(&lwin);

		if(k == 'p'){
			fprint(addr, "#%lld,$", caddr);
			write(out, b, n);
		}

		if(k == 'o'){
			b = malloc(n);
			pread(in, b, n, o);
			if(t == 14)
				fprint(addr, "#%lld,$", caddr);
			else
				fprint(addr, "$");
			write(out, b, n);
			free(b);
		}

		write(addr, "$-/^/", 5);
		pread(addr, s, 12, 0);
		caddr = atol(strtok(s, " "));

		qunlock(&lwin);
	}
}

void
hevroot(int wid, int in, int out){
	Biobuf *bin, *bxdata, *btag;
	int fdctl, fdevent, fdaddr, fdbody;
	char o, t;        /* event origin, type */
	long n, m, f, l;  /*       addr n, addr m, flag, len */
	Rune *r;          /*       runes */
	long c;
	char *ln, s[256];
	int i;

	/* setup files */
	snprintf(s, sizeof(s), "/mnt/acme/%i", wid);
	chdir(s);
	fdctl   = open("ctl", OWRITE);
	fdevent = open("event", OWRITE);
	fdaddr  = open("addr", ORDWR);
	fdbody  = open("body", OWRITE);
	bin     = Bfdopen(in, OREAD);
	rerrstr(s, sizeof(s));
	if(s[0] != 0)
		exits(s);

	/* initial prompt not setup by ride */
	fprint(fdctl, "name %s/-aplenty\n", rdir);
	fprint(fdbody, "      ");
	caddr = 0;

	/* event handle loop: cf acme(4):/event */
	r = malloc((2+4*12 + 256)*sizeof(*r));
	while((o = Bgetc(bin)) != EOF){
		t = Bgetc(bin);
		n = atol(Brdline(bin, ' '));
		m = atol(Brdline(bin, ' '));
		f = atol(Brdline(bin, ' '));
		l = atol(Brdline(bin, ' '));
		for(i = 0; i < l+1; i++) /* trailing LF not counted by l */
			Bgetrune(bin);
		if(debug)
			fprintf(stderr, "acme: %c%c%ld %ld %ld %ld\n", o, t, n , m, f, l);

		qlock(&lwin);

		/* trailing event text may be elided; read canonical source */
		if(!strchr("Dd", t)){
			if(strchr("ILX", t)){
				fprint(fdaddr, "#%ld,#%ld", n, m);
				bxdata = Bopen("xdata", OREAD);
				for(i = 0, c = Bgetrune(bxdata); c >= 0; i++, c = Bgetrune(bxdata))
					r[i] = c;
				Bterm(bxdata);
			} else if(strchr("ilx", t)) {
				btag = Bopen("tag", OREAD);
				for(i = 0, c = Bgetrune(btag); c >= 0; i++, c = Bgetrune(btag))
					r[i] = c;
				Bterm(btag);
			}
		}

		/* Ride-triggered edits */
		if(strchr("EF", o))
			goto end;

		/* XXX: Only execute first line if multiline input */
		if(t == 'I' && n >= caddr || t == 'X'){
			fprint(fdaddr, "#%lld,#%ld", caddr, m);
			bxdata  = Bopen("xdata", OREAD);
			ln = Brdline(bxdata, '\n');
			if(ln)
				write(out, ln, Blinelen(bxdata));
			Bterm(bxdata);
		}

		if(strchr("ID", t))
		if((t == 'D') + m < caddr)
			caddr += t == 'D' ? n-m : m-n;

		if(f%2 == 0 && strchr("Lidlx", t))
			fprint(fdevent, "%c%c%ld %ld\n", o, t, n, m);

		end:
		qunlock(&lwin);
	}
}

char*
errmsg(char *err){
	if(err == nil){
		err = malloc(ERRMAX);
		rerrstr(err, ERRMAX);
	}
	fprintf(stderr, "%s\n", err);
	return err;
}

void
usage(void){
	fprintf(stderr, "Usage: %s [-d] addr\n", argv0);
}

void
main(int argc, char **argv){
	char *err, *addr, b[256], p[256];
	int rid, rctl, rin, rout, revent; /* ride */
	int wid, wctl, win, wout, waddr; /* root window */

	ARGBEGIN{
	case 'd': debug++; break;
	case 'h': usage(); exits(nil);
	}ARGEND

	if(argc == 0)
		addr = getenv("rideaddr");
	else
		addr = argv[0];
	if(addr == nil){
		usage();
		exits(errmsg("no ride address"));
	}

	err = nil;

	/* new ride connection */
	if((rctl = open("/mnt/ride/clone", ORDWR)) < 0)
		exits(errmsg(err));
	sprintf(b, "connect %s\n", addr);
	write(rctl, b, strlen(b));
	pread(rctl, b, sizeof(b), 0);
	sprintf(p, "\n");
	rid = atoi(strtok(b, p));
	rdir = smprint("/mnt/ride/%d", rid);

	/* new acme window */
	if((wctl = open("/mnt/acme/new/ctl", OREAD)) < 0)
		exits(errmsg(err));
	readn(wctl, b, 12);
	wid = atoi(strtok(b, " "));

	JSONfmtinstall();
	rfork(RFNOTEG);

	switch(rfork(RFPROC|RFMEM)){
	case -1: err = "unable to start ride message handler"; break;
	case 0:
		snprintf(p, sizeof(p), "/mnt/ride/%i/text", rid);
		rin = open(p, OREAD); /* establishes connection */
		snprintf(p, sizeof(p), "/mnt/ride/%i/event", rid);
		revent = open(p, OREAD);
		snprintf(p, sizeof(p), "/mnt/acme/%i/data", wid);
		wout = open(p, OWRITE);
		snprintf(p, sizeof(p), "/mnt/acme/%i/addr", wid);
		waddr = open(p, ORDWR);
	
		hevride(rin, revent, wout, waddr);
		exits(nil);
	default: break;
	}

	switch(rfork(RFPROC|RFMEM)){
	case -1: err = "unable to start root window event handler"; break;
	case 0:
		snprintf(p, sizeof(p), "/mnt/acme/%i/event", wid);
		win = open(p, OREAD);
		snprintf(p, sizeof(p), "/mnt/ride/%i/text", rid);
		rout = open(p, OWRITE);

		hevroot(wid, win, rout);
		exits(nil);
	default: break;
	}

	wait();
	postnote(PNGROUP, getpid(), "exit");

	exits(errmsg(err));
}