xref: /plan9-contrib/sys/src/cmd/spin/pangen4.h (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
17dd7cddfSDavid du Colombier /***** spin: pangen4.h *****/
27dd7cddfSDavid du Colombier 
3*de2caf28SDavid du Colombier /*
4*de2caf28SDavid du Colombier  * This file is part of the public release of Spin. It is subject to the
5*de2caf28SDavid du Colombier  * terms in the LICENSE file that is included in this source directory.
6*de2caf28SDavid du Colombier  * Tool documentation is available at http://spinroot.com
7*de2caf28SDavid du Colombier  *
8*de2caf28SDavid du Colombier  * The DFA code below was written by Anuj Puri and Gerard J. Holzmann in
9*de2caf28SDavid du Colombier  * May 1997, and was inspired by earlier work on data compression using
10*de2caf28SDavid du Colombier  * sharing tree data structures and graph-encoded sets by J-Ch. Gregoire
11*de2caf28SDavid du Colombier  * (INRS Telecom, Quebec, Canada) and D.Zampunieris (Univ.Namur, Belgium)
12*de2caf28SDavid du Colombier  * The splay routine code included here is based on the public domain
13*de2caf28SDavid du Colombier  * version written by D. Sleator <sleator@cs.cmu.edu> in 1992.
14*de2caf28SDavid du Colombier  */
157dd7cddfSDavid du Colombier 
16*de2caf28SDavid du Colombier static const char *Dfa[] = {
177dd7cddfSDavid du Colombier 	"#ifdef MA",
18*de2caf28SDavid du Colombier #if 0
197dd7cddfSDavid du Colombier 	"/*",
207dd7cddfSDavid du Colombier 	"#include <stdio.h>",
217dd7cddfSDavid du Colombier 	"#define uchar	unsigned char",
227dd7cddfSDavid du Colombier 	"*/",
237dd7cddfSDavid du Colombier 	"#define ulong	unsigned long",
247dd7cddfSDavid du Colombier 	"#define ushort	unsigned short",
257dd7cddfSDavid du Colombier 	"",
26*de2caf28SDavid du Colombier #endif
277dd7cddfSDavid du Colombier 	"#define TWIDTH		256",
28f3793cddSDavid du Colombier 	"#define HASH(y,n)	(n)*(((long)y))",
297dd7cddfSDavid du Colombier 	"#define INRANGE(e,h)	((h>=e->From && h<=e->To)||(e->s==1 && e->S==h))",
307dd7cddfSDavid du Colombier 	"",
317dd7cddfSDavid du Colombier 	"extern char	*emalloc(unsigned long);	/* imported routine  */",
327dd7cddfSDavid du Colombier 	"extern void	dfa_init(ushort);	/* 4 exported routines */",
33312a1df1SDavid du Colombier 	"extern int	dfa_member(ulong);",
347dd7cddfSDavid du Colombier 	"extern int	dfa_store(uchar *);",
357dd7cddfSDavid du Colombier 	"extern void	dfa_stats(void);",
367dd7cddfSDavid du Colombier 	"",
377dd7cddfSDavid du Colombier 	"typedef struct Edge {",
387dd7cddfSDavid du Colombier 	"	uchar From, To;		/* max range 0..255 */",
397dd7cddfSDavid du Colombier 	"	uchar s, S;		/* if s=1, S is singleton */",
407dd7cddfSDavid du Colombier 	"	struct Vertex	*Dst;",
417dd7cddfSDavid du Colombier 	"	struct Edge	*Nxt;",
427dd7cddfSDavid du Colombier 	"} Edge;",
437dd7cddfSDavid du Colombier 	"",
447dd7cddfSDavid du Colombier 	"typedef struct Vertex {",
457dd7cddfSDavid du Colombier 	"	ulong	key, num;	/* key for splay tree, nr incoming edges */",
467dd7cddfSDavid du Colombier 	"	uchar	from[2], to[2];	/* in-node predefined edge info    */",
477dd7cddfSDavid du Colombier 	"	struct	Vertex	*dst[2];/* most nodes have 2 or more edges */",
487dd7cddfSDavid du Colombier 	"	struct	Edge	*Succ;	/* in case there are more edges */",
497dd7cddfSDavid du Colombier 	"	struct	Vertex	*lnk, *left, *right; /* splay tree plumbing */",
507dd7cddfSDavid du Colombier 	"} Vertex;",
517dd7cddfSDavid du Colombier 	"",
527dd7cddfSDavid du Colombier 	"static Edge	*free_edges;",
537dd7cddfSDavid du Colombier 	"static Vertex	*free_vertices;",
547dd7cddfSDavid du Colombier 	"static Vertex	**layers;	/* one splay tree of nodes per layer */",
557dd7cddfSDavid du Colombier 	"static Vertex	**path;		/* run of word in the DFA */",
567dd7cddfSDavid du Colombier 	"static Vertex	*R, *F, *NF;	/* Root, Final, Not-Final */",
577dd7cddfSDavid du Colombier 	"static uchar	*word, *lastword;/* string, and last string inserted */",
587dd7cddfSDavid du Colombier 	"static int	dfa_depth, iv=0, nv=0, pfrst=0, Tally;",
597dd7cddfSDavid du Colombier 	"",
607dd7cddfSDavid du Colombier 	"static void	insert_it(Vertex *, int);	/* splay-tree code */",
617dd7cddfSDavid du Colombier 	"static void	delete_it(Vertex *, int);",
627dd7cddfSDavid du Colombier 	"static Vertex	*find_it(Vertex *, Vertex *, uchar, int);",
637dd7cddfSDavid du Colombier 	"",
647dd7cddfSDavid du Colombier 	"static void",
657dd7cddfSDavid du Colombier 	"recyc_edges(Edge *e)",
667dd7cddfSDavid du Colombier 	"{",
677dd7cddfSDavid du Colombier 	"	if (!e) return;",
687dd7cddfSDavid du Colombier 	"	recyc_edges(e->Nxt);",
697dd7cddfSDavid du Colombier 	"	e->Nxt = free_edges;",
707dd7cddfSDavid du Colombier 	"	free_edges = e;",
717dd7cddfSDavid du Colombier 	"}",
727dd7cddfSDavid du Colombier 	"",
737dd7cddfSDavid du Colombier 	"static Edge *",
747dd7cddfSDavid du Colombier 	"new_edge(Vertex *dst)",
757dd7cddfSDavid du Colombier 	"{	Edge *e;",
767dd7cddfSDavid du Colombier 	"",
777dd7cddfSDavid du Colombier 	"	if (free_edges)",
787dd7cddfSDavid du Colombier 	"	{	e = free_edges;",
797dd7cddfSDavid du Colombier 	"		free_edges = e->Nxt;",
807dd7cddfSDavid du Colombier 	"		e->From = e->To = e->s = e->S = 0;",
817dd7cddfSDavid du Colombier 	"		e->Nxt = (Edge *) 0;",
827dd7cddfSDavid du Colombier 	"	} else",
837dd7cddfSDavid du Colombier 	"		e = (Edge *) emalloc(sizeof(Edge));",
847dd7cddfSDavid du Colombier 	"	e->Dst = dst;",
857dd7cddfSDavid du Colombier 	"",
867dd7cddfSDavid du Colombier 	"	return e;",
877dd7cddfSDavid du Colombier 	"}",
887dd7cddfSDavid du Colombier 	"",
897dd7cddfSDavid du Colombier 	"static void",
907dd7cddfSDavid du Colombier 	"recyc_vertex(Vertex *v)",
917dd7cddfSDavid du Colombier 	"{",
927dd7cddfSDavid du Colombier 	"	recyc_edges(v->Succ);",
937dd7cddfSDavid du Colombier 	"	v->Succ = (Edge *) free_vertices;",
947dd7cddfSDavid du Colombier 	"	free_vertices = v;",
957dd7cddfSDavid du Colombier 	"	nr_states--;",
967dd7cddfSDavid du Colombier 	"}",
977dd7cddfSDavid du Colombier 	"",
987dd7cddfSDavid du Colombier 	"static Vertex *",
997dd7cddfSDavid du Colombier 	"new_vertex(void)",
1007dd7cddfSDavid du Colombier 	"{	Vertex *v;",
1017dd7cddfSDavid du Colombier 	"",
1027dd7cddfSDavid du Colombier 	"	if (free_vertices)",
1037dd7cddfSDavid du Colombier 	"	{	v = free_vertices;",
1047dd7cddfSDavid du Colombier 	"		free_vertices = (Vertex *) v->Succ;",
1057dd7cddfSDavid du Colombier 	"		v->Succ = (Edge *) 0;",
1067dd7cddfSDavid du Colombier 	"		v->num  = 0;",
1077dd7cddfSDavid du Colombier 	"	} else",
1087dd7cddfSDavid du Colombier 	"		v = (Vertex *) emalloc(sizeof(Vertex));",
1097dd7cddfSDavid du Colombier 	"",
1107dd7cddfSDavid du Colombier 	"	nr_states++;",
1117dd7cddfSDavid du Colombier 	"	return v; ",
1127dd7cddfSDavid du Colombier 	"}",
1137dd7cddfSDavid du Colombier 	"",
1147dd7cddfSDavid du Colombier 	"static Vertex *",
1157dd7cddfSDavid du Colombier 	"allDelta(Vertex *v, int n)",
1167dd7cddfSDavid du Colombier 	"{	Vertex *dst = new_vertex();",
1177dd7cddfSDavid du Colombier 	"",
1187dd7cddfSDavid du Colombier 	"	v->from[0] = 0;",
1197dd7cddfSDavid du Colombier 	"	v->to[0] = 255;",
1207dd7cddfSDavid du Colombier 	"	v->dst[0] = dst;",
1217dd7cddfSDavid du Colombier 	"	dst->num = 256;",
1227dd7cddfSDavid du Colombier 	"	insert_it(v, n);",
1237dd7cddfSDavid du Colombier 	"	return dst;",
1247dd7cddfSDavid du Colombier 	"}",
1257dd7cddfSDavid du Colombier 	"",
1267dd7cddfSDavid du Colombier 	"static void",
1277dd7cddfSDavid du Colombier 	"insert_edge(Vertex *v, Edge *e)",
1287dd7cddfSDavid du Colombier 	"{	/* put new edge first */",
1297dd7cddfSDavid du Colombier 	"	if (!v->dst[0])",
1307dd7cddfSDavid du Colombier 	"	{	v->dst[0] = e->Dst;",
1317dd7cddfSDavid du Colombier 	"		v->from[0] = e->From;",
1327dd7cddfSDavid du Colombier 	"		v->to[0] = e->To;",
1337dd7cddfSDavid du Colombier 	"		recyc_edges(e);",
1347dd7cddfSDavid du Colombier 	"		return;",
1357dd7cddfSDavid du Colombier 	"	}",
1367dd7cddfSDavid du Colombier 	"	if (!v->dst[1])",
1377dd7cddfSDavid du Colombier 	"	{	v->from[1] = v->from[0]; v->from[0] = e->From;",
1387dd7cddfSDavid du Colombier 	"		v->to[1]   = v->to[0];   v->to[0]   = e->To;",
1397dd7cddfSDavid du Colombier 	"		v->dst[1]  = v->dst[0];  v->dst[0]  = e->Dst;",
1407dd7cddfSDavid du Colombier 	"		recyc_edges(e);",
1417dd7cddfSDavid du Colombier 	"		return;",
1427dd7cddfSDavid du Colombier 	"	} /* shift */",
1437dd7cddfSDavid du Colombier 	"	{	int f      = v->from[1];",
1447dd7cddfSDavid du Colombier 	"		int t      = v->to[1];",
1457dd7cddfSDavid du Colombier 	"		Vertex *d  = v->dst[1];",
1467dd7cddfSDavid du Colombier 	"		v->from[1] = v->from[0]; v->from[0] = e->From;",
1477dd7cddfSDavid du Colombier 	"		v->to[1]   = v->to[0];   v->to[0]   = e->To;",
1487dd7cddfSDavid du Colombier 	"		v->dst[1]  = v->dst[0];  v->dst[0]  = e->Dst;",
1497dd7cddfSDavid du Colombier 	"		e->From = f;",
1507dd7cddfSDavid du Colombier 	"		e->To   = t;",
1517dd7cddfSDavid du Colombier 	"		e->Dst  = d;",
1527dd7cddfSDavid du Colombier 	"	}",
1537dd7cddfSDavid du Colombier 	"	e->Nxt = v->Succ;",
1547dd7cddfSDavid du Colombier 	"	v->Succ = e;",
1557dd7cddfSDavid du Colombier 	"}",
1567dd7cddfSDavid du Colombier 	"",
1577dd7cddfSDavid du Colombier 	"static void",
1587dd7cddfSDavid du Colombier 	"copyRecursive(Vertex *v, Edge *e)",
1597dd7cddfSDavid du Colombier 	"{	Edge *f;",
1607dd7cddfSDavid du Colombier 	"	if (e->Nxt) copyRecursive(v, e->Nxt);",
1617dd7cddfSDavid du Colombier 	"	f = new_edge(e->Dst);",
1627dd7cddfSDavid du Colombier 	"	f->From = e->From;",
1637dd7cddfSDavid du Colombier 	"	f->To   = e->To;",
1647dd7cddfSDavid du Colombier 	"	f->s    = e->s;",
1657dd7cddfSDavid du Colombier 	"	f->S    = e->S;",
1667dd7cddfSDavid du Colombier 	"	f->Nxt  = v->Succ;",
1677dd7cddfSDavid du Colombier 	"	v->Succ = f;",
1687dd7cddfSDavid du Colombier 	"}",
1697dd7cddfSDavid du Colombier 	"",
1707dd7cddfSDavid du Colombier 	"static void",
1717dd7cddfSDavid du Colombier 	"copyEdges(Vertex *to, Vertex *from)",
1727dd7cddfSDavid du Colombier 	"{	int i;",
1737dd7cddfSDavid du Colombier 	"	for (i = 0; i < 2; i++)",
1747dd7cddfSDavid du Colombier 	"	{	to->from[i] = from->from[i];",
1757dd7cddfSDavid du Colombier 	"		to->to[i]   = from->to[i];",
1767dd7cddfSDavid du Colombier 	"		to->dst[i]  = from->dst[i];",
1777dd7cddfSDavid du Colombier 	"	}",
1787dd7cddfSDavid du Colombier 	"	if (from->Succ) copyRecursive(to, from->Succ);",
1797dd7cddfSDavid du Colombier 	"}",
1807dd7cddfSDavid du Colombier 	"",
1817dd7cddfSDavid du Colombier 	"static Edge *",
1827dd7cddfSDavid du Colombier 	"cacheDelta(Vertex *v, int h, int first)",
1837dd7cddfSDavid du Colombier 	"{	static Edge *ov, tmp;  int i;",
1847dd7cddfSDavid du Colombier 	"",
1857dd7cddfSDavid du Colombier 	"	if (!first && INRANGE(ov,h))",
1867dd7cddfSDavid du Colombier 	"		return ov; /* intercepts about 10%% */",
1877dd7cddfSDavid du Colombier 	"	for (i = 0; i < 2; i++)",
1887dd7cddfSDavid du Colombier 	"		if (v->dst[i] && h >= v->from[i] && h <= v->to[i])",
1897dd7cddfSDavid du Colombier 	"		{	tmp.From = v->from[i];",
1907dd7cddfSDavid du Colombier 	"			tmp.To   = v->to[i];",
1917dd7cddfSDavid du Colombier 	"			tmp.Dst  = v->dst[i];",
1927dd7cddfSDavid du Colombier 	"			tmp.s    =  tmp.S = 0;",
1937dd7cddfSDavid du Colombier 	"			ov = &tmp;",
1947dd7cddfSDavid du Colombier 	"			return ov;",
1957dd7cddfSDavid du Colombier 	"		}",
1967dd7cddfSDavid du Colombier 	"	for (ov = v->Succ; ov; ov = ov->Nxt)",
1977dd7cddfSDavid du Colombier 	"		if (INRANGE(ov,h)) return ov;",
1987dd7cddfSDavid du Colombier 	"",
1997dd7cddfSDavid du Colombier 	"	Uerror(\"cannot get here, cacheDelta\");",
2007dd7cddfSDavid du Colombier 	"	return (Edge *) 0;",
2017dd7cddfSDavid du Colombier 	"}",
2027dd7cddfSDavid du Colombier 	"",
2037dd7cddfSDavid du Colombier 	"static Vertex *",
2047dd7cddfSDavid du Colombier 	"Delta(Vertex *v, int h)	/* v->delta[h] */",
205312a1df1SDavid du Colombier 	"{	Edge *e;",
2067dd7cddfSDavid du Colombier 	"",
2077dd7cddfSDavid du Colombier 	"	if (v->dst[0] && h >= v->from[0] && h <= v->to[0])",
2087dd7cddfSDavid du Colombier 	"		return v->dst[0];	/* oldest edge */",
2097dd7cddfSDavid du Colombier 	"	if (v->dst[1] && h >= v->from[1] && h <= v->to[1])",
2107dd7cddfSDavid du Colombier 	"		return v->dst[1];",
2117dd7cddfSDavid du Colombier 	"	for (e = v->Succ; e; e = e->Nxt)",
2127dd7cddfSDavid du Colombier 	"		if (INRANGE(e,h))",
2137dd7cddfSDavid du Colombier 	"			return e->Dst;",
2147dd7cddfSDavid du Colombier 	"	Uerror(\"cannot happen Delta\");",
2157dd7cddfSDavid du Colombier 	"	return (Vertex *) 0;",
2167dd7cddfSDavid du Colombier 	"}",
2177dd7cddfSDavid du Colombier 	"",
2187dd7cddfSDavid du Colombier 	"static void",
2197dd7cddfSDavid du Colombier 	"numDelta(Vertex *v, int d)",
220312a1df1SDavid du Colombier 	"{	Edge *e;",
221312a1df1SDavid du Colombier 	"	ulong cnt;",
2227dd7cddfSDavid du Colombier 	"	int i;",
2237dd7cddfSDavid du Colombier 	"",
2247dd7cddfSDavid du Colombier 	"	for (i = 0; i < 2; i++)",
2257dd7cddfSDavid du Colombier 	"	if (v->dst[i])",
2267dd7cddfSDavid du Colombier 	"	{	cnt = v->dst[i]->num + d*(1 + v->to[i] - v->from[i]);",
2277dd7cddfSDavid du Colombier 	"		if (d == 1 && cnt < v->dst[i]->num) goto bad;",
2287dd7cddfSDavid du Colombier 	"		v->dst[i]->num = cnt;",
2297dd7cddfSDavid du Colombier 	"	}",
2307dd7cddfSDavid du Colombier 	"	for (e = v->Succ; e; e = e->Nxt)",
2317dd7cddfSDavid du Colombier 	"	{	cnt = e->Dst->num + d*(1 + e->To - e->From + e->s);",
2327dd7cddfSDavid du Colombier 	"		if (d == 1 && cnt < e->Dst->num)",
2337dd7cddfSDavid du Colombier 	"bad:			Uerror(\"too many incoming edges\");",
2347dd7cddfSDavid du Colombier 	"		e->Dst->num = cnt;",
2357dd7cddfSDavid du Colombier 	"	}",
2367dd7cddfSDavid du Colombier 	"}",
2377dd7cddfSDavid du Colombier 	"",
2387dd7cddfSDavid du Colombier 	"static void",
2397dd7cddfSDavid du Colombier 	"setDelta(Vertex *v, int h, Vertex *newdst)	/* v->delta[h] = newdst; */",
2407dd7cddfSDavid du Colombier 	"{	Edge *e, *f = (Edge *) 0, *g;",
2417dd7cddfSDavid du Colombier 	"	int i;",
2427dd7cddfSDavid du Colombier 	"",
2437dd7cddfSDavid du Colombier 	"	/* remove the old entry, if there */",
2447dd7cddfSDavid du Colombier 	"	for (i = 0; i < 2; i++)",
2457dd7cddfSDavid du Colombier 	"		if (v->dst[i] && h >= v->from[i] && h <= v->to[i])",
2467dd7cddfSDavid du Colombier 	"		{	if (h == v->from[i])",
2477dd7cddfSDavid du Colombier 	"			{	if (h == v->to[i])",
2487dd7cddfSDavid du Colombier 	"				{	v->dst[i] = (Vertex *) 0;",
2497dd7cddfSDavid du Colombier 	"					v->from[i] = v->to[i] = 0;",
2507dd7cddfSDavid du Colombier 	"				} else",
2517dd7cddfSDavid du Colombier 	"					v->from[i]++;",
2527dd7cddfSDavid du Colombier 	"			} else if (h == v->to[i])",
2537dd7cddfSDavid du Colombier 	"			{	v->to[i]--;",
2547dd7cddfSDavid du Colombier 	"			} else",
2557dd7cddfSDavid du Colombier 	"			{	g = new_edge(v->dst[i]);/* same dst */",
2567dd7cddfSDavid du Colombier 	"				g->From    = v->from[i];",
2577dd7cddfSDavid du Colombier 	"				g->To      = h-1;	/* left half */",
2587dd7cddfSDavid du Colombier 	"				v->from[i] = h+1;	/* right half */",
2597dd7cddfSDavid du Colombier 	"				insert_edge(v, g);",
2607dd7cddfSDavid du Colombier 	"			}",
2617dd7cddfSDavid du Colombier 	"			goto part2;",
2627dd7cddfSDavid du Colombier 	"		}",
2637dd7cddfSDavid du Colombier 	"	for (e = v->Succ; e; f = e, e = e->Nxt)",
2647dd7cddfSDavid du Colombier 	"	{	if (e->s == 1 && e->S == h)",
2657dd7cddfSDavid du Colombier 	"		{	e->s = e->S = 0;",
2667dd7cddfSDavid du Colombier 	"			goto rem_tst;",
2677dd7cddfSDavid du Colombier 	"		}",
2687dd7cddfSDavid du Colombier 	"		if (h >= e->From && h <= e->To)",
2697dd7cddfSDavid du Colombier 	"		{	if (h == e->From)",
2707dd7cddfSDavid du Colombier 	"			{	if (h == e->To)",
2717dd7cddfSDavid du Colombier 	"				{	if (e->s)",
2727dd7cddfSDavid du Colombier 	"					{	e->From = e->To = e->S;",
2737dd7cddfSDavid du Colombier 	"						e->s = 0;",
2747dd7cddfSDavid du Colombier 	"						break;",
2757dd7cddfSDavid du Colombier 	"					} else",
2767dd7cddfSDavid du Colombier 	"						goto rem_do;",
2777dd7cddfSDavid du Colombier 	"				} else",
2787dd7cddfSDavid du Colombier 	"					e->From++;",
2797dd7cddfSDavid du Colombier 	"			} else if (h == e->To)",
2807dd7cddfSDavid du Colombier 	"			{	e->To--;",
2817dd7cddfSDavid du Colombier 	"			} else				/* split */",
2827dd7cddfSDavid du Colombier 	"			{	g = new_edge(e->Dst);	/* same dst */",
2837dd7cddfSDavid du Colombier 	"				g->From = e->From;",
2847dd7cddfSDavid du Colombier 	"				g->To   = h-1;		/* g=left half */",
2857dd7cddfSDavid du Colombier 	"				e->From = h+1;		/* e=right half */",
2867dd7cddfSDavid du Colombier 	"				g->Nxt  = e->Nxt;	/* insert g */",
2877dd7cddfSDavid du Colombier 	"				e->Nxt  = g;		/* behind e */",
2887dd7cddfSDavid du Colombier 	"				break;			/* done */",
2897dd7cddfSDavid du Colombier 	"			}",
2907dd7cddfSDavid du Colombier 	"",
2917dd7cddfSDavid du Colombier 	"rem_tst:		if (e->From > e->To)",
2927dd7cddfSDavid du Colombier 	"			{	if (e->s == 0) {",
2937dd7cddfSDavid du Colombier 	"rem_do:				if (f)",
2947dd7cddfSDavid du Colombier 	"						f->Nxt = e->Nxt;",
2957dd7cddfSDavid du Colombier 	"					else",
2967dd7cddfSDavid du Colombier 	"						v->Succ = e->Nxt;",
2977dd7cddfSDavid du Colombier 	"					e->Nxt = (Edge *) 0;",
2987dd7cddfSDavid du Colombier 	"					recyc_edges(e);",
2997dd7cddfSDavid du Colombier 	"				} else",
3007dd7cddfSDavid du Colombier 	"				{	e->From = e->To = e->S;",
3017dd7cddfSDavid du Colombier 	"					e->s = 0;",
3027dd7cddfSDavid du Colombier 	"			}	}",
3037dd7cddfSDavid du Colombier 	"			break;",
3047dd7cddfSDavid du Colombier 	"	}	}",
3057dd7cddfSDavid du Colombier 	"part2:",
3067dd7cddfSDavid du Colombier 	"	/* check if newdst is already there */",
3077dd7cddfSDavid du Colombier 	"	for (i = 0; i < 2; i++)",
3087dd7cddfSDavid du Colombier 	"		if (v->dst[i] == newdst)",
3097dd7cddfSDavid du Colombier 	"		{	if (h+1 == (int) v->from[i])",
3107dd7cddfSDavid du Colombier 	"			{	v->from[i] = h;",
3117dd7cddfSDavid du Colombier 	"				return;",
3127dd7cddfSDavid du Colombier 	"			}",
3137dd7cddfSDavid du Colombier 	"			if (h == (int) v->to[i]+1)",
3147dd7cddfSDavid du Colombier 	"			{	v->to[i] = h;",
3157dd7cddfSDavid du Colombier 	"				return;",
3167dd7cddfSDavid du Colombier 	"		}	}",
3177dd7cddfSDavid du Colombier 	"	for (e = v->Succ; e; e = e->Nxt)",
3187dd7cddfSDavid du Colombier 	"	{	if (e->Dst == newdst)",
3197dd7cddfSDavid du Colombier 	"		{	if (h+1 == (int) e->From)",
3207dd7cddfSDavid du Colombier 	"			{	e->From = h;",
3217dd7cddfSDavid du Colombier 	"				if (e->s == 1 && e->S+1 == e->From)",
3227dd7cddfSDavid du Colombier 	"				{	e->From = e->S;",
3237dd7cddfSDavid du Colombier 	"					e->s = e->S = 0;",
3247dd7cddfSDavid du Colombier 	"				}",
3257dd7cddfSDavid du Colombier 	"				return;",
3267dd7cddfSDavid du Colombier 	"			}",
3277dd7cddfSDavid du Colombier 	"			if (h == (int) e->To+1)",
3287dd7cddfSDavid du Colombier 	"			{	e->To = h;",
3297dd7cddfSDavid du Colombier 	"				if (e->s == 1 && e->S == e->To+1)",
3307dd7cddfSDavid du Colombier 	"				{	e->To = e->S;",
3317dd7cddfSDavid du Colombier 	"					e->s = e->S = 0;",
3327dd7cddfSDavid du Colombier 	"				}",
3337dd7cddfSDavid du Colombier 	"				return;",
3347dd7cddfSDavid du Colombier 	"			}",
3357dd7cddfSDavid du Colombier 	"			if (e->s == 0)",
3367dd7cddfSDavid du Colombier 	"			{	e->s = 1;",
3377dd7cddfSDavid du Colombier 	"				e->S = h;",
3387dd7cddfSDavid du Colombier 	"				return;",
3397dd7cddfSDavid du Colombier 	"	}	}	}",
3407dd7cddfSDavid du Colombier 	"	/* add as a new edge */",
3417dd7cddfSDavid du Colombier 	"	e = new_edge(newdst);",
3427dd7cddfSDavid du Colombier 	"	e->From = e->To = h;",
3437dd7cddfSDavid du Colombier 	"	insert_edge(v, e);",
3447dd7cddfSDavid du Colombier 	"}",
3457dd7cddfSDavid du Colombier 	"",
3467dd7cddfSDavid du Colombier 	"static ulong",
3477dd7cddfSDavid du Colombier 	"cheap_key(Vertex *v)",
3487dd7cddfSDavid du Colombier 	"{	ulong vk2 = 0;",
3497dd7cddfSDavid du Colombier 	"",
3507dd7cddfSDavid du Colombier 	"	if (v->dst[0])",
3517dd7cddfSDavid du Colombier 	"	{	vk2 = (ulong) v->dst[0];",
3527dd7cddfSDavid du Colombier 	"		if ((ulong) v->dst[1] > vk2)",
3537dd7cddfSDavid du Colombier 	"			vk2 = (ulong) v->dst[1];",
3547dd7cddfSDavid du Colombier 	"	} else if (v->dst[1])",
3557dd7cddfSDavid du Colombier 	"		vk2 = (ulong) v->dst[1]; ",
3567dd7cddfSDavid du Colombier 	"	if (v->Succ)",
3577dd7cddfSDavid du Colombier 	"	{	Edge *e;",
3587dd7cddfSDavid du Colombier 	"		for (e = v->Succ; e; e = e->Nxt)",
3597dd7cddfSDavid du Colombier 	"			if ((ulong) e->Dst > vk2)",
3607dd7cddfSDavid du Colombier 	"				vk2 = (ulong) e->Dst;",
3617dd7cddfSDavid du Colombier 	"	}",
3627dd7cddfSDavid du Colombier 	"	Tally = (vk2>>2)&(TWIDTH-1);",
3637dd7cddfSDavid du Colombier 	"	return v->key;",
3647dd7cddfSDavid du Colombier 	"}",
3657dd7cddfSDavid du Colombier 	"",
3667dd7cddfSDavid du Colombier 	"static ulong",
3677dd7cddfSDavid du Colombier 	"mk_key(Vertex *v)	/* not sensitive to order */",
368312a1df1SDavid du Colombier 	"{	ulong m = 0, vk2 = 0;",
369312a1df1SDavid du Colombier 	"	Edge *e;",
3707dd7cddfSDavid du Colombier 	"",
3717dd7cddfSDavid du Colombier 	"	if (v->dst[0])",
3727dd7cddfSDavid du Colombier 	"	{	m += HASH(v->dst[0], v->to[0] - v->from[0] + 1);",
3737dd7cddfSDavid du Colombier 	"		vk2 = (ulong) v->dst[0]; ",
3747dd7cddfSDavid du Colombier 	"	}",
3757dd7cddfSDavid du Colombier 	"	if (v->dst[1])",
3767dd7cddfSDavid du Colombier 	"	{	m += HASH(v->dst[1], v->to[1] - v->from[1] + 1);",
3777dd7cddfSDavid du Colombier 	"		if ((ulong) v->dst[1] > vk2) vk2 = (ulong) v->dst[1]; ",
3787dd7cddfSDavid du Colombier 	"	}",
3797dd7cddfSDavid du Colombier 	"	for (e = v->Succ; e; e = e->Nxt)",
3807dd7cddfSDavid du Colombier 	"	{	m += HASH(e->Dst, e->To - e->From + 1 + e->s);",
3817dd7cddfSDavid du Colombier 	"		if ((ulong) e->Dst > vk2) vk2 = (ulong) e->Dst; ",
3827dd7cddfSDavid du Colombier 	"	}",
3837dd7cddfSDavid du Colombier 	"	Tally = (vk2>>2)&(TWIDTH-1);",
3847dd7cddfSDavid du Colombier 	"	return m;",
3857dd7cddfSDavid du Colombier 	"}",
3867dd7cddfSDavid du Colombier 	"",
3877dd7cddfSDavid du Colombier 	"static ulong",
3887dd7cddfSDavid du Colombier 	"mk_special(int sigma, Vertex *n, Vertex *v)",
389312a1df1SDavid du Colombier 	"{	ulong m = 0, vk2 = 0;",
390312a1df1SDavid du Colombier 	"	Edge *f;",
3917dd7cddfSDavid du Colombier 	"	int i;",
3927dd7cddfSDavid du Colombier 	"",
3937dd7cddfSDavid du Colombier 	"	for (i = 0; i < 2; i++)",
3947dd7cddfSDavid du Colombier 	"		if (v->dst[i])",
3957dd7cddfSDavid du Colombier 	"		{	if (sigma >= v->from[i] && sigma <= v->to[i])",
3967dd7cddfSDavid du Colombier 	"			{	m += HASH(v->dst[i], v->to[i]-v->from[i]);",
3977dd7cddfSDavid du Colombier 	"				if ((ulong) v->dst[i] > vk2",
3987dd7cddfSDavid du Colombier 	"				&&   v->to[i] > v->from[i])",
3997dd7cddfSDavid du Colombier 	"					vk2 = (ulong) v->dst[i]; ",
4007dd7cddfSDavid du Colombier 	"			} else",
4017dd7cddfSDavid du Colombier 	"			{	m += HASH(v->dst[i], v->to[i]-v->from[i]+1);",
4027dd7cddfSDavid du Colombier 	"				if ((ulong) v->dst[i] > vk2)",
4037dd7cddfSDavid du Colombier 	"					vk2 = (ulong) v->dst[i]; ",
4047dd7cddfSDavid du Colombier 	"		}	}",
4057dd7cddfSDavid du Colombier 	"	for (f = v->Succ; f; f = f->Nxt)",
4067dd7cddfSDavid du Colombier 	"	{	if (sigma >= f->From && sigma <= f->To)",
4077dd7cddfSDavid du Colombier 	"		{	m += HASH(f->Dst, f->To - f->From + f->s);",
4087dd7cddfSDavid du Colombier 	"			if ((ulong) f->Dst > vk2",
4097dd7cddfSDavid du Colombier 	"			&&   f->To - f->From + f->s > 0)",
4107dd7cddfSDavid du Colombier 	"				vk2 = (ulong) f->Dst; ",
4117dd7cddfSDavid du Colombier 	"		} else if (f->s == 1 && sigma == f->S)",
4127dd7cddfSDavid du Colombier 	"		{	m += HASH(f->Dst, f->To - f->From + 1);",
4137dd7cddfSDavid du Colombier 	"			if ((ulong) f->Dst > vk2) vk2 = (ulong) f->Dst; ",
4147dd7cddfSDavid du Colombier 	"		} else",
4157dd7cddfSDavid du Colombier 	"		{	m += HASH(f->Dst, f->To - f->From + 1 + f->s);",
4167dd7cddfSDavid du Colombier 	"			if ((ulong) f->Dst > vk2) vk2 = (ulong) f->Dst; ",
4177dd7cddfSDavid du Colombier 	"	}	}",
4187dd7cddfSDavid du Colombier 	"",
4197dd7cddfSDavid du Colombier 	"	if ((ulong) n > vk2) vk2 = (ulong) n; ",
4207dd7cddfSDavid du Colombier 	"	Tally = (vk2>>2)&(TWIDTH-1);",
4217dd7cddfSDavid du Colombier 	"	m += HASH(n, 1);",
4227dd7cddfSDavid du Colombier 	"	return m;",
4237dd7cddfSDavid du Colombier 	"}",
4247dd7cddfSDavid du Colombier 	"",
4257dd7cddfSDavid du Colombier 	"void ",
4267dd7cddfSDavid du Colombier 	"dfa_init(ushort nr_layers)",
4277dd7cddfSDavid du Colombier 	"{	int i; Vertex *r, *t;",
4287dd7cddfSDavid du Colombier 	"",
4297dd7cddfSDavid du Colombier 	"	dfa_depth = nr_layers;	/* one byte per layer */",
4307dd7cddfSDavid du Colombier 	"	path   = (Vertex **) emalloc((dfa_depth+1)*sizeof(Vertex *));",
4317dd7cddfSDavid du Colombier 	"	layers = (Vertex **) emalloc(TWIDTH*(dfa_depth+1)*sizeof(Vertex *));",
4327dd7cddfSDavid du Colombier 	"	lastword = (uchar *) emalloc((dfa_depth+1)*sizeof(uchar));",
4337dd7cddfSDavid du Colombier 	"	lastword[dfa_depth] = lastword[0] = 255;",
4347dd7cddfSDavid du Colombier 	"	path[0] = R = new_vertex(); F = new_vertex();",
4357dd7cddfSDavid du Colombier 	"",
4367dd7cddfSDavid du Colombier 	"	for (i = 1, r = R; i < dfa_depth; i++, r = t)",
4377dd7cddfSDavid du Colombier 	"		t = allDelta(r, i-1);",
4387dd7cddfSDavid du Colombier 	"	NF = allDelta(r, i-1);",
4397dd7cddfSDavid du Colombier 	"}",
4407dd7cddfSDavid du Colombier 	"",
4417dd7cddfSDavid du Colombier 	"#if 0",
4427dd7cddfSDavid du Colombier 	"static void complement_dfa(void) { Vertex *tmp = F; F = NF; NF = tmp; }",
4437dd7cddfSDavid du Colombier 	"#endif",
4447dd7cddfSDavid du Colombier 	"",
4457dd7cddfSDavid du Colombier 	"double",
4467dd7cddfSDavid du Colombier 	"tree_stats(Vertex *t)",
4477dd7cddfSDavid du Colombier 	"{	Edge *e; double cnt=0.0;",
4487dd7cddfSDavid du Colombier 	"	if (!t) return 0;",
4497dd7cddfSDavid du Colombier 	"	if (!t->key) return 0;",
4507dd7cddfSDavid du Colombier 	"	t->key = 0; /* precaution */",
4517dd7cddfSDavid du Colombier 	"	if (t->dst[0]) cnt++;",
4527dd7cddfSDavid du Colombier 	"	if (t->dst[1]) cnt++;",
4537dd7cddfSDavid du Colombier 	"	for (e = t->Succ; e; e = e->Nxt)",
4547dd7cddfSDavid du Colombier 	"		cnt++;",
4557dd7cddfSDavid du Colombier 	"	cnt += tree_stats(t->lnk);",
4567dd7cddfSDavid du Colombier 	"	cnt += tree_stats(t->left);",
4577dd7cddfSDavid du Colombier 	"	cnt += tree_stats(t->right);",
4587dd7cddfSDavid du Colombier 	"	return cnt;",
4597dd7cddfSDavid du Colombier 	"}",
4607dd7cddfSDavid du Colombier 	"",
4617dd7cddfSDavid du Colombier 	"void",
4627dd7cddfSDavid du Colombier 	"dfa_stats(void)",
4637dd7cddfSDavid du Colombier 	"{	int i, j; double cnt = 0.0;",
4647dd7cddfSDavid du Colombier 	"	for (j = 0; j < TWIDTH; j++)",
4657dd7cddfSDavid du Colombier 	"	for (i = 0; i < dfa_depth+1; i++)",
4667dd7cddfSDavid du Colombier 	"		cnt += tree_stats(layers[i*TWIDTH+j]);",
467*de2caf28SDavid du Colombier 	"	printf(\"Minimized Automaton:\t%%6lu nodes and %%6g edges\\n\",",
4687dd7cddfSDavid du Colombier 	"		nr_states, cnt);",
4697dd7cddfSDavid du Colombier 	"}",
4707dd7cddfSDavid du Colombier 	"",
4717dd7cddfSDavid du Colombier 	"int",
472312a1df1SDavid du Colombier 	"dfa_member(ulong n)",
4737dd7cddfSDavid du Colombier 	"{	Vertex **p, **q;",
4747dd7cddfSDavid du Colombier 	"	uchar *w = &word[n];",
4757dd7cddfSDavid du Colombier 	"	int i;",
4767dd7cddfSDavid du Colombier 	"",
4777dd7cddfSDavid du Colombier 	"	p = &path[n]; q = (p+1);",
4787dd7cddfSDavid du Colombier 	"	for (i = n; i < dfa_depth; i++)",
4797dd7cddfSDavid du Colombier 	"		*q++ = Delta(*p++, *w++);",
4807dd7cddfSDavid du Colombier 	"	return (*p == F);",
4817dd7cddfSDavid du Colombier 	"}",
4827dd7cddfSDavid du Colombier 	"",
4837dd7cddfSDavid du Colombier 	"int",
4847dd7cddfSDavid du Colombier 	"dfa_store(uchar *sv)",
4857dd7cddfSDavid du Colombier 	"{	Vertex **p, **q, *s, *y, *old, *new = F;",
4867dd7cddfSDavid du Colombier 	"	uchar *w, *u = lastword;",
4877dd7cddfSDavid du Colombier 	"	int i, j, k;",
4887dd7cddfSDavid du Colombier 	"",
4897dd7cddfSDavid du Colombier 	"	w = word = sv;",
4907dd7cddfSDavid du Colombier 	"	while (*w++ == *u++)	/* find first byte that differs */",
4917dd7cddfSDavid du Colombier 	"		;",
4927dd7cddfSDavid du Colombier 	"	pfrst = (int) (u - lastword) - 1;",
4937dd7cddfSDavid du Colombier 	"	memcpy(&lastword[pfrst], &sv[pfrst], dfa_depth-pfrst);",
4947dd7cddfSDavid du Colombier 	"	if (pfrst > iv) pfrst = iv;",
4957dd7cddfSDavid du Colombier 	"	if (pfrst > nv) pfrst = nv;",
496312a1df1SDavid du Colombier 	"/* phase1: */",
4977dd7cddfSDavid du Colombier 	"	p = &path[pfrst]; q = (p+1); w = &word[pfrst];",
4987dd7cddfSDavid du Colombier 	"	for (i = pfrst; i < dfa_depth; i++)",
4997dd7cddfSDavid du Colombier 	"		*q++ = Delta(*p++, *w++);	/* (*p)->delta[*w++]; */",
5007dd7cddfSDavid du Colombier 	"",
5017dd7cddfSDavid du Colombier 	"	if (*p == F) return 1;	/* it's already there */",
502312a1df1SDavid du Colombier 	"/* phase2: */",
5037dd7cddfSDavid du Colombier 	"	iv = dfa_depth;",
5047dd7cddfSDavid du Colombier 	"	do {	iv--;",
5057dd7cddfSDavid du Colombier 	"		old = new;",
5067dd7cddfSDavid du Colombier 	"		new = find_it(path[iv], old, word[iv], iv);",
5077dd7cddfSDavid du Colombier 	"	} while (new && iv > 0);",
5087dd7cddfSDavid du Colombier 	"",
509312a1df1SDavid du Colombier 	"/* phase3: */",
5107dd7cddfSDavid du Colombier 	"	nv = k = 0; s = path[0];",
5117dd7cddfSDavid du Colombier 	"	for (j = 1; j <= iv; ++j) ",
5127dd7cddfSDavid du Colombier 	"		if (path[j]->num > 1)",
5137dd7cddfSDavid du Colombier 	"		{	y = new_vertex();",
5147dd7cddfSDavid du Colombier 	"			copyEdges(y, path[j]);",
5157dd7cddfSDavid du Colombier 	"			insert_it(y, j);",
5167dd7cddfSDavid du Colombier 	"			numDelta(y, 1);",
5177dd7cddfSDavid du Colombier 	"			delete_it(s, j-1);",
5187dd7cddfSDavid du Colombier 	"			setDelta(s, word[j-1], y);",
5197dd7cddfSDavid du Colombier 	"			insert_it(s, j-1);",
5207dd7cddfSDavid du Colombier 	"			y->num = 1;	/* initial value 1 */",
5217dd7cddfSDavid du Colombier 	"			s = y;",
5227dd7cddfSDavid du Colombier 	"			path[j]->num--;	/* only 1 moved from j to y */",
5237dd7cddfSDavid du Colombier 	"			k = 1;",
5247dd7cddfSDavid du Colombier 	"		} else",
5257dd7cddfSDavid du Colombier 	"		{	s = path[j];",
5267dd7cddfSDavid du Colombier 	"			if (!k) nv = j;",
5277dd7cddfSDavid du Colombier 	"		}",
5287dd7cddfSDavid du Colombier 	"	y = Delta(s, word[iv]);",
5297dd7cddfSDavid du Colombier 	"	y->num--;",
5307dd7cddfSDavid du Colombier 	"	delete_it(s, iv); ",
5317dd7cddfSDavid du Colombier 	"	setDelta(s, word[iv], old);",
5327dd7cddfSDavid du Colombier 	"	insert_it(s, iv); ",
5337dd7cddfSDavid du Colombier 	"	old->num++;",
5347dd7cddfSDavid du Colombier 	"",
5357dd7cddfSDavid du Colombier 	"	for (j = iv+1; j < dfa_depth; j++)",
5367dd7cddfSDavid du Colombier 	"		if (path[j]->num == 0)",
5377dd7cddfSDavid du Colombier 	"		{	numDelta(path[j], -1);",
5387dd7cddfSDavid du Colombier 	"			delete_it(path[j], j);",
5397dd7cddfSDavid du Colombier 	"			recyc_vertex(path[j]);",
5407dd7cddfSDavid du Colombier 	"		} else",
5417dd7cddfSDavid du Colombier 	"			break;",
5427dd7cddfSDavid du Colombier 	"	return 0;",
5437dd7cddfSDavid du Colombier 	"}",
5447dd7cddfSDavid du Colombier 	"",
5457dd7cddfSDavid du Colombier 	"static Vertex *",
5467dd7cddfSDavid du Colombier 	"splay(ulong i, Vertex *t)",
5477dd7cddfSDavid du Colombier 	"{	Vertex N, *l, *r, *y;",
5487dd7cddfSDavid du Colombier 	"",
5497dd7cddfSDavid du Colombier 	"	if (!t) return t;",
5507dd7cddfSDavid du Colombier 	"	N.left = N.right = (Vertex *) 0;",
5517dd7cddfSDavid du Colombier 	"	l = r = &N;",
5527dd7cddfSDavid du Colombier 	"	for (;;)",
5537dd7cddfSDavid du Colombier 	"	{	if (i < t->key)",
5547dd7cddfSDavid du Colombier 	"		{	if (!t->left) break;",
5557dd7cddfSDavid du Colombier 	"			if (i < t->left->key)",
5567dd7cddfSDavid du Colombier 	"			{	y = t->left;",
5577dd7cddfSDavid du Colombier 	"				t->left = y->right;",
5587dd7cddfSDavid du Colombier 	"				y->right = t;",
5597dd7cddfSDavid du Colombier 	"				t = y;",
5607dd7cddfSDavid du Colombier 	"				if (!t->left) break;",
5617dd7cddfSDavid du Colombier 	"			}",
5627dd7cddfSDavid du Colombier 	"			r->left = t;",
5637dd7cddfSDavid du Colombier 	"			r = t;",
5647dd7cddfSDavid du Colombier 	"			t = t->left;",
5657dd7cddfSDavid du Colombier 	"		} else if (i > t->key)",
5667dd7cddfSDavid du Colombier 	"		{	if (!t->right) break;",
5677dd7cddfSDavid du Colombier 	"			if (i > t->right->key)",
5687dd7cddfSDavid du Colombier 	"			{	y = t->right;",
5697dd7cddfSDavid du Colombier 	"				t->right = y->left;",
5707dd7cddfSDavid du Colombier 	"				y->left = t;",
5717dd7cddfSDavid du Colombier 	"				t = y;",
5727dd7cddfSDavid du Colombier 	"				if (!t->right) break;",
5737dd7cddfSDavid du Colombier 	"			}",
5747dd7cddfSDavid du Colombier 	"			l->right = t;",
5757dd7cddfSDavid du Colombier 	"			l = t;",
5767dd7cddfSDavid du Colombier 	"			t = t->right;",
5777dd7cddfSDavid du Colombier 	"		} else",
5787dd7cddfSDavid du Colombier 	"			break;",
5797dd7cddfSDavid du Colombier 	"	}",
5807dd7cddfSDavid du Colombier 	"	l->right = t->left;",
5817dd7cddfSDavid du Colombier 	"	r->left = t->right;",
5827dd7cddfSDavid du Colombier 	"	t->left = N.right;",
5837dd7cddfSDavid du Colombier 	"	t->right = N.left;",
5847dd7cddfSDavid du Colombier 	"	return t;",
5857dd7cddfSDavid du Colombier 	"}",
5867dd7cddfSDavid du Colombier 	"",
5877dd7cddfSDavid du Colombier 	"static void",
5887dd7cddfSDavid du Colombier 	"insert_it(Vertex *v, int L)",
5897dd7cddfSDavid du Colombier 	"{	Vertex *new, *t;",
5907dd7cddfSDavid du Colombier 	"	ulong i; int nr;",
5917dd7cddfSDavid du Colombier 	"",
5927dd7cddfSDavid du Colombier 	"	i = mk_key(v);",
5937dd7cddfSDavid du Colombier 	"	nr = ((L*TWIDTH)+Tally);",
5947dd7cddfSDavid du Colombier 	"	t = layers[nr];",
5957dd7cddfSDavid du Colombier 	"",
5967dd7cddfSDavid du Colombier 	"	v->key = i; ",
5977dd7cddfSDavid du Colombier 	"	if (!t)",
5987dd7cddfSDavid du Colombier 	"	{	layers[nr] = v;",
5997dd7cddfSDavid du Colombier 	"		return;",
6007dd7cddfSDavid du Colombier 	"	}",
6017dd7cddfSDavid du Colombier 	"	t = splay(i, t);",
6027dd7cddfSDavid du Colombier 	"	if (i < t->key)",
6037dd7cddfSDavid du Colombier 	"	{	new = v;",
6047dd7cddfSDavid du Colombier 	"		new->left = t->left;",
6057dd7cddfSDavid du Colombier 	"		new->right = t;",
6067dd7cddfSDavid du Colombier 	"		t->left = (Vertex *) 0;",
6077dd7cddfSDavid du Colombier 	"	} else if (i > t->key)",
6087dd7cddfSDavid du Colombier 	"	{	new = v;",
6097dd7cddfSDavid du Colombier 	"		new->right = t->right;",
6107dd7cddfSDavid du Colombier 	"		new->left = t;",
6117dd7cddfSDavid du Colombier 	"		t->right = (Vertex *) 0;",
6127dd7cddfSDavid du Colombier 	"	} else	 /* it's already there */",
6137dd7cddfSDavid du Colombier 	"	{	v->lnk = t->lnk; /* put in linked list off v */",
6147dd7cddfSDavid du Colombier 	"		t->lnk = v;",
6157dd7cddfSDavid du Colombier 	"		new = t;",
6167dd7cddfSDavid du Colombier 	"	}",
6177dd7cddfSDavid du Colombier 	"	layers[nr] = new;",
6187dd7cddfSDavid du Colombier 	"}",
6197dd7cddfSDavid du Colombier 	"",
6207dd7cddfSDavid du Colombier 	"static int",
6217dd7cddfSDavid du Colombier 	"checkit(Vertex *h, Vertex *v, Vertex *n, uchar sigma)",
6227dd7cddfSDavid du Colombier 	"{	Edge *g, *f;",
6237dd7cddfSDavid du Colombier 	"	int i, k, j = 1;",
6247dd7cddfSDavid du Colombier 	"",
6257dd7cddfSDavid du Colombier 	"	for (k = 0; k < 2; k++)",
6267dd7cddfSDavid du Colombier 	"		if (h->dst[k])",
6277dd7cddfSDavid du Colombier 	"		{	if (sigma >= h->from[k] && sigma <= h->to[k])",
6287dd7cddfSDavid du Colombier 	"			{	if (h->dst[k] != n) goto no_match;",
6297dd7cddfSDavid du Colombier 	"			}",
6307dd7cddfSDavid du Colombier 	"			for (i = h->from[k]; i <= h->to[k]; i++)",
6317dd7cddfSDavid du Colombier 	"			{	if (i == sigma) continue;",
6327dd7cddfSDavid du Colombier 	"				g = cacheDelta(v, i, j); j = 0;",
6337dd7cddfSDavid du Colombier 	"				if (h->dst[k] != g->Dst)",
6347dd7cddfSDavid du Colombier 	"					goto no_match;",
6357dd7cddfSDavid du Colombier 	"				if (g->s == 0 || g->S != i)",
6367dd7cddfSDavid du Colombier 	"					i = g->To;",
6377dd7cddfSDavid du Colombier 	"		}	}",
6387dd7cddfSDavid du Colombier 	"	for (f = h->Succ; f; f = f->Nxt)",
6397dd7cddfSDavid du Colombier 	"	{	if (INRANGE(f,sigma))",
6407dd7cddfSDavid du Colombier 	"		{	if (f->Dst != n) goto no_match;",
6417dd7cddfSDavid du Colombier 	"		}",
6427dd7cddfSDavid du Colombier 	"		for (i = f->From; i <= f->To; i++)",
6437dd7cddfSDavid du Colombier 	"		{	if (i == sigma) continue;",
6447dd7cddfSDavid du Colombier 	"			g = cacheDelta(v, i, j); j = 0;",
6457dd7cddfSDavid du Colombier 	"			if (f->Dst != g->Dst)",
6467dd7cddfSDavid du Colombier 	"				goto no_match;",
6477dd7cddfSDavid du Colombier 	"			if (g->s == 1 && i == g->S)",
6487dd7cddfSDavid du Colombier 	"				continue;",
6497dd7cddfSDavid du Colombier 	"			i = g->To;",
6507dd7cddfSDavid du Colombier 	"		}",
6517dd7cddfSDavid du Colombier 	"		if (f->s && f->S != sigma)",
6527dd7cddfSDavid du Colombier 	"		{	g = cacheDelta(v, f->S, 1);",
6537dd7cddfSDavid du Colombier 	"			if (f->Dst != g->Dst)",
6547dd7cddfSDavid du Colombier 	"				goto no_match;",
6557dd7cddfSDavid du Colombier 	"		}",
6567dd7cddfSDavid du Colombier 	"	}",
6577dd7cddfSDavid du Colombier 	"	if (h->Succ || h->dst[0] || h->dst[1]) return 1;",
6587dd7cddfSDavid du Colombier 	"no_match:",
6597dd7cddfSDavid du Colombier 	"	return 0;",
6607dd7cddfSDavid du Colombier 	"}",
6617dd7cddfSDavid du Colombier 	"",
6627dd7cddfSDavid du Colombier 	"static Vertex *",
6637dd7cddfSDavid du Colombier 	"find_it(Vertex *v, Vertex *n, uchar sigma, int L)",
6647dd7cddfSDavid du Colombier 	"{	Vertex *z, *t;",
6657dd7cddfSDavid du Colombier 	"	ulong i; int nr;",
6667dd7cddfSDavid du Colombier 	"",
6677dd7cddfSDavid du Colombier 	"	i = mk_special(sigma,n,v);",
6687dd7cddfSDavid du Colombier 	"	nr = ((L*TWIDTH)+Tally);",
6697dd7cddfSDavid du Colombier 	"	t = layers[nr];",
6707dd7cddfSDavid du Colombier 	"",
6717dd7cddfSDavid du Colombier 	"	if (!t) return (Vertex *) 0;",
6727dd7cddfSDavid du Colombier 	"	layers[nr] = t = splay(i, t);",
6737dd7cddfSDavid du Colombier 	"	if (i == t->key)",
6747dd7cddfSDavid du Colombier 	"	for (z = t; z; z = z->lnk)",
6757dd7cddfSDavid du Colombier 	"		if (checkit(z, v, n, sigma))",
6767dd7cddfSDavid du Colombier 	"			return z;",
6777dd7cddfSDavid du Colombier 	"",
6787dd7cddfSDavid du Colombier 	"	return (Vertex *) 0;",
6797dd7cddfSDavid du Colombier 	"}",
6807dd7cddfSDavid du Colombier 	"",
6817dd7cddfSDavid du Colombier 	"static void",
6827dd7cddfSDavid du Colombier 	"delete_it(Vertex *v, int L)",
6837dd7cddfSDavid du Colombier 	"{	Vertex *x, *t;",
6847dd7cddfSDavid du Colombier 	"	ulong i; int nr;",
6857dd7cddfSDavid du Colombier 	"",
6867dd7cddfSDavid du Colombier 	"	i = cheap_key(v);",
6877dd7cddfSDavid du Colombier 	"	nr = ((L*TWIDTH)+Tally);",
6887dd7cddfSDavid du Colombier 	"	t = layers[nr];",
6897dd7cddfSDavid du Colombier 	"	if (!t) return;",
6907dd7cddfSDavid du Colombier 	"",
6917dd7cddfSDavid du Colombier 	"	t = splay(i, t);",
6927dd7cddfSDavid du Colombier 	"	if (i == t->key)",
6937dd7cddfSDavid du Colombier 	"	{	Vertex *z, *y = (Vertex *) 0;",
6947dd7cddfSDavid du Colombier 	"		for (z = t; z && z != v; y = z, z = z->lnk)",
6957dd7cddfSDavid du Colombier 	"			;",
6967dd7cddfSDavid du Colombier 	"		if (z != v) goto bad;",
6977dd7cddfSDavid du Colombier 	"		if (y)",
6987dd7cddfSDavid du Colombier 	"		{	y->lnk = z->lnk;",
6997dd7cddfSDavid du Colombier 	"			z->lnk = (Vertex *) 0;",
7007dd7cddfSDavid du Colombier 	"			layers[nr] = t;",
7017dd7cddfSDavid du Colombier 	"			return;",
7027dd7cddfSDavid du Colombier 	"		} else if (z->lnk)	/* z == t == v */",
7037dd7cddfSDavid du Colombier 	"		{	y = z->lnk;",
7047dd7cddfSDavid du Colombier 	"			y->left = t->left;",
7057dd7cddfSDavid du Colombier 	"			y->right = t->right;",
7067dd7cddfSDavid du Colombier 	"			t->left = t->right = t->lnk = (Vertex *) 0;",
7077dd7cddfSDavid du Colombier 	"			layers[nr] = y;",
7087dd7cddfSDavid du Colombier 	"			return;",
7097dd7cddfSDavid du Colombier 	"		}",
7107dd7cddfSDavid du Colombier 	"		/* delete the node itself */",
7117dd7cddfSDavid du Colombier 	"		if (!t->left)",
7127dd7cddfSDavid du Colombier 	"		{	x = t->right;",
7137dd7cddfSDavid du Colombier 	"		} else",
7147dd7cddfSDavid du Colombier 	"		{	x = splay(i, t->left);",
7157dd7cddfSDavid du Colombier 	"			x->right = t->right;",
7167dd7cddfSDavid du Colombier 	"		}",
7177dd7cddfSDavid du Colombier 	"		t->left = t->right = t->lnk = (Vertex *) 0;",
7187dd7cddfSDavid du Colombier 	"		layers[nr] = x;",
7197dd7cddfSDavid du Colombier 	"		return;",
7207dd7cddfSDavid du Colombier 	"	}",
7217dd7cddfSDavid du Colombier 	"bad:	Uerror(\"cannot happen delete\");",
7227dd7cddfSDavid du Colombier 	"}",
7237dd7cddfSDavid du Colombier 	"#endif", /* MA */
7247dd7cddfSDavid du Colombier 	0,
7257dd7cddfSDavid du Colombier };
726