V9/cmd/emacs/emacs_re.c

Compare this file to the similar file:
Show the results in this format:

#include "emacs_gb.h"
#include "emacs_io.h"


/* EMACS_MODES: c !fill */

#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
#define RETURN(c) return(NULL);
#define ERROR(c) return(c);

extern char casem[];
extern char bits[];

#define RESIZE 256

/* basic comparison types */

#define CCHR 1				/* single char */
#define CDOT 2				/* any char */
#define CCL 3				/* multiple guess */
#define CBLST 4				/* last expression */
#define CDOL 5				/* $ */
#define CEOF 6				/* end of line */

/* markers */

#define CBRA 8				/* \( marker */
#define CKET 9				/* \) marker */
#define CBWD 10				/* start of word */
#define CEWD 11				/* end of word */

/* modifiers */

#define BASTYP 15			/* mask for base type */

#define RNGE 16				/* range of types */

#define	NBRA	9

#define PLACE(c)	ep[c >> 3] ^= bittab[c & 07]
#define ISTHERE(c)	(ep[c >> 3] & bittab[c & 07])

char	*braslist[NBRA];
char	*braelist[NBRA];
int	nbra, ebra;
char	*loc1;
int closed;
int	loc2;

int	low;
int	size;

char	bittab[] = {
	1,
	2,
	4,
	8,
	16,
	32,
	64,
	128
};

int
compile(sp, ep)
register char *ep;
register char *sp;

/* Keywords: regular-expressions searching parsing */
{
	register int c;
	char *endbuf;
	char *lastep = sp;
	char bracket[NBRA], *bracketp;
	char neg;
	int lc;
	int i, cflg;

	lastep = NULL;
	bracketp = bracket;
	closed = nbra = ebra = 0;

	endbuf = ep + RESIZE;

	for (;;) {
		if (ep >= endbuf)
			ERROR(62);
		if((c = GETC()) != '*' && (c != '+') &&
			((c != '\\') || (PEEKC() != '{')))
			lastep = ep;
		if (c == 0) {
			*ep++ = CEOF;
			RETURN(ep);
		}
		switch (c) {

		case '.':
			*ep++ = CDOT;
			continue;

		case '\n':
			ERROR(55);
		case '*':
			if (lastep==0 || *lastep==CBRA || *lastep==CKET)
				goto defchar;
			*lastep |= RNGE;
			*ep++=0;
			*ep++=255;
			continue;
		case '+':
			if (lastep==0 ) 
				goto defchar;
			*lastep |= RNGE;
			*ep++ = 1;
			*ep++ = 255;
			continue;

		case '$':
			if(PEEKC() != 0)
				goto defchar;
			*ep++ = CDOL;
			continue;

		case '[':
			if(&ep[17] >= endbuf)
				ERROR(62);

			*ep++ = CCL;
			lc = 0;
			if((c = GETC()) == '^') {
				neg = -1;
				c = GETC();
			} else neg = 0;
			for(i = 0; i < 16; i++)
				ep[i] = neg;


			do {
				if(c == '\0')
					ERROR(61);
				if(c == '-' && (lc != 0) && (PEEKC() != ']')) {
					c = GETC();
				} else lc = c;
				while(lc <= c) {
					PLACE(lc);
					lc++;
				}
			} while((c = GETC()) != ']');
			ep[1] &= 0373; /* make sure that newline is not matched */
			ep += 16;			
			continue;

		case '\\':
			switch(c = GETC()) {

			case '(':
				if(nbra >= NBRA)
					ERROR(57);
				*bracketp++ = nbra;
				*ep++ = CBRA;
				*ep++ = nbra++;
				continue;

			case ')':
				if(bracketp <= bracket || ++ebra != nbra)
					ERROR(56);
				*ep++ = CKET;
				*ep++ = *--bracketp;
				closed++;
				continue;

			case '<':
				*ep++ = CBWD;
				continue;
			case '>':
				*ep++ = CEWD;
				continue;
				
			case '{':
				if(lastep == (char *) (0))
					goto defchar;
				*lastep |= RNGE;
				cflg = 0;
			nlim:
				c = GETC();
				if (c == '\\') {
					i = 255; /* infinity */
				} else {
					i = 0;
					while('0' <= c && c <= '9') {
						i = 10 * i + (c - '0');
						c = GETC();
					}
				}
				if (i > 255) ERROR(52);
				*ep++ = i;
				if (c == ',') {
					if(cflg++) ERROR(58);
					goto nlim; /* get 2'nd number */
				}
				if((c != '\\') || (GETC() != '}')) ERROR(59);
				if(!cflg)	/* one number */
					*ep++ = i;
				else if((ep[-1] & 0377) < (ep[-2] & 0377))
					ERROR(60);
				continue;

			case '\n':
				ERROR(55);

			case 'n':
				c = '\n';
				goto defchar;

			default:
				if(c >= '1' && c <= '9') {
					if((c -= '1') >= closed)
						ERROR(54);
					*ep++ = CBLST;
					*ep++ = c;
					continue;
				}
			}
			/* Drop through to default to use \ to turn off special chars */

		defchar:
		default:
			lastep = ep;
			*ep++ = CCHR;
			*ep++ = c;
		}
	}
}


