15dfecf96Smrg/*
25dfecf96Smrg * Copyright (c) 2002 by The XFree86 Project, Inc.
35dfecf96Smrg *
45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a
55dfecf96Smrg * copy of this software and associated documentation files (the "Software"),
65dfecf96Smrg * to deal in the Software without restriction, including without limitation
75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the
95dfecf96Smrg * Software is furnished to do so, subject to the following conditions:
105dfecf96Smrg *
115dfecf96Smrg * The above copyright notice and this permission notice shall be included in
125dfecf96Smrg * all copies or substantial portions of the Software.
135dfecf96Smrg *
145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
205dfecf96Smrg * SOFTWARE.
215dfecf96Smrg *
225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall
235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other
245dfecf96Smrg * dealings in this Software without prior written authorization from the
255dfecf96Smrg * XFree86 Project.
265dfecf96Smrg *
275dfecf96Smrg * Author: Paulo César Pereira de Andrade
285dfecf96Smrg */
295dfecf96Smrg
305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/re/re.c,v 1.8 2002/11/17 07:51:30 paulo Exp $ */
315dfecf96Smrg
325dfecf96Smrg#include <stdio.h>
335dfecf96Smrg#include "rep.h"
34b9afefc9Schristos
355dfecf96Smrg/*
365dfecf96Smrg * Types
375dfecf96Smrg */
385dfecf96Smrg
395dfecf96Smrg/*  Information used when generating the final form of the compiled re.
405dfecf96Smrg */
415dfecf96Smrgstruct _re_inf {
425dfecf96Smrg    rec_alt *alt;
435dfecf96Smrg    unsigned char *cod;
445dfecf96Smrg    long len;
455dfecf96Smrg    long spc;
465dfecf96Smrg
475dfecf96Smrg    /* Start offset of special repetition instruction */
485dfecf96Smrg    long sr[MAX_DEPTH];
495dfecf96Smrg
505dfecf96Smrg    /* Jump offset of special repetition instruction */
515dfecf96Smrg    long sj[MAX_DEPTH];
525dfecf96Smrg
535dfecf96Smrg    /* Just a flag, to know if this nesting is for a special repetition */
545dfecf96Smrg    char sp[MAX_DEPTH];
555dfecf96Smrg
565dfecf96Smrg    int bas;			/* Alternatives/repetitions depth */
575dfecf96Smrg    int par;			/* Open parenthesis counter */
585dfecf96Smrg    int ref;			/* Backreference counter */
595dfecf96Smrg
605dfecf96Smrg    rec_pat *apat;		/*  Alternatives duplicate patterns
615dfecf96Smrg				 * if a special repetition is found,
625dfecf96Smrg				 * this is done to somewhat simplify
635dfecf96Smrg				 * the bytecode engine and still allow
645dfecf96Smrg				 * some complex (and time consuming)
655dfecf96Smrg				 * patterns. */
665dfecf96Smrg
675dfecf96Smrg    int flags;
685dfecf96Smrg    int ecode;
695dfecf96Smrg};
705dfecf96Smrg
715dfecf96Smrg/*  This structure is not associated with re_cod as it's data only matters
725dfecf96Smrg * to the current match search.
735dfecf96Smrg */
745dfecf96Smrgstruct _re_eng {
755dfecf96Smrg    unsigned char *bas;		/* Base string pointer */
765dfecf96Smrg    unsigned char *str;		/* String to search for pattern */
775dfecf96Smrg    unsigned char *end;		/* Where to stop searching */
785dfecf96Smrg    unsigned char *cod;		/* Pointer in the re_cod structure */
795dfecf96Smrg    long off;			/* Number of used entries in so/eo etc */
805dfecf96Smrg
815dfecf96Smrg    /* Match offset/nesting information */
825dfecf96Smrg    long so[MAX_DEPTH];		/* (s)tart of (m)atch */
835dfecf96Smrg    long eo[MAX_DEPTH];		/* (e)nd of (m)atch */
845dfecf96Smrg    long sv[MAX_DEPTH];		/* (s)a(v)e match end offset */
855dfecf96Smrg    long re[MAX_DEPTH];		/* (re)petition count */
865dfecf96Smrg    long ss[MAX_DEPTH];		/* (s)ave (s)tart of match */
875dfecf96Smrg    unsigned char *rcod[MAX_DEPTH];	/* restart position in regex code */
885dfecf96Smrg    unsigned char *rstr[MAX_DEPTH];	/* restart position in string */
895dfecf96Smrg
905dfecf96Smrg    /* Group/backreference information */
915dfecf96Smrg    long goff;
925dfecf96Smrg    long gso[9];
935dfecf96Smrg    long geo[9];
945dfecf96Smrg};
955dfecf96Smrg
965dfecf96Smrg/*
975dfecf96Smrg * Prototypes
985dfecf96Smrg */
995dfecf96Smrgstatic void reinit(void);
1005dfecf96Smrgstatic int rec_check(re_inf*, int);
1015dfecf96Smrgstatic int rec_code(re_inf*, ReCode);
1025dfecf96Smrgstatic int rec_byte(re_inf*, int);
1035dfecf96Smrgstatic int rec_byte_byte(re_inf*, int, int);
1045dfecf96Smrgstatic int rec_code_byte(re_inf*, ReCode, int);
1055dfecf96Smrgstatic int rec_length(re_inf*, int);
1065dfecf96Smrgstatic int rec_code_byte_byte(re_inf*, ReCode, int, int);
1075dfecf96Smrgstatic int rec_build_alt(re_inf*, rec_alt*);
1085dfecf96Smrgstatic int rec_build_pat(re_inf*, rec_pat*);
1095dfecf96Smrgstatic int rec_build_rng(re_inf*, rec_rng*);
1105dfecf96Smrgstatic int rec_build_grp(re_inf*, rec_grp*);
1115dfecf96Smrgstatic int rec_build_stl(re_inf*, rec_stl*);
1125dfecf96Smrgstatic int rec_build_rep(re_inf*, rec_rep*);
1135dfecf96Smrgstatic int rec_inc_spc(re_inf*);
1145dfecf96Smrgstatic int rec_dec_spc(re_inf*);
1155dfecf96Smrgstatic int rec_add_spc(re_inf*, int);
1165dfecf96Smrgstatic int rec_off_spc(re_inf*);
1175dfecf96Smrgstatic int rec_alt_spc(re_inf*, int);
1185dfecf96Smrgstatic int rec_rep_spc(re_inf*, int);
1195dfecf96Smrg#ifdef DEBUG
1205dfecf96Smrgstatic void redump(re_cod*);
1215dfecf96Smrg#endif
1225dfecf96Smrg
1235dfecf96Smrg/*
1245dfecf96Smrg * Initialization
1255dfecf96Smrg */
1265dfecf96Smrgunsigned char re__alnum[256];
1275dfecf96Smrgunsigned char re__odigit[256];
1285dfecf96Smrgunsigned char re__ddigit[256];
1295dfecf96Smrgunsigned char re__xdigit[256];
1305dfecf96Smrgunsigned char re__control[256];
1315dfecf96Smrg
1325dfecf96Smrg/*
1335dfecf96Smrg * Implementation
1345dfecf96Smrg */
1355dfecf96Smrgint
1365dfecf96Smrgrecomp(re_cod *preg, const char *pattern, int flags)
1375dfecf96Smrg{
1385dfecf96Smrg    int i, ecode;
1395dfecf96Smrg    re_inf inf;
1405dfecf96Smrg
1415dfecf96Smrg    reinit();
1425dfecf96Smrg
1435dfecf96Smrg    preg->cod = NULL;
1445dfecf96Smrg    inf.alt = irec_comp(pattern,
1455dfecf96Smrg			flags & RE_PEND ? preg->re_endp :
1465dfecf96Smrg				pattern + strlen(pattern),
1475dfecf96Smrg			flags, &ecode);
1485dfecf96Smrg    if (ecode != 0)
1495dfecf96Smrg	return (ecode);
1505dfecf96Smrg
1515dfecf96Smrg    inf.cod = NULL;
1525dfecf96Smrg    inf.len = inf.spc = 0;
1535dfecf96Smrg    inf.bas = 0;
1545dfecf96Smrg    inf.par = 0;
1555dfecf96Smrg    inf.ref = 0;
1565dfecf96Smrg    inf.apat = NULL;
1575dfecf96Smrg    inf.flags = flags;
1585dfecf96Smrg    inf.ecode = 0;
1595dfecf96Smrg    for (i = 0; i < MAX_DEPTH; i++)
1605dfecf96Smrg	inf.sp[i] = 0;
1615dfecf96Smrg
1625dfecf96Smrg    /* First byte is runtime modifier flags */
1635dfecf96Smrg    if (rec_byte(&inf, flags & (RE_NEWLINE | RE_NOSUB)) == 0 &&
1645dfecf96Smrg	rec_byte(&inf, 0xff) == 0 &&
1655dfecf96Smrg	rec_build_alt(&inf, inf.alt) == 0 &&
1665dfecf96Smrg	rec_rep_spc(&inf, 0) == 0 &&
1675dfecf96Smrg	rec_code(&inf, Re_Done) == 0) {
1685dfecf96Smrg	/*  Number of possible references, loops will not leave this
1695dfecf96Smrg	 * value correct, but it is cheap to read it from the second
1705dfecf96Smrg	 * byte, instead of adding several extra checks in the bytecode. */
1715dfecf96Smrg	if (inf.ref)
1725dfecf96Smrg	    inf.cod[1] = inf.ref - 1;
1735dfecf96Smrg	preg->cod = inf.cod;
1745dfecf96Smrg	/*  Public structure member */
1755dfecf96Smrg	preg->re_nsub = inf.ref;
1765dfecf96Smrg    }
1775dfecf96Smrg
1785dfecf96Smrg    irec_free_alt(inf.alt);
1795dfecf96Smrg    if (inf.ecode)
1805dfecf96Smrg	free(inf.cod);
1815dfecf96Smrg#ifdef DEBUG
1825dfecf96Smrg    else if (flags & RE_DUMP)
1835dfecf96Smrg	redump(preg);
1845dfecf96Smrg#endif
1855dfecf96Smrg
1865dfecf96Smrg    return (inf.ecode);
1875dfecf96Smrg}
1885dfecf96Smrg
1895dfecf96Smrgint
1905dfecf96Smrgreexec(const re_cod *preg, const char *string,
1915dfecf96Smrg       int nmatch, re_mat pmat[], int flags)
1925dfecf96Smrg{
1935dfecf96Smrg    unsigned char *ptr, *str, newline, nosub;
1945dfecf96Smrg    int len, si, ci, bas, i, j, k, l, m;
1955dfecf96Smrg    re_eng eng;
1965dfecf96Smrg
1975dfecf96Smrg    if (preg == NULL || preg->cod == NULL || nmatch < 0 ||
1985dfecf96Smrg	((flags & RE_STARTEND) &&
1995dfecf96Smrg	 (pmat == NULL || pmat[0].rm_eo < pmat[0].rm_so)))
2005dfecf96Smrg	return (RE_INVARG);
2015dfecf96Smrg
2025dfecf96Smrg    eng.str = (unsigned char*)string;
2035dfecf96Smrg    if (flags & RE_STARTEND) {
2045dfecf96Smrg	eng.end = eng.str + pmat[0].rm_eo;
2055dfecf96Smrg	eng.str += pmat[0].rm_so;
2065dfecf96Smrg    }
2075dfecf96Smrg    else
2085dfecf96Smrg	eng.end = eng.str + strlen(string);
2095dfecf96Smrg    eng.bas = eng.str;
2105dfecf96Smrg    nosub = preg->cod[0] & RE_NOSUB;
2115dfecf96Smrg    newline = preg->cod[0] & RE_NEWLINE;
2125dfecf96Smrg    eng.cod = preg->cod + 2;
2135dfecf96Smrg
2145dfecf96Smrg    if (!nosub && preg->cod[1] != 0xff) {
2155dfecf96Smrg	for (i = 0; i <= preg->cod[1]; i++) {
2165dfecf96Smrg	    eng.gso[i] = 0;
2175dfecf96Smrg	    eng.geo[i] = -1;
2185dfecf96Smrg	}
2195dfecf96Smrg    }
2205dfecf96Smrg
2215dfecf96Smrg    /* Setup to search for start of match from the first character */
2225dfecf96Smrg    eng.so[0] = 0;
2235dfecf96Smrg    eng.eo[0] = eng.sv[0] = -1;
2245dfecf96Smrg    eng.rcod[0] = eng.cod;
2255dfecf96Smrg    eng.rstr[0] = eng.str + 1;
2265dfecf96Smrg    eng.off = 0;
2275dfecf96Smrg    eng.goff = -1;
2285dfecf96Smrg    for (ci = si = 1;;) {
2295dfecf96Smrgreset:
2305dfecf96Smrg	switch (*eng.cod) {
2315dfecf96Smrg	    /****************************************************
2325dfecf96Smrg	     * One byte codes					*
2335dfecf96Smrg	     ****************************************************/
2345dfecf96Smrg	    case Re_Any:
2355dfecf96Smrg		if (eng.str == eng.end || (newline && eng.str[0] == '\n'))
2365dfecf96Smrg		    goto fail;
2375dfecf96Smrg		goto match;
2385dfecf96Smrg	    case Re_AnyEatAnyTimes:
2395dfecf96Smrg		if (newline) {
2405dfecf96Smrg		    for (ptr = eng.str; ptr < eng.end; ptr++) {
2415dfecf96Smrg			if (*ptr == '\n')
2425dfecf96Smrg			    break;
2435dfecf96Smrg		    }
2445dfecf96Smrg		    si = ptr - eng.str;
2455dfecf96Smrg		}
2465dfecf96Smrg		else
2475dfecf96Smrg		    si = eng.end - eng.str;
2485dfecf96Smrg		goto match;
2495dfecf96Smrg	    case Re_AnyEatMaybe:
2505dfecf96Smrg		si = eng.end > eng.str;
2515dfecf96Smrg		if (newline && si && eng.str[0] == '\n')
2525dfecf96Smrg		    si = 0;
2535dfecf96Smrg		goto match;
2545dfecf96Smrg	    case Re_AnyEatAtLeast:
2555dfecf96Smrg		if (newline) {
2565dfecf96Smrg		    for (ptr = eng.str; ptr < eng.end; ptr++) {
2575dfecf96Smrg			if (*ptr == '\n')
2585dfecf96Smrg			    break;
2595dfecf96Smrg		    }
2605dfecf96Smrg		    si = ptr - eng.str;
2615dfecf96Smrg		}
2625dfecf96Smrg		else
2635dfecf96Smrg		    si = eng.end - eng.str;
2645dfecf96Smrg		if (si == 0) {
2655dfecf96Smrg		    si = 1;
2665dfecf96Smrg		    goto fail;
2675dfecf96Smrg		}
2685dfecf96Smrg		goto match;
2695dfecf96Smrg	    case Re_Odigit:
2705dfecf96Smrg		if (eng.str >= eng.end)
2715dfecf96Smrg		    goto fail;
2725dfecf96Smrg		if (re__odigit[eng.str[0]])
2735dfecf96Smrg		    goto match;
2745dfecf96Smrg		goto fail;
2755dfecf96Smrg	    case Re_OdigitNot:
2765dfecf96Smrg		if (eng.str >= eng.end || re__odigit[eng.str[0]])
2775dfecf96Smrg		    goto fail;
2785dfecf96Smrg		goto match;
2795dfecf96Smrg	    case Re_Digit:
2805dfecf96Smrg		if (eng.str >= eng.end)
2815dfecf96Smrg		    goto fail;
2825dfecf96Smrg		if (re__ddigit[eng.str[0]])
2835dfecf96Smrg		    goto match;
2845dfecf96Smrg		goto fail;
2855dfecf96Smrg	    case Re_DigitNot:
2865dfecf96Smrg		if (eng.str >= eng.end || re__ddigit[eng.str[0]])
2875dfecf96Smrg		    goto fail;
2885dfecf96Smrg		goto match;
2895dfecf96Smrg	    case Re_Xdigit:
2905dfecf96Smrg		if (eng.str >= eng.end)
2915dfecf96Smrg		    goto fail;
2925dfecf96Smrg		if (re__xdigit[eng.str[0]])
2935dfecf96Smrg		    goto match;
2945dfecf96Smrg		goto fail;
2955dfecf96Smrg	    case Re_XdigitNot:
2965dfecf96Smrg		if (eng.str >= eng.end || re__xdigit[eng.str[0]])
2975dfecf96Smrg		    goto fail;
2985dfecf96Smrg		goto match;
2995dfecf96Smrg	    case Re_Space:
3005dfecf96Smrg		if (eng.str >= eng.end)
3015dfecf96Smrg		    goto fail;
3025dfecf96Smrg		if (eng.str[0] == ' ' || eng.str[0] == '\t')
3035dfecf96Smrg		    goto match;
3045dfecf96Smrg		goto fail;
3055dfecf96Smrg	    case Re_SpaceNot:
3065dfecf96Smrg		if (eng.str >= eng.end)
3075dfecf96Smrg		    goto fail;
3085dfecf96Smrg		if (eng.str[0] != ' ' && eng.str[0] != '\t')
3095dfecf96Smrg		    goto match;
3105dfecf96Smrg		goto fail;
3115dfecf96Smrg	    case Re_Tab:
3125dfecf96Smrg		if (eng.str >= eng.end)
3135dfecf96Smrg		    goto fail;
3145dfecf96Smrg		if (eng.str[0] == '\t')
3155dfecf96Smrg		    goto match;
3165dfecf96Smrg		goto fail;
3175dfecf96Smrg	    case Re_Newline:
3185dfecf96Smrg		if (eng.str >= eng.end)
3195dfecf96Smrg		    goto fail;
3205dfecf96Smrg		if (eng.str[0] == '\n')
3215dfecf96Smrg		    goto match;
3225dfecf96Smrg		goto fail;
3235dfecf96Smrg	    case Re_Lower:
3245dfecf96Smrg		if (eng.str >= eng.end)
3255dfecf96Smrg		    goto fail;
3265dfecf96Smrg		if (eng.str[0] >= 'a' && eng.str[0] <= 'z')
3275dfecf96Smrg		    goto match;
3285dfecf96Smrg		goto fail;
3295dfecf96Smrg	    case Re_Upper:
3305dfecf96Smrg		if (eng.str >= eng.end)
3315dfecf96Smrg		    goto fail;
3325dfecf96Smrg		if (eng.str[0] >= 'A' && eng.str[0] <= 'Z')
3335dfecf96Smrg		    goto match;
3345dfecf96Smrg		goto fail;
3355dfecf96Smrg	    case Re_Alnum:
3365dfecf96Smrg		if (eng.str >= eng.end)
3375dfecf96Smrg		    goto fail;
3385dfecf96Smrg		if (re__alnum[eng.str[0]])
3395dfecf96Smrg		    goto match;
3405dfecf96Smrg		goto fail;
3415dfecf96Smrg	    case Re_AlnumNot:
3425dfecf96Smrg		if (eng.str >= eng.end)
3435dfecf96Smrg		    goto fail;
3445dfecf96Smrg		if (re__alnum[eng.str[0]])
3455dfecf96Smrg		    goto fail;
3465dfecf96Smrg		goto match;
3475dfecf96Smrg	    case Re_Control:
3485dfecf96Smrg		if (eng.str >= eng.end)
3495dfecf96Smrg		    goto fail;
3505dfecf96Smrg		if (re__control[eng.str[0]])
3515dfecf96Smrg		    goto match;
3525dfecf96Smrg		goto fail;
3535dfecf96Smrg	    case Re_ControlNot:
3545dfecf96Smrg		if (eng.str >= eng.end || re__control[eng.str[0]])
3555dfecf96Smrg		    goto fail;
3565dfecf96Smrg		goto match;
3575dfecf96Smrg
3585dfecf96Smrg	    /****************************************************
3595dfecf96Smrg	     * One byte codes, match special emtpy strings	*
3605dfecf96Smrg	     ****************************************************/
3615dfecf96Smrg	    case Re_Bol:
3625dfecf96Smrg		if (eng.str == eng.bas) {
3635dfecf96Smrg		    if ((flags & RE_NOTBOL)) {
3645dfecf96Smrg			/* String does not start at the beginning of a line */
3655dfecf96Smrg			if (newline)
3665dfecf96Smrg			    goto fail;
3675dfecf96Smrg			goto wont;
3685dfecf96Smrg		    }
3695dfecf96Smrg		    si = 0;
3705dfecf96Smrg		    goto match;
3715dfecf96Smrg		}
3725dfecf96Smrg		if (newline && eng.str[-1] == '\n') {
3735dfecf96Smrg		    si = 0;
3745dfecf96Smrg		    goto match;
3755dfecf96Smrg		}
3765dfecf96Smrg		goto fail;
3775dfecf96Smrg	    case Re_Eol:
3785dfecf96Smrg		if (eng.str == eng.end) {
3795dfecf96Smrg		    if (flags & RE_NOTEOL)
3805dfecf96Smrg			/* String does not finish at the end of a line */
3815dfecf96Smrg			goto wont;
3825dfecf96Smrg		    si = 0;
3835dfecf96Smrg		    goto match;
3845dfecf96Smrg		}
3855dfecf96Smrg		if (newline && eng.str[0] == '\n') {
3865dfecf96Smrg		    si = 0;
3875dfecf96Smrg		    goto match;
3885dfecf96Smrg		}
3895dfecf96Smrg		goto fail;
3905dfecf96Smrg	    case Re_Bow:
3915dfecf96Smrg		if (eng.str >= eng.end ||
3925dfecf96Smrg		    (eng.str > eng.bas &&
3935dfecf96Smrg		     (re__alnum[eng.str[-1]])))
3945dfecf96Smrg		    goto fail;
3955dfecf96Smrg		if (re__alnum[eng.str[0]]) {
3965dfecf96Smrg		    si = 0;
3975dfecf96Smrg		    goto match;
3985dfecf96Smrg		}
3995dfecf96Smrg		goto fail;
4005dfecf96Smrg	    case Re_Eow:
4015dfecf96Smrg		if (eng.str == eng.bas ||
4025dfecf96Smrg		    (eng.str < eng.end &&
4035dfecf96Smrg		     re__alnum[eng.str[0]]))
4045dfecf96Smrg		    goto fail;
4055dfecf96Smrg		if (re__alnum[eng.str[-1]]) {
4065dfecf96Smrg		    si = 0;
4075dfecf96Smrg		    goto match;
4085dfecf96Smrg		}
4095dfecf96Smrg		goto fail;
4105dfecf96Smrg
4115dfecf96Smrg	    /****************************************************
4125dfecf96Smrg	     * One byte code, one byte argument			*
4135dfecf96Smrg	     ****************************************************/
4145dfecf96Smrg	    case Re_Literal:
4155dfecf96Smrg		if (eng.str >= eng.end)
4165dfecf96Smrg		    goto fail;
4175dfecf96Smrg		if (eng.str[0] == eng.cod[1]) {
4185dfecf96Smrg		    ci = 2;
4195dfecf96Smrg		    goto match;
4205dfecf96Smrg		}
4215dfecf96Smrg		goto fail;
4225dfecf96Smrg	    case Re_LiteralNot:
4235dfecf96Smrg		if (eng.str >= eng.end)
4245dfecf96Smrg		    goto fail;
4255dfecf96Smrg		if (eng.str[0] != eng.cod[1]) {
4265dfecf96Smrg		    ci = 2;
4275dfecf96Smrg		    goto match;
4285dfecf96Smrg		}
4295dfecf96Smrg		goto fail;
4305dfecf96Smrg	    case Re_SearchLiteral:
4315dfecf96Smrg		for (str = eng.str; str < eng.end; str++) {
4325dfecf96Smrg		    if (*str == eng.cod[1]) {
4335dfecf96Smrg			ci = 2;
4345dfecf96Smrg			eng.str = str;
4355dfecf96Smrg			goto match;
4365dfecf96Smrg		    }
4375dfecf96Smrg		}
4385dfecf96Smrg		/* This bytecode only happens in the toplevel */
4395dfecf96Smrg		eng.so[0] = str - eng.bas;
4405dfecf96Smrg		eng.str = str;
4415dfecf96Smrg		goto fail;
4425dfecf96Smrg
4435dfecf96Smrg	    /****************************************************
4445dfecf96Smrg	     * One byte code, two bytes argument		*
4455dfecf96Smrg	     ****************************************************/
4465dfecf96Smrg	    case Re_CaseLiteral:
4475dfecf96Smrg		if (eng.str >= eng.end)
4485dfecf96Smrg		    goto fail;
4495dfecf96Smrg		if (eng.str[0] == eng.cod[1] || eng.str[0] == eng.cod[2]) {
4505dfecf96Smrg		    ci = 3;
4515dfecf96Smrg		    goto match;
4525dfecf96Smrg		}
4535dfecf96Smrg		goto fail;
4545dfecf96Smrg	    case Re_CaseLiteralNot:
4555dfecf96Smrg		if (eng.str >= eng.end)
4565dfecf96Smrg		    goto fail;
4575dfecf96Smrg		if (eng.str[0] != eng.cod[1] && eng.str[0] != eng.cod[2]) {
4585dfecf96Smrg		    ci = 3;
4595dfecf96Smrg		    goto match;
4605dfecf96Smrg		}
4615dfecf96Smrg		goto fail;
4625dfecf96Smrg	    case Re_SearchCaseLiteral:
4635dfecf96Smrg		for (str = eng.str; str < eng.end; str++) {
4645dfecf96Smrg		    if (*str == eng.cod[1] || *str == eng.cod[2]) {
4655dfecf96Smrg			ci = 3;
4665dfecf96Smrg			eng.str = str;
4675dfecf96Smrg			goto match;
4685dfecf96Smrg		    }
4695dfecf96Smrg		}
4705dfecf96Smrg		eng.so[0] = str - eng.bas;
4715dfecf96Smrg		eng.str = str;
4725dfecf96Smrg		goto fail;
4735dfecf96Smrg
4745dfecf96Smrg	    /****************************************************
4755dfecf96Smrg	     * One byte codes, two arguments, n bytes		*
4765dfecf96Smrg	     ****************************************************/
4775dfecf96Smrg	    case Re_String:
4785dfecf96Smrg		len = eng.cod[1];
4795dfecf96Smrg		if (len & 0x80) {
4805dfecf96Smrg		    i = 3;
4815dfecf96Smrg		    len = (len & 0x7f) + (eng.cod[2] << 7);
4825dfecf96Smrg		}
4835dfecf96Smrg		else
4845dfecf96Smrg		    i = 2;
4855dfecf96Smrg		if (eng.end - eng.str < len)
4865dfecf96Smrg		    goto fail;
4875dfecf96Smrg		ptr = eng.cod + i;
4885dfecf96Smrg		str = eng.str;
4895dfecf96Smrg		for (k = len; k > 0; k--) {
4905dfecf96Smrg		    if (*ptr++ != *str++)
4915dfecf96Smrg			goto fail;
4925dfecf96Smrg		}
4935dfecf96Smrg		ci = i + len;
4945dfecf96Smrg		si = len;
4955dfecf96Smrg		goto match;
4965dfecf96Smrg	    case Re_SearchString:
4975dfecf96Smrg		len = eng.cod[1];
4985dfecf96Smrg		if (len & 0x80) {
4995dfecf96Smrg		    i = 3;
5005dfecf96Smrg		    len = (len & 0x7f) + (eng.cod[2] << 7);
5015dfecf96Smrg		}
5025dfecf96Smrg		else
5035dfecf96Smrg		    i = 2;
5045dfecf96Smrg		for (str = eng.str; eng.end - str >= len; str = eng.str++) {
5055dfecf96Smrg		    for (ptr = eng.cod + i, str = eng.str, k = len; k > 0; k--)
5065dfecf96Smrg			if (*ptr++ != *str++)
5075dfecf96Smrg			    break;
5085dfecf96Smrg		    if (k == 0) {
5095dfecf96Smrg			/* Substring found */
5105dfecf96Smrg			ci = i + len;
5115dfecf96Smrg			si = str - eng.str;
5125dfecf96Smrg			goto match;
5135dfecf96Smrg		    }
5145dfecf96Smrg		}
5155dfecf96Smrg		eng.so[0] = eng.end - eng.bas;
5165dfecf96Smrg		eng.str = eng.end;
5175dfecf96Smrg		goto fail;
5185dfecf96Smrg
5195dfecf96Smrg	    case Re_CaseString:
5205dfecf96Smrg		len = eng.cod[1];
5215dfecf96Smrg		if (len & 0x80) {
5225dfecf96Smrg		    i = 3;
5235dfecf96Smrg		    len = (len & 0x7f) + (eng.cod[2] << 7);
5245dfecf96Smrg		}
5255dfecf96Smrg		else
5265dfecf96Smrg		    i = 2;
5275dfecf96Smrg
5285dfecf96Smrg		len >>= 1;
5295dfecf96Smrg		/*  Check if there are at least len/2 bytes left, string
5305dfecf96Smrg		 * is represented as two bytes, lower and upper case */
5315dfecf96Smrg		if (eng.end - eng.str < len)
5325dfecf96Smrg		    goto fail;
5335dfecf96Smrg		ptr = eng.cod + i;
5345dfecf96Smrg		str = eng.str;
5355dfecf96Smrg		for (k = len; k > 0; str++, ptr += 2, k--) {
5365dfecf96Smrg		    if (*str != ptr[0] && *str != ptr[1])
5375dfecf96Smrg			goto fail;
5385dfecf96Smrg		}
5395dfecf96Smrg		ci = i + (len << 1);
5405dfecf96Smrg		si = len;
5415dfecf96Smrg		goto match;
5425dfecf96Smrg	    case Re_SearchCaseString:
5435dfecf96Smrg		len = eng.cod[1];
5445dfecf96Smrg		if (len & 0x80) {
5455dfecf96Smrg		    i = 3;
5465dfecf96Smrg		    len = (len & 0x7f) + (eng.cod[2] << 7);
5475dfecf96Smrg		}
5485dfecf96Smrg		else
5495dfecf96Smrg		    i = 2;
5505dfecf96Smrg		len >>= 1;
5515dfecf96Smrg		for (str = eng.str; eng.end - str >= len; str = eng.str++) {
5525dfecf96Smrg		    for (ptr = eng.cod + i, str = eng.str, k = len;
5535dfecf96Smrg			 k > 0; k--, ptr += 2, str++)
5545dfecf96Smrg			if (ptr[0] != str[0] && ptr[1] != str[0])
5555dfecf96Smrg			    break;
5565dfecf96Smrg		    if (k == 0) {
5575dfecf96Smrg			/* Substring found */
5585dfecf96Smrg			ci = i + (len << 1);
5595dfecf96Smrg			si = str - eng.str;
5605dfecf96Smrg			goto match;
5615dfecf96Smrg		    }
5625dfecf96Smrg		}
5635dfecf96Smrg		eng.so[0] = eng.end - eng.bas;
5645dfecf96Smrg		eng.str = eng.end;
5655dfecf96Smrg		goto fail;
5665dfecf96Smrg
5675dfecf96Smrg	    case Re_StringList:
5685dfecf96Smrg		/* Number of strings */
5695dfecf96Smrg		k = eng.cod[1];
5705dfecf96Smrg
5715dfecf96Smrg		/* Where to jump after match */
5725dfecf96Smrg		bas = eng.cod[2] | (eng.cod[3] << 8);
5735dfecf96Smrg
5745dfecf96Smrg		str = eng.str;
5755dfecf96Smrg		ptr = eng.cod + k + 4;
5765dfecf96Smrg		l = eng.end - eng.str;
5775dfecf96Smrg		for (j = 0; j < k; j++) {
5785dfecf96Smrg		    len = eng.cod[j + 4];
5795dfecf96Smrg		    if (len <= l) {
5805dfecf96Smrg			for (i = 0; i < len; i++)
5815dfecf96Smrg			    if (ptr[i] != str[i])
5825dfecf96Smrg				goto next_stl;
5835dfecf96Smrg			goto stl_match;
5845dfecf96Smrg		    }
5855dfecf96Smrgnext_stl:
5865dfecf96Smrg		    ptr += len;
5875dfecf96Smrg		}
5885dfecf96Smrg		goto fail;
5895dfecf96Smrgstl_match:
5905dfecf96Smrg		ci = bas;
5915dfecf96Smrg		si = len;
5925dfecf96Smrg		goto match;
5935dfecf96Smrg
5945dfecf96Smrg	    case Re_CaseStringList:
5955dfecf96Smrg		/* Number of strings */
5965dfecf96Smrg		k = eng.cod[1];
5975dfecf96Smrg
5985dfecf96Smrg		/* Where to jump after match */
5995dfecf96Smrg		bas = eng.cod[2] | (eng.cod[3] << 8);
6005dfecf96Smrg
6015dfecf96Smrg		str = eng.str;
6025dfecf96Smrg		ptr = eng.cod + k + 4;
6035dfecf96Smrg		l = eng.end - eng.str;
6045dfecf96Smrg		for (j = 0; j < k; j++) {
6055dfecf96Smrg		    len = eng.cod[j + 4];
6065dfecf96Smrg		    if ((len >> 1) <= l) {
6075dfecf96Smrg			for (i = m = 0; i < len; m++, i += 2)
6085dfecf96Smrg			    if (ptr[i] != str[m] && ptr[i + 1] != str[m])
6095dfecf96Smrg				goto next_cstl;
6105dfecf96Smrg			goto cstl_match;
6115dfecf96Smrg		    }
6125dfecf96Smrgnext_cstl:
6135dfecf96Smrg		    ptr += len;
6145dfecf96Smrg		}
6155dfecf96Smrg		goto fail;
6165dfecf96Smrgcstl_match:
6175dfecf96Smrg		ci = bas;
6185dfecf96Smrg		si = len >> 1;
6195dfecf96Smrg		goto match;
6205dfecf96Smrg
6215dfecf96Smrg
6225dfecf96Smrg	    case Re_LargeStringList:
6235dfecf96Smrg		/* Where to jump after match */
6245dfecf96Smrg		bas = eng.cod[1] | (eng.cod[2] << 8);
6255dfecf96Smrg
6265dfecf96Smrg		str = eng.str;
6275dfecf96Smrg
6285dfecf96Smrg		/* First entry in index map */
6295dfecf96Smrg		ptr = eng.cod + 3;
6305dfecf96Smrg		i = (int)str[0] << 1;
6315dfecf96Smrg		j = ptr[i] | (ptr[i + 1] << 8);
6325dfecf96Smrg		if (j == 0xffff)
6335dfecf96Smrg		    /* No entry with this byte */
6345dfecf96Smrg		    goto fail;
6355dfecf96Smrg
6365dfecf96Smrg		/* Bytes left in input */
6375dfecf96Smrg		l = eng.end - eng.str;
6385dfecf96Smrg
6395dfecf96Smrg		/* First entry matching initial byte */
6405dfecf96Smrg		ptr += 512 + j;
6415dfecf96Smrg
6425dfecf96Smrg		for (len = ptr[0];
6435dfecf96Smrg		     str[0] == ptr[1];
6445dfecf96Smrg		     ptr += len + 1, len = ptr[0]) {
6455dfecf96Smrg		    if (len <= l) {
6465dfecf96Smrg			for (i = 1; i < len; i++) {
6475dfecf96Smrg			    if (ptr[i + 1] != str[i])
6485dfecf96Smrg				goto next_lstl;
6495dfecf96Smrg			}
6505dfecf96Smrg			ci = bas;
6515dfecf96Smrg			si = len;
6525dfecf96Smrg			goto match;
6535dfecf96Smrg		    }
6545dfecf96Smrgnext_lstl:;
6555dfecf96Smrg		}
6565dfecf96Smrg		goto fail;
6575dfecf96Smrg
6585dfecf96Smrg	    case Re_LargeCaseStringList:
6595dfecf96Smrg		/* Where to jump after match */
6605dfecf96Smrg		bas = eng.cod[1] | (eng.cod[2] << 8);
6615dfecf96Smrg
6625dfecf96Smrg		str = eng.str;
6635dfecf96Smrg
6645dfecf96Smrg		/* First entry in index map */
6655dfecf96Smrg		ptr = eng.cod + 3;
6665dfecf96Smrg		i = (int)str[0] << 1;
6675dfecf96Smrg		j = ptr[i] | (ptr[i + 1] << 8);
6685dfecf96Smrg		if (j == 0xffff)
6695dfecf96Smrg		    /* No entry with this byte */
6705dfecf96Smrg		    goto fail;
6715dfecf96Smrg
6725dfecf96Smrg		/* Bytes left in input */
6735dfecf96Smrg		l = eng.end - eng.str;
6745dfecf96Smrg
6755dfecf96Smrg		/* First entry matching initial byte */
6765dfecf96Smrg		ptr += 512 + j;
6775dfecf96Smrg
6785dfecf96Smrg		for (len = ptr[0];
6795dfecf96Smrg		     str[0] == ptr[1] || str[0] == ptr[2];
6805dfecf96Smrg		     ptr += len + 1, len = ptr[0]) {
6815dfecf96Smrg		    if ((k = (len >> 1)) <= l) {
6825dfecf96Smrg			for (i = 2, j = 1; i < len; i += 2, j++) {
6835dfecf96Smrg			    if (ptr[i + 1] != str[j] && ptr[i + 2] != str[j])
6845dfecf96Smrg				goto next_lcstl;
6855dfecf96Smrg			}
6865dfecf96Smrg			ci = bas;
6875dfecf96Smrg			si = k;
6885dfecf96Smrg			goto match;
6895dfecf96Smrg		    }
6905dfecf96Smrgnext_lcstl:;
6915dfecf96Smrg		}
6925dfecf96Smrg		goto fail;
6935dfecf96Smrg
6945dfecf96Smrg
6955dfecf96Smrg	    /****************************************************
6965dfecf96Smrg	     * Character range matching				*
6975dfecf96Smrg	     ****************************************************/
6985dfecf96Smrg	    case Re_Range:
6995dfecf96Smrg		if (eng.str < eng.end && eng.cod[eng.str[0] + 1]) {
7005dfecf96Smrg		    ci = 257;
7015dfecf96Smrg		    goto match;
7025dfecf96Smrg		}
7035dfecf96Smrg		goto fail;
7045dfecf96Smrg	    case Re_RangeNot:
7055dfecf96Smrg		if (eng.str >= eng.end || eng.cod[eng.str[0] + 1])
7065dfecf96Smrg		    goto fail;
7075dfecf96Smrg		ci = 257;
7085dfecf96Smrg		goto match;
7095dfecf96Smrg
7105dfecf96Smrg	    /****************************************************
7115dfecf96Smrg	     * Group handling					*
7125dfecf96Smrg	     ****************************************************/
7135dfecf96Smrg	    case Re_Open:
7145dfecf96Smrg		if (++eng.goff >= 9)
7155dfecf96Smrg		    return (RE_ASSERT);
7165dfecf96Smrg		eng.gso[eng.goff] = eng.str - eng.bas;
7175dfecf96Smrg		++eng.cod;
7185dfecf96Smrg		continue;
7195dfecf96Smrg	    case Re_Close:
7205dfecf96Smrg		eng.geo[eng.goff] = eng.str - eng.bas;
7215dfecf96Smrg		++eng.cod;
7225dfecf96Smrg		continue;
7235dfecf96Smrg	    case Re_Update:
7245dfecf96Smrg		bas = eng.cod[1];
7255dfecf96Smrg		eng.geo[eng.goff] = eng.str - eng.bas;
7265dfecf96Smrg		eng.cod += 2;		/* + Update + bas */
7275dfecf96Smrg		continue;
7285dfecf96Smrg
7295dfecf96Smrg	    /****************************************************
7305dfecf96Smrg	     * Backreference					*
7315dfecf96Smrg	     ****************************************************/
7325dfecf96Smrg	    case Re_Backref:
7335dfecf96Smrg		i = eng.cod[1];
7345dfecf96Smrg		j = eng.gso[i];
7355dfecf96Smrg		k = eng.geo[i];
7365dfecf96Smrg		len = k - j;
7375dfecf96Smrg		if (k < j || eng.end - eng.str < len)
7385dfecf96Smrg		    goto fail;
7395dfecf96Smrg		ptr = eng.bas + j;
7405dfecf96Smrg		str = eng.str;
7415dfecf96Smrg		for (l = len; l > 0; l--) {
7425dfecf96Smrg		    if (*ptr++ != *str++)
7435dfecf96Smrg			goto fail;
7445dfecf96Smrg		}
7455dfecf96Smrg		ci = 2;
7465dfecf96Smrg		si = len;
7475dfecf96Smrg		goto match;
7485dfecf96Smrg
7495dfecf96Smrg	    /****************************************************
7505dfecf96Smrg	     * Alternatives handling				*
7515dfecf96Smrg	     ****************************************************/
7525dfecf96Smrg	    case Re_Alt:
7535dfecf96Smrg		bas = eng.off;
7545dfecf96Smrg		if (++eng.off >= MAX_DEPTH)
7555dfecf96Smrg		    return (RE_ASSERT);
7565dfecf96Smrg
7575dfecf96Smrg		/* Get offset of next alternative */
7585dfecf96Smrg		i = eng.cod[1] | (eng.cod[2] << 8);
7595dfecf96Smrg
7605dfecf96Smrg		/* Setup for next alternative if the current fails */
7615dfecf96Smrg		eng.rcod[eng.off] = eng.cod + i + 1;	/* + Alt */
7625dfecf96Smrg
7635dfecf96Smrg		/* If fail, test the next alternative in the same string */
7645dfecf96Smrg		eng.rstr[eng.off] = eng.str;
7655dfecf96Smrg
7665dfecf96Smrg		/* Setup match offsets */
7675dfecf96Smrg		if (eng.so[bas] <= eng.eo[bas])
7685dfecf96Smrg		    eng.so[eng.off] = eng.eo[bas];
7695dfecf96Smrg		else
7705dfecf96Smrg		    eng.so[eng.off] = eng.so[bas];
7715dfecf96Smrg		eng.sv[eng.off] = eng.eo[eng.off] = eng.so[eng.off] - 1;
7725dfecf96Smrg
7735dfecf96Smrg		/* Save start of possible previous matches */
7745dfecf96Smrg		eng.ss[eng.off] = eng.so[bas];
7755dfecf96Smrg
7765dfecf96Smrg		/* Skip code */
7775dfecf96Smrg		eng.cod += 3;
7785dfecf96Smrg
7795dfecf96Smrg		/* Go try the first alternative */
7805dfecf96Smrg		continue;
7815dfecf96Smrg
7825dfecf96Smrg	    case Re_AltNext:
7835dfecf96Smrg		bas = eng.off - 1;
7845dfecf96Smrg		/* Check if matched and if it is a better match */
785dcec6066Smrg		if (eng.eo[eng.off] >= eng.so[eng.off] &&
786dcec6066Smrg		    eng.sv[eng.off] - eng.so[eng.off] <
7875dfecf96Smrg		    eng.eo[eng.off] - eng.so[eng.off])
7885dfecf96Smrg		    eng.sv[eng.off] = eng.eo[eng.off];
7895dfecf96Smrg
7905dfecf96Smrg		/* Get offset of next alternative */
7915dfecf96Smrg		i = eng.cod[1] | (eng.cod[2] << 8);
7925dfecf96Smrg
7935dfecf96Smrg		/* Setup for next alternative if the current fails */
7945dfecf96Smrg		eng.rcod[eng.off] = eng.cod + i + 1;	/* + AltNext */
7955dfecf96Smrg
7965dfecf96Smrg		/* Setup match offset */
7975dfecf96Smrg		eng.eo[eng.off] = eng.so[eng.off] - 1;
7985dfecf96Smrg
7995dfecf96Smrg		/* Reset string for next alternative */
8005dfecf96Smrg		eng.str = eng.rstr[eng.off];
8015dfecf96Smrg
8025dfecf96Smrg		/* Skip code */
8035dfecf96Smrg		eng.cod += 3;
8045dfecf96Smrg
8055dfecf96Smrg		/* Go try the next alternative */
8065dfecf96Smrg		continue;
8075dfecf96Smrg
8085dfecf96Smrg	    case Re_AltDone:
8095dfecf96Smrg		bas = eng.off - 1;
8105dfecf96Smrg		/* Check if matched and if it is a better match */
8115dfecf96Smrg		if (eng.sv[eng.off] - eng.so[eng.off] <
8125dfecf96Smrg		    eng.eo[eng.off] - eng.so[eng.off])
8135dfecf96Smrg		    eng.sv[eng.off] = eng.eo[eng.off];
8145dfecf96Smrg
8155dfecf96Smrg		/* If there is a match */
8165dfecf96Smrg		if (eng.sv[eng.off] >= eng.so[eng.off]) {
8175dfecf96Smrg		    eng.so[bas] = eng.ss[eng.off];
8185dfecf96Smrg		    eng.eo[bas] = eng.sv[eng.off];
8195dfecf96Smrg		    eng.str = eng.bas + eng.eo[bas];
8205dfecf96Smrg
8215dfecf96Smrg		    /* Pop stack and skip code */
8225dfecf96Smrg		    --eng.off;
8235dfecf96Smrg		    ++eng.cod;
8245dfecf96Smrg
8255dfecf96Smrg		    /* Go try next regular expression pattern */
8265dfecf96Smrg		    continue;
8275dfecf96Smrg		}
8285dfecf96Smrg
8295dfecf96Smrg		/* Failed, reset string and pop stack */
8305dfecf96Smrg		eng.str = eng.rstr[eng.off];
8315dfecf96Smrg		--eng.off;
8325dfecf96Smrg		goto fail;
8335dfecf96Smrg
8345dfecf96Smrg
8355dfecf96Smrg	    /****************************************************
8365dfecf96Smrg	     * Repetition					*
8375dfecf96Smrg	     ****************************************************/
8385dfecf96Smrg
8395dfecf96Smrg		/*  Note that the repetition counter is not
8405dfecf96Smrg		 * updated for <re>*, <re>+ and <re>?
8415dfecf96Smrg		 * it is easy to updated, but since it is not
8425dfecf96Smrg		 * really useful, code to do it was removed
8435dfecf96Smrg		 * to save a few cpu cicles. */
8445dfecf96Smrg
8455dfecf96Smrg#define REPETITION_SETUP()					\
8465dfecf96Smrg	if (++eng.off >= MAX_DEPTH)				\
8475dfecf96Smrg	    return (RE_ASSERT);					\
8485dfecf96Smrg								\
8495dfecf96Smrg	/* Return here for recovery if match fail */		\
8505dfecf96Smrg	eng.rcod[eng.off] = eng.cod;				\
8515dfecf96Smrg								\
8525dfecf96Smrg	/* Setup match offsets */				\
8535dfecf96Smrg	if (eng.so[bas] <= eng.eo[bas])				\
8545dfecf96Smrg	    eng.so[eng.off] = eng.eo[bas];			\
8555dfecf96Smrg	else							\
8565dfecf96Smrg	    eng.so[eng.off] = eng.so[bas];			\
8575dfecf96Smrg	eng.ss[eng.off] = eng.so[bas];				\
8585dfecf96Smrg	eng.sv[eng.off] = eng.eo[eng.off] = eng.so[eng.off] - 1;\
8595dfecf96Smrg								\
8605dfecf96Smrg	/* Skip repetition instruction */			\
8615dfecf96Smrg	eng.cod += 4;
8625dfecf96Smrg
8635dfecf96Smrg
8645dfecf96Smrg	    case Re_AnyTimes:
8655dfecf96Smrg		bas = eng.cod[1];
8665dfecf96Smrg		if (eng.off == bas) {
8675dfecf96Smrg		    /* First iteration */
8685dfecf96Smrg		    REPETITION_SETUP();
8695dfecf96Smrg		}
8705dfecf96Smrg		else {
8715dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off] &&
8725dfecf96Smrg			eng.eo[eng.off] > eng.sv[eng.off]) {
8735dfecf96Smrg			/* Update offset of match */
8745dfecf96Smrg			eng.sv[eng.off] = eng.eo[eng.off];
8755dfecf96Smrg
8765dfecf96Smrg			/* Skip repetition instruction */
8775dfecf96Smrg			eng.cod += 4;
8785dfecf96Smrg		    }
8795dfecf96Smrg		    else {
8805dfecf96Smrg			/* Match failed but it is ok */
8815dfecf96Smrg			len = eng.cod[2] | (eng.cod[3] << 8);
8825dfecf96Smrg			eng.so[bas] = eng.ss[eng.off];
8835dfecf96Smrg			if (eng.sv[eng.off] >= eng.so[eng.off])
8845dfecf96Smrg			    /* Something matched earlier, update */
8855dfecf96Smrg			    eng.eo[bas] = eng.sv[eng.off];
8865dfecf96Smrg			else if (eng.eo[bas] < eng.so[bas])
8875dfecf96Smrg			    /* Empty match */
8885dfecf96Smrg			    eng.eo[bas] = eng.so[bas];
8895dfecf96Smrg
8905dfecf96Smrg			/* Try next pattern at correct offset */
8915dfecf96Smrg			eng.str = eng.bas + eng.eo[bas];
8925dfecf96Smrg
8935dfecf96Smrg			/* Pop stack and skip code */
8945dfecf96Smrg			--eng.off;
8955dfecf96Smrg			eng.cod += len;
8965dfecf96Smrg		    }
8975dfecf96Smrg		}
8985dfecf96Smrg		continue;
8995dfecf96Smrg
9005dfecf96Smrg	    case Re_Maybe:
9015dfecf96Smrg		bas = eng.cod[1];
9025dfecf96Smrg		if (eng.off == bas) {
9035dfecf96Smrg		    /* First iteration */
9045dfecf96Smrg		    REPETITION_SETUP();
9055dfecf96Smrg		}
9065dfecf96Smrg		else {
9075dfecf96Smrg		    /* Matched or first iteration is done */
9085dfecf96Smrg		    len = eng.cod[2] | (eng.cod[3] << 8);
9095dfecf96Smrg		    eng.so[bas] = eng.ss[eng.off];
9105dfecf96Smrg		    if (eng.eo[eng.off] > eng.so[eng.off]) {
9115dfecf96Smrg			/* Something matched earlier, update */
9125dfecf96Smrg			eng.eo[bas] = eng.eo[eng.off];
9135dfecf96Smrg			eng.str = eng.bas + eng.eo[bas];
9145dfecf96Smrg			/* Don't need to update counter */
9155dfecf96Smrg		    }
9165dfecf96Smrg		    else {
9175dfecf96Smrg			/* Empty match */
9185dfecf96Smrg			if (eng.eo[bas] < eng.so[bas])
9195dfecf96Smrg			    eng.eo[bas] = eng.so[bas];
9205dfecf96Smrg
9215dfecf96Smrg			/* Try next pattern at correct offset */
9225dfecf96Smrg			eng.str = eng.bas + eng.eo[bas];
9235dfecf96Smrg		    }
9245dfecf96Smrg
9255dfecf96Smrg		    /* Pop stack */
9265dfecf96Smrg		    --eng.off;
9275dfecf96Smrg
9285dfecf96Smrg		    /* Skip code */
9295dfecf96Smrg		    eng.cod += len;
9305dfecf96Smrg		}
9315dfecf96Smrg		continue;
9325dfecf96Smrg
9335dfecf96Smrg	    case Re_AtLeast:
9345dfecf96Smrg		bas = eng.cod[1];
9355dfecf96Smrg		if (eng.off == bas) {
9365dfecf96Smrg		    /* First iteration */
9375dfecf96Smrg		    REPETITION_SETUP();
9385dfecf96Smrg		}
9395dfecf96Smrg		else {
9405dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off] &&
9415dfecf96Smrg			eng.eo[eng.off] > eng.sv[eng.off]) {
9425dfecf96Smrg			/* Update offset of match */
9435dfecf96Smrg			eng.sv[eng.off] = eng.eo[eng.off];
9445dfecf96Smrg
9455dfecf96Smrg			/* Skip repetition instruction */
9465dfecf96Smrg			eng.cod += 4;
9475dfecf96Smrg		    }
9485dfecf96Smrg		    else {
9495dfecf96Smrg			/* Last try failed */
9505dfecf96Smrg			len = eng.cod[2] | (eng.cod[3] << 8);
9515dfecf96Smrg			if (eng.sv[eng.off] >= eng.so[eng.off]) {
9525dfecf96Smrg			    /* Something matched earlier, update */
9535dfecf96Smrg			    eng.so[bas] = eng.ss[eng.off];
9545dfecf96Smrg			    eng.eo[bas] = eng.sv[eng.off];
9555dfecf96Smrg			    eng.str = eng.bas + eng.eo[bas];
9565dfecf96Smrg			}
9575dfecf96Smrg			else {
9585dfecf96Smrg			    /*	Do it here, so that the fail label does
9595dfecf96Smrg			     * not need to do too expensive work for
9605dfecf96Smrg			     * simple patterns. */
9615dfecf96Smrg			    eng.so[bas] = eng.str - eng.bas;
9625dfecf96Smrg
9635dfecf96Smrg			    /* Zero matches, pop stack and restart */
9645dfecf96Smrg			    --eng.off;
9655dfecf96Smrg			    goto fail;
9665dfecf96Smrg			}
9675dfecf96Smrg
9685dfecf96Smrg			/* Pop stack and skip code */
9695dfecf96Smrg			--eng.off;
9705dfecf96Smrg			eng.cod += len;
9715dfecf96Smrg		    }
9725dfecf96Smrg		}
9735dfecf96Smrg		continue;
9745dfecf96Smrg
9755dfecf96Smrg
9765dfecf96Smrg	    /****************************************************
9775dfecf96Smrg	     * Repetition with arguments			*
9785dfecf96Smrg	     ****************************************************/
9795dfecf96Smrg	    case Re_Exact:
9805dfecf96Smrg#define COMPLEX_REPETITION_SETUP_0()				\
9815dfecf96Smrg	i = eng.cod[1];						\
9825dfecf96Smrg	bas = eng.cod[2];
9835dfecf96Smrg
9845dfecf96Smrg#define COMPLEX_REPETITION_SETUP()				\
9855dfecf96Smrg	/* First iteration */					\
9865dfecf96Smrg	if (++eng.off >= MAX_DEPTH)				\
9875dfecf96Smrg	    return (RE_ASSERT);					\
9885dfecf96Smrg								\
9895dfecf96Smrg	/*  Remeber number or repetitions */			\
9905dfecf96Smrg	eng.re[eng.off] = 0;					\
9915dfecf96Smrg								\
9925dfecf96Smrg	/* Return here for recovery if match fail */		\
9935dfecf96Smrg	eng.rcod[eng.off] = eng.cod;				\
9945dfecf96Smrg								\
9955dfecf96Smrg	/* Setup match offsets */				\
9965dfecf96Smrg	if (eng.so[bas] <= eng.eo[bas])				\
9975dfecf96Smrg	    eng.so[eng.off] = eng.eo[bas];			\
9985dfecf96Smrg	else							\
9995dfecf96Smrg	    eng.so[eng.off] = eng.so[bas];			\
10005dfecf96Smrg	eng.sv[eng.off] = eng.eo[eng.off] = eng.so[eng.off] - 1;\
10015dfecf96Smrg	eng.ss[eng.off] = eng.so[bas];				\
10025dfecf96Smrg								\
10035dfecf96Smrg	/* Skip repetition instruction */			\
10045dfecf96Smrg	eng.cod += 5;
10055dfecf96Smrg
10065dfecf96Smrg		COMPLEX_REPETITION_SETUP_0();
10075dfecf96Smrg		if (eng.off == bas) {
10085dfecf96Smrg		    /* First iteration */
10095dfecf96Smrg		    COMPLEX_REPETITION_SETUP();
10105dfecf96Smrg		}
10115dfecf96Smrg		else {
10125dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off] &&
10135dfecf96Smrg			eng.eo[eng.off] > eng.sv[eng.off]) {
10145dfecf96Smrg			/* Update offset of match */
10155dfecf96Smrg			eng.sv[eng.off] = eng.eo[eng.off];
10165dfecf96Smrg
10175dfecf96Smrg			/* Update repetition counter */
10185dfecf96Smrg			if (++eng.re[eng.off] == i) {
10195dfecf96Smrg			    /* Matched the required times */
10205dfecf96Smrg			    eng.so[bas] = eng.ss[eng.off];
10215dfecf96Smrg			    eng.eo[bas] = eng.sv[eng.off];
10225dfecf96Smrg			    eng.str = eng.bas + eng.eo[bas];
10235dfecf96Smrg
10245dfecf96Smrg			    /* Update code */
10255dfecf96Smrg			    k = eng.cod[3] | (eng.cod[4] << 8);
10265dfecf96Smrg			    eng.cod += k;
10275dfecf96Smrg
10285dfecf96Smrg			    /* Pop stack and go for next pattern */
10295dfecf96Smrg			    --eng.off;
10305dfecf96Smrg			    continue;
10315dfecf96Smrg			}
10325dfecf96Smrg
10335dfecf96Smrg			/* Skip repetition instruction */
10345dfecf96Smrg			eng.cod += 5;
10355dfecf96Smrg		    }
10365dfecf96Smrg		    else {
10375dfecf96Smrg			/*  Do it here, so that the fail label does
10385dfecf96Smrg			 * not need to do too expensive work for
10395dfecf96Smrg			 * simple patterns. */
10405dfecf96Smrg			eng.so[bas] = eng.str - eng.bas;
10415dfecf96Smrg
10425dfecf96Smrg			/* Pop stack and restart */
10435dfecf96Smrg			--eng.off;
10445dfecf96Smrg			goto fail;
10455dfecf96Smrg		    }
10465dfecf96Smrg		}
10475dfecf96Smrg		continue;
10485dfecf96Smrg
10495dfecf96Smrg	    case Re_Min:
10505dfecf96Smrg		COMPLEX_REPETITION_SETUP_0();
10515dfecf96Smrg		if (eng.off == bas) {
10525dfecf96Smrg		    /* First iteration */
10535dfecf96Smrg		    COMPLEX_REPETITION_SETUP();
10545dfecf96Smrg		}
10555dfecf96Smrg		else {
10565dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off] &&
10575dfecf96Smrg			eng.eo[eng.off] > eng.sv[eng.off]) {
10585dfecf96Smrg			/* Update offset of match */
10595dfecf96Smrg			eng.sv[eng.off] = eng.eo[eng.off];
10605dfecf96Smrg
10615dfecf96Smrg			/* Update repetition counter */
10625dfecf96Smrg			++eng.re[eng.off];
10635dfecf96Smrg
10645dfecf96Smrg			/* Skip repetition instruction and try again */
10655dfecf96Smrg			eng.cod += 5;
10665dfecf96Smrg		    }
10675dfecf96Smrg		    else {
10685dfecf96Smrg			/* Match failed! */
10695dfecf96Smrg			if (eng.re[eng.off] < i) {
10705dfecf96Smrg			    /*	Do it here, so that the fail label does
10715dfecf96Smrg			     * not need to do too expensive work for
10725dfecf96Smrg			     * simple patterns. */
10735dfecf96Smrg			    eng.so[bas] = eng.str - eng.bas;
10745dfecf96Smrg
10755dfecf96Smrg			    /* Didn't match required number of times */
10765dfecf96Smrg			    --eng.off;
10775dfecf96Smrg			    goto fail;
10785dfecf96Smrg			}
10795dfecf96Smrg			else {
10805dfecf96Smrg			    /* Matched minimum number of times */
10815dfecf96Smrg			    eng.eo[bas] = eng.sv[eng.off];
10825dfecf96Smrg			    eng.str = eng.bas + eng.eo[bas];
10835dfecf96Smrg			    k = eng.cod[3] | (eng.cod[4] << 8);
10845dfecf96Smrg
10855dfecf96Smrg			    /* Update code and pop stack */
10865dfecf96Smrg			    eng.cod += k;
10875dfecf96Smrg			    --eng.off;
10885dfecf96Smrg			}
10895dfecf96Smrg		    }
10905dfecf96Smrg		}
10915dfecf96Smrg		continue;
10925dfecf96Smrg
10935dfecf96Smrg	    case Re_Max:
10945dfecf96Smrg		COMPLEX_REPETITION_SETUP_0();
10955dfecf96Smrg		if (eng.off == bas) {
10965dfecf96Smrg		    /* First iteration */
10975dfecf96Smrg		    COMPLEX_REPETITION_SETUP();
10985dfecf96Smrg		}
10995dfecf96Smrg		else {
11005dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off] &&
11015dfecf96Smrg			eng.eo[eng.off] > eng.sv[eng.off]) {
11025dfecf96Smrg			/* Update offset of match */
11035dfecf96Smrg			eng.sv[eng.off] = eng.eo[eng.off];
11045dfecf96Smrg
11055dfecf96Smrg			/* Update repetition counter */
11065dfecf96Smrg			if (++eng.re[eng.off] == i) {
11075dfecf96Smrg			    /* Matched the maximum times */
11085dfecf96Smrg			    eng.so[bas] = eng.ss[eng.off];
11095dfecf96Smrg			    eng.eo[bas] = eng.sv[eng.off];
11105dfecf96Smrg			    eng.str = eng.bas + eng.eo[bas];
11115dfecf96Smrg
11125dfecf96Smrg			    k = eng.cod[3] | (eng.cod[4] << 8);
11135dfecf96Smrg
11145dfecf96Smrg			    /* Update code and pop stack */
11155dfecf96Smrg			    eng.cod += k;
11165dfecf96Smrg			    --eng.off;
11175dfecf96Smrg			    continue;
11185dfecf96Smrg			}
11195dfecf96Smrg
11205dfecf96Smrg			/* Skip repetition instruction and try again */
11215dfecf96Smrg			eng.cod += 5;
11225dfecf96Smrg		    }
11235dfecf96Smrg		    else {
11245dfecf96Smrg			/* No matches, but zero matches are ok */
11255dfecf96Smrg			k = eng.cod[3] | (eng.cod[4] << 8);
11265dfecf96Smrg			if (eng.sv[eng.off] >= eng.so[eng.off]) {
11275dfecf96Smrg			    /* Something matched earlier, update */
11285dfecf96Smrg			    eng.so[bas] = eng.ss[eng.off];
11295dfecf96Smrg			    eng.eo[bas] = eng.sv[eng.off];
11305dfecf96Smrg			    eng.str = eng.bas + eng.eo[bas];
11315dfecf96Smrg			}
11325dfecf96Smrg			else {
11335dfecf96Smrg			    /* Empty match */
11345dfecf96Smrg			    if (eng.eo[bas] < eng.so[bas])
11355dfecf96Smrg				eng.eo[bas] = eng.so[bas];
11365dfecf96Smrg
11375dfecf96Smrg			    /* Try next pattern at correct offset */
11385dfecf96Smrg			    eng.str = eng.bas + eng.eo[bas];
11395dfecf96Smrg			}
11405dfecf96Smrg
11415dfecf96Smrg			/* Pop stack and update code */
11425dfecf96Smrg			--eng.off;
11435dfecf96Smrg			eng.cod += k;
11445dfecf96Smrg		    }
11455dfecf96Smrg		}
11465dfecf96Smrg		continue;
11475dfecf96Smrg
11485dfecf96Smrg	    case Re_MinMax:
11495dfecf96Smrg		bas = eng.cod[3];
11505dfecf96Smrg		if (eng.off == bas) {
11515dfecf96Smrg		    /* First iteration */
11525dfecf96Smrg		    COMPLEX_REPETITION_SETUP();
11535dfecf96Smrg		}
11545dfecf96Smrg		else {
11555dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off] &&
11565dfecf96Smrg			eng.eo[eng.off] > eng.sv[eng.off]) {
11575dfecf96Smrg			/* Update offset of match */
11585dfecf96Smrg			eng.sv[eng.off] = eng.eo[eng.off];
11595dfecf96Smrg
11605dfecf96Smrg			/* Update repetition counter */
11615dfecf96Smrg			if (++eng.re[eng.off] == eng.cod[2]) {
11625dfecf96Smrg			    /* Matched the maximum times */
11635dfecf96Smrg			    eng.so[bas] = eng.ss[eng.off];
11645dfecf96Smrg			    eng.eo[bas] = eng.sv[eng.off];
11655dfecf96Smrg			    eng.str = eng.bas + eng.eo[bas];
11665dfecf96Smrg			    k = eng.cod[4] | (eng.cod[5] << 8);
11675dfecf96Smrg
11685dfecf96Smrg			    /* Update code and pop stack */
11695dfecf96Smrg			    eng.cod += k;
11705dfecf96Smrg			    --eng.off;
11715dfecf96Smrg			    continue;
11725dfecf96Smrg			}
11735dfecf96Smrg
11745dfecf96Smrg			/* Skip repetition instruction and try again */
11755dfecf96Smrg			eng.cod += 6;
11765dfecf96Smrg		    }
11775dfecf96Smrg		    else {
11785dfecf96Smrg			/* Match failed! */
11795dfecf96Smrg			if (eng.re[eng.off] < eng.cod[1]) {
11805dfecf96Smrg			    /*	Do it here, so that the fail label does
11815dfecf96Smrg			     * not need to do too expensive work for
11825dfecf96Smrg			     * simple patterns. */
11835dfecf96Smrg			    eng.so[bas] = eng.str - eng.bas;
11845dfecf96Smrg
11855dfecf96Smrg			    /* Didn't match required number of times */
11865dfecf96Smrg			    --eng.off;
11875dfecf96Smrg			    goto fail;
11885dfecf96Smrg			}
11895dfecf96Smrg			else {
11905dfecf96Smrg			    /* Matched minimum number of times */
11915dfecf96Smrg			    eng.so[bas] = eng.ss[eng.off];
11925dfecf96Smrg			    eng.eo[bas] = eng.sv[eng.off];
11935dfecf96Smrg			    eng.str = eng.bas + eng.eo[bas];
11945dfecf96Smrg			    k = eng.cod[4] | (eng.cod[5] << 8);
11955dfecf96Smrg
11965dfecf96Smrg			    /* Update code and pop stack */
11975dfecf96Smrg			    eng.cod += k;
11985dfecf96Smrg			    --eng.off;
11995dfecf96Smrg			}
12005dfecf96Smrg		    }
12015dfecf96Smrg		}
12025dfecf96Smrg		continue;
12035dfecf96Smrg
12045dfecf96Smrg
12055dfecf96Smrg	    /****************************************************
12065dfecf96Smrg	     * Special repetition handling			*
12075dfecf96Smrg	     ****************************************************/
12085dfecf96Smrg	    case Re_AnyAnyTimes:
12095dfecf96Smrg		/* code(1) + bas(1) + gbas(1) + jump(2) */
12105dfecf96Smrg		bas = eng.cod[1];
12115dfecf96Smrg		if (eng.off == bas) {
12125dfecf96Smrg		    /* First iteration */
12135dfecf96Smrg		    if (++eng.off >= MAX_DEPTH)
12145dfecf96Smrg			return (RE_ASSERT);
12155dfecf96Smrg
12165dfecf96Smrg		    /* Return here for recovery if match fail */
12175dfecf96Smrg		    eng.rcod[eng.off] = eng.cod;
12185dfecf96Smrg
12195dfecf96Smrg		    /* If fail, test the next pattern at the same point */
12205dfecf96Smrg		    eng.rstr[eng.off] = eng.str;
12215dfecf96Smrg
12225dfecf96Smrg		    /* Setup match offsets */
12235dfecf96Smrg		    eng.so[eng.off] = eng.str - eng.bas;
12245dfecf96Smrg		    eng.eo[eng.off] = eng.so[eng.off] - 1;
12255dfecf96Smrg
12265dfecf96Smrg		    if (newline)
12275dfecf96Smrg			/*  Use the repetition counter to store start of
12285dfecf96Smrg			 * skipped string, to later check if skipping a
12295dfecf96Smrg			 * newline. */
12305dfecf96Smrg			eng.re[eng.off] = eng.so[eng.off];
12315dfecf96Smrg
12325dfecf96Smrg		    /* Save start of possible previous matches */
12335dfecf96Smrg		    eng.ss[eng.off] = eng.so[bas];
12345dfecf96Smrg
12355dfecf96Smrg		    /* Skip repetition instruction */
12365dfecf96Smrg		    eng.cod += 5;
12375dfecf96Smrg		}
12385dfecf96Smrg		else {
12395dfecf96Smrg		    /* -1 as an unsigned char */
12405dfecf96Smrg		    if (eng.cod[2] != 0xff)
12415dfecf96Smrg			eng.goff = eng.cod[2];
12425dfecf96Smrg		    else
12435dfecf96Smrg			eng.goff = -1;
12445dfecf96Smrg
12455dfecf96Smrg		    if (newline) {
12465dfecf96Smrg			ptr = eng.bas + eng.re[eng.off];
12475dfecf96Smrg			str = eng.bas + eng.so[eng.off];
12485dfecf96Smrg			for (; ptr < str; ptr++)
12495dfecf96Smrg			    if (*ptr == '\n') {
12505dfecf96Smrg				eng.cod = eng.rcod[0];
12515dfecf96Smrg				eng.so[0] = ptr - eng.bas + 1;
12525dfecf96Smrg				eng.eo[0] = eng.so[0] - 1;
12535dfecf96Smrg				eng.rstr[0] = eng.str = ptr + 1;
12545dfecf96Smrg				eng.off = 0;
12555dfecf96Smrg				goto reset;
12565dfecf96Smrg			    }
12575dfecf96Smrg			/* If looping, don't do too many noops */
12585dfecf96Smrg			eng.re[eng.off] = ptr - eng.bas;
12595dfecf96Smrg		    }
12605dfecf96Smrg
12615dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off]) {
12625dfecf96Smrg			/* Note that this is only true if all possibly
12635dfecf96Smrg			 * nested special repetitions also matched. */
12645dfecf96Smrg
12655dfecf96Smrg			if (eng.goff >= 0) {
12665dfecf96Smrg			    if (eng.cod[5] == Re_Update)
12675dfecf96Smrg				eng.gso[eng.goff] = eng.eo[bas] +
12685dfecf96Smrg						    (eng.so[bas] > eng.eo[bas]);
12695dfecf96Smrg			    else if (eng.geo[eng.goff] < eng.so[eng.off])
12705dfecf96Smrg				eng.geo[eng.goff] = eng.so[eng.off];
12715dfecf96Smrg			}
12725dfecf96Smrg
12735dfecf96Smrg			/* Jump relative offset */
12745dfecf96Smrg			len = eng.cod[3] | (eng.cod[4] << 8);
12755dfecf96Smrg
12765dfecf96Smrg			/* Restore offset from where started trying */
12775dfecf96Smrg			eng.so[bas] = eng.ss[eng.off];
12785dfecf96Smrg			eng.eo[bas] = eng.eo[eng.off];
12795dfecf96Smrg
12805dfecf96Smrg			/* Pop stack and skip code */
12815dfecf96Smrg			--eng.off;
12825dfecf96Smrg			eng.cod += len;
12835dfecf96Smrg		    }
12845dfecf96Smrg		    else {
12855dfecf96Smrg			/* Only give up if the entire string was scanned */
12865dfecf96Smrg			if (eng.str < eng.end) {
12875dfecf96Smrg			    /* Update restart point for next pattern */
12885dfecf96Smrg			    eng.str = ++eng.rstr[eng.off];
12895dfecf96Smrg
12905dfecf96Smrg			    /* Reset start of nested match */
12915dfecf96Smrg			    eng.so[eng.off] = eng.str - eng.bas;
12925dfecf96Smrg
12935dfecf96Smrg			    /* Skip repetition instruction */
12945dfecf96Smrg			    eng.cod += 5;
12955dfecf96Smrg			}
12965dfecf96Smrg			else {
12975dfecf96Smrg			    /* Entire string scanned and failed */
12985dfecf96Smrg
12995dfecf96Smrg			    /* Jump relative offset */
13005dfecf96Smrg			    len = eng.cod[3] | (eng.cod[4] << 8);
13015dfecf96Smrg
13025dfecf96Smrg			    /* Restore offset from where started trying */
13035dfecf96Smrg			    eng.so[bas] = eng.ss[eng.off];
13045dfecf96Smrg			    eng.eo[bas] = eng.ss[eng.off] - 1;
13055dfecf96Smrg
13065dfecf96Smrg			    /* Pop stack and skip code */
13075dfecf96Smrg			    --eng.off;
13085dfecf96Smrg			    eng.cod += len;
13095dfecf96Smrg			}
13105dfecf96Smrg		    }
13115dfecf96Smrg		}
13125dfecf96Smrg		continue;
13135dfecf96Smrg
13145dfecf96Smrg	    /*  This is significantly different than matching <re>.*<re>
13155dfecf96Smrg	     * because it may need to restart several times since it is
13165dfecf96Smrg	     * possible to find too many false positives, for example:
13175dfecf96Smrg	     *	a.*b	=> once one "a" is found, scan all
13185dfecf96Smrg	     *		   the remaining string searching for a "b"
13195dfecf96Smrg	     *  a.?b	=> the string may have too many "a"s, but the
13205dfecf96Smrg	     *		   first occurrences of "a" may not be followed
13215dfecf96Smrg	     *		   by any-character and a "b" or a single "b".
13225dfecf96Smrg	     */
13235dfecf96Smrg	    case Re_AnyMaybe:
13245dfecf96Smrg		bas = eng.cod[1];
13255dfecf96Smrg		if (eng.off == bas) {
13265dfecf96Smrg		    /* First iteration */
13275dfecf96Smrg		    if (++eng.off >= MAX_DEPTH)
13285dfecf96Smrg			return (RE_ASSERT);
13295dfecf96Smrg
13305dfecf96Smrg		    /* Return here for recovery if match fail */
13315dfecf96Smrg		    eng.rcod[eng.off] = eng.cod;
13325dfecf96Smrg
13335dfecf96Smrg		    /* First try without eating a byte */
13345dfecf96Smrg		    eng.rstr[eng.off] = eng.str;
13355dfecf96Smrg
13365dfecf96Smrg		    /* Remember this is the first try if match fail */
13375dfecf96Smrg		    eng.re[eng.off] = 0;
13385dfecf96Smrg
13395dfecf96Smrg		    /* Setup match offsets */
13405dfecf96Smrg		    eng.so[eng.off] = eng.str - eng.bas;
13415dfecf96Smrg		    eng.eo[eng.off] = eng.so[eng.off] - 1;
13425dfecf96Smrg
13435dfecf96Smrg		    /* Save start of possible previous matches */
13445dfecf96Smrg		    eng.ss[eng.off] = eng.so[bas];
13455dfecf96Smrg
13465dfecf96Smrg		    /* Skip repetition instruction */
13475dfecf96Smrg		    eng.cod += 5;
13485dfecf96Smrg		}
13495dfecf96Smrg		else {
13505dfecf96Smrg		    /* -1 as an unsigned char */
13515dfecf96Smrg		    if (eng.cod[2] != 0xff)
13525dfecf96Smrg			eng.goff = eng.cod[2];
13535dfecf96Smrg		    else
13545dfecf96Smrg			eng.goff = -1;
13555dfecf96Smrg
13565dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off]) {
13575dfecf96Smrg			/* Something matched */
13585dfecf96Smrg
13595dfecf96Smrg			if (eng.goff >= 0) {
13605dfecf96Smrg			    if (eng.cod[5] == Re_Update)
13615dfecf96Smrg				eng.gso[eng.goff] = eng.eo[bas] +
13625dfecf96Smrg						    (eng.so[bas] > eng.eo[bas]);
13635dfecf96Smrg			    else if (eng.geo[eng.goff] < eng.so[eng.off])
13645dfecf96Smrg				eng.geo[eng.goff] = eng.so[eng.off];
13655dfecf96Smrg			}
13665dfecf96Smrg
13675dfecf96Smrg			/* Jump relative offset */
13685dfecf96Smrg			len = eng.cod[3] | (eng.cod[4] << 8);
13695dfecf96Smrg
13705dfecf96Smrg			/* Update offset of match */
13715dfecf96Smrg			eng.eo[bas] = eng.eo[eng.off];
13725dfecf96Smrg
13735dfecf96Smrg			/* Pop stack and skip code */
13745dfecf96Smrg			--eng.off;
13755dfecf96Smrg			eng.cod += len;
13765dfecf96Smrg		    }
13775dfecf96Smrg		    else if (eng.re[eng.off] == 0 &&
13785dfecf96Smrg			     (!newline || eng.rstr[eng.off][1] != '\n')) {
13795dfecf96Smrg			/* Try this time skiping a byte */
13805dfecf96Smrg			++eng.re[eng.off];
13815dfecf96Smrg
13825dfecf96Smrg			/* Reset string, skip code and go try one time more */
13835dfecf96Smrg			eng.str = ++eng.rstr[eng.off];
13845dfecf96Smrg			eng.cod += 5;
13855dfecf96Smrg		    }
13865dfecf96Smrg		    else {
13875dfecf96Smrg			/* Failed to match */
13885dfecf96Smrg
13895dfecf96Smrg			/* Update offsets */
13905dfecf96Smrg			eng.eo[bas] = eng.ss[eng.off];
13915dfecf96Smrg			eng.so[bas] = eng.eo[bas] + 1;
13925dfecf96Smrg
13935dfecf96Smrg			eng.str = eng.rstr[eng.off] + (eng.re[eng.off] == 0);
13945dfecf96Smrg
13955dfecf96Smrg			/* Pop stack and return to toplevel code */
13965dfecf96Smrg			--eng.off;
13975dfecf96Smrg			if (eng.str >= eng.end)
13985dfecf96Smrg			    goto wont;
13995dfecf96Smrg			eng.cod = eng.rcod[bas];
14005dfecf96Smrg		    }
14015dfecf96Smrg		}
14025dfecf96Smrg		continue;
14035dfecf96Smrg
14045dfecf96Smrg	    /* .+ almost identical to .* but requires eating at least one byte */
14055dfecf96Smrg	    case Re_AnyAtLeast:
14065dfecf96Smrg		bas = eng.cod[1];
14075dfecf96Smrg		if (eng.off == bas) {
14085dfecf96Smrg		    /* First iteration */
14095dfecf96Smrg		    if (++eng.off >= MAX_DEPTH)
14105dfecf96Smrg			return (RE_ASSERT);
14115dfecf96Smrg
14125dfecf96Smrg		    /* Return here for recovery if match fail */
14135dfecf96Smrg		    eng.rcod[eng.off] = eng.cod;
14145dfecf96Smrg
14155dfecf96Smrg		    /* Skip one byte for the restart string */
14165dfecf96Smrg		    if (newline && eng.str[0] == '\n') {
14175dfecf96Smrg			/* Cannot skip newline */
14185dfecf96Smrg			eng.cod = eng.rcod[0];
14195dfecf96Smrg			eng.rstr[0] = ++eng.str;
14205dfecf96Smrg			eng.so[0] = eng.str - eng.bas;
14215dfecf96Smrg			eng.eo[0] = eng.so[0] - 1;
14225dfecf96Smrg			eng.off = 0;
14235dfecf96Smrg			goto reset;
14245dfecf96Smrg		    }
14255dfecf96Smrg		    eng.rstr[eng.off] = ++eng.str;
14265dfecf96Smrg
14275dfecf96Smrg		    /* Setup match offsets */
14285dfecf96Smrg		    eng.so[eng.off] = eng.str - eng.bas;
14295dfecf96Smrg		    eng.eo[eng.off] = eng.so[eng.off] - 1;
14305dfecf96Smrg
14315dfecf96Smrg		    if (newline)
14325dfecf96Smrg			/*  Use the repetition counter to store start of
14335dfecf96Smrg			 * skipped string, to later check if skipping a
14345dfecf96Smrg			 * newline. */
14355dfecf96Smrg			eng.re[eng.off] = eng.so[eng.off];
14365dfecf96Smrg
14375dfecf96Smrg		    /* Save start of possible previous matches */
14385dfecf96Smrg		    eng.ss[eng.off] = eng.so[bas];
14395dfecf96Smrg
14405dfecf96Smrg		    /* Skip repetition instruction */
14415dfecf96Smrg		    eng.cod += 5;
14425dfecf96Smrg		}
14435dfecf96Smrg		else {
14445dfecf96Smrg		    /* -1 as an unsigned char */
14455dfecf96Smrg		    if (eng.cod[2] != 0xff)
14465dfecf96Smrg			eng.goff = eng.cod[2];
14475dfecf96Smrg		    else
14485dfecf96Smrg			eng.goff = -1;
14495dfecf96Smrg
14505dfecf96Smrg		    if (newline) {
14515dfecf96Smrg			ptr = eng.bas + eng.re[eng.off];
14525dfecf96Smrg			str = eng.bas + eng.so[eng.off];
14535dfecf96Smrg			for (; ptr < str; ptr++)
14545dfecf96Smrg			    if (*ptr == '\n') {
14555dfecf96Smrg				eng.cod = eng.rcod[0];
14565dfecf96Smrg				eng.so[0] = ptr - eng.bas + 1;
14575dfecf96Smrg				eng.eo[0] = eng.so[0] - 1;
14585dfecf96Smrg				eng.rstr[0] = eng.str = ptr + 1;
14595dfecf96Smrg				eng.off = 0;
14605dfecf96Smrg				goto reset;
14615dfecf96Smrg			    }
14625dfecf96Smrg			/* If looping, don't do too many noops */
14635dfecf96Smrg			eng.re[eng.off] = ptr - eng.bas;
14645dfecf96Smrg		    }
14655dfecf96Smrg
14665dfecf96Smrg		    if (eng.eo[eng.off] >= eng.so[eng.off]) {
14675dfecf96Smrg			/* Note that this is only true if all possibly
14685dfecf96Smrg			 * nested special repetitions also matched. */
14695dfecf96Smrg
14705dfecf96Smrg			if (eng.goff >= 0) {
14715dfecf96Smrg			    if (eng.cod[5] == Re_Update)
14725dfecf96Smrg				eng.gso[eng.goff] = eng.eo[bas] +
14735dfecf96Smrg						    (eng.so[bas] > eng.eo[bas]);
14745dfecf96Smrg			    else if (eng.geo[eng.goff] < eng.so[eng.off])
14755dfecf96Smrg				eng.geo[eng.goff] = eng.so[eng.off];
14765dfecf96Smrg			}
14775dfecf96Smrg
14785dfecf96Smrg			/* Jump relative offset */
14795dfecf96Smrg			len = eng.cod[3] | (eng.cod[4] << 8);
14805dfecf96Smrg
14815dfecf96Smrg			/* Restore offset from where started trying */
14825dfecf96Smrg			eng.so[bas] = eng.ss[eng.off];
14835dfecf96Smrg			eng.eo[bas] = eng.eo[eng.off];
14845dfecf96Smrg
14855dfecf96Smrg			/* Pop stack and skip code */
14865dfecf96Smrg			--eng.off;
14875dfecf96Smrg			eng.cod += len;
14885dfecf96Smrg		    }
14895dfecf96Smrg		    else {
14905dfecf96Smrg			/* Only give up if the entire string was scanned */
14915dfecf96Smrg			if (eng.str < eng.end) {
14925dfecf96Smrg			    /* Update restart point for next pattern */
14935dfecf96Smrg			    eng.str = ++eng.rstr[eng.off];
14945dfecf96Smrg
14955dfecf96Smrg			    /* Reset start of nested match */
14965dfecf96Smrg			    eng.so[eng.off] = eng.str - eng.bas;
14975dfecf96Smrg
14985dfecf96Smrg			    /* Skip repetition instruction */
14995dfecf96Smrg			    eng.cod += 5;
15005dfecf96Smrg			}
15015dfecf96Smrg			else {
15025dfecf96Smrg			    /* Entire string scanned and failed */
15035dfecf96Smrg
15045dfecf96Smrg			    /* Jump relative offset */
15055dfecf96Smrg			    len = eng.cod[3] | (eng.cod[4] << 8);
15065dfecf96Smrg
15075dfecf96Smrg			    /* Restore offset from where started trying */
15085dfecf96Smrg			    eng.so[bas] = eng.ss[eng.off];
15095dfecf96Smrg			    eng.eo[bas] = eng.ss[eng.off] - 1;
15105dfecf96Smrg
15115dfecf96Smrg			    /* Pop stack and skip code */
15125dfecf96Smrg			    --eng.off;
15135dfecf96Smrg			    eng.cod += len;
15145dfecf96Smrg			}
15155dfecf96Smrg		    }
15165dfecf96Smrg		}
15175dfecf96Smrg		continue;
15185dfecf96Smrg
15195dfecf96Smrg
15205dfecf96Smrg	    /****************************************************
15215dfecf96Smrg	     * Repetition matched!				*
15225dfecf96Smrg	     ****************************************************/
15235dfecf96Smrg	    case Re_RepJump:
15245dfecf96Smrg		/* eng.cod[1] is toplevel offset of repetition */
15255dfecf96Smrg		if (eng.off > eng.cod[1])
15265dfecf96Smrg		    /* If still needs to try matches */
15275dfecf96Smrg		    eng.cod -= eng.cod[2];
15285dfecf96Smrg		else
15295dfecf96Smrg		    eng.cod += 3;	/* + RepJump + bas + len-size */
15305dfecf96Smrg		continue;
15315dfecf96Smrg
15325dfecf96Smrg	    case Re_RepLongJump:
15335dfecf96Smrg		/* eng.cod[1] is toplevel offset of repetition */
15345dfecf96Smrg		if (eng.off > eng.cod[1])
15355dfecf96Smrg		    /* If still needs to try matches */
15365dfecf96Smrg		    eng.cod -= eng.cod[2] | (eng.cod[3] << 8);
15375dfecf96Smrg		else
15385dfecf96Smrg		    eng.cod += 4;	/* + RepLongJump + bas + len-size */
15395dfecf96Smrg		continue;
15405dfecf96Smrg
15415dfecf96Smrg	    /****************************************************
15425dfecf96Smrg	     * Finished						*
15435dfecf96Smrg	     ****************************************************/
15445dfecf96Smrg	    case Re_DoneIf:
15455dfecf96Smrg		if (eng.eo[eng.off] >= eng.so[eng.off]) {
15465dfecf96Smrg		    eng.so[0] = eng.ss[eng.off];
15475dfecf96Smrg		    eng.eo[0] = eng.eo[eng.off];
15485dfecf96Smrg		    goto done;
15495dfecf96Smrg		}
15505dfecf96Smrg		++eng.cod;
15515dfecf96Smrg		continue;
15525dfecf96Smrg	    case Re_MaybeDone:
15535dfecf96Smrg		if (eng.eo[eng.off] >= eng.so[eng.off]) {
15545dfecf96Smrg		    eng.so[0] = eng.ss[eng.off];
15555dfecf96Smrg		    eng.eo[0] = eng.eo[eng.off];
15565dfecf96Smrg		    goto done;
15575dfecf96Smrg		}
15585dfecf96Smrg		++eng.cod;
15595dfecf96Smrg		continue;
15605dfecf96Smrg	    case Re_Done:
15615dfecf96Smrg		goto done;
15625dfecf96Smrg
15635dfecf96Smrg	    default:
15645dfecf96Smrg		/* Fatal internal error */
15655dfecf96Smrg		return (RE_ASSERT);
15665dfecf96Smrg	}
15675dfecf96Smrg
15685dfecf96Smrg
15695dfecf96Smrgwont:
15705dfecf96Smrg	/* Surely won't match */
15715dfecf96Smrg	if (eng.off == 0) {
15725dfecf96Smrg	    eng.eo[0] = eng.so[0] - 1;
15735dfecf96Smrg	    break;
15745dfecf96Smrg	}
15755dfecf96Smrg
15765dfecf96Smrg
15775dfecf96Smrgfail:
15785dfecf96Smrg	if (eng.off == 0) {
15795dfecf96Smrg	    /* If the entire string scanned */
15805dfecf96Smrg	    if (++eng.str > eng.end) {
15815dfecf96Smrg		eng.eo[0] = eng.so[0] - 1;
15825dfecf96Smrg		break;
15835dfecf96Smrg	    }
15845dfecf96Smrg	    eng.goff = -1;
15855dfecf96Smrg	    /* Update start of possible match after restart */
15865dfecf96Smrg	    if (eng.eo[0] >= eng.so[0]) {
15875dfecf96Smrg		/* If first fail */
15885dfecf96Smrg		eng.str = eng.rstr[0];
15895dfecf96Smrg		++eng.rstr[0];
15905dfecf96Smrg		eng.so[0] = eng.str - eng.bas;
15915dfecf96Smrg		eng.eo[0] = eng.so[eng.off] - 1;
15925dfecf96Smrg	    }
15935dfecf96Smrg	    else
15945dfecf96Smrg		/* Just trying at next byte */
15955dfecf96Smrg		++eng.so[0];
15965dfecf96Smrg	}
15975dfecf96Smrg	else
15985dfecf96Smrg	    /* Remember this match failed */
15995dfecf96Smrg	    eng.eo[eng.off] = eng.so[eng.off] - 1;
16005dfecf96Smrg
16015dfecf96Smrg	/* Restart code */
16025dfecf96Smrg	eng.cod = eng.rcod[eng.off];
16035dfecf96Smrg	continue;
16045dfecf96Smrg
16055dfecf96Smrg
16065dfecf96Smrgmatch:
16075dfecf96Smrg	/* If first match */
16085dfecf96Smrg	if (eng.eo[eng.off] < eng.so[eng.off]) {
16095dfecf96Smrg	    if (eng.off == 0)
16105dfecf96Smrg		eng.rstr[0] = eng.str + 1;
16115dfecf96Smrg	    eng.so[eng.off] = eng.eo[eng.off] = eng.str - eng.bas;
16125dfecf96Smrg	}
16135dfecf96Smrg	eng.eo[eng.off] += si;
16145dfecf96Smrg	eng.cod += ci;
16155dfecf96Smrg	eng.str += si;
16165dfecf96Smrg	ci = si = 1;
16175dfecf96Smrg	continue;
16185dfecf96Smrg
16195dfecf96Smrgdone:
16205dfecf96Smrg	break;
16215dfecf96Smrg    }
16225dfecf96Smrg
16235dfecf96Smrg    if (nmatch) {
16245dfecf96Smrg	if (flags & RE_STARTEND)
16255dfecf96Smrg	    len = pmat[0].rm_so;
16265dfecf96Smrg	else
16275dfecf96Smrg	    len = 0;
16285dfecf96Smrg	if (!nosub) {
16295dfecf96Smrg	    if (preg->cod[1] != 0xff)
16305dfecf96Smrg		eng.goff = preg->cod[1];
16315dfecf96Smrg	    pmat[0].rm_so = eng.so[0];
16325dfecf96Smrg	    pmat[0].rm_eo = eng.eo[0];
16335dfecf96Smrg	    for (i = 1; i < nmatch; i++) {
16345dfecf96Smrg		if (i - 1 <= eng.goff) {
16355dfecf96Smrg		    pmat[i].rm_so = eng.gso[i - 1];
16365dfecf96Smrg		    pmat[i].rm_eo = eng.geo[i - 1];
16375dfecf96Smrg		}
16385dfecf96Smrg		else {
16395dfecf96Smrg		    pmat[i].rm_so = 0;
16405dfecf96Smrg		    pmat[i].rm_eo = -1;
16415dfecf96Smrg		}
16425dfecf96Smrg	    }
16435dfecf96Smrg	    if (len) {
16445dfecf96Smrg		/* Update offsets, since the match was done in a substring */
16455dfecf96Smrg		j = eng.goff + 2 > nmatch ? nmatch : eng.goff + 2;
16465dfecf96Smrg		for (i = 0; i < j; i++) {
16475dfecf96Smrg		    pmat[i].rm_so += len;
16485dfecf96Smrg		    pmat[i].rm_eo += len;
16495dfecf96Smrg		}
16505dfecf96Smrg	    }
16515dfecf96Smrg	}
16525dfecf96Smrg	else {
16535dfecf96Smrg	    /*	Already know these values, allow compiling the regex with
16545dfecf96Smrg	     * RE_NOSUB to use parenthesis only for grouping, but avoiding
16555dfecf96Smrg	     * the runtime overhead of keeping track of the subexpression
16565dfecf96Smrg	     * offsets. */
16575dfecf96Smrg	    pmat[0].rm_so = eng.so[0] + len;
16585dfecf96Smrg	    pmat[0].rm_eo = eng.eo[0] + len;
16595dfecf96Smrg	}
16605dfecf96Smrg    }
16615dfecf96Smrg
16625dfecf96Smrg    return (eng.so[0] <= eng.eo[0] ? 0 : RE_NOMATCH);
16635dfecf96Smrg}
16645dfecf96Smrg
16655dfecf96Smrgint
16665dfecf96Smrgreerror(int ecode, const re_cod *preg, char *ebuffer, int ebuffer_size)
16675dfecf96Smrg{
16681c4d503eSmrg    static const char *errors[] = {
16695dfecf96Smrg	"No error",
16705dfecf96Smrg	"Failed to match",			/* NOMATCH */
16715dfecf96Smrg
16725dfecf96Smrg	/* Errors not generated */
16735dfecf96Smrg	"Invalid regular expression",		/* BADPAT */
16745dfecf96Smrg	"Invalid collating element",		/* ECOLLATE */
16755dfecf96Smrg	"Invalid character class",		/* ECTYPE */
16765dfecf96Smrg
16775dfecf96Smrg	"`\' applied to unescapable character",	/* EESCAPE */
16785dfecf96Smrg	"Invalid backreference number",		/* ESUBREG */
16795dfecf96Smrg	"Brackets `[ ]' not balanced",		/* EBRACK */
16805dfecf96Smrg	"Parentheses `( )' not balanced",	/* EPAREN */
16815dfecf96Smrg	"Braces `{ }' not balanced",		/* EBRACE */
16825dfecf96Smrg	"Invalid repetition count(s) in `{ }'",	/* BADBR */
16835dfecf96Smrg	"Invalid character range in `[ ]'",	/* ERANGE */
16845dfecf96Smrg	"Out of memory",			/* ESPACE */
16855dfecf96Smrg	"`?', `*', or `+' operand invalid",	/* BADRPT */
16865dfecf96Smrg	"Empty (sub)expression",		/* EMPTY */
16875dfecf96Smrg	"Assertion error - you found a bug",	/* ASSERT */
16885dfecf96Smrg	"Invalid argument"			/* INVARG */
16895dfecf96Smrg    };
16901c4d503eSmrg    const char *str;
16915dfecf96Smrg
16925dfecf96Smrg    if (ecode >= 0 && ecode < sizeof(errors) / sizeof(errors[0]))
16935dfecf96Smrg	str = errors[ecode];
16945dfecf96Smrg    else
16955dfecf96Smrg	str = "Unknown error";
16965dfecf96Smrg
16975dfecf96Smrg    return (snprintf(ebuffer, ebuffer_size, "%s", str));
16985dfecf96Smrg}
16995dfecf96Smrg
17005dfecf96Smrgvoid
17015dfecf96Smrgrefree(re_cod *cod)
17025dfecf96Smrg{
17035dfecf96Smrg    free(cod->cod);
17045dfecf96Smrg    cod->cod = NULL;
17055dfecf96Smrg}
17065dfecf96Smrg
17075dfecf96Smrgstatic void
17085dfecf96Smrgreinit(void)
17095dfecf96Smrg{
17105dfecf96Smrg    int i;
17115dfecf96Smrg    static int first = 1;
17125dfecf96Smrg
17135dfecf96Smrg    if (!first)
17145dfecf96Smrg	return;
17155dfecf96Smrg    first = 0;
17165dfecf96Smrg
17175dfecf96Smrg    re__alnum['_'] = 1;
17185dfecf96Smrg
17195dfecf96Smrg    for (i = '0'; i <= '7'; i++)
17205dfecf96Smrg	re__alnum[i] = re__odigit[i] = re__ddigit[i] = re__xdigit[i] = 1;
17215dfecf96Smrg
17225dfecf96Smrg    for (; i <= '9'; i++)
17235dfecf96Smrg	re__alnum[i] = re__ddigit[i] = re__xdigit[i] = 1;
17245dfecf96Smrg
17255dfecf96Smrg    for (i = 'a'; i <= 'f'; i++)
17265dfecf96Smrg	re__alnum[i] = re__xdigit[i] = 1;
17275dfecf96Smrg    for (; i <= 'z'; i++)
17285dfecf96Smrg	re__alnum[i] = 1;
17295dfecf96Smrg
17305dfecf96Smrg    for (i = 'A'; i <= 'F'; i++)
17315dfecf96Smrg	re__alnum[i] = re__xdigit[i] = 1;
17325dfecf96Smrg    for (; i <= 'Z'; i++)
17335dfecf96Smrg	re__alnum[i] = 1;
17345dfecf96Smrg
17355dfecf96Smrg    for (i = 1; i < 32; i++)
17365dfecf96Smrg	re__control[i] = 1;
17375dfecf96Smrg    re__control[127] = 1;
17385dfecf96Smrg    /* Don't show tabs as control characters */
17395dfecf96Smrg    re__control['\t'] = 0;
17405dfecf96Smrg}
17415dfecf96Smrg
17425dfecf96Smrgstatic int
17435dfecf96Smrgrec_check(re_inf *inf, int count)
17445dfecf96Smrg{
17455dfecf96Smrg    if (inf->len + count >= inf->spc) {
17465dfecf96Smrg	int spc;
17475dfecf96Smrg	unsigned char *cod;
17485dfecf96Smrg
17495dfecf96Smrg	if ((spc = (count % 64)) != 0)
17505dfecf96Smrg	    spc = 64 - spc;
17515dfecf96Smrg	spc += count + inf->spc;
17525dfecf96Smrg	if ((cod = realloc(inf->cod, spc)) == NULL)
17535dfecf96Smrg	    return (inf->ecode = RE_ESPACE);
17545dfecf96Smrg	inf->cod = cod;
17555dfecf96Smrg	inf->spc = spc;
17565dfecf96Smrg    }
17575dfecf96Smrg
17585dfecf96Smrg    return (inf->ecode);
17595dfecf96Smrg}
17605dfecf96Smrg
17615dfecf96Smrgstatic int
17625dfecf96Smrgrec_code(re_inf *inf, ReCode code)
17635dfecf96Smrg{
17645dfecf96Smrg    if (rec_check(inf, 1) == 0)
17655dfecf96Smrg	inf->cod[inf->len++] = code;
17665dfecf96Smrg
17675dfecf96Smrg    return (inf->ecode);
17685dfecf96Smrg}
17695dfecf96Smrg
17705dfecf96Smrgstatic int
17715dfecf96Smrgrec_byte(re_inf *inf, int value)
17725dfecf96Smrg{
17735dfecf96Smrg    if (rec_check(inf, 1) == 0)
17745dfecf96Smrg	inf->cod[inf->len++] = value;
17755dfecf96Smrg
17765dfecf96Smrg    return (inf->ecode);
17775dfecf96Smrg}
17785dfecf96Smrg
17795dfecf96Smrgstatic int
17805dfecf96Smrgrec_code_byte(re_inf *inf, ReCode code, int value)
17815dfecf96Smrg{
17825dfecf96Smrg    if (rec_check(inf, 2) == 0) {
17835dfecf96Smrg	inf->cod[inf->len++] = code;
17845dfecf96Smrg	inf->cod[inf->len++] = value;
17855dfecf96Smrg    }
17865dfecf96Smrg
17875dfecf96Smrg    return (inf->ecode);
17885dfecf96Smrg}
17895dfecf96Smrg
17905dfecf96Smrgstatic int
17915dfecf96Smrgrec_length(re_inf *inf, int length)
17925dfecf96Smrg{
17935dfecf96Smrg    int lo, hi, two;
17945dfecf96Smrg
17955dfecf96Smrg    if (length >= 16384)
17965dfecf96Smrg	return (inf->ecode = RE_ESPACE);
17975dfecf96Smrg
17985dfecf96Smrg    lo = length & 0xff;
17995dfecf96Smrg    hi = length & 0xff00;
18005dfecf96Smrg    two = ((length > 0x7f) != 0) + 1;
18015dfecf96Smrg    if (two == 2) {
18025dfecf96Smrg	hi <<= 1;
18035dfecf96Smrg	hi |= (lo & 0x80) != 0;
18045dfecf96Smrg	lo |= 0x80;
18055dfecf96Smrg    }
18065dfecf96Smrg
18075dfecf96Smrg    if (rec_check(inf, two) == 0) {
18085dfecf96Smrg	inf->cod[inf->len++] = lo;
18095dfecf96Smrg	if (two == 2)
18105dfecf96Smrg	    inf->cod[inf->len++] = hi >> 8;
18115dfecf96Smrg    }
18125dfecf96Smrg
18135dfecf96Smrg    return (inf->ecode);
18145dfecf96Smrg}
18155dfecf96Smrg
18165dfecf96Smrgstatic int
18175dfecf96Smrgrec_byte_byte(re_inf *inf, int value0, int value1)
18185dfecf96Smrg{
18195dfecf96Smrg    if (rec_check(inf, 2) == 0) {
18205dfecf96Smrg	inf->cod[inf->len++] = value0;
18215dfecf96Smrg	inf->cod[inf->len++] = value1;
18225dfecf96Smrg    }
18235dfecf96Smrg
18245dfecf96Smrg    return (inf->ecode);
18255dfecf96Smrg}
18265dfecf96Smrg
18275dfecf96Smrgstatic int
18285dfecf96Smrgrec_code_byte_byte(re_inf *inf, ReCode code, int value0, int value1)
18295dfecf96Smrg{
18305dfecf96Smrg    if (rec_check(inf, 3) == 0) {
18315dfecf96Smrg	inf->cod[inf->len++] = code;
18325dfecf96Smrg	inf->cod[inf->len++] = value0;
18335dfecf96Smrg	inf->cod[inf->len++] = value1;
18345dfecf96Smrg    }
18355dfecf96Smrg
18365dfecf96Smrg    return (inf->ecode);
18375dfecf96Smrg}
18385dfecf96Smrg
18395dfecf96Smrgstatic int
18405dfecf96Smrgrec_build_alt(re_inf *inf, rec_alt *alt)
18415dfecf96Smrg{
18425dfecf96Smrg    int offset, value, bas = inf->bas + 1;
18435dfecf96Smrg
18445dfecf96Smrg    if (alt) {
18455dfecf96Smrg	if (alt->next) {
18465dfecf96Smrg	    if (rec_inc_spc(inf))
18475dfecf96Smrg		return (inf->ecode);
18485dfecf96Smrg
18495dfecf96Smrg	    /* A real a list of alternatives */
18505dfecf96Smrg	    rec_code(inf, Re_Alt);
18515dfecf96Smrg
18525dfecf96Smrg	    offset = inf->len;		/* Remember current offset */
18535dfecf96Smrg	    rec_byte_byte(inf, 0, 0);	/* Reserve two bytes for retry address */
18545dfecf96Smrg	    while (alt && inf->ecode == 0) {
18555dfecf96Smrg		if (rec_build_pat(inf, alt->pat))
18565dfecf96Smrg		    break;
18575dfecf96Smrg		alt = alt->next;
18585dfecf96Smrg		if (alt && inf->ecode == 0) {
18595dfecf96Smrg		    /* Handle (hyper)complex repetitions */
18605dfecf96Smrg		    if (inf->bas != bas) {
18615dfecf96Smrg			/* Duplicate patterns up to end of expression */
18625dfecf96Smrg			rec_build_pat(inf, inf->apat);
18635dfecf96Smrg			/* Restore engine state for next alternative(s) */
18645dfecf96Smrg			rec_alt_spc(inf, bas - 1);
18655dfecf96Smrg		    }
18665dfecf96Smrg
18675dfecf96Smrg		    /* If the jump would be so long */
18685dfecf96Smrg		    if ((value = inf->len - offset) >= 16384) {
18695dfecf96Smrg			inf->ecode = RE_ESPACE;
18705dfecf96Smrg			break;
18715dfecf96Smrg		    }
18725dfecf96Smrg		    inf->cod[offset] = value & 0xff;
18735dfecf96Smrg		    inf->cod[offset + 1] = (value & 0xff00) >> 8;
18745dfecf96Smrg
18755dfecf96Smrg		    rec_code(inf, Re_AltNext);
18765dfecf96Smrg		    offset = inf->len;
18775dfecf96Smrg		    rec_byte_byte(inf, 0, 0);
18785dfecf96Smrg		}
18795dfecf96Smrg	    }
18805dfecf96Smrg	    if (inf->ecode == 0) {
18815dfecf96Smrg		/* Handle (hyper)complex repetitions */
18825dfecf96Smrg		if (inf->bas != bas) {
18835dfecf96Smrg		    /* Duplicate patterns up to end of expression */
18845dfecf96Smrg		    rec_build_pat(inf, inf->apat);
18855dfecf96Smrg		    /* Restore engine state for next alternative(s) */
18865dfecf96Smrg		    rec_alt_spc(inf, bas - 1);
18875dfecf96Smrg		}
18885dfecf96Smrg
18895dfecf96Smrg		/* If the jump would be so long */
18905dfecf96Smrg		if ((value = inf->len - offset) >= 16384)
18915dfecf96Smrg		    return (inf->ecode = RE_ESPACE);
18925dfecf96Smrg		inf->cod[offset] = value & 0xff;
18935dfecf96Smrg		inf->cod[offset + 1] = (value & 0xff00) >> 8;
18945dfecf96Smrg		/* Last jump is here */
18955dfecf96Smrg		rec_code(inf, Re_AltDone);
18965dfecf96Smrg	    }
18975dfecf96Smrg	    rec_dec_spc(inf);
18985dfecf96Smrg	}
18995dfecf96Smrg	else
19005dfecf96Smrg	    /* Single alternative */
19015dfecf96Smrg	    rec_build_pat(inf, alt->pat);
19025dfecf96Smrg    }
19035dfecf96Smrg
19045dfecf96Smrg    return (inf->ecode);
19055dfecf96Smrg}
19065dfecf96Smrg
19075dfecf96Smrgstatic int
19085dfecf96Smrgrec_build_pat(re_inf *inf, rec_pat *pat)
19095dfecf96Smrg{
19105dfecf96Smrg    rec_pat *apat;
19115dfecf96Smrg    int length, offset = 0, distance, jump = 0, bas = 0;
19125dfecf96Smrg
19135dfecf96Smrg    while (pat && inf->ecode == 0) {
19145dfecf96Smrg	if (pat->rep) {
19155dfecf96Smrg	    bas = inf->bas;
19165dfecf96Smrg	    if (pat->type == Rep_Group && !inf->par && rec_code(inf, Re_Open))
19175dfecf96Smrg		return (inf->ecode);
19185dfecf96Smrg	    if (rec_inc_spc(inf))
19195dfecf96Smrg		return (inf->ecode);
19205dfecf96Smrg	    offset = inf->len;
19215dfecf96Smrg	    if (rec_build_rep(inf, pat->rep))
19225dfecf96Smrg		break;
19235dfecf96Smrg	    /* Reserve space to jump after repetition done */
19245dfecf96Smrg	    jump = inf->len;
19255dfecf96Smrg	    rec_byte_byte(inf, 0, 0);
19265dfecf96Smrg	}
19275dfecf96Smrg	switch (pat->type) {
19285dfecf96Smrg	    case Rep_AnyAnyTimes:
19295dfecf96Smrg	    case Rep_AnyMaybe:
19305dfecf96Smrg	    case Rep_AnyAtLeast:
19315dfecf96Smrg		if (rec_add_spc(inf, pat->type == Rep_AnyMaybe))
19325dfecf96Smrg		    return (inf->ecode);
19335dfecf96Smrg		if (rec_code(inf, (ReCode)pat->type) == 0 &&
19345dfecf96Smrg		    rec_byte(inf, inf->bas - 1) == 0 &&
19355dfecf96Smrg		    rec_byte(inf, inf->ref - 1) == 0)
19365dfecf96Smrg		    rec_off_spc(inf);
19375dfecf96Smrg		break;
19385dfecf96Smrg	    case Rep_Literal:
19395dfecf96Smrg	    case Rep_LiteralNot:
19405dfecf96Smrg	    case Rep_SearchLiteral:
19415dfecf96Smrg		rec_code_byte(inf, (ReCode)pat->type, pat->data.chr);
19425dfecf96Smrg		break;
19435dfecf96Smrg	    case Rep_CaseLiteral:
19445dfecf96Smrg	    case Rep_CaseLiteralNot:
19455dfecf96Smrg	    case Rep_SearchCaseLiteral:
19465dfecf96Smrg		rec_code_byte_byte(inf, (ReCode)pat->type,
19475dfecf96Smrg				   pat->data.cse.lower, pat->data.cse.upper);
19485dfecf96Smrg		break;
19495dfecf96Smrg	    case Rep_Range:
19505dfecf96Smrg	    case Rep_RangeNot:
19515dfecf96Smrg		if (rec_code(inf, (ReCode)pat->type) == 0)
19525dfecf96Smrg		    rec_build_rng(inf, pat->data.rng);
19535dfecf96Smrg		break;
19545dfecf96Smrg	    case Rep_String:
19555dfecf96Smrg	    case Rep_SearchString:
19565dfecf96Smrg	    case Rep_CaseString:
19575dfecf96Smrg	    case Rep_SearchCaseString:
19585dfecf96Smrg		rec_code(inf, (ReCode)pat->type);
19595dfecf96Smrg		length = strlen((char*)pat->data.str);
19605dfecf96Smrg		if (rec_length(inf, length) == 0 && rec_check(inf, length) == 0) {
19615dfecf96Smrg		    memcpy(inf->cod + inf->len, pat->data.str, length);
19625dfecf96Smrg		    inf->len += length;
19635dfecf96Smrg		}
19645dfecf96Smrg		break;
19655dfecf96Smrg	    case Rep_Any:
19665dfecf96Smrg	    case Rep_AnyEatAnyTimes:
19675dfecf96Smrg	    case Rep_AnyEatMaybe:
19685dfecf96Smrg	    case Rep_AnyEatAtLeast:
19695dfecf96Smrg	    case Rep_Odigit:
19705dfecf96Smrg	    case Rep_OdigitNot:
19715dfecf96Smrg	    case Rep_Digit:
19725dfecf96Smrg	    case Rep_DigitNot:
19735dfecf96Smrg	    case Rep_Xdigit:
19745dfecf96Smrg	    case Rep_XdigitNot:
19755dfecf96Smrg	    case Rep_Space:
19765dfecf96Smrg	    case Rep_SpaceNot:
19775dfecf96Smrg	    case Rep_Tab:
19785dfecf96Smrg	    case Rep_Newline:
19795dfecf96Smrg	    case Rep_Lower:
19805dfecf96Smrg	    case Rep_Upper:
19815dfecf96Smrg	    case Rep_Alnum:
19825dfecf96Smrg	    case Rep_AlnumNot:
19835dfecf96Smrg	    case Rep_Control:
19845dfecf96Smrg	    case Rep_ControlNot:
19855dfecf96Smrg	    case Rep_Bol:
19865dfecf96Smrg	    case Rep_Eol:
19875dfecf96Smrg	    case Rep_Bow:
19885dfecf96Smrg	    case Rep_Eow:
19895dfecf96Smrg		rec_code(inf, (ReCode)pat->type);
19905dfecf96Smrg		break;
19915dfecf96Smrg	    case Rep_Backref:
19925dfecf96Smrg		rec_code_byte(inf, Re_Backref, pat->data.chr);
19935dfecf96Smrg		break;
19945dfecf96Smrg	    case Rep_Group:
19955dfecf96Smrg		if (pat->rep == NULL && !inf->par && rec_code(inf, Re_Open))
19965dfecf96Smrg		    break;
19975dfecf96Smrg		apat = inf->apat;
19985dfecf96Smrg		inf->apat = pat->next;
19995dfecf96Smrg		rec_build_grp(inf, pat->data.grp);
20005dfecf96Smrg		inf->apat = apat;
20015dfecf96Smrg		break;
20025dfecf96Smrg	    case Rep_StringList:
20035dfecf96Smrg		rec_build_stl(inf, pat->data.stl);
20045dfecf96Smrg		break;
20055dfecf96Smrg	}
20065dfecf96Smrg	if (pat->rep) {
20075dfecf96Smrg#if 0
20085dfecf96Smrg	    if (rec_dec_spc(inf))
20095dfecf96Smrg		return (inf->ecode);
20105dfecf96Smrg#else
20115dfecf96Smrg	    if (rec_rep_spc(inf, bas))
20125dfecf96Smrg		return (inf->ecode);
20135dfecf96Smrg#endif
20145dfecf96Smrg	    distance = inf->len - offset;
20155dfecf96Smrg	    if (distance > 255) {
20165dfecf96Smrg		if (rec_code(inf, Re_RepLongJump) ||
20175dfecf96Smrg		    rec_byte(inf, inf->bas) ||
20185dfecf96Smrg		    rec_byte(inf, distance & 0xff) ||
20195dfecf96Smrg		    rec_byte(inf, (distance & 0xff00) >> 8))
20205dfecf96Smrg		break;
20215dfecf96Smrg	    }
20225dfecf96Smrg	    else if (rec_code(inf, Re_RepJump) ||
20235dfecf96Smrg		     rec_byte(inf, inf->bas) ||
20245dfecf96Smrg		     rec_byte(inf, distance))
20255dfecf96Smrg		break;
20265dfecf96Smrg	    distance = inf->len - offset;
20275dfecf96Smrg	    inf->cod[jump] = distance & 0xff;
20285dfecf96Smrg	    inf->cod[jump + 1] = (distance & 0xff00) >> 8;
20295dfecf96Smrg	}
20305dfecf96Smrg	pat = pat->next;
20315dfecf96Smrg    }
20325dfecf96Smrg
20335dfecf96Smrg    return (inf->ecode);
20345dfecf96Smrg}
20355dfecf96Smrg
20365dfecf96Smrgstatic int
20375dfecf96Smrgrec_build_rng(re_inf *inf, rec_rng *rng)
20385dfecf96Smrg{
20395dfecf96Smrg    if (rec_check(inf, sizeof(rng->range)) == 0) {
20405dfecf96Smrg	memcpy(inf->cod + inf->len, rng->range, sizeof(rng->range));
20415dfecf96Smrg	inf->len += sizeof(rng->range);
20425dfecf96Smrg    }
20435dfecf96Smrg
20445dfecf96Smrg    return (inf->ecode);
20455dfecf96Smrg}
20465dfecf96Smrg
20475dfecf96Smrgstatic int
20485dfecf96Smrgrec_build_grp(re_inf *inf, rec_grp *grp)
20495dfecf96Smrg{
20505dfecf96Smrg    int par = inf->par;
20515dfecf96Smrg
20525dfecf96Smrg    if (!(inf->flags & RE_NOSUB)) {
20535dfecf96Smrg	++inf->par;
20545dfecf96Smrg	if (par == 0)
20555dfecf96Smrg	    ++inf->ref;
20565dfecf96Smrg	if (rec_build_alt(inf, grp->alt) == 0) {
20575dfecf96Smrg	    if (par == 0) {
20585dfecf96Smrg		if (grp->comp)
20595dfecf96Smrg		    rec_code_byte(inf, Re_Update, inf->ref - 1);
20605dfecf96Smrg		else
20615dfecf96Smrg		    rec_code(inf, Re_Close);
20625dfecf96Smrg	    }
20635dfecf96Smrg	}
20645dfecf96Smrg	--inf->par;
20655dfecf96Smrg    }
20665dfecf96Smrg    else
20675dfecf96Smrg	rec_build_alt(inf, grp->alt);
20685dfecf96Smrg
20695dfecf96Smrg    return (inf->ecode);
20705dfecf96Smrg}
20715dfecf96Smrg
20725dfecf96Smrgstatic int
20735dfecf96Smrgrec_build_stl(re_inf *inf, rec_stl *stl)
20745dfecf96Smrg{
20755dfecf96Smrg    int i, len, rlen;
20765dfecf96Smrg    ReCode code;
20775dfecf96Smrg
20785dfecf96Smrg    /* Calculate jump distance information */
20795dfecf96Smrg    rlen = stl->tlen + stl->nstrs + 4;
20805dfecf96Smrg    /* + code + nstrs + place-offset + data-length */
20815dfecf96Smrg
20825dfecf96Smrg    if (stl->nstrs >= LARGE_STL_COUNT) {
20835dfecf96Smrg	rlen += 511;		/* Don't write number of strings */
20845dfecf96Smrg	code = stl->type == Rep_StringList ?
20855dfecf96Smrg		Re_LargeStringList : Re_LargeCaseStringList;
20865dfecf96Smrg    }
20875dfecf96Smrg    else
20885dfecf96Smrg	code = (ReCode)stl->type;
20895dfecf96Smrg
20905dfecf96Smrg    if (rlen >= 16386)
20915dfecf96Smrg	return (inf->ecode = RE_ESPACE);
20925dfecf96Smrg    if (rec_check(inf, rlen) ||
20935dfecf96Smrg	rec_code(inf, code))
20945dfecf96Smrg	return (inf->ecode);
20955dfecf96Smrg
20965dfecf96Smrg    /* Space is allocated, just write the data */
20975dfecf96Smrg    if (stl->nstrs < LARGE_STL_COUNT)
20985dfecf96Smrg	inf->cod[inf->len++] = stl->nstrs;
20995dfecf96Smrg
21005dfecf96Smrg    inf->cod[inf->len++] = rlen & 0xff;
21015dfecf96Smrg    inf->cod[inf->len++] = (rlen & 0xff00) >> 8;
21025dfecf96Smrg
21035dfecf96Smrg    if (stl->nstrs < LARGE_STL_COUNT) {
21045dfecf96Smrg	for (i = 0; i < stl->nstrs; i++)
21055dfecf96Smrg	    inf->cod[inf->len++] = stl->lens[i];
21065dfecf96Smrg	for (i = 0; i < stl->nstrs; i++) {
21075dfecf96Smrg	    len = stl->lens[i];
21085dfecf96Smrg	    if (len > 2) {
21095dfecf96Smrg		memcpy(inf->cod + inf->len, stl->strs[i], len);
21105dfecf96Smrg		inf->len += len;
21115dfecf96Smrg	    }
21125dfecf96Smrg	    else {
21135dfecf96Smrg		if (len == 1)
21145dfecf96Smrg		    inf->cod[inf->len++] = (long)stl->strs[i];
21155dfecf96Smrg		else {
21165dfecf96Smrg		    inf->cod[inf->len++] = (long)stl->strs[i] & 0xff;
21175dfecf96Smrg		    inf->cod[inf->len++] = ((long)stl->strs[i] & 0xff00) >> 8;
21185dfecf96Smrg		}
21195dfecf96Smrg	    }
21205dfecf96Smrg	}
21215dfecf96Smrg    }
21225dfecf96Smrg    else {
21235dfecf96Smrg	/* The string length goes before the string itself */
21245dfecf96Smrg	int j, chl, chu;
21255dfecf96Smrg
21265dfecf96Smrg	/* Fill everything with an invalid jump address */
21275dfecf96Smrg	memset(inf->cod + inf->len, 0xff, 512);
21285dfecf96Smrg	for (i = len = 0, j = -1; i < stl->nstrs; i++) {
21295dfecf96Smrg	    chl = stl->lens[i] > 2 ? stl->strs[i][0] : (long)stl->strs[i] & 0xff;
21305dfecf96Smrg	    if (chl != j) {
21315dfecf96Smrg		inf->cod[inf->len + (chl << 1)] = len & 0xff;
21325dfecf96Smrg		inf->cod[inf->len + (chl << 1) + 1] = (len & 0xff00) >> 8;
21335dfecf96Smrg		if (code == Re_LargeCaseStringList) {
21345dfecf96Smrg		    chu = stl->lens[i] > 2 ?
21355dfecf96Smrg			stl->strs[i][1] : ((long)(stl->strs[i]) & 0xff00) >> 8;
21365dfecf96Smrg		    inf->cod[inf->len + (chu << 1)] = len & 0xff;
21375dfecf96Smrg		    inf->cod[inf->len + (chu << 1) + 1] = (len & 0xff00) >> 8;
21385dfecf96Smrg		}
21395dfecf96Smrg		j = chl;
21405dfecf96Smrg	    }
21415dfecf96Smrg	    len += stl->lens[i] + 1;
21425dfecf96Smrg	}
21435dfecf96Smrg	inf->len += 512;
21445dfecf96Smrg
21455dfecf96Smrg	for (i = 0; i < stl->nstrs; i++) {
21465dfecf96Smrg	    len = stl->lens[i];
21475dfecf96Smrg	    inf->cod[inf->len++] = len;
21485dfecf96Smrg	    if (len > 2) {
21495dfecf96Smrg		memcpy(inf->cod + inf->len, stl->strs[i], len);
21505dfecf96Smrg		inf->len += len;
21515dfecf96Smrg	    }
21525dfecf96Smrg	    else {
21535dfecf96Smrg		if (len == 1)
21545dfecf96Smrg		    inf->cod[inf->len++] = (long)stl->strs[i];
21555dfecf96Smrg		else {
21565dfecf96Smrg		    inf->cod[inf->len++] = (long)stl->strs[i] & 0xff;
21575dfecf96Smrg		    inf->cod[inf->len++] = ((long)stl->strs[i] & 0xff00) >> 8;
21585dfecf96Smrg		}
21595dfecf96Smrg	    }
21605dfecf96Smrg	}
21615dfecf96Smrg    }
21625dfecf96Smrg
21635dfecf96Smrg    return (inf->ecode);
21645dfecf96Smrg}
21655dfecf96Smrg
21665dfecf96Smrgstatic int
21675dfecf96Smrgrec_build_rep(re_inf *inf, rec_rep *rep)
21685dfecf96Smrg{
21695dfecf96Smrg    if (rep) {
21705dfecf96Smrg	switch (rep->type) {
21715dfecf96Smrg	    case Rer_AnyTimes:
21725dfecf96Smrg	    case Rer_AtLeast:
21735dfecf96Smrg	    case Rer_Maybe:
21745dfecf96Smrg		rec_code(inf, (ReCode)rep->type);
21755dfecf96Smrg		break;
21765dfecf96Smrg	    case Rer_Exact:
21775dfecf96Smrg		if (rec_code(inf, Re_Exact) == 0)
21785dfecf96Smrg		    rec_byte(inf, rep->mine);
21795dfecf96Smrg		break;
21805dfecf96Smrg	    case Rer_Min:
21815dfecf96Smrg		if (rec_code(inf, Re_Min) == 0)
21825dfecf96Smrg		    rec_byte(inf, rep->mine);
21835dfecf96Smrg		break;
21845dfecf96Smrg	    case Rer_Max:
21855dfecf96Smrg		if (rec_code(inf, Re_Max) == 0)
21865dfecf96Smrg		    rec_byte(inf, rep->maxc);
21875dfecf96Smrg		break;
21885dfecf96Smrg	    case Rer_MinMax:
21895dfecf96Smrg		if (rec_code(inf, Re_MinMax) == 0 &&
21905dfecf96Smrg		    rec_byte(inf, rep->mine) == 0)
21915dfecf96Smrg		    rec_byte(inf, rep->maxc);
21925dfecf96Smrg		break;
21935dfecf96Smrg	}
21945dfecf96Smrg	/* It is incremented in rec_build_pat */
21955dfecf96Smrg	rec_byte(inf, inf->bas - 1);
21965dfecf96Smrg    }
21975dfecf96Smrg
21985dfecf96Smrg    return (inf->ecode);
21995dfecf96Smrg}
22005dfecf96Smrg
22015dfecf96Smrgstatic int
22025dfecf96Smrgrec_inc_spc(re_inf *inf)
22035dfecf96Smrg{
22045dfecf96Smrg    if (++inf->bas >= MAX_DEPTH)
22055dfecf96Smrg	return (inf->ecode = RE_ESPACE);
22065dfecf96Smrg
22075dfecf96Smrg    return (inf->ecode);
22085dfecf96Smrg}
22095dfecf96Smrg
22105dfecf96Smrgstatic int
22115dfecf96Smrgrec_dec_spc(re_inf *inf)
22125dfecf96Smrg{
22135dfecf96Smrg    if (--inf->bas < 0)
22145dfecf96Smrg	return (inf->ecode = RE_ASSERT);
22155dfecf96Smrg
22165dfecf96Smrg    return (inf->ecode);
22175dfecf96Smrg}
22185dfecf96Smrg
22195dfecf96Smrgstatic int
22205dfecf96Smrgrec_add_spc(re_inf *inf, int maybe)
22215dfecf96Smrg{
22225dfecf96Smrg    if (++inf->bas >= MAX_DEPTH)
22235dfecf96Smrg	return (inf->ecode = RE_ESPACE);
22245dfecf96Smrg    inf->sp[inf->bas] = maybe + 1;
22255dfecf96Smrg
22265dfecf96Smrg    return (inf->ecode);
22275dfecf96Smrg}
22285dfecf96Smrg
22295dfecf96Smrg/* Could be joined with rec_rep_spc, code almost identical */
22305dfecf96Smrgstatic int
22315dfecf96Smrgrec_alt_spc(re_inf *inf, int top)
22325dfecf96Smrg{
22335dfecf96Smrg    int distance, i, bas = inf->bas;
22345dfecf96Smrg
22355dfecf96Smrg    while ((inf->bas > top) && inf->sp[inf->bas]) {
22365dfecf96Smrg	/* Jump to this repetition for cleanup */
22375dfecf96Smrg	distance = inf->len - inf->sr[inf->bas];
22385dfecf96Smrg
22395dfecf96Smrg	/* This will generate a jump to a jump decision opcode */
22405dfecf96Smrg	inf->sj[inf->bas] = inf->len;
22415dfecf96Smrg
22425dfecf96Smrg	if (distance > 255) {
22435dfecf96Smrg	    if (rec_code(inf, Re_RepLongJump) ||
22445dfecf96Smrg		rec_byte(inf, inf->bas - 1) ||
22455dfecf96Smrg		rec_byte(inf, distance & 0xff) ||
22465dfecf96Smrg		rec_byte(inf, (distance & 0xff00) >> 8))
22475dfecf96Smrg	    break;
22485dfecf96Smrg	}
22495dfecf96Smrg	else if (rec_code(inf, Re_RepJump) ||
22505dfecf96Smrg		 rec_byte(inf, inf->bas - 1) ||
22515dfecf96Smrg		 rec_byte(inf, distance))
22525dfecf96Smrg 	    break;
22535dfecf96Smrg
22545dfecf96Smrg	/* Top of stack value before repetition, or end condition value */
22555dfecf96Smrg	--inf->bas;
22565dfecf96Smrg    }
22575dfecf96Smrg
22585dfecf96Smrg    i = inf->bas + 1;
22595dfecf96Smrg
22605dfecf96Smrg    if (inf->ecode == 0 && i <= bas && inf->sp[i]) {
22615dfecf96Smrg	/*  Only the repetition at the bottom jump to code after testing
22625dfecf96Smrg	 * all possibilities */
22635dfecf96Smrg	distance = inf->len - inf->sr[i];
22645dfecf96Smrg	inf->cod[inf->sr[i] + 3] = distance & 0xff;
22655dfecf96Smrg	inf->cod[inf->sr[i] + 4] = (distance & 0xff00) >> 8;
22665dfecf96Smrg
22675dfecf96Smrg	/* The bottom jump is here */
22685dfecf96Smrg	if (rec_code(inf, inf->sp[i] == 1 ? Re_DoneIf : Re_MaybeDone))
22695dfecf96Smrg	   return (inf->ecode);
22705dfecf96Smrg
22715dfecf96Smrg	/*  Generate jumps to the previous special repetition */
22725dfecf96Smrg	for (++i; i <= bas; i++) {
22735dfecf96Smrg	    if (inf->sp[i]) {
22745dfecf96Smrg		distance = inf->sj[i] - inf->sr[i];
22755dfecf96Smrg		inf->cod[inf->sr[i] + 3] = distance & 0xff;
22765dfecf96Smrg		inf->cod[inf->sr[i] + 4] = (distance & 0xff00) >> 8;
22775dfecf96Smrg	    }
22785dfecf96Smrg	}
22795dfecf96Smrg    }
22805dfecf96Smrg
22815dfecf96Smrg    return (inf->ecode);
22825dfecf96Smrg}
22835dfecf96Smrg
22845dfecf96Smrgstatic int
22855dfecf96Smrgrec_rep_spc(re_inf *inf, int top)
22865dfecf96Smrg{
22875dfecf96Smrg    int distance, i, bas = inf->bas;
22885dfecf96Smrg
22895dfecf96Smrg    while (inf->bas > top) {
22905dfecf96Smrg	if (inf->sp[inf->bas]) {
22915dfecf96Smrg	    /* Jump to this repetition for cleanup */
22925dfecf96Smrg	    distance = inf->len - inf->sr[inf->bas];
22935dfecf96Smrg
22945dfecf96Smrg	    /* This will generate a jump to a jump decision opcode */
22955dfecf96Smrg	    inf->sj[inf->bas] = inf->len;
22965dfecf96Smrg
22975dfecf96Smrg	    if (distance > 255) {
22985dfecf96Smrg		if (rec_code(inf, Re_RepLongJump) ||
22995dfecf96Smrg		    rec_byte(inf, inf->bas - 1) ||
23005dfecf96Smrg		    rec_byte(inf, distance & 0xff) ||
23015dfecf96Smrg		    rec_byte(inf, (distance & 0xff00) >> 8))
23025dfecf96Smrg		break;
23035dfecf96Smrg	    }
23045dfecf96Smrg	    else if (rec_code(inf, Re_RepJump) ||
23055dfecf96Smrg		     rec_byte(inf, inf->bas - 1) ||
23065dfecf96Smrg		     rec_byte(inf, distance))
23075dfecf96Smrg		break;
23085dfecf96Smrg	}
23095dfecf96Smrg
23105dfecf96Smrg	/* Top of stack value before repetition, or end condition value */
23115dfecf96Smrg	--inf->bas;
23125dfecf96Smrg    }
23135dfecf96Smrg
23145dfecf96Smrg    /* Find first special repetition offset. XXX This should be a noop */
23155dfecf96Smrg    for (i = 0; i < bas; i++)
23165dfecf96Smrg	if (inf->sp[i])
23175dfecf96Smrg	    break;
23185dfecf96Smrg
23195dfecf96Smrg    if (inf->ecode == 0 && i <= bas && inf->sp[i]) {
23205dfecf96Smrg	/*  Only the repetition at the bottom jump to code after testing
23215dfecf96Smrg	 * all possibilities */
23225dfecf96Smrg	distance = inf->len - inf->sr[i];
23235dfecf96Smrg	inf->cod[inf->sr[i] + 3] = distance & 0xff;
23245dfecf96Smrg	inf->cod[inf->sr[i] + 4] = (distance & 0xff00) >> 8;
23255dfecf96Smrg
23265dfecf96Smrg	/*  Generate jumps to the previous special repetition */
23275dfecf96Smrg	for (++i; i <= bas; i++) {
23285dfecf96Smrg	    if (inf->sp[i]) {
23295dfecf96Smrg		distance = inf->sj[i] - inf->sr[i];
23305dfecf96Smrg		inf->cod[inf->sr[i] + 3] = distance & 0xff;
23315dfecf96Smrg		inf->cod[inf->sr[i] + 4] = (distance & 0xff00) >> 8;
23325dfecf96Smrg	    }
23335dfecf96Smrg	}
23345dfecf96Smrg    }
23355dfecf96Smrg
23365dfecf96Smrg    return (inf->ecode);
23375dfecf96Smrg}
23385dfecf96Smrg
23395dfecf96Smrgstatic int
23405dfecf96Smrgrec_off_spc(re_inf *inf)
23415dfecf96Smrg{
23425dfecf96Smrg    /* The jump address before the three bytes instruction */
23435dfecf96Smrg    inf->sr[inf->bas] = inf->len - 3;
23445dfecf96Smrg    /*  Don't know yet where to go after done with the special
23455dfecf96Smrg     * repetition, just reserve two bytes for the jump address. */
23465dfecf96Smrg    return (rec_byte_byte(inf, 0, 0));
23475dfecf96Smrg}
23485dfecf96Smrg
23495dfecf96Smrg#ifdef DEBUG
23505dfecf96Smrgstatic void
23515dfecf96Smrgredump(re_cod *code)
23525dfecf96Smrg{
23535dfecf96Smrg    int i, j, k;
23545dfecf96Smrg    unsigned char *cod = code->cod, *stl;
23555dfecf96Smrg
23565dfecf96Smrg    if (cod[0] & RE_NOSUB)
23575dfecf96Smrg	printf("Nosub\n");
23585dfecf96Smrg    if (cod[0] & RE_NEWLINE)
23595dfecf96Smrg	printf("Newline\n");
23605dfecf96Smrg    ++cod;
23615dfecf96Smrg    if (cod[0] != 0xff)
23625dfecf96Smrg	printf("%d backrefs\n", cod[0] + 1);
23635dfecf96Smrg    ++cod;
23645dfecf96Smrg    for (;;) {
23655dfecf96Smrg	switch (*cod++) {
23665dfecf96Smrg	    case Re_Open:
23675dfecf96Smrg		printf("Open");
23685dfecf96Smrg		break;
23695dfecf96Smrg	    case Re_Close:
23705dfecf96Smrg		printf("Close");
23715dfecf96Smrg		break;
23725dfecf96Smrg	    case Re_Update:
23735dfecf96Smrg		printf("Update (%d)", (int)*cod++);
23745dfecf96Smrg		break;
23755dfecf96Smrg	    case Re_Alt:
23765dfecf96Smrg		printf("Alt");
23775dfecf96Smrg		i = cod[0] | cod[1];
23785dfecf96Smrg		cod += 2;
23795dfecf96Smrg		printf(" %d", i);
23805dfecf96Smrg		break;
23815dfecf96Smrg	    case Re_AltNext:
23825dfecf96Smrg		printf("Alt-next");
23835dfecf96Smrg		i = cod[0] | cod[1];
23845dfecf96Smrg		cod += 2;
23855dfecf96Smrg		printf(" %d", i);
23865dfecf96Smrg		break;
23875dfecf96Smrg	    case Re_AltDone:
23885dfecf96Smrg		printf("Alt-done");
23895dfecf96Smrg		break;
23905dfecf96Smrg	    case Re_AnyTimes:
23915dfecf96Smrg		printf("-> Anytimes %d", (int)*cod++);
23925dfecf96Smrg		i = cod[0] | (cod[1] << 8);
23935dfecf96Smrg		cod += 2;
23945dfecf96Smrg		printf(" /%d", i);
23955dfecf96Smrg		break;
23965dfecf96Smrg	    case Re_AnyEatAnyTimes:
23975dfecf96Smrg		printf("Any-eat-anytimes");
23985dfecf96Smrg		break;
23995dfecf96Smrg	    case Re_AnyAnyTimes:
24005dfecf96Smrg		printf("-> Any-anytimes %d", (int)*cod++);
24015dfecf96Smrg		printf(" (%d)", (int)*cod++);
24025dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24035dfecf96Smrg		cod += 2;
24045dfecf96Smrg		printf(" /%d", i);
24055dfecf96Smrg		break;
24065dfecf96Smrg	    case Re_AnyEatMaybe:
24075dfecf96Smrg		printf("Any-eat-maybe");
24085dfecf96Smrg		break;
24095dfecf96Smrg	    case Re_AnyMaybe:
24105dfecf96Smrg		printf("-> Any-maybe %d", (int)*cod++);
24115dfecf96Smrg		printf(" (%d)", (int)*cod++);
24125dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24135dfecf96Smrg		cod += 2;
24145dfecf96Smrg		printf(" /%d", i);
24155dfecf96Smrg		break;
24165dfecf96Smrg	    case Re_AnyAtLeast:
24175dfecf96Smrg		printf("-> Any-atleast %d", (int)*cod++);
24185dfecf96Smrg		printf(" (%d)", (int)*cod++);
24195dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24205dfecf96Smrg		cod += 2;
24215dfecf96Smrg		printf(" /%d", i);
24225dfecf96Smrg		break;
24235dfecf96Smrg	    case Re_AnyEatAtLeast:
24245dfecf96Smrg		printf("Any-eat-atleast");
24255dfecf96Smrg		break;
24265dfecf96Smrg	    case Re_Maybe:
24275dfecf96Smrg		printf("-> Maybe %d", (int)*cod++);
24285dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24295dfecf96Smrg		cod += 2;
24305dfecf96Smrg		printf(" /%d", i);
24315dfecf96Smrg		break;
24325dfecf96Smrg	    case Re_AtLeast:
24335dfecf96Smrg		printf("-> Atleast %d", (int)*cod++);
24345dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24355dfecf96Smrg		cod += 2;
24365dfecf96Smrg		printf(" /%d", i);
24375dfecf96Smrg		break;
24385dfecf96Smrg	    case Re_Exact:
24395dfecf96Smrg		printf("-> Exact ");
24405dfecf96Smrg		i = *cod++;
24415dfecf96Smrg		printf("%d", i);
24425dfecf96Smrg		printf(" %d", (int)*cod++);
24435dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24445dfecf96Smrg		cod += 2;
24455dfecf96Smrg		printf(" /%d", i);
24465dfecf96Smrg		break;
24475dfecf96Smrg	    case Re_Min:
24485dfecf96Smrg		printf("-> Min ");
24495dfecf96Smrg		i = *cod++;
24505dfecf96Smrg		printf("%d", i);
24515dfecf96Smrg		printf(" %d", (int)*cod++);
24525dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24535dfecf96Smrg		cod += 2;
24545dfecf96Smrg		printf(" /%d", i);
24555dfecf96Smrg		break;
24565dfecf96Smrg	    case Re_Max:
24575dfecf96Smrg		printf("-> Max ");
24585dfecf96Smrg		i = *cod++;
24595dfecf96Smrg		printf("%d", i);
24605dfecf96Smrg		printf(" %d", (int)*cod++);
24615dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24625dfecf96Smrg		cod += 2;
24635dfecf96Smrg		printf(" /%d", i);
24645dfecf96Smrg		break;
24655dfecf96Smrg	    case Re_MinMax:
24665dfecf96Smrg		printf("-> Min-max ");
24675dfecf96Smrg		i = *cod++;
24685dfecf96Smrg		printf("%d ", i);
24695dfecf96Smrg		i = *cod++;
24705dfecf96Smrg		printf("%d", i);
24715dfecf96Smrg		printf(" %d", (int)*cod++);
24725dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24735dfecf96Smrg		cod += 2;
24745dfecf96Smrg		printf(" /%d", i);
24755dfecf96Smrg		break;
24765dfecf96Smrg	    case Re_RepJump:
24775dfecf96Smrg		printf("<- Rep-jump %d ", (int)*cod++);
24785dfecf96Smrg		i = *cod++;
24795dfecf96Smrg		printf("%d", i);
24805dfecf96Smrg		break;
24815dfecf96Smrg	    case Re_RepLongJump:
24825dfecf96Smrg		printf("<- Rep-long-jump %d ", (int)*cod++);
24835dfecf96Smrg		i = cod[0] | (cod[1] << 8);
24845dfecf96Smrg		printf("%d", i);
24855dfecf96Smrg		break;
24865dfecf96Smrg	    case Re_Any:
24875dfecf96Smrg		printf("Any");
24885dfecf96Smrg		break;
24895dfecf96Smrg	    case Re_Odigit:
24905dfecf96Smrg		printf("Odigit");
24915dfecf96Smrg		break;
24925dfecf96Smrg	    case Re_OdigitNot:
24935dfecf96Smrg		printf("Odigit-not");
24945dfecf96Smrg		break;
24955dfecf96Smrg	    case Re_Digit:
24965dfecf96Smrg		printf("Digit");
24975dfecf96Smrg		break;
24985dfecf96Smrg	    case Re_DigitNot:
24995dfecf96Smrg		printf("Digit-not");
25005dfecf96Smrg		break;
25015dfecf96Smrg	    case Re_Xdigit:
25025dfecf96Smrg		printf("Xdigit");
25035dfecf96Smrg		break;
25045dfecf96Smrg	    case Re_XdigitNot:
25055dfecf96Smrg		printf("Xdigit-not");
25065dfecf96Smrg		break;
25075dfecf96Smrg	    case Re_Space:
25085dfecf96Smrg		printf("Space");
25095dfecf96Smrg		break;
25105dfecf96Smrg	    case Re_SpaceNot:
25115dfecf96Smrg		printf("Space-not");
25125dfecf96Smrg		break;
25135dfecf96Smrg	    case Re_Tab:
25145dfecf96Smrg		printf("Tab");
25155dfecf96Smrg		break;
25165dfecf96Smrg	    case Re_Newline:
25175dfecf96Smrg		printf("Newline");
25185dfecf96Smrg		break;
25195dfecf96Smrg	    case Re_Lower:
25205dfecf96Smrg		printf("Lower");
25215dfecf96Smrg		break;
25225dfecf96Smrg	    case Re_Upper:
25235dfecf96Smrg		printf("Upper");
25245dfecf96Smrg		break;
25255dfecf96Smrg	    case Re_Alnum:
25265dfecf96Smrg		printf("Alnum");
25275dfecf96Smrg		break;
25285dfecf96Smrg	    case Re_AlnumNot:
25295dfecf96Smrg		printf("Alnum-not");
25305dfecf96Smrg		break;
25315dfecf96Smrg	    case Re_Control:
25325dfecf96Smrg		printf("Control");
25335dfecf96Smrg		break;
25345dfecf96Smrg	    case Re_ControlNot:
25355dfecf96Smrg		printf("Control-not");
25365dfecf96Smrg		break;
25375dfecf96Smrg	    case Re_Bol:
25385dfecf96Smrg		printf("Bol");
25395dfecf96Smrg		break;
25405dfecf96Smrg	    case Re_Eol:
25415dfecf96Smrg		printf("Eol");
25425dfecf96Smrg		break;
25435dfecf96Smrg	    case Re_Bow:
25445dfecf96Smrg		printf("Bow");
25455dfecf96Smrg		break;
25465dfecf96Smrg	    case Re_Eow:
25475dfecf96Smrg		printf("Eow");
25485dfecf96Smrg		break;
25495dfecf96Smrg	    case Re_Range:
25505dfecf96Smrg		printf("Range ");
25515dfecf96Smrg		goto range;
25525dfecf96Smrg	    case Re_RangeNot:
25535dfecf96Smrg		printf("Range-not ");
25545dfecf96Smrgrange:
25555dfecf96Smrg		for (i = 0; i < 256; i += 32) {
25565dfecf96Smrg		    for (j = k = 0; j < 32; j++)
25575dfecf96Smrg			k |= (*cod++ & 1) << (31 - j);
25585dfecf96Smrg		    printf("%x ", k);
25595dfecf96Smrg		}
25605dfecf96Smrg		break;
25615dfecf96Smrg	    case Re_Literal:
25625dfecf96Smrg		printf("Literal %c", *cod++);
25635dfecf96Smrg		break;
25645dfecf96Smrg	    case Re_LiteralNot:
25655dfecf96Smrg		printf("Literal-not %c", *cod++);
25665dfecf96Smrg		break;
25675dfecf96Smrg	    case Re_SearchLiteral:
25685dfecf96Smrg		printf("Search-literal %c", *cod++);
25695dfecf96Smrg		break;
25705dfecf96Smrg	    case Re_CaseLiteral:
25715dfecf96Smrg		printf("Case-literal %c", *cod++);
25725dfecf96Smrg		putchar(*cod++);
25735dfecf96Smrg		break;
25745dfecf96Smrg	    case Re_CaseLiteralNot:
25755dfecf96Smrg		printf("Case-literal-not %c", *cod++);
25765dfecf96Smrg		putchar(*cod++);
25775dfecf96Smrg		break;
25785dfecf96Smrg	    case Re_SearchCaseLiteral:
25795dfecf96Smrg		printf("Search-case-literal %c", *cod++);
25805dfecf96Smrg		putchar(*cod++);
25815dfecf96Smrg		break;
25825dfecf96Smrg	    case Re_String:
25835dfecf96Smrg		printf("String ");
25845dfecf96Smrg		goto string;
25855dfecf96Smrg	    case Re_SearchString:
25865dfecf96Smrg		printf("Search-string ");
25875dfecf96Smrg		goto string;
25885dfecf96Smrg	    case Re_CaseString:
25895dfecf96Smrg		printf("Case-string ");
25905dfecf96Smrg		goto string;
25915dfecf96Smrg	    case Re_SearchCaseString:
25925dfecf96Smrg		printf("Search-case-string ");
25935dfecf96Smrgstring:
25945dfecf96Smrg		i = *cod++;
25955dfecf96Smrg		if (i & 0x80)
25965dfecf96Smrg		    i = (i & 0x7f) | (*cod++ << 7);
25975dfecf96Smrg		for (j = 0; j < i; j++)
25985dfecf96Smrg		    putchar(*cod++);
25995dfecf96Smrg		break;
26005dfecf96Smrg	    case Re_StringList:
26015dfecf96Smrg		printf("String-list");
26025dfecf96Smrg		goto string_list;
26035dfecf96Smrg	    case Re_CaseStringList:
26045dfecf96Smrg		printf("Case-string-list");
26055dfecf96Smrgstring_list:
26065dfecf96Smrg		j = *cod++;
26075dfecf96Smrg		cod += 2;
26085dfecf96Smrg		stl = cod + j;
26095dfecf96Smrg		for (i = 0; i < j; i++) {
26105dfecf96Smrg		    k = *cod++;
26115dfecf96Smrg		    putchar(i ? ',' : ' ');
26125dfecf96Smrg		    fwrite(stl, k, 1, stdout);
26135dfecf96Smrg		    stl += k;
26145dfecf96Smrg		}
26155dfecf96Smrg		cod = stl;
26165dfecf96Smrg		break;
26175dfecf96Smrg	    case Re_LargeStringList:
26185dfecf96Smrg		printf("Large-string-list");
26195dfecf96Smrglarge_string_list:
26205dfecf96Smrg		i = cod[0] | (cod[1] << 8);
26215dfecf96Smrg		stl = cod + i - 1;
26225dfecf96Smrg		for (i = 0, cod += 514; cod < stl; i++) {
26235dfecf96Smrg		    k = *cod++;
26245dfecf96Smrg		    putchar(i ? ',' : ' ');
26255dfecf96Smrg		    fwrite(cod, k, 1, stdout);
26265dfecf96Smrg		    cod += k;
26275dfecf96Smrg		}
26285dfecf96Smrg		cod = stl;
26295dfecf96Smrg		break;
26305dfecf96Smrg	    case Re_LargeCaseStringList:
26315dfecf96Smrg		printf("Large-case-string-list");
26325dfecf96Smrg		goto large_string_list;
26335dfecf96Smrg	    case Re_Backref:
26345dfecf96Smrg		printf("Backref %d", (int)*cod++);
26355dfecf96Smrg		break;
26365dfecf96Smrg	    case Re_DoneIf:
26375dfecf96Smrg		printf("Done-if");
26385dfecf96Smrg		break;
26395dfecf96Smrg	    case Re_MaybeDone:
26405dfecf96Smrg		printf("Maybe-done");
26415dfecf96Smrg		break;
26425dfecf96Smrg	    case Re_Done:
26435dfecf96Smrg		printf("Done\n");
26445dfecf96Smrg		return;
26455dfecf96Smrg	}
26465dfecf96Smrg	putchar('\n');
26475dfecf96Smrg    }
26485dfecf96Smrg}
26495dfecf96Smrg#endif
2650