microEmacs

boesch at Shasta.UUCP boesch at Shasta.UUCP
Wed Mar 4 10:05:21 AEST 1987


----
In article <1261 at dataio.Data-IO.COM> bright at dataio.Data-IO.COM (Walter Bright) writes:
>Here's a microEmacs function I wrote to add a toggling over parentheses
>and brackets command.
>Bind to your favorite keystroke and enjoy!
>
Thanks to Walter for writing this utility for UEMACS.
I added a simple state machine to allow his brace matcher to 
ignore occurences of the target characters in C comments or strings.
(I've set it up to only do this in CMODE because other languages
have different comment and string formats).

It correctly handles even nasty strings and strings that cross
line boundaries.  Ie:
      ptr = "I will not be confused by \
this construct } ";

Here is the source:

#include        <stdio.h>
#include	"estruct.h"
#include        "edef.h"


/*********************************
 * Search for the next occurence of the character at dot.
 * If character is a (){}[]<>, search for matching bracket, taking
 * proper account of nesting.
 * Written by Walter Bright.
 */

static int searchstate;
int searchparen(f, n)
    {
    register LINE *clp;
    register int cbo;
    register int len;
    register int i;
    char chinc,chdec,ch;
    int count;
    int forward;
    static char bracket[][2] = {{'(',')'},{'<','>'},{'[',']'},{'{','}'}};

    clp = curwp->w_dotp;		/* get pointer to current line	*/
    cbo = curwp->w_doto;		/* and offset into that line	*/
    count = 0;

    len = llength(clp);
    if (cbo >= len)
	chinc = '\n';
    else
	chinc = lgetc(clp,cbo);

    forward = TRUE;			/* assume search forward	*/
    chdec = chinc;
    for (i = 0; i < 4; i++)
	if (bracket[i][0] == chinc)
	{	chdec = bracket[i][1];
		break;
	}
    for (i = 0; i < 4; i++)
	if (bracket[i][1] == chinc)
	{	chdec = bracket[i][0];
		forward = FALSE;	/* search backwards		*/
		break;
	}

    searchstate = 0;       /* start state for ignore */
    
    while (1)
    {
	if (forward)
	{
	    if (cbo >= len)
	    {	/* proceed to next line */
		clp = lforw(clp);
		if (clp == curbp->b_linep)	/* if end of buffer	*/
		    break;
		len = llength(clp);
		cbo = 0;
	    }
	    else
		cbo++;
	}
	else /* backward */
	{
	    if (cbo == 0)
            {
		clp = lback(clp);
		if (clp == curbp->b_linep)
		    break;
		len = llength(clp);
		cbo = len;
            }
	    else
		--cbo;
	}

	ch = (cbo < len) ? lgetc(clp,cbo) : '\n';
	if (!searchignore(ch,forward)) 
	    {
	    if (eq(ch,chdec))
        	{   if (count-- == 0)
	            {
		    /* We've found it	*/
	            curwp->w_dotp  = clp;
	            curwp->w_doto  = cbo;
	            curwp->w_flag |= WFMOVE;
	            return (TRUE);
	            }
	        }
	else if (eq(ch,chinc))
	    count++;
        }
    }
    mlwrite("Not found");
    return (FALSE);
}

/* this routine determines when to ignore characters */
/* ie. those in comments and those in quotes         */
static searchstatus;

struct statetrans {
    int bslash;
    int fslash;
    int quote;
    int dquote;
    int star;
    int nl;
    int other;
    int ignore;
}  statetrans[] =     { /* bsl fsl quo dqu sta  nl oth ign */
    /* 0 normal         */  {0, 1,  4,  6,  0,  0,  0,  0},
    /* 1 normal seen /  */  {0, 1,  4,  6,  2,  0,  0,  0},
    /* 2 comment        */  {2, 2,  2,  2,  3,  2,  2,  1},
    /* 3 comment seen * */  {2, 0,  2,  2,  3,  2,  2,  1},
    /* 4 quote          */  {5, 4,  0,  4,  4,  0,  4,  1},
    /* 5 quote seen \   */  {4, 4,  4,  4,  4,  4,  4,  1},
    /* 6 string         */  {7, 6,  6,  0,  6,  0,  6,  1},
    /* 7 string seen \  */  {6, 6,  6,  6,  6,  6,  6,  1},

    /* backwards state diagram */ 
                        /* bsl fsl quo dqu sta  nl oth ign */
    /* 0 normal         */  {0, 1,  4,  6,  0,  0,  0,  0},
    /* 1 normal seen /  */  {0, 1,  4,  6,  2,  0,  0,  0},
    /* 2 comment        */  {2, 2,  2,  2,  3,  2,  2,  1},
    /* 3 comment seen * */  {2, 0,  2,  2,  3,  2,  2,  1},
    /* 4 quote          */  {4, 4,  5,  4,  4,  5,  4,  1},
    /* 5 quote seen end */  {4, 0,  0,  0,  0,  0,  0,  0},
    /* 6 string         */  {6, 6,  6,  7,  6,  7,  6,  1},
    /* 7 string seen end*/  {6, 0,  0,  0,  0,  0,  0,  0}
};

static int
searchignore(ch, forward)
    int forward;
    int ch;
{
    int lss = searchstate;      /* local search state */
    
    /* if not cmode check all chars */
    if (!(curbp->b_mode & MDCMOD)) return (0); 

    if (!forward) lss += 8;     /* switch to backward table */

    switch(ch) {
    case '\\': searchstate = statetrans[lss].bslash; break;
    case '/' : searchstate = statetrans[lss].fslash; break;
    case '\'': searchstate = statetrans[lss].quote;  break;
    case '"' : searchstate = statetrans[lss].dquote; break;
    case '*' : searchstate = statetrans[lss].star;   break;
    case '\n': searchstate = statetrans[lss].nl;     break;
    default  : searchstate = statetrans[lss].other;  break;
    }    
    return(statetrans[lss].ignore);
}

/* END OF SOURCE */



More information about the Comp.sources.unix mailing list