⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mesg.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "sam.h"Header	h;uchar	indata[DATASIZE];uchar	outdata[2*DATASIZE+3];	/* room for overflow message */uchar	*inp;uchar	*outp;uchar	*outmsg = outdata;Posn	cmdpt;Posn	cmdptadv;Buffer	snarfbuf;int	waitack;int	noflush;int	tversion;int	inshort(void);long	inlong(void);vlong	invlong(void);int	inmesg(Tmesg);void	outshort(int);void	outlong(long);void	outvlong(vlong);void	outcopy(int, void*);void	outsend(void);void	outstart(Hmesg);void	setgenstr(File*, Posn, Posn);#ifdef DEBUGchar *hname[] = {	[Hversion]	"Hversion",	[Hbindname]	"Hbindname",	[Hcurrent]	"Hcurrent",	[Hnewname]	"Hnewname",	[Hmovname]	"Hmovname",	[Hgrow]		"Hgrow",	[Hcheck0]	"Hcheck0",	[Hcheck]	"Hcheck",	[Hunlock]	"Hunlock",	[Hdata]		"Hdata",	[Horigin]	"Horigin",	[Hunlockfile]	"Hunlockfile",	[Hsetdot]	"Hsetdot",	[Hgrowdata]	"Hgrowdata",	[Hmoveto]	"Hmoveto",	[Hclean]	"Hclean",	[Hdirty]	"Hdirty",	[Hcut]		"Hcut",	[Hsetpat]	"Hsetpat",	[Hdelname]	"Hdelname",	[Hclose]	"Hclose",	[Hsetsnarf]	"Hsetsnarf",	[Hsnarflen]	"Hsnarflen",	[Hack]		"Hack",	[Hexit]		"Hexit",	[Hplumb]		"Hplumb",};char *tname[] = {	[Tversion]	"Tversion",	[Tstartcmdfile]	"Tstartcmdfile",	[Tcheck]	"Tcheck",	[Trequest]	"Trequest",	[Torigin]	"Torigin",	[Tstartfile]	"Tstartfile",	[Tworkfile]	"Tworkfile",	[Ttype]		"Ttype",	[Tcut]		"Tcut",	[Tpaste]	"Tpaste",	[Tsnarf]	"Tsnarf",	[Tstartnewfile]	"Tstartnewfile",	[Twrite]	"Twrite",	[Tclose]	"Tclose",	[Tlook]		"Tlook",	[Tsearch]	"Tsearch",	[Tsend]		"Tsend",	[Tdclick]	"Tdclick",	[Tstartsnarf]	"Tstartsnarf",	[Tsetsnarf]	"Tsetsnarf",	[Tack]		"Tack",	[Texit]		"Texit",	[Tplumb]		"Tplumb",};voidjournal(int out, char *s){	static int fd = 0;	if(fd <= 0)		fd = create("/tmp/sam.out", 1, 0666L);	fprint(fd, "%s%s\n", out? "out: " : "in:  ", s);}voidjournaln(int out, long n){	char buf[32];	snprint(buf, sizeof(buf), "%ld", n);	journal(out, buf);}voidjournalv(int out, vlong v){	char buf[32];	sprint(buf, sizeof(buf), "%lld", v);	journal(out, buf);}#else#define	journal(a, b)#define journaln(a, b)#define journalv(a, b)#endifintrcvchar(void){	static uchar buf[64];	static i, nleft = 0;	if(nleft <= 0){		nleft = read(0, (char *)buf, sizeof buf);		if(nleft <= 0)			return -1;		i = 0;	}	--nleft;	return buf[i++];}intrcv(void){	int c;	static state = 0;	static count = 0;	static i = 0;	while((c=rcvchar()) != -1)		switch(state){		case 0:			h.type = c;			state++;			break;		case 1:			h.count0 = c;			state++;			break;		case 2:			h.count1 = c;			count = h.count0|(h.count1<<8);			i = 0;			if(count > DATASIZE)				panic("count>DATASIZE");			if(count == 0)				goto zerocount;			state++;			break;		case 3:			indata[i++] = c;			if(i == count){		zerocount:				indata[i] = 0;				state = count = 0;				return inmesg(h.type);			}			break;		}	return 0;}File *whichfile(int tag){	int i;	for(i = 0; i<file.nused; i++)		if(file.filepptr[i]->tag==tag)			return file.filepptr[i];	hiccough((char *)0);	return 0;}intinmesg(Tmesg type){	Rune buf[1025];	char cbuf[64];	int i, m;	short s;	long l, l1;	vlong v;	File *f;	Posn p0, p1, p;	Range r;	String *str;	char *c, *wdir;	Rune *rp;	Plumbmsg *pm;	if(type > TMAX)		panic("inmesg");	journal(0, tname[type]);	inp = indata;	switch(type){	case -1:		panic("rcv error");	default:		fprint(2, "unknown type %d\n", type);		panic("rcv unknown");	case Tversion:		tversion = inshort();		journaln(0, tversion);		break;	case Tstartcmdfile:		v = invlong();		/* for 64-bit pointers */		journalv(0, v);		Strdupl(&genstr, samname);		cmd = newfile();		cmd->unread = 0;		outTsv(Hbindname, cmd->tag, v);		outTs(Hcurrent, cmd->tag);		logsetname(cmd, &genstr);		cmd->rasp = listalloc('P');		cmd->mod = 0;		if(cmdstr.n){			loginsert(cmd, 0L, cmdstr.s, cmdstr.n);			Strdelete(&cmdstr, 0L, (Posn)cmdstr.n);		}		fileupdate(cmd, FALSE, TRUE);		outT0(Hunlock);		break;	case Tcheck:		/* go through whichfile to check the tag */		outTs(Hcheck, whichfile(inshort())->tag);		break;	case Trequest:		f = whichfile(inshort());		p0 = inlong();		p1 = p0+inshort();		journaln(0, p0);		journaln(0, p1-p0);		if(f->unread)			panic("Trequest: unread");		if(p1>f->nc)			p1 = f->nc;		if(p0>f->nc) /* can happen e.g. scrolling during command */			p0 = f->nc;		if(p0 == p1){			i = 0;			r.p1 = r.p2 = p0;		}else{			r = rdata(f->rasp, p0, p1-p0);			i = r.p2-r.p1;			bufread(f, r.p1, buf, i);		}		buf[i]=0;		outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1));		break;	case Torigin:		s = inshort();		l = inlong();		l1 = inlong();		journaln(0, l1);		lookorigin(whichfile(s), l, l1);		break;	case Tstartfile:		termlocked++;		f = whichfile(inshort());		if(!f->rasp)	/* this might be a duplicate message */			f->rasp = listalloc('P');		current(f);		outTsv(Hbindname, f->tag, invlong());	/* for 64-bit pointers */		outTs(Hcurrent, f->tag);		journaln(0, f->tag);		if(f->unread)			load(f);		else{			if(f->nc>0){				rgrow(f->rasp, 0L, f->nc);				outTsll(Hgrow, f->tag, 0L, f->nc);			}			outTs(Hcheck0, f->tag);			moveto(f, f->dot.r);		}		break;	case Tworkfile:		i = inshort();		f = whichfile(i);		current(f);		f->dot.r.p1 = inlong();		f->dot.r.p2 = inlong();		f->tdot = f->dot.r;		journaln(0, i);		journaln(0, f->dot.r.p1);		journaln(0, f->dot.r.p2);		break;	case Ttype:		f = whichfile(inshort());		p0 = inlong();		journaln(0, p0);		journal(0, (char*)inp);		str = tmpcstr((char*)inp);		i = str->n;		loginsert(f, p0, str->s, str->n);		if(fileupdate(f, FALSE, FALSE))			seq++;		if(f==cmd && p0==f->nc-i && i>0 && str->s[i-1]=='\n'){			freetmpstr(str);			termlocked++;			termcommand();		}else			freetmpstr(str);		f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this already */		f->tdot = f->dot.r;		break;	case Tcut:		f = whichfile(inshort());		p0 = inlong();		p1 = inlong();		journaln(0, p0);		journaln(0, p1);		logdelete(f, p0, p1);		if(fileupdate(f, FALSE, FALSE))			seq++;		f->dot.r.p1 = f->dot.r.p2 = p0;		f->tdot = f->dot.r;   /* terminal knows the value of dot already */		break;	case Tpaste:		f = whichfile(inshort());		p0 = inlong();		journaln(0, p0);		for(l=0; l<snarfbuf.nc; l+=m){			m = snarfbuf.nc-l;			if(m>BLOCKSIZE)				m = BLOCKSIZE;			bufread(&snarfbuf, l, genbuf, m);			loginsert(f, p0, tmprstr(genbuf, m)->s, m);		}		if(fileupdate(f, FALSE, TRUE))			seq++;		f->dot.r.p1 = p0;		f->dot.r.p2 = p0+snarfbuf.nc;		f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */		telldot(f);		outTs(Hunlockfile, f->tag);		break;	case Tsnarf:		i = inshort();		p0 = inlong();		p1 = inlong();		snarf(whichfile(i), p0, p1, &snarfbuf, 0);		break;	case Tstartnewfile:		v = invlong();		Strdupl(&genstr, empty);		f = newfile();		f->rasp = listalloc('P');		outTsv(Hbindname, f->tag, v);		logsetname(f, &genstr);		outTs(Hcurrent, f->tag);		current(f);		load(f);		break;	case Twrite:		termlocked++;		i = inshort();		journaln(0, i);		f = whichfile(i);		addr.r.p1 = 0;		addr.r.p2 = f->nc;		if(f->name.s[0] == 0)			error(Enoname);		Strduplstr(&genstr, &f->name);		writef(f);		break;	case Tclose:		termlocked++;		i = inshort();		journaln(0, i);		f = whichfile(i);		current(f);		trytoclose(f);		/* if trytoclose fails, will error out */		delete(f);		break;	case Tlook:		f = whichfile(inshort());		termlocked++;		p0 = inlong();		p1 = inlong();		journaln(0, p0);		journaln(0, p1);		setgenstr(f, p0, p1);		for(l = 0; l<genstr.n; l++){			i = genstr.s[l];			if(utfrune(".*+?(|)\\[]^$", i)){				str = tmpcstr("\\");				Strinsert(&genstr, str, l++);				freetmpstr(str);			}		}		Straddc(&genstr, '\0');		nextmatch(f, &genstr, p1, 1);		moveto(f, sel.p[0]);		break;	case Tsearch:		termlocked++;		if(curfile == 0)			error(Enofile);		if(lastpat.s[0] == 0)			panic("Tsearch");		nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1);		moveto(curfile, sel.p[0]);		break;	case Tsend:		termlocked++;		inshort();	/* ignored */		p0 = inlong();		p1 = inlong();		setgenstr(cmd, p0, p1);		bufreset(&snarfbuf);		bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n);		outTl(Hsnarflen, genstr.n);		if(genstr.s[genstr.n-1] != '\n')			Straddc(&genstr, '\n');		loginsert(cmd, cmd->nc, genstr.s, genstr.n);		fileupdate(cmd, FALSE, TRUE);		cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc;		telldot(cmd);		termcommand();		break;	case Tdclick:		f = whichfile(inshort());		p1 = inlong();		doubleclick(f, p1);		f->tdot.p1 = f->tdot.p2 = p1;		telldot(f);		outTs(Hunlockfile, f->tag);		break;	case Tstartsnarf:		if (snarfbuf.nc <= 0) {	/* nothing to export */			outTs(Hsetsnarf, 0);			break;		}		c = 0;		i = 0;		m = snarfbuf.nc;		if(m > SNARFSIZE) {			m = SNARFSIZE;			dprint("?warning: snarf buffer truncated\n");		}		rp = malloc(m*sizeof(Rune));		if(rp){			bufread(&snarfbuf, 0, rp, m);			c = Strtoc(tmprstr(rp, m));			free(rp);			i = strlen(c);		}		outTs(Hsetsnarf, i);		if(c){			Write(1, c, i);			free(c);		} else			dprint("snarf buffer too long\n");		break;	case Tsetsnarf:		m = inshort();		if(m > SNARFSIZE)			error(Etoolong);		c = malloc(m+1);		if(c){			for(i=0; i<m; i++)				c[i] = rcvchar();			c[m] = 0;			str = tmpcstr(c);			free(c);			bufreset(&snarfbuf);			bufinsert(&snarfbuf, (Posn)0, str->s, str->n);			freetmpstr(str);			outT0(Hunlock);		}		break;	case Tack:		waitack = 0;		break;	case Tplumb:		f = whichfile(inshort());		p0 = inlong();		p1 = inlong();		pm = emalloc(sizeof(Plumbmsg));		pm->src = strdup("sam");		pm->dst = 0;		/* construct current directory */		c = Strtoc(&f->name);		if(c[0] == '/')			pm->wdir = c;		else{			wdir = emalloc(1024);			getwd(wdir, 1024);			pm->wdir = emalloc(1024);			snprint(pm->wdir, 1024, "%s/%s", wdir, c);			cleanname(pm->wdir);			free(wdir);			free(c);		}		c = strrchr(pm->wdir, '/');		if(c)			*c = '\0';		pm->type = strdup("text");		if(p1 > p0)			pm->attr = nil;		else{			p = p0;			while(p0>0 && (i=filereadc(f, p0 - 1))!=' ' && i!='\t' && i!='\n')				p0--;			while(p1<f->nc && (i=filereadc(f, p1))!=' ' && i!='\t' && i!='\n')				p1++;			sprint(cbuf, "click=%ld", p-p0);			pm->attr = plumbunpackattr(cbuf);		}		if(p0==p1 || p1-p0>=BLOCKSIZE){			plumbfree(pm);			break;		}		setgenstr(f, p0, p1);		pm->data = Strtoc(&genstr);		pm->ndata = strlen(pm->data);		c = plumbpack(pm, &i);		if(c != 0){			outTs(Hplumb, i);			Write(1, c, i);			free(c);		}		plumbfree(pm);		break;	case Texit:		exits(0);	}	return TRUE;}voidsnarf(File *f, Posn p1, Posn p2, Buffer *buf, int emptyok){	Posn l;	int i;	if(!emptyok && p1==p2)		return;	bufreset(buf);	/* Stage through genbuf to avoid compaction problems (vestigial) */	if(p2 > f->nc){		fprint(2, "bad snarf addr p1=%ld p2=%ld f->nc=%d\n", p1, p2, f->nc); /*ZZZ should never happen, can remove */		p2 = f->nc;	}	for(l=p1; l<p2; l+=i){		i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l;		bufread(f, l, genbuf, i);		bufinsert(buf, buf->nc, tmprstr(genbuf, i)->s, i);	}}intinshort(void){	ushort n;	n = inp[0] | (inp[1]<<8);	inp += 2;	return n;}longinlong(void){	ulong n;	n = inp[0] | (inp[1]<<8) | (inp[2]<<16) | (inp[3]<<24);	inp += 4;	return n;}vlonginvlong(void){	vlong v;		v = (inp[7]<<24) | (inp[6]<<16) | (inp[5]<<8) | inp[4];	v = (v<<16) | (inp[3]<<8) | inp[2];	v = (v<<16) | (inp[1]<<8) | inp[0];	inp += 8;	return v;}voidsetgenstr(File *f, Posn p0, Posn p1){	if(p0 != p1){		if(p1-p0 >= TBLOCKSIZE)			error(Etoolong);		Strinsure(&genstr, p1-p0);		bufread(f, p0, genbuf, p1-p0);		memmove(genstr.s, genbuf, RUNESIZE*(p1-p0));		genstr.n = p1-p0;	}else{		if(snarfbuf.nc == 0)			error(Eempty);		if(snarfbuf.nc > TBLOCKSIZE)			error(Etoolong);		bufread(&snarfbuf, (Posn)0, genbuf, snarfbuf.nc);		Strinsure(&genstr, snarfbuf.nc);		memmove(genstr.s, genbuf, RUNESIZE*snarfbuf.nc);		genstr.n = snarfbuf.nc;	}}voidoutT0(Hmesg type){	outstart(type);	outsend();}voidoutTl(Hmesg type, long l){	outstart(type);	outlong(l);	outsend();}voidoutTs(Hmesg type, int s){	outstart(type);	journaln(1, s);	outshort(s);	outsend();}voidoutS(String *s){	char *c;	int i;	c = Strtoc(s);	i = strlen(c);	outcopy(i, c);	if(i > 99)		c[99] = 0;	journaln(1, i);	journal(1, c);	free(c);}voidoutTsS(Hmesg type, int s1, String *s){	outstart(type);	outshort(s1);	outS(s);	outsend();}voidoutTslS(Hmesg type, int s1, Posn l1, String *s){	outstart(type);	outshort(s1);	journaln(1, s1);	outlong(l1);	journaln(1, l1);	outS(s);	outsend();}voidoutTS(Hmesg type, String *s){	outstart(type);	outS(s);	outsend();}voidoutTsllS(Hmesg type, int s1, Posn l1, Posn l2, String *s){	outstart(type);	outshort(s1);	outlong(l1);	outlong(l2);	journaln(1, l1);	journaln(1, l2);	outS(s);	outsend();}voidoutTsll(Hmesg type, int s, Posn l1, Posn l2){	outstart(type);	outshort(s);	outlong(l1);	outlong(l2);	journaln(1, l1);	journaln(1, l2);	outsend();}voidoutTsl(Hmesg type, int s, Posn l){	outstart(type);	outshort(s);	outlong(l);	journaln(1, l);	outsend();}voidoutTsv(Hmesg type, int s, vlong v){	outstart(type);	outshort(s);	outvlong(v);	journalv(1, v);	outsend();}voidoutstart(Hmesg type){	journal(1, hname[type]);	outmsg[0] = type;	outp = outmsg+3;}voidoutcopy(int count, void *data){	memmove(outp, data, count);	outp += count;}voidoutshort(int s){	*outp++ = s;	*outp++ = s>>8; }voidoutlong(long l){	*outp++ = l;	*outp++ = l>>8;	*outp++ = l>>16;	*outp++ = l>>24;}voidoutvlong(vlong v){	int i;	for(i = 0; i < 8; i++){		*outp++ = v;		v >>= 8;	}}voidoutsend(void){	int outcount;	outcount = outp-outmsg;	outcount -= 3;	outmsg[1] = outcount;	outmsg[2] = outcount>>8;	outmsg = outp;	if(!noflush){		outcount = outmsg-outdata;		if (write(1, (char*) outdata, outcount) != outcount)			rescue();		outmsg = outdata;		return;	}	if(outmsg < outdata+DATASIZE)		return;	outflush();}voidoutflush(void){	if(outmsg == outdata)		return;	noflush = 0;	outT0(Hack);	waitack = 1;	do		if(rcv() == 0){			rescue();			exits("eof");		}	while(waitack);	outmsg = outdata;	noflush = 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -