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

📄 exec.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <cursor.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include <fcall.h>#include <plumb.h>#include "dat.h"#include "fns.h"Buffer	snarfbuf;void	del(Text*, Text*, Text*, int, int, Rune*, int);void	delcol(Text*, Text*, Text*, int, int, Rune*, int);void	dump(Text*, Text*, Text*, int, int, Rune*, int);void	edit(Text*, Text*, Text*, int, int, Rune*, int);void	exit(Text*, Text*, Text*, int, int, Rune*, int);void	fontx(Text*, Text*, Text*, int, int, Rune*, int);void	get(Text*, Text*, Text*, int, int, Rune*, int);void	id(Text*, Text*, Text*, int, int, Rune*, int);void	incl(Text*, Text*, Text*, int, int, Rune*, int);void	indent(Text*, Text*, Text*, int, int, Rune*, int);void	kill(Text*, Text*, Text*, int, int, Rune*, int);void	local(Text*, Text*, Text*, int, int, Rune*, int);void	look(Text*, Text*, Text*, int, int, Rune*, int);void	newcol(Text*, Text*, Text*, int, int, Rune*, int);void	paste(Text*, Text*, Text*, int, int, Rune*, int);void	put(Text*, Text*, Text*, int, int, Rune*, int);void	putall(Text*, Text*, Text*, int, int, Rune*, int);void	sendx(Text*, Text*, Text*, int, int, Rune*, int);void	sort(Text*, Text*, Text*, int, int, Rune*, int);void	tab(Text*, Text*, Text*, int, int, Rune*, int);void	zeroxx(Text*, Text*, Text*, int, int, Rune*, int);typedef struct Exectab Exectab;struct Exectab{	Rune	*name;	void	(*fn)(Text*, Text*, Text*, int, int, Rune*, int);	int		mark;	int		flag1;	int		flag2;};Exectab exectab[] = {	{ L"Cut",		cut,		TRUE,	TRUE,	TRUE	},	{ L"Del",		del,		FALSE,	FALSE,	XXX		},	{ L"Delcol",	delcol,	FALSE,	XXX,		XXX		},	{ L"Delete",	del,		FALSE,	TRUE,	XXX		},	{ L"Dump",	dump,	FALSE,	TRUE,	XXX		},	{ L"Edit",		edit,		FALSE,	XXX,		XXX		},	{ L"Exit",		exit,		FALSE,	XXX,		XXX		},	{ L"Font",		fontx,	FALSE,	XXX,		XXX		},	{ L"Get",		get,		FALSE,	TRUE,	XXX		},	{ L"ID",		id,		FALSE,	XXX,		XXX		},	{ L"Incl",		incl,		FALSE,	XXX,		XXX		},	{ L"Indent",	indent,	FALSE,	XXX,		XXX		},	{ L"Kill",		kill,		FALSE,	XXX,		XXX		},	{ L"Load",		dump,	FALSE,	FALSE,	XXX		},	{ L"Local",		local,	FALSE,	XXX,		XXX		},	{ L"Look",		look,		FALSE,	XXX,		XXX		},	{ L"New",		new,		FALSE,	XXX,		XXX		},	{ L"Newcol",	newcol,	FALSE,	XXX,		XXX		},	{ L"Paste",		paste,	TRUE,	TRUE,	XXX		},	{ L"Put",		put,		FALSE,	XXX,		XXX		},	{ L"Putall",		putall,	FALSE,	XXX,		XXX		},	{ L"Redo",		undo,	FALSE,	FALSE,	XXX		},	{ L"Send",		sendx,	TRUE,	XXX,		XXX		},	{ L"Snarf",		cut,		FALSE,	TRUE,	FALSE	},	{ L"Sort",		sort,		FALSE,	XXX,		XXX		},	{ L"Tab",		tab,		FALSE,	XXX,		XXX		},	{ L"Undo",		undo,	FALSE,	TRUE,	XXX		},	{ L"Zerox",	zeroxx,	FALSE,	XXX,		XXX		},	{ nil, 			nil,		0,		0,		0		},};Exectab*lookup(Rune *r, int n){	Exectab *e;	int nr;	r = skipbl(r, n, &n);	if(n == 0)		return nil;	findbl(r, n, &nr);	nr = n-nr;	for(e=exectab; e->name; e++)		if(runeeq(r, nr, e->name, runestrlen(e->name)) == TRUE)			return e;	return nil;}intisexecc(int c){	if(isfilec(c))		return 1;	return c=='<' || c=='|' || c=='>';}voidexecute(Text *t, uint aq0, uint aq1, int external, Text *argt){	uint q0, q1;	Rune *r, *s;	char *b, *a, *aa;	Exectab *e;	int c, n, f;	Runestr dir;	q0 = aq0;	q1 = aq1;	if(q1 == q0){	/* expand to find word (actually file name) */		/* if in selection, choose selection */		if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){			q0 = t->q0;			q1 = t->q1;		}else{			while(q1<t->file->nc && isexecc(c=textreadc(t, q1)) && c!=':')				q1++;			while(q0>0 && isexecc(c=textreadc(t, q0-1)) && c!=':')				q0--;			if(q1 == q0)				return;		}	}	r = runemalloc(q1-q0);	bufread(t->file, q0, r, q1-q0);	e = lookup(r, q1-q0);	if(!external && t->w!=nil && t->w->nopen[QWevent]>0){		f = 0;		if(e)			f |= 1;		if(q0!=aq0 || q1!=aq1){			bufread(t->file, aq0, r, aq1-aq0);			f |= 2;		}		aa = getbytearg(argt, TRUE, TRUE, &a);		if(a){				if(strlen(a) > EVENTSIZE){	/* too big; too bad */				free(aa);				free(a);				warning(nil, "`argument string too long\n");				return;			}			f |= 8;		}		c = 'x';		if(t->what == Body)			c = 'X';		n = aq1-aq0;		if(n <= EVENTSIZE)			winevent(t->w, "%c%d %d %d %d %.*S\n", c, aq0, aq1, f, n, n, r);		else			winevent(t->w, "%c%d %d %d 0 \n", c, aq0, aq1, f, n);		if(q0!=aq0 || q1!=aq1){			n = q1-q0;			bufread(t->file, q0, r, n);			if(n <= EVENTSIZE)				winevent(t->w, "%c%d %d 0 %d %.*S\n", c, q0, q1, n, n, r);			else				winevent(t->w, "%c%d %d 0 0 \n", c, q0, q1, n);		}		if(a){			winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(a), a);			if(aa)				winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(aa), aa);			else				winevent(t->w, "%c0 0 0 0 \n", c);		}		free(r);		free(aa);		free(a);		return;	}	if(e){		if(e->mark && seltext!=nil)		if(seltext->what == Body){			seq++;			filemark(seltext->w->body.file);		}		s = skipbl(r, q1-q0, &n);		s = findbl(s, n, &n);		s = skipbl(s, n, &n);		(*e->fn)(t, seltext, argt, e->flag1, e->flag2, s, n);		free(r);		return;	}	b = runetobyte(r, q1-q0);	free(r);	dir = dirname(t, nil, 0);	if(dir.nr==1 && dir.r[0]=='.'){	/* sigh */		free(dir.r);		dir.r = nil;		dir.nr = 0;	}	aa = getbytearg(argt, TRUE, TRUE, &a);	if(t->w)		incref(t->w);	run(t->w, b, dir.r, dir.nr, TRUE, aa, a, FALSE);}char*printarg(Text *argt, uint q0, uint q1){	char *buf;	if(argt->what!=Body || argt->file->name==nil)		return nil;	buf = emalloc(argt->file->nname+32);	if(q0 == q1)		sprint(buf, "%.*S:#%d", argt->file->nname, argt->file->name, q0);	else		sprint(buf, "%.*S:#%d,#%d", argt->file->nname, argt->file->name, q0, q1);	return buf;}char*getarg(Text *argt, int doaddr, int dofile, Rune **rp, int *nrp){	int n;	Expand e;	char *a;	*rp = nil;	*nrp = 0;	if(argt == nil)		return nil;	a = nil;	textcommit(argt, TRUE);	if(expand(argt, argt->q0, argt->q1, &e)){		free(e.bname);		if(e.nname && dofile){			e.name = runerealloc(e.name, e.nname+1);			if(doaddr)				a = printarg(argt, e.q0, e.q1);			*rp = e.name;			*nrp = e.nname;			return a;		}		free(e.name);	}else{		e.q0 = argt->q0;		e.q1 = argt->q1;	}	n = e.q1 - e.q0;	*rp = runemalloc(n+1);	bufread(argt->file, e.q0, *rp, n);	if(doaddr)		a = printarg(argt, e.q0, e.q1);	*nrp = n;	return a;}char*getbytearg(Text *argt, int doaddr, int dofile, char **bp){	Rune *r;	int n;	char *aa;	*bp = nil;	aa = getarg(argt, doaddr, dofile, &r, &n);	if(r == nil)		return nil;	*bp = runetobyte(r, n);	free(r);	return aa;}voidnewcol(Text *et, Text*, Text*, int, int, Rune*, int){	Column *c;	c = rowadd(et->row, nil, -1);	if(c)		winsettag(coladd(c, nil, nil, -1));}voiddelcol(Text *et, Text*, Text*, int, int, Rune*, int){	int i;	Column *c;	Window *w;	c = et->col;	if(c==nil || colclean(c)==0)		return;	for(i=0; i<c->nw; i++){		w = c->w[i];		if(w->nopen[QWevent]+w->nopen[QWaddr]+w->nopen[QWdata]+w->nopen[QWxdata] > 0){			warning(nil, "can't delete column; %.*S is running an external command\n", w->body.file->nname, w->body.file->name);			return;		}	}	rowclose(et->col->row, et->col, TRUE);}voiddel(Text *et, Text*, Text*, int flag1, int, Rune*, int){	if(et->col==nil || et->w == nil)		return;	if(flag1 || et->w->body.file->ntext>1 || winclean(et->w, FALSE))		colclose(et->col, et->w, TRUE);}voidsort(Text *et, Text*, Text*, int, int, Rune*, int){	if(et->col)		colsort(et->col);}uintseqof(Window *w, int isundo){	/* if it's undo, see who changed with us */	if(isundo)		return w->body.file->seq;	/* if it's redo, see who we'll be sync'ed up with */	return fileredoseq(w->body.file);}voidundo(Text *et, Text*, Text*, int flag1, int, Rune*, int){	int i, j;	Column *c;	Window *w;	uint seq;	if(et==nil || et->w== nil)		return;	seq = seqof(et->w, flag1);	if(seq == 0){		/* nothing to undo */		return;	}	/*	 * Undo the executing window first. Its display will update. other windows	 * in the same file will not call show() and jump to a different location in the file.	 * Simultaneous changes to other files will be chaotic, however.	 */	winundo(et->w, flag1);	for(i=0; i<row.ncol; i++){		c = row.col[i];		for(j=0; j<c->nw; j++){			w = c->w[j];			if(w == et->w)				continue;			if(seqof(w, flag1) == seq)				winundo(w, flag1);		}	}}char*getname(Text *t, Text *argt, Rune *arg, int narg, int isput){	char *s;	Rune *r;	int i, n, promote;	Runestr dir;	getarg(argt, FALSE, TRUE, &r, &n);	promote = FALSE;	if(r == nil)		promote = TRUE;	else if(isput){		/* if are doing a Put, want to synthesize name even for non-existent file */		/* best guess is that file name doesn't contain a slash */		promote = TRUE;		for(i=0; i<n; i++)			if(r[i] == '/'){				promote = FALSE;				break;			}		if(promote){			t = argt;			arg = r;			narg = n;		}	}	if(promote){		n = narg;		if(n <= 0){			s = runetobyte(t->file->name, t->file->nname);			return s;		}		/* prefix with directory name if necessary */		dir.r = nil;		dir.nr = 0;		if(n>0 && arg[0]!='/'){			dir = dirname(t, nil, 0);			if(dir.nr==1 && dir.r[0]=='.'){	/* sigh */				free(dir.r);				dir.r = nil;				dir.nr = 0;			}		}		if(dir.r){			r = runemalloc(dir.nr+n+1);			runemove(r, dir.r, dir.nr);			free(dir.r);			if(dir.nr>0 && r[dir.nr]!='/' && n>0 && arg[0]!='/')				r[dir.nr++] = '/';			runemove(r+dir.nr, arg, n);			n += dir.nr;		}else{			r = runemalloc(n+1);			runemove(r, arg, n);		}	}	s = runetobyte(r, n);	free(r);	if(strlen(s) == 0){		free(s);		s = nil;	}	return s;}voidzeroxx(Text *et, Text *t, Text*, int, int, Rune*, int){	Window *nw;	int c, locked;	locked = FALSE;	if(t!=nil && t->w!=nil && t->w!=et->w){		locked = TRUE;		c = 'M';		if(et->w)			c = et->w->owner;		winlock(t->w, c);	}	if(t == nil)		t = et;	if(t==nil || t->w==nil)		return;	t = &t->w->body;	if(t->w->isdir)		warning(nil, "%.*S is a directory; Zerox illegal\n", t->file->nname, t->file->name);	else{		nw = coladd(t->w->col, nil, t->w, -1);		/* ugly: fix locks so w->unlock works */		winlock1(nw, t->w->owner);	}	if(locked)		winunlock(t->w);}voidget(Text *et, Text *t, Text *argt, int flag1, int, Rune *arg, int narg){	char *name;	Rune *r;	int i, n, dirty, samename, isdir;	Window *w;	Text *u;	Dir *d;	if(flag1)		if(et==nil || et->w==nil)			return;	if(!et->w->isdir && (et->w->body.file->nc>0 && !winclean(et->w, TRUE)))		return;	w = et->w;	t = &w->body;	name = getname(t, argt, arg, narg, FALSE);	if(name == nil){		warning(nil, "no file name\n");		return;	}	if(t->file->ntext>1){		d = dirstat(name);		isdir = (d!=nil && (d->qid.type & QTDIR));		free(d);		if(isdir){			warning(nil, "%s is a directory; can't read with multiple windows on it\n", name);			return;		}	}	r = bytetorune(name, &n);	for(i=0; i<t->file->ntext; i++){		u = t->file->text[i];		/* second and subsequent calls with zero an already empty buffer, but OK */		textreset(u);		windirfree(u->w);	}	samename = runeeq(r, n, t->file->name, t->file->nname);	textload(t, 0, name, samename);	if(samename){		t->file->mod = FALSE;		dirty = FALSE;	}else{		t->file->mod = TRUE;		dirty = TRUE;	}	for(i=0; i<t->file->ntext; i++)		t->file->text[i]->w->dirty = dirty;	free(name);	free(r);	winsettag(w);	t->file->unread = FALSE;	for(i=0; i<t->file->ntext; i++){		u = t->file->text[i];		textsetselect(&u->w->tag, u->w->tag.file->nc, u->w->tag.file->nc);		textscrdraw(u);	}}voidputfile(File *f, int q0, int q1, Rune *namer, int nname){	uint n, m;	Rune *r;	char *s, *name;	int i, fd, q;	Dir *d, *d1;	Window *w;	int isapp;	w = f->curtext->w;	name = runetobyte(namer, nname);	d = dirstat(name);	if(d!=nil && runeeq(namer, nname, f->name, f->nname)){		/* f->mtime+1 because when talking over NFS it's often off by a second */		if(f->dev!=d->dev || f->qidpath!=d->qid.path || f->mtime+1<d->mtime){			f->dev = d->dev;			f->qidpath = d->qid.path;			f->mtime = d->mtime;			if(f->unread)				warning(nil, "%s not written; file already exists\n", name);			else				warning(nil, "%s modified%s%s since last read\n", name, d->muid[0]?" by ":"", d->muid);			goto Rescue1;		}	}	fd = create(name, OWRITE, 0666);	if(fd < 0){		warning(nil, "can't create file %s: %r\n", name);		goto Rescue1;	}	r = fbufalloc();	s = fbufalloc();	free(d);	d = dirfstat(fd);	isapp = (d!=nil && d->length>0 && (d->qid.type&QTAPPEND));	if(isapp){		warning(nil, "%s not written; file is append only\n", name);		goto Rescue2;	}	for(q=q0; q<q1; q+=n){		n = q1 - q;		if(n > BUFSIZE/UTFmax)			n = BUFSIZE/UTFmax;		bufread(f, q, r, n);		m = snprint(s, BUFSIZE+1, "%.*S", n, r);		if(write(fd, s, m) != m){			warning(nil, "can't write file %s: %r\n", name);			goto Rescue2;		}	}	if(runeeq(namer, nname, f->name, f->nname)){		if(q0!=0 || q1!=f->nc){			f->mod = TRUE;			w->dirty = TRUE;			f->unread = TRUE;		}else{			d1 = dirfstat(fd);			if(d1 != nil){				free(d);				d = d1;			}			f->qidpath = d->qid.path;			f->dev = d->dev;			f->mtime = d->mtime;			f->mod = FALSE;			w->dirty = FALSE;			f->unread = FALSE;		}		for(i=0; i<f->ntext; i++){			f->text[i]->w->putseq = f->seq;			f->text[i]->w->dirty = w->dirty;		}	}	fbuffree(s);	fbuffree(r);	free(d);	free(namer);	free(name);	close(fd);	winsettag(w);	return;    Rescue2:	fbuffree(s);	fbuffree(r);	close(fd);	/* fall through */    Rescue1:	free(d);	free(namer);	free(name);}voidput(Text *et, Text*, Text *argt, int, int, Rune *arg, int narg){	int nname;	Rune  *namer;	Window *w;	File *f;	char *name;	if(et==nil || et->w==nil || et->w->isdir)		return;	w = et->w;	f = w->body.file;	name = getname(&w->body, argt, arg, narg, TRUE);	if(name == nil){		warning(nil, "no file name\n");		return;	}	namer = bytetorune(name, &nname);	putfile(f, 0, f->nc, namer, nname);	free(name);}voiddump(Text *, Text *, Text *argt, int isdump, int, Rune *arg, int narg){	char *name;	if(narg)		name = runetobyte(arg, narg);	else		getbytearg(argt, FALSE, TRUE, &name);	if(isdump)		rowdump(&row, name);	else		rowload(&row, name, FALSE);	free(name);}voidcut(Text *et, Text *t, Text*, int dosnarf, int docut, Rune*, int){	uint q0, q1, n, locked, c;	Rune *r;	/* use current window if snarfing and its selection is non-null */	if(et!=nil && dosnarf && et->w!=nil && t==nil){		if(et->w->body.q1>et->w->body.q0){			t = &et->w->body;			if(docut)				filemark(t->file);	/* seq has been incremented by execute */		}else if(et->w->tag.q1>et->w->tag.q0)			t = &et->w->tag;	}	if(t == nil){		/* can only happen if seltext == nil */		return;	}	locked = FALSE;	if(t->w!=nil && et->w!=t->w){		locked = TRUE;		c = 'M';		if(et->w)			c = et->w->owner;		winlock(t->w, c);	}	if(t->q0 == t->q1){		if(locked)			winunlock(t->w);		return;	}	if(dosnarf){		q0 = t->q0;		q1 = t->q1;		bufdelete(&snarfbuf, 0, snarfbuf.nc);		r = fbufalloc();		while(q0 < q1){			n = q1 - q0;			if(n > RBUFSIZE)				n = RBUFSIZE;

⌨️ 快捷键说明

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