V10/cmd/gre/egcanon.c

#include	"re.h"
#include	"lre.h"
#include	"hdr.h"

#define 	DEBUG

static Expr **proot;

#define	PURE(e)		(!(e)->backref && !(e)->parens)
#define	PROC(kid)	if(ee = proc(kid)){ ee->parent = (kid)->parent; free((char *)kid); kid = ee; }

static Expr *
proc(Expr *e)
{
	Expr *ee;

	if(e->type == Cat){
		if(PURE(e->l)){
			if(proot){
				*proot = eg_newexpr(Cat, 0, *proot, e->l);
				return((ee = proc(e->r))? ee:e->r);
			} else
				proot = &e->l;
		} else {
			PROC(e->l)
		}
		if(PURE(e->r)){
			if(proot){
				*proot = eg_newexpr(Cat, 0, *proot, e->r);
				return(e->l);
			} else
				proot = &e->r;
		} else {
			PROC(e->r)
		}
		return(0);
	}
	proot = 0;
	switch(e->type)
	{
	case Alternate:
		PROC(e->l)
		proot = 0;
		PROC(e->r)
		break;
	case Star:
	case Plus:
	case Quest:
	case EOP:
	case Group:
		PROC(e->l)
		break;
	}
	proot = 0;
	return(0);
}

void
egcanon(Expr *e)
{
#ifdef	DEBUG
	char before[EPRINTSIZE], after[EPRINTSIZE];
#endif

#ifdef	DEBUG
	eg_epr(e, before, 0);
	if(TRACE(3)){
		PR "egcanon(%s):\n", before);
	}
#endif
	proot = 0;
	if(!PURE(e))
		proc(e);
#ifdef	DEBUG
	eg_epr(e, after, 0);
	if(TRACE(3)){
		PR "egcanon returns %s\n", after);
	}
	if(strcmp(before, after)){
		EPR "URK! egcanon did not preserve!\nbefore=%s\n after=%s\n", before, after);
		exit(1);
	}
#endif
}