File:  [MW Coherent from dump] / coherent / g / usr / bin / me / bracket.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:35 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * This routine gets a bracket character from where the dot lies
 * and searches for the corresponding bracket.
 */
#include	<stdio.h>
#include	"ed.h"

static int o_col, o_row, r_col, r_char, r_row = -1;

/*
 * This is called before each comand is executed.
 */
bracketoff()
{
	if (bind.bracket && (r_row >= 0)) {
		tmove(r_row, r_col);
		tputc(r_char);
		r_row = -1;
		tmove(o_row, o_col);
		return (TRUE);
	}
	return (FALSE);
}

/*
 * toggle bracket mode.
 */
bracketsw()
{
	bind.bracket ^= 1;
}

bracketsearch()
{
	bstart(0);	/* do full search */
}

/*
 * This is called after each screen update.
 */
bracketmode(row, col)
{
	r_row = -1;
	if (bind.bracket)
		bstart(1);
	movecursor(row, col);
	tmove(o_row = row, o_col = col);
}

static
bstart(modesw)
{
	register LINE	*clp;
	int	cbo;

	if (((o_col = cbo = curwp->w_doto) == llength(clp = curwp->w_dotp)))
		if (modesw)
			--cbo;
		else
			return (FALSE);

	switch (lgetc(clp, cbo)) {
	case '/':
		if ((++cbo == llength(clp)) || ('*' != lgetc(clp, cbo--)))
			break;
	case '[':
	case '{':
	case '(':
		return (brksearch(1, modesw, clp, cbo));
	case '*':
		if ((++cbo == llength(clp)) || ('/' != lgetc(clp, cbo)))
			break;
	case ']':
	case '}':
	case ')':
		return (brksearch(-1, modesw, clp, cbo));
	case '"':
	case '\'':
		if (modesw)
			break;
		if (mlyesno("Forward search"))
			return (brksearch(1, modesw, clp, cbo));
		return (brksearch(-1, modesw, clp, cbo));
	}
	if (!modesw)
		mlwrite("Place dot on \"'(){}[] /* or */");
	return (FALSE);
}

/* defines for states of forward and backward searches */
#define NORMAL		0	/* normal state */
#define SLASH		1	/* slash maybe comment */
#define COMMENT	2	/* comment */
#define STAR		3	/* star in comment */
#define DQUOTE		4	/* in string */
#define SQUOTE		5	/* in single quote */
#define BSL			6	/* backslash */
#define BADEXPR	7	/* bad expression encountered */
#define STARTB		8	/* starting search */

/*
 * scan for end of balanced c expression forward or backward.
 */
static
brksearch(dir, mode, clp, cbo)
int dir;	/* 1 forward -1 backward */
int mode;	/* 1 paren mode, 0 match paren command */
LINE *clp;	/* line to start search */
int cbo;	/* char to start search */
{
	register int c, state;
	LINE *end;
	int prev, pstate, bcnt, pcnt, ccnt, bscnt, ctrs;

	bcnt = ccnt = pcnt = bscnt = 0;
	state = STARTB;
	if (mode) {	/* end is top or bottom of window */
		if (dir < 0)
			end = lback(curwp->w_linep);
		else
			for (end = curwp->w_linep, c = curwp->w_ntrows;
			    (c-- > 0) && (curbp->b_linep != end);
			    end = lforw(end)) ;
	} else	/* end is buffer end */
		end = curbp->b_linep;

	while (clp != end) {
		if (dir > 0) { /* get next char */
			if (cbo == llength(clp)) {
				clp = lforw(clp);
				cbo = 0;
				c = '\n';
			} else
				c = lgetc(clp, cbo++);
		} else { /* get prev char. watch \ here. */
			c = prev;
			if (cbo < 0) {
				clp = lback(clp);
				cbo = llength(clp) - 1;
				prev = '\n';
			}
			else if (('\\' == (prev = lgetc(clp, cbo--))) &&
				(state != COMMENT) && (state != SLASH)) {
				bscnt ^= 1;	/* count \ */
				prev = c; /* don't discard char */
				continue;
			}
			if (bscnt) { /* odd \ discard c */
				bscnt = 0;
				continue;
			}
		}

		switch (state) {	/* do state processing */
		case SLASH:		/* / encountered */
			if (c == '*') {
				state = COMMENT;
				continue;
			}
			state = NORMAL;
		case NORMAL:		/* not in anything */
			break;
		case STAR:		/* * in comment */
			if (c == '/') {
				state = NORMAL;
				goto processed;
			}
			state = COMMENT;
		case COMMENT:		/* in comment */
			if (c == '*')
				state = STAR;
			continue;
		case SQUOTE:		/* in ' string */
		case DQUOTE:		/* in " string */
			switch (c) {
			case '\n':
				state = BADEXPR;
				goto processed;
			case '\\':	/* can't get here if dir < 0 */
				pstate = state;
				state = BSL;
				continue;
			case '"':
				if (state != DQUOTE)
					continue;
				state = NORMAL;
				goto processed;
			case '\'':
				if (state != SQUOTE)
					continue;
				state = NORMAL;
				goto processed;
			default:
				continue;
			}
		case BSL:	/* can't get here if dir < 0 */
			state = pstate;
			continue;
		case STARTB:
			state = NORMAL;
			if (dir < 0)
				continue;
		}	

		switch (c) { /* process chars in NORMAL state */
		case '[':
			bcnt += dir;
			break;
		case '{':
			ccnt += dir;
			if (pcnt | bcnt)
				state = BADEXPR;
			break;
		case ';':
			if (bcnt)
				state = BADEXPR;
			break;
		case '(':
			pcnt += dir;
			break;
		case '"':
			state = DQUOTE;
			continue;
		case '\'':
			state = SQUOTE;
			continue;
		case '\\':	/* can't get here if dir < 0 */
			pstate = state;
			state = BSL;
			continue;
		case '/':
			state = SLASH;
			continue;
		case ']':
			bcnt -= dir;
			break;
		case '}':
			ccnt -= dir;
			if (pcnt | bcnt)
				state = BADEXPR;
			break;
		case ')':
			pcnt -= dir;
		}

		/* done if BADEXPR or balanced expr or ) with no ( etc */
processed:	if (((ctrs = bcnt | ccnt | pcnt) <= 0) || (state == BADEXPR)) {
			if (dir > 0) {
				if (--cbo < 0) {
					clp = lback(clp);
					cbo = llength(clp);
				}
			} else { /* we are on prev so back up 2 */
				for (bscnt = 0; bscnt < 2; bscnt++) {
					if (++cbo > llength(clp)) {
						clp = lforw(clp);
						cbo = 0;
						break;
					}
				}
			}
			if (mode) { /* paren mode */
				if ((ctrs < 0) || (state == BADEXPR) ||
				   (0 > (r_row = locatecursor(clp))))
					return (FALSE);
				tmove(r_row, (r_col = truecol(clp, cbo)));
				tstand(1);
				tputc(r_char = c);
				tstand(0);
			} else { /* match paren command */
				curwp->w_dotp = clp;
				curwp->w_doto = cbo;
				curwp->w_flag |= WFMOVE;
				if ((ctrs < 0) || (state == BADEXPR)) {
					mlwrite("Bad expression");
					return (FALSE);
				}
			}
			return (TRUE);
		}
	}
	if (!mode)
		mlwrite("End not found");
	return (FALSE);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.