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

📄 sed.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
				c = '\n';	/* fake an end-of-line */				prog.curr = 0;			}		} else 			c = -1;	} else if ((c = Bgetrune(prog.bp)) < 0)			Bterm(prog.bp);	return c;}voidaddress(Addr *ap){	int c;	long	lno;	if((c = *cp++) == '$')		ap->type = A_DOL;	else if(c == '/') {		seof = c;		if (ap->rp = compile())			ap->type = A_RE;		else			ap->type = A_LAST;	}	else if (c >= '0' && c <= '9') {		lno = c-'0';		while ((c = *cp) >= '0' && c <= '9')			lno = lno*10 + *cp++-'0';		if(!lno)			quit("line number 0 is illegal",0);		ap->type = A_LINE;		ap->line = lno;	}	else {		cp--;		ap->type = A_NONE;	}}cmp(char *a, char *b)		/* compare characters */{	while(*a == *b++)		if (*a == '\0')			return(0);		else a++;	return(1);}rcmp(Rune *a, Rune *b)		/* compare runes */{	while(*a == *b++)		if (*a == '\0')			return(0);		else a++;	return(1);}char *text(char *p)		/* extract character string */{	Rune	r;	while(*cp == '\t' || *cp == ' ')			cp++;	while (*cp) {		if ((r = *cp++) == '\\')			if ((r = *cp++) == 0)				break;;		if (r == '\n')			while (*cp == '\t' || *cp == ' ')					cp++;		p += runetochar(p, &r);	}	*p++ = '\0';	return p;}Rune *stext(Rune *p, Rune *end)		/* extract rune string */{	while(*cp == '\t' || *cp == ' ')		cp++;	while (*cp) {		if (*cp == '\\')			if (*++cp == 0)				break;		if (p >= end-1)			quit(TMMES, (char *) linebuf);		if ((*p++ = *cp++) == '\n')			while(*cp == '\t' || *cp == ' ')					cp++;	}	*p++ = 0;	return p;}Label *search (Label *ptr){	Label	*rp;	for (rp = ltab; rp < ptr; rp++)		if(rcmp(rp->asc, ptr->asc) == 0)			return(rp);	return(0);}voiddechain(void){	Label	*lptr;	SedCom	*rptr, *trptr;	for(lptr = ltab; lptr < lab; lptr++) {		if(lptr->address == 0)			quit("Undefined label: %S", (char *) lptr->asc);		if(lptr->chain) {			rptr = lptr->chain;			while(trptr = rptr->lb1) {				rptr->lb1 = lptr->address;				rptr = trptr;			}			rptr->lb1 = lptr->address;		}	}}intycomp(SedCom *r){	int 	i;	Rune	*rp;	Rune	c, *tsp, highc;	Rune	*sp;	highc = 0;	for(tsp = cp; *tsp != seof; tsp++) {		if(*tsp == '\\')			tsp++;		if(*tsp == '\n' || *tsp == '\0')			return(0);		if (*tsp > highc) highc = *tsp;	}	tsp++;	if ((rp = r->text = (Rune *) malloc(sizeof(Rune)*(highc+2))) == 0)		quit("Out of memory", 0);	*rp++ = highc;				/* save upper bound */	for (i = 0; i <= highc; i++)		rp[i] = i;	sp = cp;	while((c = *sp++) != seof) {		if(c == '\\' && *sp == 'n') {			sp++;			c = '\n';		}		if((rp[c] = *tsp++) == '\\' && *tsp == 'n') {			rp[c] = '\n';			tsp++;		}		if(rp[c] == seof || rp[c] == '\0') {			free(r->re1);			r->re1 = 0;			return(0);		}	}	if(*tsp != seof) {		free(r->re1);		r->re1 = 0;		return(0);	}	cp = tsp+1;	return(1);}voidexecute(void){	SedCom	*ipc;	while (spend = gline(linebuf)){		for(ipc = pspace; ipc->command; ) {			if (!executable(ipc)) {				ipc++;				continue;			}			command(ipc);			if(delflag)				break;			if(jflag) {				jflag = 0;				if((ipc = ipc->lb1) == 0)					break;			} else				ipc++;		}		if(!nflag && !delflag)			putline(&fout, linebuf, spend-linebuf);		if(aptr > abuf) {			arout();		}		delflag = 0;	}}	/* determine if a statement should be applied to an input line */intexecutable(SedCom *ipc){	if (ipc->active) {	/* Addr1 satisfied - accept until Addr2 */		if (ipc->active == 1)		/* Second line */			ipc->active = 2;		switch(ipc->ad2.type) {			case A_NONE:	/* No second addr; use first */				ipc->active = 0;				break;			case A_DOL:	/* Accept everything */				return !ipc->negfl;			case A_LINE:	/* Line at end of range? */				if (lnum <= ipc->ad2.line) {					if (ipc->ad2.line == lnum)						ipc->active = 0;					return !ipc->negfl;				}				ipc->active = 0;	/* out of range */				return ipc->negfl;			case A_RE:	/* Check for matching R.E. */				if (match(ipc->ad2.rp, linebuf))					ipc->active = 0;				return !ipc->negfl;			default:		/* internal error */				quit("Internal error", 0);		}	}	switch (ipc->ad1.type) {	/* Check first address */		case A_NONE:			/* Everything matches */			return !ipc->negfl;		case A_DOL:			/* Only last line */			if (dolflag)				return !ipc->negfl;			break;		case A_LINE:			/* Check line number */			if (ipc->ad1.line == lnum) {				ipc->active = 1;	/* In range */				return !ipc->negfl;			}			break;		case A_RE:			/* Check R.E. */			if (match(ipc->ad1.rp, linebuf)) {				ipc->active = 1;	/* In range */				return !ipc->negfl;			}			break;		default:			quit("Internal error", 0);	}	return ipc->negfl;}match(Reprog *pattern, Rune *buf){	if (!pattern)		return 0;	subexp[0].rsp = buf; 	subexp[0].ep = 0;	if (rregexec(pattern, linebuf, subexp, MAXSUB)) {		loc1 = subexp[0].rsp;		loc2 = subexp[0].rep;		return 1;	}	loc1 = loc2 = 0;	return 0;}substitute(SedCom *ipc){	int len;	if(!match(ipc->re1, linebuf))		return 0;	/*	 * we have at least one match.  some patterns, e.g. '$' or '^', can	 * produce zero-length matches, so during a global substitute we	 * must bump to the character after a zero-length match to keep from looping.	 */	sflag = 1;	if(ipc->gfl == 0)		/* single substitution */		dosub(ipc->rhs);	else	do{				/* global substitution */		len = loc2-loc1;	/* length of match */		dosub(ipc->rhs);	/* dosub moves loc2 */		if(*loc2 == 0)		/* end of string */			break;		if(len == 0)		/* zero-length R.E. match */			loc2++;		/* bump over zero-length match */		if(*loc2 == 0)		/* end of string */			break;	} while(match(ipc->re1, loc2));	return 1;}voiddosub(Rune *rhsbuf){	Rune *lp, *sp;	Rune *rp;	int c, n;	lp = linebuf;	sp = genbuf;	rp = rhsbuf;	while (lp < loc1)		*sp++ = *lp++;	while(c = *rp++) {		if (c == '&') {			sp = place(sp, loc1, loc2);			continue;		}		if (c == 0xFFFF && (c = *rp++) >= '1' && c < MAXSUB+'0') {			n = c-'0';			if (subexp[n].rsp && subexp[n].rep) {				sp = place(sp, subexp[n].rsp, subexp[n].rep);				continue;			}			else {				fprint(2, "sed: Invalid back reference \\%d\n",n);				errexit();			}		}		*sp++ = c;		if (sp >= &genbuf[LBSIZE])			fprint(2, "sed: Output line too long.\n");	}	lp = loc2;	loc2 = sp - genbuf + linebuf;	while (*sp++ = *lp++)		if (sp >= &genbuf[LBSIZE])			fprint(2, "sed: Output line too long.\n");	lp = linebuf;	sp = genbuf;	while (*lp++ = *sp++)		;	spend = lp-1;}Rune *place(Rune *sp, Rune *l1, Rune *l2){	while (l1 < l2) {		*sp++ = *l1++;		if (sp >= &genbuf[LBSIZE])			fprint(2, "sed: Output line too long.\n");	}	return(sp);}char *trans(int c){	static char buf[] = "\\x0000";	static char hex[] = "0123456789abcdef";	switch(c) {		case '\b':			return "\\b";		case '\n':			return "\\n";		case '\r':			return "\\r";		case '\t':			return "\\t";		case '\\':			return "\\\\";	}	buf[2] = hex[(c>>12)&0xF];	buf[3] = hex[(c>>8)&0xF];	buf[4] = hex[(c>>4)&0xF];	buf[5] = hex[c&0xF];	return buf;}voidcommand(SedCom *ipc){	int	i, c;	Rune	*p1, *p2;	char	*ucp;	Rune	*rp;	Rune	*execp;	switch(ipc->command) {		case ACOM:			*aptr++ = ipc;			if(aptr >= abuf+MAXADDS) {				quit("sed: Too many appends after line %ld\n",					(char *) lnum);			}			*aptr = 0;			break;		case CCOM:			delflag = 1;			if(ipc->active == 1) {				for(rp = ipc->text; *rp; rp++)					Bputrune(&fout, *rp);				Bputc(&fout, '\n');			}			break;		case DCOM:			delflag++;			break;		case CDCOM:			p1 = p2 = linebuf;			while(*p1 != '\n') {				if(*p1++ == 0) {					delflag++;					return;				}			}			p1++;			while(*p2++ = *p1++)				;			spend = p2-1;			jflag++;			break;		case EQCOM:			Bprint(&fout, "%ld\n", lnum);			break;		case GCOM:			p1 = linebuf;			p2 = holdsp;			while(*p1++ = *p2++)				;			spend = p1-1;			break;		case CGCOM:			*spend++ = '\n';			p1 = spend;			p2 = holdsp;			while(*p1++ = *p2++)				if(p1 >= lbend)					break;			spend = p1-1;			break;		case HCOM:			p1 = holdsp;			p2 = linebuf;			while(*p1++ = *p2++);			hspend = p1-1;			break;		case CHCOM:			*hspend++ = '\n';			p1 = hspend;			p2 = linebuf;			while(*p1++ = *p2++)				if(p1 >= hend)					break;			hspend = p1-1;			break;		case ICOM:			for(rp = ipc->text; *rp; rp++)				Bputrune(&fout, *rp);			Bputc(&fout, '\n');			break;		case BCOM:			jflag = 1;			break;		case LCOM:			c = 0;			for (i = 0, rp = linebuf; *rp; rp++) {				c = *rp;				if(c >= 0x20 && c < 0x7F && c != '\\') {					Bputc(&fout, c);					if(i++ > 71) {						Bprint(&fout, "\\\n");						i = 0;					}				} else {					for (ucp = trans(*rp); *ucp; ucp++){						c = *ucp;						Bputc(&fout, c);						if(i++ > 71) {							Bprint(&fout, "\\\n");							i = 0;						}					}				}			}			if(c == ' ')				Bprint(&fout, "\\n");			Bputc(&fout, '\n');			break;		case NCOM:			if(!nflag)				putline(&fout, linebuf, spend-linebuf);			if(aptr > abuf)				arout();			if((execp = gline(linebuf)) == 0) {				delflag = 1;				break;			}			spend = execp;			break;		case CNCOM:			if(aptr > abuf)				arout();			*spend++ = '\n';			if((execp = gline(spend)) == 0) {				delflag = 1;				break;			}			spend = execp;			break;		case PCOM:			putline(&fout, linebuf, spend-linebuf);			break;		case CPCOM:	cpcom:			for(rp = linebuf; *rp && *rp != '\n'; rp++)				Bputc(&fout, *rp);			Bputc(&fout, '\n');			break;		case QCOM:			if(!nflag)				putline(&fout, linebuf, spend-linebuf);			if(aptr > abuf)				arout();			exits(0);		case RCOM:			*aptr++ = ipc;			if(aptr >= &abuf[MAXADDS])				quit("sed: Too many reads after line %ld\n",					(char *) lnum);			*aptr = 0;			break;		case SCOM:			i = substitute(ipc);			if(i && ipc->pfl)				if(ipc->pfl == 1)					putline(&fout, linebuf, spend-linebuf);				else					goto cpcom;			if(i && ipc->fcode)				goto wcom;			break;		case TCOM:			if(sflag == 0)	break;			sflag = 0;			jflag = 1;			break;		wcom:		case WCOM:			putline(ipc->fcode,linebuf, spend-linebuf);			break;		case XCOM:			p1 = linebuf;			p2 = genbuf;			while(*p2++ = *p1++);			p1 = holdsp;			p2 = linebuf;			while(*p2++ = *p1++);			spend = p2 - 1;			p1 = genbuf;			p2 = holdsp;			while(*p2++ = *p1++);			hspend = p2 - 1;			break;		case YCOM:			p1 = linebuf;			p2 = ipc->text;			for (i = *p2++;	*p1; p1++){				if (*p1 <= i) *p1 = p2[*p1];			}			break;	}}voidputline(Biobuf *bp, Rune *buf, int n){	while (n--)		Bputrune(bp, *buf++);	Bputc(bp, '\n');}ecmp(Rune *a, Rune *b, int count){	while(count--)		if(*a++ != *b++)	return(0);	return(1);}voidarout(void){	Rune	*p1;	Biobuf	*fi;	int	c;	char	*s;	char	buf[128];	for (aptr = abuf; *aptr; aptr++) {		if((*aptr)->command == ACOM) {			for(p1 = (*aptr)->text; *p1; p1++ )				Bputrune(&fout, *p1);			Bputc(&fout, '\n');		} else {			for(s = buf, p1= (*aptr)->text; *p1; p1++)					s += runetochar(s, p1);			*s = '\0';			if((fi = Bopen(buf, OREAD)) == 0)				continue;			while((c = Bgetc(fi)) >= 0)				Bputc(&fout, c);			Bterm(fi);		}	}	aptr = abuf;	*aptr = 0;}voiderrexit(void){	exits("error");}voidquit (char *msg, char *arg){	fprint(2, "sed: ");	fprint(2, msg, arg);	fprint(2, "\n");	errexit();}Rune *gline(Rune *addr){	long	c;	Rune *p;	static long peekc = 0;	if (f == 0 && opendata() < 0)		return 0;	sflag = 0;	lnum++;/*	Bflush(&fout);********* dumped 4/30/92 - bobf****/	do {		p = addr;		for (c = (peekc ? peekc : Bgetrune(f)); c >= 0; c = Bgetrune(f)) {			if (c == '\n') {				if ((peekc = Bgetrune(f)) < 0) {					if (fhead == 0)						dolflag = 1;				}				*p = '\0';				return p;			}			if (c && p < lbend)				*p++ = c;		}		/* return partial final line, adding implicit newline */		if(p != addr) {			*p = '\0';			peekc = -1;			if (fhead == 0)				dolflag = 1;			return p;		}		peekc = 0;		Bterm(f);	} while (opendata() > 0);	/* Switch to next stream */	f = 0;	return 0;}	/* Data file input section - the intent is to transparently	 *	catenate all data input streams.	 */voidenroll(char *filename)		/* Add a file to the input file cache */{	FileCache *fp;	if ((fp = (FileCache *) malloc(sizeof (FileCache))) == 0)		quit("Out of memory", 0);	if (ftail == 0)		fhead = fp;	else		ftail->next = fp;	ftail = fp;	fp->next = 0;	fp->name = filename;	/* 0 => stdin */}intopendata(void){	if (fhead == 0)		return -1;	if (fhead->name) {		if ((f = Bopen(fhead->name, OREAD)) == 0)			quit("Can't open %s", fhead->name);	} else {		Binit(&stdin, 0, OREAD);		f = &stdin;	}	fhead = fhead->next;	return 1;}

⌨️ 快捷键说明

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