sed0.c

来自「unix v7是最后一个广泛发布的研究型UNIX版本」· C语言 代码 · 共 970 行

C
970
字号
#include <stdio.h>#include "sed.h"struct label	*labtab = ltab;char	CGMES[]	= "command garbled: %s\n";char	TMMES[]	= "Too much text: %s\n";char	LTL[]	= "Label too long: %s\n";char	AD0MES[]	= "No addresses allowed: %s\n";char	AD1MES[]	= "Only one address allowed: %s\n";char	bittab[]  = {		1,		2,		4,		8,		16,		32,		64,		128	};main(argc, argv)char	*argv[];{	eargc = argc;	eargv = argv;	badp = &bad;	aptr = abuf;	lab = labtab + 1;	/* 0 reserved for end-pointer */	rep = ptrspace;	rep->ad1 = respace;	lbend = &linebuf[LBSIZE];	hend = &holdsp[LBSIZE];	lcomend = &genbuf[71];	ptrend = &ptrspace[PTRSIZE];	reend = &respace[RESIZE];	labend = &labtab[LABSIZE];	lnum = 0;	pending = 0;	depth = 0;	spend = linebuf;	hspend = holdsp;	fcode[0] = stdout;	nfiles = 1;	if(eargc == 1)		exit(0);	while (--eargc > 0 && (++eargv)[0][0] == '-')		switch (eargv[0][1]) {		case 'n':			nflag++;			continue;		case 'f':			if(eargc-- <= 0)	exit(2);			if((fin = fopen(*++eargv, "r")) == NULL) {				fprintf(stderr, "Cannot open pattern-file: %s\n", *eargv);				exit(2);			}			fcomp();			fclose(fin);			continue;		case 'e':			eflag++;			fcomp();			eflag = 0;			continue;		case 'g':			gflag++;			continue;		default:			fprintf(stdout, "Unknown flag: %c\n", eargv[0][1]);			continue;		}	if(compfl == 0) {		eargv--;		eargc++;		eflag++;		fcomp();		eargv++;		eargc--;		eflag = 0;	}	if(depth) {		fprintf(stderr, "Too many {'s");		exit(2);	}	labtab->address = rep;	dechain();/*	abort();	/*DEBUG*/	if(eargc <= 0)		execute((char *)NULL);	else while(--eargc >= 0) {		execute(*eargv++);	}	fclose(stdout);	exit(0);}fcomp(){	register char	*p, *op, *tp;	char	*address();	union reptr	*pt, *pt1;	int	i;	struct label	*lpt;	compfl = 1;	op = lastre;	if(rline(linebuf) < 0)	return;	if(*linebuf == '#') {		if(linebuf[1] == 'n')			nflag = 1;	}	else {		cp = linebuf;		goto comploop;	}	for(;;) {		if(rline(linebuf) < 0)	break;		cp = linebuf;comploop:/*	fprintf(stdout, "cp: %s\n", cp);	/*DEBUG*/		while(*cp == ' ' || *cp == '\t')	cp++;		if(*cp == '\0' || *cp == '#')		continue;		if(*cp == ';') {			cp++;			goto comploop;		}		p = address(rep->ad1);		if(p == badp) {			fprintf(stderr, CGMES, linebuf);			exit(2);		}		if(p == rep->ad1) {			if(op)				rep->ad1 = op;			else {				fprintf(stderr, "First RE may not be null\n");				exit(2);			}		} else if(p == 0) {			p = rep->ad1;			rep->ad1 = 0;		} else {			op = rep->ad1;			if(*cp == ',' || *cp == ';') {				cp++;				if((rep->ad2 = p) > reend) {					fprintf(stderr, TMMES, linebuf);					exit(2);				}				p = address(rep->ad2);				if(p == badp || p == 0) {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				if(p == rep->ad2)					rep->ad2 = op;				else					op = rep->ad2;			} else				rep->ad2 = 0;		}		if(p > reend) {			fprintf(stderr, "Too much text: %s\n", linebuf);			exit(2);		}		while(*cp == ' ' || *cp == '\t')	cp++;swit:		switch(*cp++) {			default:				fprintf(stderr, "Unrecognized command: %s\n", linebuf);				exit(2);			case '!':				rep->negfl = 1;				goto swit;			case '{':				rep->command = BCOM;				rep->negfl = !(rep->negfl);				cmpend[depth++] = &rep->lb1;				if(++rep >= ptrend) {					fprintf(stderr, "Too many commands: %s\n", linebuf);					exit(2);				}				rep->ad1 = p;				if(*cp == '\0')	continue;				goto comploop;			case '}':				if(rep->ad1) {					fprintf(stderr, AD0MES, linebuf);					exit(2);				}				if(--depth < 0) {					fprintf(stderr, "Too many }'s\n");					exit(2);				}				*cmpend[depth] = rep;				rep->ad1 = p;				continue;			case '=':				rep->command = EQCOM;				if(rep->ad2) {					fprintf(stderr, AD1MES, linebuf);					exit(2);				}				break;			case ':':				if(rep->ad1) {					fprintf(stderr, AD0MES, linebuf);					exit(2);				}				while(*cp++ == ' ');				cp--;				tp = lab->asc;				while((*tp++ = *cp++))					if(tp >= &(lab->asc[8])) {						fprintf(stderr, LTL, linebuf);						exit(2);					}				*--tp = '\0';				if(lpt = search(lab)) {					if(lpt->address) {						fprintf(stderr, "Duplicate labels: %s\n", linebuf);						exit(2);					}				} else {					lab->chain = 0;					lpt = lab;					if(++lab >= labend) {						fprintf(stderr, "Too many labels: %s\n", linebuf);						exit(2);					}				}				lpt->address = rep;				rep->ad1 = p;				continue;			case 'a':				rep->command = ACOM;				if(rep->ad2) {					fprintf(stderr, AD1MES, linebuf);					exit(2);				}				if(*cp == '\\')	cp++;				if(*cp++ != '\n') {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				rep->re1 = p;				p = text(rep->re1);				break;			case 'c':				rep->command = CCOM;				if(*cp == '\\')	cp++;				if(*cp++ != ('\n')) {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				rep->re1 = p;				p = text(rep->re1);				break;			case 'i':				rep->command = ICOM;				if(rep->ad2) {					fprintf(stderr, AD1MES, linebuf);					exit(2);				}				if(*cp == '\\')	cp++;				if(*cp++ != ('\n')) {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				rep->re1 = p;				p = text(rep->re1);				break;			case 'g':				rep->command = GCOM;				break;			case 'G':				rep->command = CGCOM;				break;			case 'h':				rep->command = HCOM;				break;			case 'H':				rep->command = CHCOM;				break;			case 't':				rep->command = TCOM;				goto jtcommon;			case 'b':				rep->command = BCOM;jtcommon:				while(*cp++ == ' ');				cp--;				if(*cp == '\0') {					if(pt = labtab->chain) {						while(pt1 = pt->lb1)							pt = pt1;						pt->lb1 = rep;					} else						labtab->chain = rep;					break;				}				tp = lab->asc;				while((*tp++ = *cp++))					if(tp >= &(lab->asc[8])) {						fprintf(stderr, LTL, linebuf);						exit(2);					}				cp--;				*--tp = '\0';				if(lpt = search(lab)) {					if(lpt->address) {						rep->lb1 = lpt->address;					} else {						pt = lpt->chain;						while(pt1 = pt->lb1)							pt = pt1;						pt->lb1 = rep;					}				} else {					lab->chain = rep;					lab->address = 0;					if(++lab >= labend) {						fprintf(stderr, "Too many labels: %s\n", linebuf);						exit(2);					}				}				break;			case 'n':				rep->command = NCOM;				break;			case 'N':				rep->command = CNCOM;				break;			case 'p':				rep->command = PCOM;				break;			case 'P':				rep->command = CPCOM;				break;			case 'r':				rep->command = RCOM;				if(rep->ad2) {					fprintf(stderr, AD1MES, linebuf);					exit(2);				}				if(*cp++ != ' ') {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				rep->re1 = p;				p = text(rep->re1);				break;			case 'd':				rep->command = DCOM;				break;			case 'D':				rep->command = CDCOM;				rep->lb1 = ptrspace;				break;			case 'q':				rep->command = QCOM;				if(rep->ad2) {					fprintf(stderr, AD1MES, linebuf);					exit(2);				}				break;			case 'l':				rep->command = LCOM;				break;			case 's':				rep->command = SCOM;				seof = *cp++;				rep->re1 = p;				p = compile(rep->re1);				if(p == badp) {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				if(p == rep->re1) {					rep->re1 = op;				} else {					op = rep->re1;				}				if((rep->rhs = p) > reend) {					fprintf(stderr, TMMES, linebuf);					exit(2);				}				if((p = compsub(rep->rhs)) == badp) {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				if(*cp == 'g') {					cp++;					rep->gfl++;				} else if(gflag)					rep->gfl++;				if(*cp == 'p') {					cp++;					rep->pfl = 1;				}				if(*cp == 'P') {					cp++;					rep->pfl = 2;				}				if(*cp == 'w') {					cp++;					if(*cp++ !=  ' ') {						fprintf(stderr, CGMES, linebuf);						exit(2);					}					if(nfiles >= 10) {						fprintf(stderr, "Too many files in w commands\n");						exit(2);					}					text(fname[nfiles]);					for(i = nfiles - 1; i >= 0; i--)						if(cmp(fname[nfiles],fname[i]) == 0) {							rep->fcode = fcode[i];							goto done;						}					if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) {						fprintf(stderr, "cannot open %s\n", fname[nfiles]);						exit(2);					}					fcode[nfiles++] = rep->fcode;				}				break;			case 'w':				rep->command = WCOM;				if(*cp++ != ' ') {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				if(nfiles >= 10){					fprintf(stderr, "Too many files in w commands\n");					exit(2);				}				text(fname[nfiles]);				for(i = nfiles - 1; i >= 0; i--)					if(cmp(fname[nfiles], fname[i]) == 0) {						rep->fcode = fcode[i];						goto done;					}				if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) {					fprintf(stderr, "Cannot create %s\n", fname[nfiles]);					exit(2);				}				fcode[nfiles++] = rep->fcode;				break;			case 'x':				rep->command = XCOM;				break;			case 'y':				rep->command = YCOM;				seof = *cp++;				rep->re1 = p;				p = ycomp(rep->re1);				if(p == badp) {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				if(p > reend) {					fprintf(stderr, TMMES, linebuf);					exit(2);				}				break;		}done:		if(++rep >= ptrend) {			fprintf(stderr, "Too many commands, last: %s\n", linebuf);			exit(2);		}		rep->ad1 = p;		if(*cp++ != '\0') {			if(cp[-1] == ';')				goto comploop;			fprintf(stderr, CGMES, linebuf);			exit(2);		}	}	rep->command = 0;	lastre = op;}char	*compsub(rhsbuf)char	*rhsbuf;{	register char	*p, *q;	p = rhsbuf;	q = cp;	for(;;) {		if((*p = *q++) == '\\') {			*p = *q++;			if(*p > numbra + '0' && *p <= '9')				return(badp);			*p++ |= 0200;			continue;		}		if(*p == seof) {			*p++ = '\0';			cp = q;			return(p);		}		if(*p++ == '\0') {			return(badp);		}	}}char *compile(expbuf)char	*expbuf;{	register c;	register char *ep, *sp;	char	neg;	char *lastep, *cstart;	int cclcnt;	int	closed;	char	bracket[NBRA], *bracketp;	if(*cp == seof) {		cp++;		return(expbuf);	}	ep = expbuf;	lastep = 0;	bracketp = bracket;	closed = numbra = 0;	sp = cp;	if (*sp == '^') {		*ep++ = 1;		sp++;	} else {		*ep++ = 0;	}	for (;;) {		if (ep >= &expbuf[ESIZE]) {			cp = sp;			return(badp);		}		if((c = *sp++) == seof) {			if(bracketp != bracket) {				cp = sp;				return(badp);			}			cp = sp;			*ep++ = CEOF;			return(ep);		}		if(c != '*')			lastep = ep;		switch (c) {		case '\\':			if((c = *sp++) == '(') {				if(numbra >= NBRA) {					cp = sp;					return(badp);				}				*bracketp++ = numbra;				*ep++ = CBRA;				*ep++ = numbra++;				continue;			}			if(c == ')') {				if(bracketp <= bracket) {					cp = sp;					return(badp);				}				*ep++ = CKET;				*ep++ = *--bracketp;				closed++;				continue;			}			if(c >= '1' && c <= '9') {				if((c -= '1') >= closed)					return(badp);					*ep++ = CBACK;				*ep++ = c;				continue;			}			if(c == '\n') {				cp = sp;				return(badp);			}			if(c == 'n') {				c = '\n';			}			goto defchar;		case '\0':			continue;		case '\n':			cp = sp;			return(badp);		case '.':			*ep++ = CDOT;			continue;		case '*':			if (lastep == 0)				goto defchar;			if(*lastep == CKET) {				cp = sp;				return(badp);			}			*lastep |= STAR;			continue;		case '$':			if (*sp != seof)				goto defchar;			*ep++ = CDOL;			continue;		case '[':			if(&ep[17] >= &expbuf[ESIZE]) {				fprintf(stderr, "RE too long: %s\n", linebuf);				exit(2);			}			*ep++ = CCL;			neg = 0;			if((c = *sp++) == '^') {				neg = 1;				c = *sp++;			}			cstart = sp;			do {				if(c == '\0') {					fprintf(stderr, CGMES, linebuf);					exit(2);				}				if (c=='-' && sp>cstart && *sp!=']') {					for (c = sp[-2]; c<*sp; c++)						ep[c>>3] |= bittab[c&07];				}				if(c == '\\') {					switch(c = *sp++) {						case 'n':							c = '\n';							break;					}				}				ep[c >> 3] |= bittab[c & 07];			} while((c = *sp++) != ']');			if(neg)				for(cclcnt = 0; cclcnt < 16; cclcnt++)					ep[cclcnt] ^= -1;			ep[0] &= 0376;			ep += 16;			continue;		defchar:		default:			*ep++ = CCHR;			*ep++ = c;		}	}}rline(lbuf)char	*lbuf;{	register char	*p, *q;	register	t;	static char	*saveq;	p = lbuf - 1;	if(eflag) {		if(eflag > 0) {			eflag = -1;			if(eargc-- <= 0)				exit(2);			q = *++eargv;			while(*++p = *q++) {				if(*p == '\\') {					if((*++p = *q++) == '\0') {						saveq = 0;						return(-1);					} else						continue;				}				if(*p == '\n') {					*p = '\0';					saveq = q;					return(1);				}			}			saveq = 0;			return(1);		}		if((q = saveq) == 0)	return(-1);		while(*++p = *q++) {			if(*p == '\\') {				if((*++p = *q++) == '0') {					saveq = 0;					return(-1);				} else					continue;			}			if(*p == '\n') {				*p = '\0';				saveq = q;				return(1);			}		}		saveq = 0;		return(1);	}	while((t = getc(fin)) != EOF) {		*++p = t;		if(*p == '\\') {			t = getc(fin);			*++p = t;		}		else if(*p == '\n') {			*p = '\0';			return(1);		}	}	*++p = '\0';	return(-1);}char	*address(expbuf)char	*expbuf;{	register char	*rcp;	long	lno;	if(*cp == '$') {		cp++;		*expbuf++ = CEND;		*expbuf++ = CEOF;		return(expbuf);	}	if(*cp == '/') {		seof = '/';		cp++;		return(compile(expbuf));	}	rcp = cp;	lno = 0;	while(*rcp >= '0' && *rcp <= '9')		lno = lno*10 + *rcp++ - '0';	if(rcp > cp) {		*expbuf++ = CLNUM;		*expbuf++ = nlno;		tlno[nlno++] = lno;		if(nlno >= NLINES) {			fprintf(stderr, "Too many line numbers\n");			exit(2);		}		*expbuf++ = CEOF;		cp = rcp;		return(expbuf);	}	return(0);}cmp(a, b)char	*a,*b;{	register char	*ra, *rb;	ra = a - 1;	rb = b - 1;	while(*++ra == *++rb)		if(*ra == '\0')	return(0);	return(1);}char	*text(textbuf)char	*textbuf;{	register char	*p, *q;	p = textbuf;	q = cp;	while(*q == '\t' || *q == ' ')	q++;	for(;;) {		if((*p = *q++) == '\\')			*p = *q++;		if(*p == '\0') {			cp = --q;			return(++p);		}		if(*p == '\n') {			while(*q == '\t' || *q == ' ')	q++;		}		p++;	}}struct label	*search(ptr)struct label	*ptr;{	struct label	*rp;	rp = labtab;	while(rp < ptr) {		if(cmp(rp->asc, ptr->asc) == 0)			return(rp);		rp++;	}	return(0);}dechain(){	struct label	*lptr;	union reptr	*rptr, *trptr;	for(lptr = labtab; lptr < lab; lptr++) {		if(lptr->address == 0) {			fprintf(stderr, "Undefined label: %s\n", lptr->asc);			exit(2);		}		if(lptr->chain) {			rptr = lptr->chain;			while(trptr = rptr->lb1) {				rptr->lb1 = lptr->address;				rptr = trptr;			}			rptr->lb1 = lptr->address;		}	}}char *ycomp(expbuf)char	*expbuf;{	register char	c, *ep, *tsp;	char	*sp;	ep = expbuf;	sp = cp;	for(tsp = cp; *tsp != seof; tsp++) {		if(*tsp == '\\')			tsp++;		if(*tsp == '\n')			return(badp);	}	tsp++;	while((c = *sp++ & 0177) != seof) {		if(c == '\\' && *sp == 'n') {			sp++;			c = '\n';		}		if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {			ep[c] = '\n';			tsp++;		}		if(ep[c] == seof || ep[c] == '\0')			return(badp);	}	if(*tsp != seof)		return(badp);	cp = ++tsp;	for(c = 0; !(c & 0200); c++)		if(ep[c] == 0)			ep[c] = c;	return(ep + 0200);}

⌨️ 快捷键说明

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