advance(lp, ep)
register char *lp, *ep;

/* Keywords: regular-expressions searching star-processing:10 */

{
	register char *curlp;
	char c;
	int typ;
	char *bbeg;
	int ct;

	for (;;) switch (typ = *ep++) {

	case CCHR:
		if (*ep++ == casem[(*lp++)&0177])
			continue;
		return(0);

	case CDOT:
		if (*lp++ != EOL)
			continue;
		return(0);

	case CBWD:
		if (bits[lp[-1]] & 01) continue;
		return(0);
	case CEWD:
		if (bits[*lp] & 01) continue;
		return(0);
	case CDOL:
		if (*lp==EOL) {
			continue;
		}
		return(0);

	case CEOF:
		loc2 = lp-klptr;
		return(1);

	case CCL:
		c = casem[*lp++ & 0177];
		if(ISTHERE(c)) {
			ep += 16;
			continue;
		}
		return(0);
	case CBRA:
		braslist[*ep++] = lp;
		continue;

	case CKET:
		braelist[*ep++] = lp;
		continue;

	case CCHR|RNGE:
		c = *ep++;
		getrnge(ep);
grnge:		ct = 0;
		curlp = lp;
		while(ct < size) {
			switch(typ&BASTYP) {
				
			case CCHR: if(casem[(*lp++)&0177] != c) goto broke;
				break;
			case CDOT: if (*lp++ == EOL) goto broke;
				break;
			case CCL: c = casem[(*lp++)&0177];
				if(!ISTHERE(c)) goto broke;
				break;
			}
			if (++ct == low) curlp = lp;
		}
broke:		if (ct < low) return(0); /* too few */

		if (size == ct) lp++;	/* didn't do last compare */
		if ((typ&BASTYP) == CCL) ep += 16;
		ep += 2;

		while (lp > curlp) {
			if (advance(--lp, ep)) return(1);
		}
		return(0);
	case CDOT|RNGE:
		getrnge(ep);
		goto grnge;
	case CCL|RNGE:
		getrnge(ep + 16);
		goto grnge;
	case CBLST:
		bbeg = braslist[*ep];
		ct = braelist[*ep++] - bbeg;

		if(ecmp(bbeg, lp, ct)) {
			lp += ct;
			continue;
		}
		return(0);

	case CBLST|RNGE:
		bbeg = braslist[*ep];
		ct = braelist[*ep++] - bbeg;
		ep+=2;
		curlp = lp;
		while(ecmp(bbeg, lp, ct))
			lp += ct;

		while(lp >= curlp) {
			if(advance(lp, ep))	return(1);
			lp -= ct;
		}
		return(0);
	}
}

getrnge(str)
register char *str;
/* Keywords: regular-expressions searching:20 star-processing */

{
	low = *str++ & 0377;
	size = *str&0377;
	if (size == 255) size = 2000;
}

ecmp(a, b, count)
register char	*a, *b;
register int count;

/* Keywords: star-processing regular-expressions searching:10 */

