meillo@0: /* meillo@0: * Simple Regular Expression functions. Derived from Unix 7th Edition, meillo@0: * /usr/src/cmd/expr.y meillo@0: * meillo@0: * Modified by Gunnar Ritter, Freiburg i. Br., Germany, February 2002. meillo@0: * meillo@0: * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. meillo@0: * meillo@0: * Redistribution and use in source and binary forms, with or without meillo@0: * modification, are permitted provided that the following conditions meillo@0: * are met: meillo@0: * Redistributions of source code and documentation must retain the meillo@0: * above copyright notice, this list of conditions and the following meillo@0: * disclaimer. meillo@0: * Redistributions in binary form must reproduce the above copyright meillo@0: * notice, this list of conditions and the following disclaimer in the meillo@0: * documentation and/or other materials provided with the distribution. meillo@0: * All advertising materials mentioning features or use of this software meillo@0: * must display the following acknowledgement: meillo@0: * This product includes software developed or owned by Caldera meillo@0: * International, Inc. meillo@0: * Neither the name of Caldera International, Inc. nor the names of meillo@0: * other contributors may be used to endorse or promote products meillo@0: * derived from this software without specific prior written permission. meillo@0: * meillo@0: * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA meillo@0: * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR meillo@0: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED meillo@0: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE meillo@0: * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE meillo@0: * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR meillo@0: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF meillo@0: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR meillo@0: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, meillo@0: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE meillo@0: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, meillo@0: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. meillo@0: */ meillo@0: meillo@0: #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4 meillo@0: #define REGEXP_H_USED __attribute__ ((used)) meillo@0: #elif defined __GNUC__ meillo@0: #define REGEXP_H_USED __attribute__ ((unused)) meillo@0: #else meillo@0: #define REGEXP_H_USED meillo@0: #endif meillo@0: static const char regexp_h_sccsid[] REGEXP_H_USED = meillo@0: "@(#)regexp.sl 1.56 (gritter) 5/29/05"; meillo@0: meillo@0: #if !defined (REGEXP_H_USED_FROM_VI) && !defined (__dietlibc__) meillo@0: #define REGEXP_H_WCHARS meillo@0: #endif meillo@0: meillo@0: #define CBRA 2 meillo@0: #define CCHR 4 meillo@0: #define CDOT 8 meillo@0: #define CCL 12 meillo@0: /* CLNUM 14 used in sed */ meillo@0: /* CEND 16 used in sed */ meillo@0: #define CDOL 20 meillo@0: #define CCEOF 22 meillo@0: #define CKET 24 meillo@0: #define CBACK 36 meillo@0: #define CNCL 40 meillo@0: #define CBRC 44 meillo@0: #define CLET 48 meillo@0: #define CCH1 52 meillo@0: #define CCH2 56 meillo@0: #define CCH3 60 meillo@0: meillo@0: #define STAR 01 meillo@0: #define RNGE 03 meillo@0: #define REGEXP_H_LEAST 0100 meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: #define CMB 0200 meillo@0: #else /* !REGEXP_H_WCHARS */ meillo@0: #define CMB 0 meillo@0: #endif /* !REGEXP_H_WCHARS */ meillo@0: meillo@0: #define NBRA 9 meillo@0: meillo@0: #define PLACE(c) ep[c >> 3] |= bittab[c & 07] meillo@0: #define ISTHERE(c) (ep[c >> 3] & bittab[c & 07]) meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: #define REGEXP_H_IS_THERE(ep, c) ((ep)[c >> 3] & bittab[c & 07]) meillo@0: #endif meillo@0: meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: #define regexp_h_uletter(c) (isalpha(c) || (c) == '_') meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: #define regexp_h_wuletter(c) (iswalpha(c) || (c) == L'_') meillo@0: meillo@0: /* meillo@0: * Used to allocate memory for the multibyte star algorithm. meillo@0: */ meillo@0: #ifndef regexp_h_malloc meillo@0: #define regexp_h_malloc(n) malloc(n) meillo@0: #endif meillo@0: #ifndef regexp_h_free meillo@0: #define regexp_h_free(p) free(p) meillo@0: #endif meillo@0: meillo@0: /* meillo@0: * Can be predefined to 'inline' to inline some multibyte functions; meillo@0: * may improve performance for files that contain many multibyte meillo@0: * sequences. meillo@0: */ meillo@0: #ifndef regexp_h_inline meillo@0: #define regexp_h_inline meillo@0: #endif meillo@0: meillo@0: /* meillo@0: * Mask to determine whether the first byte of a sequence possibly meillo@0: * starts a multibyte character. Set to 0377 to force mbtowc() for meillo@0: * any byte sequence (except 0). meillo@0: */ meillo@0: #ifndef REGEXP_H_MASK meillo@0: #define REGEXP_H_MASK 0200 meillo@0: #endif meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: /* meillo@0: * For regexpr.h. meillo@0: */ meillo@0: #ifndef regexp_h_static meillo@0: #define regexp_h_static meillo@0: #endif meillo@0: #ifndef REGEXP_H_STEP_INIT meillo@0: #define REGEXP_H_STEP_INIT meillo@0: #endif meillo@0: #ifndef REGEXP_H_ADVANCE_INIT meillo@0: #define REGEXP_H_ADVANCE_INIT meillo@0: #endif meillo@0: meillo@0: char *braslist[NBRA]; meillo@0: char *braelist[NBRA]; meillo@0: int nbra; meillo@0: char *loc1, *loc2, *locs; meillo@0: int sed; meillo@0: int nodelim; meillo@0: meillo@0: regexp_h_static int circf; meillo@0: regexp_h_static int low; meillo@0: regexp_h_static int size; meillo@0: meillo@0: regexp_h_static unsigned char bittab[] = { meillo@0: 1, meillo@0: 2, meillo@0: 4, meillo@0: 8, meillo@0: 16, meillo@0: 32, meillo@0: 64, meillo@0: 128 meillo@0: }; meillo@0: static int regexp_h_advance(register const char *lp, meillo@0: register const char *ep); meillo@0: static void regexp_h_getrnge(register const char *str, int least); meillo@0: meillo@0: static const char *regexp_h_bol; /* beginning of input line (for \<) */ meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: static int regexp_h_wchars; meillo@0: static int regexp_h_mbcurmax; meillo@0: meillo@0: static const char *regexp_h_firstwc; /* location of first meillo@0: multibyte character meillo@0: on input line */ meillo@0: meillo@0: #define regexp_h_getwc(c) { \ meillo@0: if (regexp_h_wchars) { \ meillo@0: char mbbuf[MB_LEN_MAX + 1], *mbptr; \ meillo@0: wchar_t wcbuf; \ meillo@0: int mb, len; \ meillo@0: mbptr = mbbuf; \ meillo@0: do { \ meillo@0: mb = GETC(); \ meillo@0: *mbptr++ = mb; \ meillo@0: *mbptr = '\0'; \ meillo@0: } while ((len = mbtowc(&wcbuf, mbbuf, regexp_h_mbcurmax)) < 0 \ meillo@0: && mb != eof && mbptr < mbbuf + MB_LEN_MAX); \ meillo@0: if (len == -1) \ meillo@0: ERROR(67); \ meillo@0: c = wcbuf; \ meillo@0: } else { \ meillo@0: c = GETC(); \ meillo@0: } \ meillo@0: } meillo@0: meillo@0: #define regexp_h_store(wc, mb, me) { \ meillo@0: int len; \ meillo@0: if (wc == WEOF) \ meillo@0: ERROR(67); \ meillo@0: if ((len = me - mb) <= regexp_h_mbcurmax) { \ meillo@0: char mt[MB_LEN_MAX]; \ meillo@0: if (wctomb(mt, wc) >= len) \ meillo@0: ERROR(50); \ meillo@0: } \ meillo@0: switch (len = wctomb(mb, wc)) { \ meillo@0: case -1: \ meillo@0: ERROR(67); \ meillo@0: case 0: \ meillo@0: mb++; \ meillo@0: break; \ meillo@0: default: \ meillo@0: mb += len; \ meillo@0: } \ meillo@0: } meillo@0: meillo@0: static regexp_h_inline wint_t meillo@0: regexp_h_fetchwc(const char **mb, int islp) meillo@0: { meillo@0: wchar_t wc; meillo@0: int len; meillo@0: meillo@0: if ((len = mbtowc(&wc, *mb, regexp_h_mbcurmax)) < 0) { meillo@0: (*mb)++; meillo@0: return WEOF; meillo@0: } meillo@0: if (islp && regexp_h_firstwc == NULL) meillo@0: regexp_h_firstwc = *mb; meillo@0: /*if (len == 0) { meillo@0: (*mb)++; meillo@0: return L'\0'; meillo@0: } handled in singlebyte code */ meillo@0: *mb += len; meillo@0: return wc; meillo@0: } meillo@0: meillo@0: #define regexp_h_fetch(mb, islp) ((*(mb) & REGEXP_H_MASK) == 0 ? \ meillo@0: (*(mb)++&0377): \ meillo@0: regexp_h_fetchwc(&(mb), islp)) meillo@0: meillo@0: static regexp_h_inline wint_t meillo@0: regexp_h_showwc(const char *mb) meillo@0: { meillo@0: wchar_t wc; meillo@0: meillo@0: if (mbtowc(&wc, mb, regexp_h_mbcurmax) < 0) meillo@0: return WEOF; meillo@0: return wc; meillo@0: } meillo@0: meillo@0: #define regexp_h_show(mb) ((*(mb) & REGEXP_H_MASK) == 0 ? (*(mb)&0377): \ meillo@0: regexp_h_showwc(mb)) meillo@0: meillo@0: /* meillo@0: * Return the character immediately preceding mb. Since no byte is meillo@0: * required to be the first byte of a character, the longest multibyte meillo@0: * character ending at &[mb-1] is searched. meillo@0: */ meillo@0: static regexp_h_inline wint_t meillo@0: regexp_h_previous(const char *mb) meillo@0: { meillo@0: const char *p = mb; meillo@0: wchar_t wc, lastwc = WEOF; meillo@0: int len, max = 0; meillo@0: meillo@0: if (regexp_h_firstwc == NULL || mb <= regexp_h_firstwc) meillo@0: return (mb > regexp_h_bol ? (mb[-1] & 0377) : WEOF); meillo@0: while (p-- > regexp_h_bol) { meillo@0: mbtowc(NULL, NULL, 0); meillo@0: if ((len = mbtowc(&wc, p, mb - p)) >= 0) { meillo@0: if (len < max || len < mb - p) meillo@0: break; meillo@0: max = len; meillo@0: lastwc = wc; meillo@0: } else if (len < 0 && max > 0) meillo@0: break; meillo@0: } meillo@0: return lastwc; meillo@0: } meillo@0: meillo@0: #define regexp_h_cclass(set, c, af) \ meillo@0: ((c) == 0 || (c) == WEOF ? 0 : ( \ meillo@0: ((c) > 0177) ? \ meillo@0: regexp_h_cclass_wc(set, c, af) : ( \ meillo@0: REGEXP_H_IS_THERE((set)+1, (c)) ? (af) : !(af) \ meillo@0: ) \ meillo@0: ) \ meillo@0: ) meillo@0: meillo@0: static regexp_h_inline int meillo@0: regexp_h_cclass_wc(const char *set, register wint_t c, int af) meillo@0: { meillo@0: register wint_t wc, wl = WEOF; meillo@0: const char *end; meillo@0: meillo@0: end = &set[18] + set[0] - 1; meillo@0: set += 17; meillo@0: while (set < end) { meillo@0: wc = regexp_h_fetch(set, 0); meillo@0: #ifdef REGEXP_H_VI_BACKSLASH meillo@0: if (wc == '\\' && set < end && meillo@0: (*set == ']' || *set == '-' || meillo@0: *set == '^' || *set == '\\')) { meillo@0: wc = regexp_h_fetch(set, 0); meillo@0: } else meillo@0: #endif /* REGEXP_H_VI_BACKSLASH */ meillo@0: if (wc == '-' && wl != WEOF && set < end) { meillo@0: wc = regexp_h_fetch(set, 0); meillo@0: #ifdef REGEXP_H_VI_BACKSLASH meillo@0: if (wc == '\\' && set < end && meillo@0: (*set == ']' || *set == '-' || meillo@0: *set == '^' || *set == '\\')) { meillo@0: wc = regexp_h_fetch(set, 0); meillo@0: } meillo@0: #endif /* REGEXP_H_VI_BACKSLASH */ meillo@0: if (c > wl && c < wc) meillo@0: return af; meillo@0: } meillo@0: if (c == wc) meillo@0: return af; meillo@0: wl = wc; meillo@0: } meillo@0: return !af; meillo@0: } meillo@0: #else /* !REGEXP_H_WCHARS */ meillo@0: #define regexp_h_wchars 0 meillo@0: #define regexp_h_getwc(c) { c = GETC(); } meillo@0: #endif /* !REGEXP_H_WCHARS */ meillo@0: meillo@0: regexp_h_static char * meillo@0: compile(char *instring, char *ep, const char *endbuf, int seof) meillo@0: { meillo@0: INIT /* Dependent declarations and initializations */ meillo@0: register int c; meillo@0: register int eof = seof; meillo@0: char *lastep = instring; meillo@0: int cclcnt; meillo@0: char bracket[NBRA], *bracketp; meillo@0: int closed; meillo@0: char neg; meillo@0: int lc; meillo@0: int i, cflg; meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: char *eq; meillo@0: regexp_h_mbcurmax = MB_CUR_MAX; meillo@0: regexp_h_wchars = regexp_h_mbcurmax > 1 ? CMB : 0; meillo@0: #endif meillo@0: lastep = 0; meillo@0: bracketp = bracket; meillo@0: if((c = GETC()) == eof || c == '\n') { meillo@0: if (c == '\n') { meillo@0: UNGETC(c); meillo@0: nodelim = 1; meillo@0: } meillo@0: if(*ep == 0 && !sed) meillo@0: ERROR(41); meillo@0: if (bracketp > bracket) meillo@0: ERROR(42); meillo@0: RETURN(ep); meillo@0: } meillo@0: circf = closed = nbra = 0; meillo@0: if (c == '^') meillo@0: circf++; meillo@0: else meillo@0: UNGETC(c); meillo@0: for (;;) { meillo@0: if (ep >= endbuf) meillo@0: ERROR(50); meillo@0: regexp_h_getwc(c); meillo@0: if(c != '*' && ((c != '\\') || (PEEKC() != '{'))) meillo@0: lastep = ep; meillo@0: if (c == eof) { meillo@0: *ep++ = CCEOF; meillo@0: if (bracketp > bracket) meillo@0: ERROR(42); meillo@0: RETURN(ep); meillo@0: } meillo@0: switch (c) { meillo@0: meillo@0: case '.': meillo@0: *ep++ = CDOT|regexp_h_wchars; meillo@0: continue; meillo@0: meillo@0: case '\n': meillo@0: if (sed == 0) { meillo@0: UNGETC(c); meillo@0: *ep++ = CCEOF; meillo@0: nodelim = 1; meillo@0: RETURN(ep); meillo@0: } meillo@0: ERROR(36); meillo@0: case '*': meillo@0: if (lastep==0 || *lastep==CBRA || *lastep==CKET || meillo@0: *lastep==(CBRC|regexp_h_wchars) || meillo@0: *lastep==(CLET|regexp_h_wchars)) meillo@0: goto defchar; meillo@0: *lastep |= STAR; meillo@0: continue; meillo@0: meillo@0: case '$': meillo@0: if(PEEKC() != eof) meillo@0: goto defchar; meillo@0: *ep++ = CDOL; meillo@0: continue; meillo@0: meillo@0: case '[': meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: if (regexp_h_wchars == 0) { meillo@0: #endif meillo@0: if(&ep[33] >= endbuf) meillo@0: ERROR(50); meillo@0: meillo@0: *ep++ = CCL; meillo@0: lc = 0; meillo@0: for(i = 0; i < 32; i++) meillo@0: ep[i] = 0; meillo@0: meillo@0: neg = 0; meillo@0: if((c = GETC()) == '^') { meillo@0: neg = 1; meillo@0: c = GETC(); meillo@0: } meillo@0: meillo@0: do { meillo@0: c &= 0377; meillo@0: if(c == '\0' || c == '\n') meillo@0: ERROR(49); meillo@0: #ifdef REGEXP_H_VI_BACKSLASH meillo@0: if(c == '\\' && ((c = PEEKC()) == ']' || meillo@0: c == '-' || c == '^' || meillo@0: c == '\\')) { meillo@0: c = GETC(); meillo@0: c &= 0377; meillo@0: } else meillo@0: #endif /* REGEXP_H_VI_BACKSLASH */ meillo@0: if(c == '-' && lc != 0) { meillo@0: if ((c = GETC()) == ']') { meillo@0: PLACE('-'); meillo@0: break; meillo@0: } meillo@0: #ifdef REGEXP_H_VI_BACKSLASH meillo@0: if(c == '\\' && meillo@0: ((c = PEEKC()) == ']' || meillo@0: c == '-' || meillo@0: c == '^' || meillo@0: c == '\\')) meillo@0: c = GETC(); meillo@0: #endif /* REGEXP_H_VI_BACKSLASH */ meillo@0: c &= 0377; meillo@0: while(lc < c) { meillo@0: PLACE(lc); meillo@0: lc++; meillo@0: } meillo@0: } meillo@0: lc = c; meillo@0: PLACE(c); meillo@0: } while((c = GETC()) != ']'); meillo@0: if(neg) { meillo@0: for(cclcnt = 0; cclcnt < 32; cclcnt++) meillo@0: ep[cclcnt] ^= 0377; meillo@0: ep[0] &= 0376; meillo@0: } meillo@0: meillo@0: ep += 32; meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: } else { meillo@0: if (&ep[18] >= endbuf) meillo@0: ERROR(50); meillo@0: *ep++ = CCL|CMB; meillo@0: *ep++ = 0; meillo@0: lc = 0; meillo@0: for (i = 0; i < 16; i++) meillo@0: ep[i] = 0; meillo@0: eq = &ep[16]; meillo@0: regexp_h_getwc(c); meillo@0: if (c == L'^') { meillo@0: regexp_h_getwc(c); meillo@0: ep[-2] = CNCL|CMB; meillo@0: } meillo@0: do { meillo@0: if (c == '\0' || c == '\n') meillo@0: ERROR(49); meillo@0: #ifdef REGEXP_H_VI_BACKSLASH meillo@0: if(c == '\\' && ((c = PEEKC()) == ']' || meillo@0: c == '-' || c == '^' || meillo@0: c == '\\')) { meillo@0: regexp_h_store(c, eq, endbuf); meillo@0: regexp_h_getwc(c); meillo@0: } else meillo@0: #endif /* REGEXP_H_VI_BACKSLASH */ meillo@0: if (c == '-' && lc != 0 && lc <= 0177) { meillo@0: regexp_h_store(c, eq, endbuf); meillo@0: regexp_h_getwc(c); meillo@0: if (c == ']') { meillo@0: PLACE('-'); meillo@0: break; meillo@0: } meillo@0: #ifdef REGEXP_H_VI_BACKSLASH meillo@0: if(c == '\\' && meillo@0: ((c = PEEKC()) == ']' || meillo@0: c == '-' || meillo@0: c == '^' || meillo@0: c == '\\')) { meillo@0: regexp_h_store(c, eq, meillo@0: endbuf); meillo@0: regexp_h_getwc(c); meillo@0: } meillo@0: #endif /* REGEXP_H_VI_BACKSLASH */ meillo@0: while (lc < (c & 0177)) { meillo@0: PLACE(lc); meillo@0: lc++; meillo@0: } meillo@0: } meillo@0: lc = c; meillo@0: if (c <= 0177) meillo@0: PLACE(c); meillo@0: regexp_h_store(c, eq, endbuf); meillo@0: regexp_h_getwc(c); meillo@0: } while (c != L']'); meillo@0: if ((i = eq - &ep[16]) > 255) meillo@0: ERROR(50); meillo@0: lastep[1] = i; meillo@0: ep = eq; meillo@0: } meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: continue; meillo@0: meillo@0: case '\\': meillo@0: regexp_h_getwc(c); meillo@0: switch(c) { meillo@0: meillo@0: case '(': meillo@0: if(nbra >= NBRA) meillo@0: ERROR(43); meillo@0: *bracketp++ = nbra; meillo@0: *ep++ = CBRA; meillo@0: *ep++ = nbra++; meillo@0: continue; meillo@0: meillo@0: case ')': meillo@0: if(bracketp <= bracket) meillo@0: ERROR(42); meillo@0: *ep++ = CKET; meillo@0: *ep++ = *--bracketp; meillo@0: closed++; meillo@0: continue; meillo@0: meillo@0: case '<': meillo@0: *ep++ = CBRC|regexp_h_wchars; meillo@0: continue; meillo@0: meillo@0: case '>': meillo@0: *ep++ = CLET|regexp_h_wchars; meillo@0: continue; meillo@0: meillo@0: case '{': meillo@0: if(lastep == (char *) (0)) meillo@0: goto defchar; meillo@0: *lastep |= RNGE; meillo@0: cflg = 0; meillo@0: nlim: meillo@0: c = GETC(); meillo@0: i = 0; meillo@0: do { meillo@0: if ('0' <= c && c <= '9') meillo@0: i = 10 * i + c - '0'; meillo@0: else meillo@0: ERROR(16); meillo@0: } while(((c = GETC()) != '\\') && (c != ',')); meillo@0: if (i > 255) meillo@0: ERROR(11); meillo@0: *ep++ = i; meillo@0: if (c == ',') { meillo@0: if(cflg++) meillo@0: ERROR(44); meillo@0: if((c = GETC()) == '\\') { meillo@0: *ep++ = (char)255; meillo@0: *lastep |= REGEXP_H_LEAST; meillo@0: } else { meillo@0: UNGETC(c); meillo@0: goto nlim; /* get 2'nd number */ meillo@0: } meillo@0: } meillo@0: if(GETC() != '}') meillo@0: ERROR(45); meillo@0: if(!cflg) /* one number */ meillo@0: *ep++ = i; meillo@0: else if((ep[-1] & 0377) < (ep[-2] & 0377)) meillo@0: ERROR(46); meillo@0: continue; meillo@0: meillo@0: case '\n': meillo@0: ERROR(36); meillo@0: meillo@0: case 'n': meillo@0: c = '\n'; meillo@0: goto defchar; meillo@0: meillo@0: default: meillo@0: if(c >= '1' && c <= '9') { meillo@0: if((c -= '1') >= closed) meillo@0: ERROR(25); meillo@0: *ep++ = CBACK; meillo@0: *ep++ = c; meillo@0: continue; meillo@0: } meillo@0: } meillo@0: /* Drop through to default to use \ to turn off special chars */ meillo@0: meillo@0: defchar: meillo@0: default: meillo@0: lastep = ep; meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: if (regexp_h_wchars == 0) { meillo@0: #endif meillo@0: *ep++ = CCHR; meillo@0: *ep++ = c; meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: } else { meillo@0: char mbbuf[MB_LEN_MAX]; meillo@0: meillo@0: switch (wctomb(mbbuf, c)) { meillo@0: case 1: *ep++ = CCH1; meillo@0: break; meillo@0: case 2: *ep++ = CCH2; meillo@0: break; meillo@0: case 3: *ep++ = CCH3; meillo@0: break; meillo@0: default: meillo@0: *ep++ = CCHR|CMB; meillo@0: } meillo@0: regexp_h_store(c, ep, endbuf); meillo@0: } meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: } meillo@0: } meillo@0: } meillo@0: meillo@0: int meillo@0: step(const char *p1, const char *p2) meillo@0: { meillo@0: register int c; meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: register int d; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: REGEXP_H_STEP_INIT /* get circf */ meillo@0: regexp_h_bol = p1; meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: regexp_h_firstwc = NULL; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: if (circf) { meillo@0: loc1 = (char *)p1; meillo@0: return(regexp_h_advance(p1, p2)); meillo@0: } meillo@0: /* fast check for first character */ meillo@0: if (*p2==CCHR) { meillo@0: c = p2[1] & 0377; meillo@0: do { meillo@0: if ((*p1 & 0377) != c) meillo@0: continue; meillo@0: if (regexp_h_advance(p1, p2)) { meillo@0: loc1 = (char *)p1; meillo@0: return(1); meillo@0: } meillo@0: } while (*p1++); meillo@0: return(0); meillo@0: } meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: else if (*p2==CCH1) { meillo@0: do { meillo@0: if (p1[0] == p2[1] && regexp_h_advance(p1, p2)) { meillo@0: loc1 = (char *)p1; meillo@0: return(1); meillo@0: } meillo@0: c = regexp_h_fetch(p1, 1); meillo@0: } while (c); meillo@0: return(0); meillo@0: } else if (*p2==CCH2) { meillo@0: do { meillo@0: if (p1[0] == p2[1] && p1[1] == p2[2] && meillo@0: regexp_h_advance(p1, p2)) { meillo@0: loc1 = (char *)p1; meillo@0: return(1); meillo@0: } meillo@0: c = regexp_h_fetch(p1, 1); meillo@0: } while (c); meillo@0: return(0); meillo@0: } else if (*p2==CCH3) { meillo@0: do { meillo@0: if (p1[0] == p2[1] && p1[1] == p2[2] && p1[2] == p2[3]&& meillo@0: regexp_h_advance(p1, p2)) { meillo@0: loc1 = (char *)p1; meillo@0: return(1); meillo@0: } meillo@0: c = regexp_h_fetch(p1, 1); meillo@0: } while (c); meillo@0: return(0); meillo@0: } else if ((*p2&0377)==(CCHR|CMB)) { meillo@0: d = regexp_h_fetch(p2, 0); meillo@0: do { meillo@0: c = regexp_h_fetch(p1, 1); meillo@0: if (c == d && regexp_h_advance(p1, p2)) { meillo@0: loc1 = (char *)p1; meillo@0: return(1); meillo@0: } meillo@0: } while(c); meillo@0: return(0); meillo@0: } meillo@0: /* regular algorithm */ meillo@0: if (regexp_h_wchars) meillo@0: do { meillo@0: if (regexp_h_advance(p1, p2)) { meillo@0: loc1 = (char *)p1; meillo@0: return(1); meillo@0: } meillo@0: c = regexp_h_fetch(p1, 1); meillo@0: } while (c); meillo@0: else meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: do { meillo@0: if (regexp_h_advance(p1, p2)) { meillo@0: loc1 = (char *)p1; meillo@0: return(1); meillo@0: } meillo@0: } while (*p1++); meillo@0: return(0); meillo@0: } meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: /* meillo@0: * It is painfully slow to read character-wise backwards in a meillo@0: * multibyte string (see regexp_h_previous() above). For the star meillo@0: * algorithm, we therefore keep track of every character as it is meillo@0: * read in forward direction. meillo@0: * meillo@0: * Don't use alloca() for stack blocks since there is no measurable meillo@0: * speedup and huge amounts of memory are used up for long input meillo@0: * lines. meillo@0: */ meillo@0: #ifndef REGEXP_H_STAKBLOK meillo@0: #define REGEXP_H_STAKBLOK 1000 meillo@0: #endif meillo@0: meillo@0: struct regexp_h_stack { meillo@0: struct regexp_h_stack *s_nxt; meillo@0: struct regexp_h_stack *s_prv; meillo@0: const char *s_ptr[REGEXP_H_STAKBLOK]; meillo@0: }; meillo@0: meillo@0: #define regexp_h_push(sb, sp, sc, lp) (regexp_h_wchars ? \ meillo@0: regexp_h_pushwc(sb, sp, sc, lp) : (void)0) meillo@0: meillo@0: static regexp_h_inline void meillo@0: regexp_h_pushwc(struct regexp_h_stack **sb, meillo@0: struct regexp_h_stack **sp, meillo@0: const char ***sc, const char *lp) meillo@0: { meillo@0: if (regexp_h_firstwc == NULL || lp < regexp_h_firstwc) meillo@0: return; meillo@0: if (*sb == NULL) { meillo@0: if ((*sb = regexp_h_malloc(sizeof **sb)) == NULL) meillo@0: return; meillo@0: (*sb)->s_nxt = (*sb)->s_prv = NULL; meillo@0: *sp = *sb; meillo@0: *sc = &(*sb)->s_ptr[0]; meillo@0: } else if (*sc >= &(*sp)->s_ptr[REGEXP_H_STAKBLOK]) { meillo@0: if ((*sp)->s_nxt == NULL) { meillo@0: struct regexp_h_stack *bq; meillo@0: meillo@0: if ((bq = regexp_h_malloc(sizeof *bq)) == NULL) meillo@0: return; meillo@0: bq->s_nxt = NULL; meillo@0: bq->s_prv = *sp; meillo@0: (*sp)->s_nxt = bq; meillo@0: *sp = bq; meillo@0: } else meillo@0: *sp = (*sp)->s_nxt; meillo@0: *sc = &(*sp)->s_ptr[0]; meillo@0: } meillo@0: *(*sc)++ = lp; meillo@0: } meillo@0: meillo@0: static regexp_h_inline const char * meillo@0: regexp_h_pop(struct regexp_h_stack **sb, struct regexp_h_stack **sp, meillo@0: const char ***sc, const char *lp) meillo@0: { meillo@0: if (regexp_h_firstwc == NULL || lp <= regexp_h_firstwc) meillo@0: return &lp[-1]; meillo@0: if (*sp == NULL) meillo@0: return regexp_h_firstwc; meillo@0: if (*sc == &(*sp)->s_ptr[0]) { meillo@0: if ((*sp)->s_prv == NULL) { meillo@0: regexp_h_free(*sp); meillo@0: *sp = NULL; meillo@0: *sb = NULL; meillo@0: return regexp_h_firstwc; meillo@0: } meillo@0: *sp = (*sp)->s_prv; meillo@0: regexp_h_free((*sp)->s_nxt); meillo@0: (*sp)->s_nxt = NULL ; meillo@0: *sc = &(*sp)->s_ptr[REGEXP_H_STAKBLOK]; meillo@0: } meillo@0: return *(--(*sc)); meillo@0: } meillo@0: meillo@0: static void meillo@0: regexp_h_zerostak(struct regexp_h_stack **sb, struct regexp_h_stack **sp) meillo@0: { meillo@0: for (*sp = *sb; *sp && (*sp)->s_nxt; *sp = (*sp)->s_nxt) meillo@0: if ((*sp)->s_prv) meillo@0: regexp_h_free((*sp)->s_prv); meillo@0: if (*sp) { meillo@0: if ((*sp)->s_prv) meillo@0: regexp_h_free((*sp)->s_prv); meillo@0: regexp_h_free(*sp); meillo@0: } meillo@0: *sp = *sb = NULL; meillo@0: } meillo@0: #else /* !REGEXP_H_WCHARS */ meillo@0: #define regexp_h_push(sb, sp, sc, lp) meillo@0: #endif /* !REGEXP_H_WCHARS */ meillo@0: meillo@0: static int meillo@0: regexp_h_advance(const char *lp, const char *ep) meillo@0: { meillo@0: register const char *curlp; meillo@0: int c, least; meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: int d; meillo@0: struct regexp_h_stack *sb = NULL, *sp = NULL; meillo@0: const char **sc; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: char *bbeg; meillo@0: int ct; meillo@0: meillo@0: for (;;) switch (least = *ep++ & 0377, least & ~REGEXP_H_LEAST) { meillo@0: meillo@0: case CCHR: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CCH1: meillo@0: #endif meillo@0: if (*ep++ == *lp++) meillo@0: continue; meillo@0: return(0); meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CCHR|CMB: meillo@0: if (regexp_h_fetch(ep, 0) == regexp_h_fetch(lp, 1)) meillo@0: continue; meillo@0: return(0); meillo@0: meillo@0: case CCH2: meillo@0: if (ep[0] == lp[0] && ep[1] == lp[1]) { meillo@0: ep += 2, lp += 2; meillo@0: continue; meillo@0: } meillo@0: return(0); meillo@0: meillo@0: case CCH3: meillo@0: if (ep[0] == lp[0] && ep[1] == lp[1] && ep[2] == lp[2]) { meillo@0: ep += 3, lp += 3; meillo@0: continue; meillo@0: } meillo@0: return(0); meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CDOT: meillo@0: if (*lp++) meillo@0: continue; meillo@0: return(0); meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CDOT|CMB: meillo@0: if ((c = regexp_h_fetch(lp, 1)) != L'\0' && c != WEOF) meillo@0: continue; meillo@0: return(0); meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CDOL: meillo@0: if (*lp==0) meillo@0: continue; meillo@0: return(0); meillo@0: meillo@0: case CCEOF: meillo@0: loc2 = (char *)lp; meillo@0: return(1); meillo@0: meillo@0: case CCL: meillo@0: c = *lp++ & 0377; meillo@0: if(ISTHERE(c)) { meillo@0: ep += 32; meillo@0: continue; meillo@0: } meillo@0: return(0); meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CCL|CMB: meillo@0: case CNCL|CMB: meillo@0: c = regexp_h_fetch(lp, 1); meillo@0: if (regexp_h_cclass(ep, c, (ep[-1] & 0377) == (CCL|CMB))) { meillo@0: ep += (*ep & 0377) + 17; meillo@0: continue; meillo@0: } meillo@0: return 0; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CBRA: meillo@0: braslist[*ep++ & 0377] = (char *)lp; meillo@0: continue; meillo@0: meillo@0: case CKET: meillo@0: braelist[*ep++ & 0377] = (char *)lp; meillo@0: continue; meillo@0: meillo@0: case CBRC: meillo@0: if (lp == regexp_h_bol && locs == NULL) meillo@0: continue; meillo@0: if ((isdigit(lp[0] & 0377) || regexp_h_uletter(lp[0] & 0377)) meillo@0: && !regexp_h_uletter(lp[-1] & 0377) meillo@0: && !isdigit(lp[-1] & 0377)) meillo@0: continue; meillo@0: return(0); meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CBRC|CMB: meillo@0: c = regexp_h_show(lp); meillo@0: d = regexp_h_previous(lp); meillo@0: if ((iswdigit(c) || regexp_h_wuletter(c)) meillo@0: && !regexp_h_wuletter(d) meillo@0: && !iswdigit(d)) meillo@0: continue; meillo@0: return(0); meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CLET: meillo@0: if (!regexp_h_uletter(lp[0] & 0377) && !isdigit(lp[0] & 0377)) meillo@0: continue; meillo@0: return(0); meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CLET|CMB: meillo@0: c = regexp_h_show(lp); meillo@0: if (!regexp_h_wuletter(c) && !iswdigit(c)) meillo@0: continue; meillo@0: return(0); meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CCHR|RNGE: meillo@0: c = *ep++; meillo@0: regexp_h_getrnge(ep, least); meillo@0: while(low--) meillo@0: if(*lp++ != c) meillo@0: return(0); meillo@0: curlp = lp; meillo@0: while(size--) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: if(*lp++ != c) meillo@0: break; meillo@0: } meillo@0: if(size < 0) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: lp++; meillo@0: } meillo@0: ep += 2; meillo@0: goto star; meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CCHR|RNGE|CMB: meillo@0: case CCH1|RNGE: meillo@0: case CCH2|RNGE: meillo@0: case CCH3|RNGE: meillo@0: c = regexp_h_fetch(ep, 0); meillo@0: regexp_h_getrnge(ep, least); meillo@0: while (low--) meillo@0: if (regexp_h_fetch(lp, 1) != c) meillo@0: return 0; meillo@0: curlp = lp; meillo@0: while (size--) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: if (regexp_h_fetch(lp, 1) != c) meillo@0: break; meillo@0: } meillo@0: if(size < 0) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: regexp_h_fetch(lp, 1); meillo@0: } meillo@0: ep += 2; meillo@0: goto star; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CDOT|RNGE: meillo@0: regexp_h_getrnge(ep, least); meillo@0: while(low--) meillo@0: if(*lp++ == '\0') meillo@0: return(0); meillo@0: curlp = lp; meillo@0: while(size--) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: if(*lp++ == '\0') meillo@0: break; meillo@0: } meillo@0: if(size < 0) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: lp++; meillo@0: } meillo@0: ep += 2; meillo@0: goto star; meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CDOT|RNGE|CMB: meillo@0: regexp_h_getrnge(ep, least); meillo@0: while (low--) meillo@0: if ((c = regexp_h_fetch(lp, 1)) == L'\0' || c == WEOF) meillo@0: return 0; meillo@0: curlp = lp; meillo@0: while (size--) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: if ((c = regexp_h_fetch(lp, 1)) == L'\0' || c == WEOF) meillo@0: break; meillo@0: } meillo@0: if (size < 0) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: regexp_h_fetch(lp, 1); meillo@0: } meillo@0: ep += 2; meillo@0: goto star; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CCL|RNGE: meillo@0: regexp_h_getrnge(ep + 32, least); meillo@0: while(low--) { meillo@0: c = *lp++ & 0377; meillo@0: if(!ISTHERE(c)) meillo@0: return(0); meillo@0: } meillo@0: curlp = lp; meillo@0: while(size--) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: c = *lp++ & 0377; meillo@0: if(!ISTHERE(c)) meillo@0: break; meillo@0: } meillo@0: if(size < 0) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: lp++; meillo@0: } meillo@0: ep += 34; /* 32 + 2 */ meillo@0: goto star; meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CCL|RNGE|CMB: meillo@0: case CNCL|RNGE|CMB: meillo@0: regexp_h_getrnge(ep + (*ep & 0377) + 17, least); meillo@0: while (low--) { meillo@0: c = regexp_h_fetch(lp, 1); meillo@0: if (!regexp_h_cclass(ep, c, meillo@0: (ep[-1] & 0377 & ~REGEXP_H_LEAST) meillo@0: == (CCL|RNGE|CMB))) meillo@0: return 0; meillo@0: } meillo@0: curlp = lp; meillo@0: while (size--) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: c = regexp_h_fetch(lp, 1); meillo@0: if (!regexp_h_cclass(ep, c, meillo@0: (ep[-1] & 0377 & ~REGEXP_H_LEAST) meillo@0: == (CCL|RNGE|CMB))) meillo@0: break; meillo@0: } meillo@0: if (size < 0) { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: regexp_h_fetch(lp, 1); meillo@0: } meillo@0: ep += (*ep & 0377) + 19; meillo@0: goto star; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CBACK: meillo@0: bbeg = braslist[*ep & 0377]; meillo@0: ct = braelist[*ep++ & 0377] - bbeg; meillo@0: meillo@0: if(strncmp(bbeg, lp, ct) == 0) { meillo@0: lp += ct; meillo@0: continue; meillo@0: } meillo@0: return(0); meillo@0: meillo@0: case CBACK|STAR: meillo@0: bbeg = braslist[*ep & 0377]; meillo@0: ct = braelist[*ep++ & 0377] - bbeg; meillo@0: curlp = lp; meillo@0: while(strncmp(bbeg, lp, ct) == 0) meillo@0: lp += ct; meillo@0: meillo@0: while(lp >= curlp) { meillo@0: if(regexp_h_advance(lp, ep)) return(1); meillo@0: lp -= ct; meillo@0: } meillo@0: return(0); meillo@0: meillo@0: meillo@0: case CDOT|STAR: meillo@0: curlp = lp; meillo@0: do meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: while (*lp++); meillo@0: goto star; meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CDOT|STAR|CMB: meillo@0: curlp = lp; meillo@0: do meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: while ((c = regexp_h_fetch(lp, 1)) != L'\0' && c != WEOF); meillo@0: goto star; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CCHR|STAR: meillo@0: curlp = lp; meillo@0: do meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: while (*lp++ == *ep); meillo@0: ep++; meillo@0: goto star; meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CCHR|STAR|CMB: meillo@0: case CCH1|STAR: meillo@0: case CCH2|STAR: meillo@0: case CCH3|STAR: meillo@0: curlp = lp; meillo@0: d = regexp_h_fetch(ep, 0); meillo@0: do meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: while (regexp_h_fetch(lp, 1) == d); meillo@0: goto star; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: case CCL|STAR: meillo@0: curlp = lp; meillo@0: do { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: c = *lp++ & 0377; meillo@0: } while(ISTHERE(c)); meillo@0: ep += 32; meillo@0: goto star; meillo@0: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: case CCL|STAR|CMB: meillo@0: case CNCL|STAR|CMB: meillo@0: curlp = lp; meillo@0: do { meillo@0: regexp_h_push(&sb, &sp, &sc, lp); meillo@0: c = regexp_h_fetch(lp, 1); meillo@0: } while (regexp_h_cclass(ep, c, (ep[-1] & 0377) meillo@0: == (CCL|STAR|CMB))); meillo@0: ep += (*ep & 0377) + 17; meillo@0: goto star; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: meillo@0: star: meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: if (regexp_h_wchars == 0) { meillo@0: #endif meillo@0: do { meillo@0: if(--lp == locs) meillo@0: break; meillo@0: if (regexp_h_advance(lp, ep)) meillo@0: return(1); meillo@0: } while (lp > curlp); meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: } else { meillo@0: do { meillo@0: lp = regexp_h_pop(&sb, &sp, &sc, lp); meillo@0: if (lp <= locs) meillo@0: break; meillo@0: if (regexp_h_advance(lp, ep)) { meillo@0: regexp_h_zerostak(&sb, &sp); meillo@0: return(1); meillo@0: } meillo@0: } while (lp > curlp); meillo@0: regexp_h_zerostak(&sb, &sp); meillo@0: } meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: return(0); meillo@0: meillo@0: } meillo@0: } meillo@0: meillo@0: static void meillo@0: regexp_h_getrnge(register const char *str, int least) meillo@0: { meillo@0: low = *str++ & 0377; meillo@0: size = least & REGEXP_H_LEAST ? /*20000*/INT_MAX : (*str & 0377) - low; meillo@0: } meillo@0: meillo@0: int meillo@0: advance(const char *lp, const char *ep) meillo@0: { meillo@0: REGEXP_H_ADVANCE_INIT /* skip past circf */ meillo@0: regexp_h_bol = lp; meillo@0: #ifdef REGEXP_H_WCHARS meillo@0: regexp_h_firstwc = NULL; meillo@0: #endif /* REGEXP_H_WCHARS */ meillo@0: return regexp_h_advance(lp, ep); meillo@0: }