{
	while(count--)
		if(*a++ != *b++)	return(0);
	return(1);
}



rsrch(arg)

/* Keywords: searching regular-expressions commands key-bindings:10 */

int arg;
{
	register int dir;
	extern char presst[];
	register char *xp;
	register char c;
	int ol,oc;
	int x,y;	
	
	if (arg < 0) {
		dir = -1;
		arg = -arg;
	} else {
		dir = 1;
	}
	ol = curln;
	oc = column;
	if (xp = getname("expr: ")) {	/* get expression */
		if (*xp == 0) xp = presst; /* last string */
		prompt1("expr: %s",xp);
		while(rgsrch(curln,column,xp,(arg == 1),dir)) {
			move(kline,kcol);
			ol = curln;
			oc = column;
			strcpy(presst,xp);
			if (infrn == 0) {
				disup();
				x = mline;
				y = mcol;
				prompt1("expr: %s",xp);
				mgo(x,y);
				c = getchar();
			} else return(1);
			
			if (x=issrch(c)) {
				dir=x;
				forw(dir);
			} else {
				unprompt();
				ungetch(c);
				return(1);
			}
		}
		prompt1("Search failed");
		move(ol,oc);
		if (infrn >=0) beep();
	}
	return(0);
}

/* rgsrch -- regular expression search */

rgsrch(froml,fromc,cp,wrap,dir)
int froml;
int fromc;
int wrap;
register int dir;
char *cp;

/* Keywords: regular-expressions searching query-replace:20 */

{
	register int en;
	char rebuf[RESIZE];
	register int beg;
	char *lp;
	
	lp = cp;
	while (beg = *lp) *lp++ = casem[beg&0177]; /* map string to allowed case */
	if (*cp == '^') {
		cp++;
		beg = 1;
	} else beg = 0;
	if (en = compile(cp,rebuf)) { /* if format error */
		error(WARN,en);
		return(0);
	}
	kline = froml;
	kcol = fromc;

	while (1) {
		if (brkflg) brkit();
		klptr = mkline(kline);
		if (beg) {
			if ((kcol == 0) || (dir<0)) {
				kcol = 0;
				if(advance(klptr,rebuf)) {
					loc1 = klptr+kcol;
					return(1);
				}
			}
		} else { 
			while (1) {
				if ((rebuf[0] != CCHR) || (rebuf[1] == casem[klptr[kcol]&0177])) {

					if (advance(klptr+kcol, rebuf)) {

/* The following line rejects an attempt to match the last newline in the buffer */
						if ((kline == nlines) && klptr[kcol] == EOL) goto nomatch;
						loc1 = klptr+kcol;
						return(1);
					}
				}
				if (dir>0) {
					if (klptr[kcol] == EOL) goto nomatch;
					else kcol++;
				} else {
					if (kcol == 0) goto nomatch;
					else kcol--;
				}
				if ((kline == froml) && (kcol == fromc)) return(0);
			}
		}
nomatch:	kline += dir;
		if (wrap) {
			if (kline > nlines) kline = 1;
			if (kline < 1) kline = nlines;

		} else {
			if ((kline > nlines) || (kline <1)) return(0);
		}
		if (beg || (dir>0))  kcol = 0;
		else kcol = leng(kline);
		if (wrap && (kline == froml) && (kcol == fromc)) return(0);
		if (beg && (kline == froml)) return(0);
	}
}			

/* regrep -- replace sub expression */
/* assumes last deleted text is in the kill stack, pointers set up */

regrep(i)

register int i;

/* Keywords: query-replace commands regular-expressions */


{
	register int x;
	register int y;
	
	if (i <= closed) {
		yank(1);		/* bring back everything */
		y = braslist[i]-loc1;	/* length to kill */		
		back(y);	/* adjust mark position correctly */
		
		exch(1);		/* back to beggining */
		fdel(y);		 /* kill first part */
		kpop();
		forw(braelist[i]-braslist[i]);
		mkill(1);		/* now kill the rest */
		kpop();
		unpop(3);		/* Remove from the undo stack */
		return(1);
	} else return(0);
}