]> sourceware.org Git - newlib-cygwin.git/commitdiff
Replace regex files with multibyte-aware version from FreeBSD.
authorCorinna Vinschen <corinna@vinschen.de>
Thu, 4 Feb 2010 12:35:49 +0000 (12:35 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Thu, 4 Feb 2010 12:35:49 +0000 (12:35 +0000)
* Makefile.in (install-headers): Remove extra command to install
regex.h.
(uninstall-headers): Remove extra command to uninstall regex.h.
* nlsfuncs.cc (collate_lcid): Make externally available to allow
access to collation internals from regex functions.
(collate_charset): Ditto.
* wchar.h: Add __cplusplus guards to make C-clean.
* include/regex.h: New file, replacing regex/regex.h.  Remove UCB
advertising clause.
* regex/COPYRIGHT: Accommodate BSD license.  Remove UCB advertising
clause.
* regex/cclass.h: Remove.
* regex/cname.h: New file from FreeBSD.
* regex/engine.c: Ditto.
(NONCHAR): Tweak for Cygwin.
* regex/engine.ih: Remove.
* regex/mkh: Remove.
* regex/regcomp.c: New file from FreeBSD.  Tweak slightly for Cygwin.
Import required collate internals from nlsfunc.cc.
(p_ere_exp): Add GNU-specific \< and \> handling for word boundaries.
(p_simp_re): Ditto.
(__collate_range_cmp): Define.
(p_b_term): Use Cygwin-specific collate internals.
(findmust): Ditto.
* regex/regcomp.ih: Remove.
* regex/regerror.c: New file from FreeBSD.  Fix a few compiler warnings.
* regex/regerror.ih: Remove.
* regex/regex.7: New file from FreeBSD.  Remove UCB advertising clause.
* regex/regex.h: Remove.  Replaced by include/regex.h.
* regex/regexec.c: New file from FreeBSD.  Fix a few compiler warnings.
* regex/regfree.c: New file from FreeBSD.
* regex/tests: Remove.
* regex/utils.h: New file from FreeBSD.

23 files changed:
winsup/cygwin/ChangeLog
winsup/cygwin/Makefile.in
winsup/cygwin/include/regex.h [new file with mode: 0644]
winsup/cygwin/nlsfuncs.cc
winsup/cygwin/regex/COPYRIGHT
winsup/cygwin/regex/cclass.h [deleted file]
winsup/cygwin/regex/cname.h
winsup/cygwin/regex/engine.c
winsup/cygwin/regex/engine.ih [deleted file]
winsup/cygwin/regex/mkh [deleted file]
winsup/cygwin/regex/regcomp.c
winsup/cygwin/regex/regcomp.ih [deleted file]
winsup/cygwin/regex/regerror.c
winsup/cygwin/regex/regerror.ih [deleted file]
winsup/cygwin/regex/regex.3
winsup/cygwin/regex/regex.7
winsup/cygwin/regex/regex.h [deleted file]
winsup/cygwin/regex/regex2.h
winsup/cygwin/regex/regexec.c
winsup/cygwin/regex/regfree.c
winsup/cygwin/regex/tests [deleted file]
winsup/cygwin/regex/utils.h
winsup/cygwin/wchar.h

index 506ff09c2f7366ef2302b7034f72f85c0bce5503..12499e1b9dcbf9f08a69257b86d15661577e1430 100644 (file)
@@ -1,3 +1,40 @@
+2010-02-04  Corinna Vinschen  <corinna@vinschen.de>
+
+       Replace regex files with multibyte-aware version from FreeBSD.
+       * Makefile.in (install-headers): Remove extra command to install
+       regex.h.
+       (uninstall-headers): Remove extra command to uninstall regex.h.
+       * nlsfuncs.cc (collate_lcid): Make externally available to allow
+       access to collation internals from regex functions.
+       (collate_charset): Ditto.
+       * wchar.h: Add __cplusplus guards to make C-clean.
+       * include/regex.h: New file, replacing regex/regex.h.  Remove UCB
+       advertising clause.
+       * regex/COPYRIGHT: Accommodate BSD license.  Remove UCB advertising
+       clause.
+       * regex/cclass.h: Remove.
+       * regex/cname.h: New file from FreeBSD.
+       * regex/engine.c: Ditto.
+       (NONCHAR): Tweak for Cygwin.
+       * regex/engine.ih: Remove.
+       * regex/mkh: Remove.
+       * regex/regcomp.c: New file from FreeBSD.  Tweak slightly for Cygwin.
+       Import required collate internals from nlsfunc.cc.
+       (p_ere_exp): Add GNU-specific \< and \> handling for word boundaries.
+       (p_simp_re): Ditto.
+       (__collate_range_cmp): Define.
+       (p_b_term): Use Cygwin-specific collate internals.
+       (findmust): Ditto.
+       * regex/regcomp.ih: Remove.
+       * regex/regerror.c: New file from FreeBSD.  Fix a few compiler warnings.
+       * regex/regerror.ih: Remove.
+       * regex/regex.7: New file from FreeBSD.  Remove UCB advertising clause.
+       * regex/regex.h: Remove.  Replaced by include/regex.h.
+       * regex/regexec.c: New file from FreeBSD.  Fix a few compiler warnings.
+       * regex/regfree.c: New file from FreeBSD.
+       * regex/tests: Remove.
+       * regex/utils.h: New file from FreeBSD.
+
 2010-02-03  Christopher Faylor  <me+cygwin@cgf.cx>
 
        * sigproc.cc (get_proc_lock): Fix error message typo.
index 7273921b19f75204f62cc6c09c9580104c98cf86..741dd66ff24cd7b621e8f1d26b485f0dac3f8583 100644 (file)
@@ -329,7 +329,6 @@ install-headers:
              $(INSTALL_DATA) $$i $(DESTDIR)$(tooldir)/$$sub/`basename $$i` ; \
            done ; \
        done ; \
-       $(INSTALL_DATA) regex/regex.h $(DESTDIR)$(tooldir)/include/regex.h
 
 install-man:
        @$(MKDIRP) $(DESTDIR)$(mandir)/man2 $(DESTDIR)$(mandir)/man3 $(DESTDIR)$(mandir)/man5 $(DESTDIR)$(mandir)/man7
@@ -364,7 +363,6 @@ uninstall-headers:
              rm -f $(tooldir)/$$sub/`basename $$i` ; \
            done ; \
        done ; \
-       rm -f $(tooldir)/include/regex.h
 
 uninstall-man:
        cd $(srcdir); \
diff --git a/winsup/cygwin/include/regex.h b/winsup/cygwin/include/regex.h
new file mode 100644 (file)
index 0000000..d7c673c
--- /dev/null
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 1992 Henry Spencer.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regex.h     8.2 (Berkeley) 1/3/94
+ * $FreeBSD$
+ */
+
+#ifndef _REGEX_H_
+#define        _REGEX_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+/* types */
+#ifdef __CYGWIN__
+typedef        _off_t          regoff_t;
+
+#define __need_size_t
+#include <stddef.h>
+#else /* !__CYGWIN__ */
+typedef        __off_t         regoff_t;
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+#endif /* !__CYGWIN__ */
+
+typedef struct {
+       int re_magic;
+       size_t re_nsub;         /* number of parenthesized subexpressions */
+#ifdef __CYGWIN__
+       const char *re_endp;    /* end pointer for REG_PEND */
+#else
+       __const char *re_endp;  /* end pointer for REG_PEND */
+#endif
+       struct re_guts *re_g;   /* none of your business :-) */
+} regex_t;
+
+typedef struct {
+       regoff_t rm_so;         /* start of match */
+       regoff_t rm_eo;         /* end of match */
+} regmatch_t;
+
+/* regcomp() flags */
+#define        REG_BASIC       0000
+#define        REG_EXTENDED    0001
+#define        REG_ICASE       0002
+#define        REG_NOSUB       0004
+#define        REG_NEWLINE     0010
+#define        REG_NOSPEC      0020
+#define        REG_PEND        0040
+#define        REG_DUMP        0200
+
+/* regerror() flags */
+#define        REG_ENOSYS      (-1)
+#ifdef __CYGWIN__
+#define        REG_NOERROR      0      /* GNU extension */
+#endif
+#define        REG_NOMATCH      1
+#define        REG_BADPAT       2
+#define        REG_ECOLLATE     3
+#define        REG_ECTYPE       4
+#define        REG_EESCAPE      5
+#define        REG_ESUBREG      6
+#define        REG_EBRACK       7
+#define        REG_EPAREN       8
+#define        REG_EBRACE       9
+#define        REG_BADBR       10
+#define        REG_ERANGE      11
+#define        REG_ESPACE      12
+#define        REG_BADRPT      13
+#define        REG_EMPTY       14
+#define        REG_ASSERT      15
+#define        REG_INVARG      16
+#define        REG_ILLSEQ      17
+#define        REG_ATOI        255     /* convert name to number (!) */
+#define        REG_ITOA        0400    /* convert number to name (!) */
+
+/* regexec() flags */
+#define        REG_NOTBOL      00001
+#define        REG_NOTEOL      00002
+#define        REG_STARTEND    00004
+#define        REG_TRACE       00400   /* tracing of execution */
+#define        REG_LARGE       01000   /* force large representation */
+#define        REG_BACKR       02000   /* force use of backref code */
+
+__BEGIN_DECLS
+int    regcomp(regex_t * __restrict, const char * __restrict, int);
+size_t regerror(int, const regex_t * __restrict, char * __restrict, size_t);
+/*
+ * XXX forth parameter should be `regmatch_t [__restrict]', but isn't because
+ * of a bug in GCC 3.2 (when -std=c99 is specified) which perceives this as a
+ * syntax error.
+ */
+int    regexec(const regex_t * __restrict, const char * __restrict, size_t,
+           regmatch_t * __restrict, int);
+void   regfree(regex_t *);
+__END_DECLS
+
+#endif /* !_REGEX_H_ */
index f8892533b7d98311ae4a8c65a26752d391442d94..3310fb7520c87b4ce02c0d538e8ccb4b0329ac32 100644 (file)
@@ -638,9 +638,9 @@ __set_lc_monetary_from_win (const char *name,
   return 1;
 }
 
-static LCID collate_lcid = 0;
+LCID collate_lcid = 0;
 static mbtowc_p collate_mbtowc = __ascii_mbtowc;
-static char collate_charset[ENCODING_LEN + 1] = "ASCII";
+char collate_charset[ENCODING_LEN + 1] = "ASCII";
 
 /* Called from newlib's setlocale() if category is LC_COLLATE.  Stores
    LC_COLLATE locale information.  This is subsequently accessed by the
index 30c1f7a48837ef317290fddf2da98146f4f6ff29..dc823b1245a2dfd104e5c4638881608135663d41 100644 (file)
@@ -1,4 +1,4 @@
-Copyright 1992, 1993, 1994, 1997 Henry Spencer.  All rights reserved.
+Copyright 1992, 1993, 1994 Henry Spencer.  All rights reserved.
 This software is not subject to any license of the American Telephone
 and Telegraph Company or of the Regents of the University of California.
 
@@ -18,3 +18,35 @@ to the following restrictions:
    ever read sources, credits must appear in the documentation.
 
 4. This notice may not be removed or altered.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+/*-
+ * Copyright (c) 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)COPYRIGHT   8.1 (Berkeley) 3/16/94
+ */
diff --git a/winsup/cygwin/regex/cclass.h b/winsup/cygwin/regex/cclass.h
deleted file mode 100644 (file)
index 7ddb44a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* character-class table */
-static struct cclass {
-       const char *name;
-       const char *chars;
-       const char *multis;
-} cclasses[] = {
-       {"alnum",       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789",                           ""},
-       {"alpha",       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
-                                               ""},
-       {"blank",       " \t",          ""},
-       {"cntrl",       "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\
-       \25\26\27\30\31\32\33\34\35\36\37\177", ""},
-       {"digit",       "0123456789",   ""},
-       {"graph",       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-       0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-                                               ""},
-       {"lower",       "abcdefghijklmnopqrstuvwxyz",
-                                               ""},
-       {"print",       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-       0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
-                                               ""},
-       {"punct",       "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-                                               ""},
-       {"space",       "\t\n\v\f\r ",  ""},
-       {"upper",       "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
-                                               ""},
-       {"xdigit",      "0123456789ABCDEFabcdef",
-                                               ""},
-       {NULL,          0,              ""}
-};
index 1000f603e00153e68c84279e08e83c1789a188cc..4ad1ea93bb7c305b743a9bce8404448ecfcf2a14 100644 (file)
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)cname.h     8.3 (Berkeley) 3/20/94
+ * $FreeBSD: src/lib/libc/regex/cname.h,v 1.4 2007/01/09 00:28:04 imp Exp $
+ */
+
 /* character-name table */
 static struct cname {
        const char *name;
        char code;
 } cnames[] = {
-       {"NUL", '\0'},
-       {"SOH", '\001'},
-       {"STX", '\002'},
-       {"ETX", '\003'},
-       {"EOT", '\004'},
-       {"ENQ", '\005'},
-       {"ACK", '\006'},
-       {"BEL", '\007'},
-       {"alert",       '\007'},
-       {"BS",          '\010'},
-       {"backspace",   '\b'},
-       {"HT",          '\011'},
-       {"tab",         '\t'},
-       {"LF",          '\012'},
-       {"newline",     '\n'},
-       {"VT",          '\013'},
+       {"NUL",                 '\0'},
+       {"SOH",                 '\001'},
+       {"STX",                 '\002'},
+       {"ETX",                 '\003'},
+       {"EOT",                 '\004'},
+       {"ENQ",                 '\005'},
+       {"ACK",                 '\006'},
+       {"BEL",                 '\007'},
+       {"alert",               '\007'},
+       {"BS",                  '\010'},
+       {"backspace",           '\b'},
+       {"HT",                  '\011'},
+       {"tab",                 '\t'},
+       {"LF",                  '\012'},
+       {"newline",             '\n'},
+       {"VT",                  '\013'},
        {"vertical-tab",        '\v'},
-       {"FF",          '\014'},
-       {"form-feed",   '\f'},
-       {"CR",          '\015'},
+       {"FF",                  '\014'},
+       {"form-feed",           '\f'},
+       {"CR",                  '\015'},
        {"carriage-return",     '\r'},
-       {"SO",  '\016'},
-       {"SI",  '\017'},
-       {"DLE", '\020'},
-       {"DC1", '\021'},
-       {"DC2", '\022'},
-       {"DC3", '\023'},
-       {"DC4", '\024'},
-       {"NAK", '\025'},
-       {"SYN", '\026'},
-       {"ETB", '\027'},
-       {"CAN", '\030'},
-       {"EM",  '\031'},
-       {"SUB", '\032'},
-       {"ESC", '\033'},
-       {"IS4", '\034'},
-       {"FS",  '\034'},
-       {"IS3", '\035'},
-       {"GS",  '\035'},
-       {"IS2", '\036'},
-       {"RS",  '\036'},
-       {"IS1", '\037'},
-       {"US",  '\037'},
+       {"SO",                  '\016'},
+       {"SI",                  '\017'},
+       {"DLE",                 '\020'},
+       {"DC1",                 '\021'},
+       {"DC2",                 '\022'},
+       {"DC3",                 '\023'},
+       {"DC4",                 '\024'},
+       {"NAK",                 '\025'},
+       {"SYN",                 '\026'},
+       {"ETB",                 '\027'},
+       {"CAN",                 '\030'},
+       {"EM",                  '\031'},
+       {"SUB",                 '\032'},
+       {"ESC",                 '\033'},
+       {"IS4",                 '\034'},
+       {"FS",                  '\034'},
+       {"IS3",                 '\035'},
+       {"GS",                  '\035'},
+       {"IS2",                 '\036'},
+       {"RS",                  '\036'},
+       {"IS1",                 '\037'},
+       {"US",                  '\037'},
        {"space",               ' '},
        {"exclamation-mark",    '!'},
        {"quotation-mark",      '"'},
        {"number-sign",         '#'},
        {"dollar-sign",         '$'},
-       {"percent-sign",                '%'},
+       {"percent-sign",        '%'},
        {"ampersand",           '&'},
        {"apostrophe",          '\''},
        {"left-parenthesis",    '('},
        {"right-parenthesis",   ')'},
-       {"asterisk",    '*'},
-       {"plus-sign",   '+'},
-       {"comma",       ','},
-       {"hyphen",      '-'},
+       {"asterisk",            '*'},
+       {"plus-sign",           '+'},
+       {"comma",               ','},
+       {"hyphen",              '-'},
        {"hyphen-minus",        '-'},
-       {"period",      '.'},
-       {"full-stop",   '.'},
-       {"slash",       '/'},
-       {"solidus",     '/'},
+       {"period",              '.'},
+       {"full-stop",           '.'},
+       {"slash",               '/'},
+       {"solidus",             '/'},
        {"zero",                '0'},
-       {"one",         '1'},
-       {"two",         '2'},
-       {"three",       '3'},
+       {"one",                 '1'},
+       {"two",                 '2'},
+       {"three",               '3'},
        {"four",                '4'},
        {"five",                '5'},
-       {"six",         '6'},
-       {"seven",       '7'},
-       {"eight",       '8'},
+       {"six",                 '6'},
+       {"seven",               '7'},
+       {"eight",               '8'},
        {"nine",                '9'},
-       {"colon",       ':'},
-       {"semicolon",   ';'},
+       {"colon",               ':'},
+       {"semicolon",           ';'},
        {"less-than-sign",      '<'},
        {"equals-sign",         '='},
        {"greater-than-sign",   '>'},
@@ -85,12 +121,12 @@ static struct cname {
        {"left-square-bracket", '['},
        {"backslash",           '\\'},
        {"reverse-solidus",     '\\'},
-       {"right-square-bracket",        ']'},
+       {"right-square-bracket",']'},
        {"circumflex",          '^'},
        {"circumflex-accent",   '^'},
        {"underscore",          '_'},
        {"low-line",            '_'},
-       {"grave-accent",                '`'},
+       {"grave-accent",        '`'},
        {"left-brace",          '{'},
        {"left-curly-bracket",  '{'},
        {"vertical-line",       '|'},
index 42c91dc0f9092b986f4afd84e5024b6c7d648462..ca24cc50cd142c6a6e34d23d9aaee0703d38c02c 100644 (file)
@@ -1,3 +1,41 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)engine.c    8.5 (Berkeley) 3/20/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/regex/engine.c,v 1.23 2009/09/16 06:32:23 dds Exp $");
+
 /*
  * The matching engine and friends.  This file is #included by regexec.c
  * after suitable #defines of a variety of macros used herein, so that
 #define        at      lat
 #define        match   lmat
 #endif
+#ifdef MNAMES
+#define        matcher mmatcher
+#define        fast    mfast
+#define        slow    mslow
+#define        dissect mdissect
+#define        backref mbackref
+#define        step    mstep
+#define        print   mprint
+#define        at      mat
+#define        match   mmat
+#endif
 
 /* another structure passed up and down to avoid zillions of parameters */
 struct match {
        struct re_guts *g;
        int eflags;
        regmatch_t *pmatch;     /* [nsub+1] (0 element unused) */
-       char *offp;             /* offsets work from here */
-       char *beginp;           /* start of string -- virtual NUL precedes */
-       char *endp;             /* end of string -- virtual NUL here */
-       char *coldp;            /* can be no match starting before here */
-       char **lastpos;         /* [nplus+1] */
+       const char *offp;       /* offsets work from here */
+       const char *beginp;     /* start of string -- virtual NUL precedes */
+       const char *endp;       /* end of string -- virtual NUL here */
+       const char *coldp;      /* can be no match starting before here */
+       const char **lastpos;   /* [nplus+1] */
        STATEVARS;
        states st;              /* current states */
        states fresh;           /* states for a fresh start */
        states tmp;             /* temporary */
        states empty;           /* empty set of states */
+       mbstate_t mbs;          /* multibyte conversion state */
 };
 
-#include "engine.ih"
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === engine.c === */
+static int matcher(struct re_guts *g, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+static const char *dissect(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static const char *backref(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst, sopno lev, int);
+static const char *fast(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static const char *slow(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static states step(struct re_guts *g, sopno start, sopno stop, states bef, wint_t ch, states aft);
+#define MAX_RECURSION  100
+#define        BOL     (OUT-1)
+#define        EOL     (BOL-1)
+#define        BOLEOL  (BOL-2)
+#define        NOTHING (BOL-3)
+#define        BOW     (BOL-4)
+#define        EOW     (BOL-5)
+#define        BADCHAR (BOL-6)
+#ifdef __CYGWIN__
+/* In contrast to BSD, wint_t on Cygwin is unsigned.  This breaks this test,
+   unless the compared values are casted to signed. */
+#define        NONCHAR(c)      ((int)(c) <= (int)OUT)
+#else
+#define        NONCHAR(c)      ((c) <= OUT)
+#endif
+#ifdef REDEBUG
+static void print(struct match *m, const char *caption, states st, int ch, FILE *d);
+#endif
+#ifdef REDEBUG
+static void at(struct match *m, const char *title, const char *start, const char *stop, sopno startst, sopno stopst);
+#endif
+#ifdef REDEBUG
+static const char *pchar(int ch);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
 
 #ifdef REDEBUG
 #define        SP(t, s, c)     print(m, t, s, c, stdout)
@@ -59,26 +149,32 @@ struct match {
 
 /*
  - matcher - the actual matching engine
- == static int matcher(register struct re_guts *g, char *string, \
+ == static int matcher(struct re_guts *g, const char *string, \
  ==    size_t nmatch, regmatch_t pmatch[], int eflags);
  */
 static int                     /* 0 success, REG_NOMATCH failure */
-matcher(g, string, nmatch, pmatch, eflags)
-register struct re_guts *g;
-char *string;
-size_t nmatch;
-regmatch_t pmatch[];
-int eflags;
+matcher(struct re_guts *g,
+       const char *string,
+       size_t nmatch,
+       regmatch_t pmatch[],
+       int eflags)
 {
-       register char *endp;
-       register size_t i;
+       const char *endp;
+       int i;
        struct match mv;
-       register struct match *m = &mv;
-       register char *dp;
-       const register sopno gf = g->firststate+1;      /* +1 for OEND */
-       const register sopno gl = g->laststate;
-       char *start;
-       char *stop;
+       struct match *m = &mv;
+       const char *dp;
+       const sopno gf = g->firststate+1;       /* +1 for OEND */
+       const sopno gl = g->laststate;
+       const char *start;
+       const char *stop;
+       /* Boyer-Moore algorithms variables */
+       const char *pp;
+       int cj, mj;
+       const char *mustfirst;
+       const char *mustlast;
+       int *matchjump;
+       int *charjump;
 
        /* simplify the situation where possible */
        if (g->cflags&REG_NOSUB)
@@ -95,12 +191,46 @@ int eflags;
 
        /* prescreening; this does wonders for this rather slow code */
        if (g->must != NULL) {
-               for (dp = start; dp < stop; dp++)
-                       if (*dp == g->must[0] && stop - dp >= g->mlen &&
-                               memcmp(dp, g->must, (size_t)g->mlen) == 0)
-                               break;
-               if (dp == stop)         /* we didn't find g->must */
-                       return(REG_NOMATCH);
+               if (g->charjump != NULL && g->matchjump != NULL) {
+                       mustfirst = g->must;
+                       mustlast = g->must + g->mlen - 1;
+                       charjump = g->charjump;
+                       matchjump = g->matchjump;
+                       pp = mustlast;
+                       for (dp = start+g->mlen-1; dp < stop;) {
+                               /* Fast skip non-matches */
+                               while (dp < stop && charjump[(int)*dp])
+                                       dp += charjump[(int)*dp];
+
+                               if (dp >= stop)
+                                       break;
+
+                               /* Greedy matcher */
+                               /* We depend on not being used for
+                                * for strings of length 1
+                                */
+                               while (*--dp == *--pp && pp != mustfirst);
+
+                               if (*dp == *pp)
+                                       break;
+
+                               /* Jump to next possible match */
+                               mj = matchjump[pp - mustfirst];
+                               cj = charjump[(int)*dp];
+                               dp += (cj < mj ? mj : cj);
+                               pp = mustlast;
+                       }
+                       if (pp != mustfirst)
+                               return(REG_NOMATCH);
+               } else {
+                       for (dp = start; dp < stop; dp++)
+                               if (*dp == g->must[0] &&
+                                   stop - dp >= g->mlen &&
+                                   memcmp(dp, g->must, (size_t)g->mlen) == 0)
+                                       break;
+                       if (dp == stop)         /* we didn't find g->must */
+                               return(REG_NOMATCH);
+               }
        }
 
        /* match struct setup */
@@ -117,11 +247,22 @@ int eflags;
        SETUP(m->tmp);
        SETUP(m->empty);
        CLEAR(m->empty);
+       ZAPSTATE(&m->mbs);
+
+       /* Adjust start according to moffset, to speed things up */
+       if (g->moffset > -1)
+               start = ((dp - g->moffset) < start) ? start : dp - g->moffset;
+
+       SP("mloop", m->st, *start);
 
        /* this loop does only one repetition except for backrefs */
        for (;;) {
                endp = fast(m, start, stop, gf, gl);
                if (endp == NULL) {             /* a miss */
+                       if (m->pmatch != NULL)
+                               free((char *)m->pmatch);
+                       if (m->lastpos != NULL)
+                               free((char *)m->lastpos);
                        STATETEARDOWN(m);
                        return(REG_NOMATCH);
                }
@@ -136,7 +277,8 @@ int eflags;
                        if (endp != NULL)
                                break;
                        assert(m->coldp < m->endp);
-                       m->coldp++;
+                       m->coldp += XMBRTOWC(NULL, m->coldp,
+                           m->endp - m->coldp, &m->mbs, 0);
                }
                if (nmatch == 1 && !g->backrefs)
                        break;          /* no further info needed */
@@ -156,15 +298,15 @@ int eflags;
                        dp = dissect(m, m->coldp, endp, gf, gl);
                } else {
                        if (g->nplus > 0 && m->lastpos == NULL)
-                               m->lastpos = (char **)malloc((g->nplus+1) *
-                                                       sizeof(char *));
+                               m->lastpos = malloc((g->nplus+1) *
+                                               sizeof(const char *));
                        if (g->nplus > 0 && m->lastpos == NULL) {
                                free(m->pmatch);
                                STATETEARDOWN(m);
                                return(REG_ESPACE);
                        }
                        NOTE("backref dissect");
-                       dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+                       dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
                }
                if (dp != NULL)
                        break;
@@ -187,7 +329,7 @@ int eflags;
                        }
 #endif
                        NOTE("backoff dissect");
-                       dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+                       dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
                }
                assert(dp == NULL || dp == endp);
                if (dp != NULL)         /* found a shorter one */
@@ -195,7 +337,9 @@ int eflags;
 
                /* despite initial appearances, there is no match here */
                NOTE("false alarm");
-               start = m->coldp + 1;   /* recycle starting later */
+               /* recycle starting later */
+               start = m->coldp + XMBRTOWC(NULL, m->coldp,
+                   stop - m->coldp, &m->mbs, 0);
                assert(start <= stop);
        }
 
@@ -225,30 +369,29 @@ int eflags;
 
 /*
  - dissect - figure out what matched what, no back references
- == static char *dissect(register struct match *m, char *start, \
- ==    char *stop, sopno startst, sopno stopst);
+ == static const char *dissect(struct match *m, const char *start, \
+ ==    const char *stop, sopno startst, sopno stopst);
  */
-static char *                  /* == stop (success) always */
-dissect(m, start, stop, startst, stopst)
-register struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char *            /* == stop (success) always */
+dissect(struct match *m,
+       const char *start,
+       const char *stop,
+       sopno startst,
+       sopno stopst)
 {
-       register int i;
-       register sopno ss;      /* start sop of current subRE */
-       register sopno es;      /* end sop of current subRE */
-       register char *sp;      /* start of string matched by it */
-       register char *stp;     /* string matched by it cannot pass here */
-       register char *rest;    /* start of rest of string */
-       register char *tail;    /* string unmatched by rest of RE */
-       register sopno ssub;    /* start sop of subsubRE */
-       register sopno esub;    /* end sop of subsubRE */
-       register char *ssp;     /* start of string matched by subsubRE */
-       register char *sep;     /* end of string matched by subsubRE */
-       register char *oldssp;  /* previous ssp */
-       register char *dp;
+       int i;
+       sopno ss;               /* start sop of current subRE */
+       sopno es;               /* end sop of current subRE */
+       const char *sp;         /* start of string matched by it */
+       const char *stp;        /* string matched by it cannot pass here */
+       const char *rest;       /* start of rest of string */
+       const char *tail;       /* string unmatched by rest of RE */
+       sopno ssub;             /* start sop of subsubRE */
+       sopno esub;             /* end sop of subsubRE */
+       const char *ssp;        /* start of string matched by subsubRE */
+       const char *sep;        /* end of string matched by subsubRE */
+       const char *oldssp;     /* previous ssp */
+       const char *dp;
 
        AT("diss", start, stop, startst, stopst);
        sp = start;
@@ -273,7 +416,7 @@ sopno stopst;
                        assert(nope);
                        break;
                case OCHAR:
-                       sp++;
+                       sp += XMBRTOWC(NULL, sp, stop - start, &m->mbs, 0);
                        break;
                case OBOL:
                case OEOL:
@@ -282,7 +425,7 @@ sopno stopst;
                        break;
                case OANY:
                case OANYOF:
-                       sp++;
+                       sp += XMBRTOWC(NULL, sp, stop - start, &m->mbs, 0);
                        break;
                case OBACK_:
                case O_BACK:
@@ -413,30 +556,31 @@ sopno stopst;
 
 /*
  - backref - figure out what matched what, figuring in back references
- == static char *backref(register struct match *m, char *start, \
- ==    char *stop, sopno startst, sopno stopst, sopno lev);
+ == static const char *backref(struct match *m, const char *start, \
+ ==    const char *stop, sopno startst, sopno stopst, sopno lev);
  */
-static char *                  /* == stop (success) or NULL (failure) */
-backref(m, start, stop, startst, stopst, lev)
-register struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
-sopno lev;                     /* PLUS nesting level */
+static const char *            /* == stop (success) or NULL (failure) */
+backref(struct match *m,
+       const char *start,
+       const char *stop,
+       sopno startst,
+       sopno stopst,
+       sopno lev,              /* PLUS nesting level */
+       int rec)
 {
-       register int i;
-       register sopno ss;      /* start sop of current subRE */
-       register char *sp;      /* start of string matched by it */
-       register sopno ssub;    /* start sop of subsubRE */
-       register sopno esub;    /* end sop of subsubRE */
-       register char *ssp;     /* start of string matched by subsubRE */
-       register char *dp;
-       register size_t len;
-       register int hard;
-       register sop s;
-       register regoff_t offsave;
-       register cset *cs;
+       int i;
+       sopno ss;               /* start sop of current subRE */
+       const char *sp;         /* start of string matched by it */
+       sopno ssub;             /* start sop of subsubRE */
+       sopno esub;             /* end sop of subsubRE */
+       const char *ssp;        /* start of string matched by subsubRE */
+       const char *dp;
+       size_t len;
+       int hard;
+       sop s;
+       regoff_t offsave;
+       cset *cs;
+       wint_t wc;
 
        AT("back", start, stop, startst, stopst);
        sp = start;
@@ -446,17 +590,25 @@ sopno lev;                        /* PLUS nesting level */
        for (ss = startst; !hard && ss < stopst; ss++)
                switch (OP(s = m->g->strip[ss])) {
                case OCHAR:
-                       if (sp == stop || *sp++ != (char)OPND(s))
+                       if (sp == stop)
+                               return(NULL);
+                       sp += XMBRTOWC(&wc, sp, stop - sp, &m->mbs, BADCHAR);
+                       if (wc != OPND(s))
                                return(NULL);
                        break;
                case OANY:
                        if (sp == stop)
                                return(NULL);
-                       sp++;
+                       sp += XMBRTOWC(&wc, sp, stop - sp, &m->mbs, BADCHAR);
+                       if (wc == BADCHAR)
+                               return (NULL);
                        break;
                case OANYOF:
+                       if (sp == stop)
+                               return (NULL);
                        cs = &m->g->sets[OPND(s)];
-                       if (sp == stop || !CHIN(cs, *sp++))
+                       sp += XMBRTOWC(&wc, sp, stop - sp, &m->mbs, BADCHAR);
+                       if (wc == BADCHAR || !CHIN(cs, wc))
                                return(NULL);
                        break;
                case OBOL:
@@ -529,6 +681,8 @@ sopno lev;                  /* PLUS nesting level */
                        return(NULL);
                assert(m->pmatch[i].rm_so != -1);
                len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
+               if (len == 0 && rec++ > MAX_RECURSION)
+                       return(NULL);
                assert(stop - m->beginp >= len);
                if (sp > stop - len)
                        return(NULL);   /* not enough left to match */
@@ -537,28 +691,28 @@ sopno lev;                        /* PLUS nesting level */
                        return(NULL);
                while (m->g->strip[ss] != SOP(O_BACK, i))
                        ss++;
-               return(backref(m, sp+len, stop, ss+1, stopst, lev));
+               return(backref(m, sp+len, stop, ss+1, stopst, lev, rec));
                break;
        case OQUEST_:           /* to null or not */
-               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
                if (dp != NULL)
                        return(dp);     /* not */
-               return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
+               return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec));
                break;
        case OPLUS_:
                assert(m->lastpos != NULL);
                assert(lev+1 <= m->g->nplus);
                m->lastpos[lev+1] = sp;
-               return(backref(m, sp, stop, ss+1, stopst, lev+1));
+               return(backref(m, sp, stop, ss+1, stopst, lev+1, rec));
                break;
        case O_PLUS:
                if (sp == m->lastpos[lev])      /* last pass matched null */
-                       return(backref(m, sp, stop, ss+1, stopst, lev-1));
+                       return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
                /* try another pass */
                m->lastpos[lev] = sp;
-               dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
+               dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec);
                if (dp == NULL)
-                       return(backref(m, sp, stop, ss+1, stopst, lev-1));
+                       return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
                else
                        return(dp);
                break;
@@ -567,7 +721,7 @@ sopno lev;                  /* PLUS nesting level */
                esub = ss + OPND(s) - 1;
                assert(OP(m->g->strip[esub]) == OOR1);
                for (;;) {      /* find first matching branch */
-                       dp = backref(m, sp, stop, ssub, esub, lev);
+                       dp = backref(m, sp, stop, ssub, esub, lev, rec);
                        if (dp != NULL)
                                return(dp);
                        /* that one missed, try next one */
@@ -588,7 +742,7 @@ sopno lev;                  /* PLUS nesting level */
                assert(0 < i && i <= m->g->nsub);
                offsave = m->pmatch[i].rm_so;
                m->pmatch[i].rm_so = sp - m->offp;
-               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
                if (dp != NULL)
                        return(dp);
                m->pmatch[i].rm_so = offsave;
@@ -599,7 +753,7 @@ sopno lev;                  /* PLUS nesting level */
                assert(0 < i && i <= m->g->nsub);
                offsave = m->pmatch[i].rm_eo;
                m->pmatch[i].rm_eo = sp - m->offp;
-               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
                if (dp != NULL)
                        return(dp);
                m->pmatch[i].rm_eo = offsave;
@@ -613,42 +767,57 @@ sopno lev;                        /* PLUS nesting level */
        /* "can't happen" */
        assert(nope);
        /* NOTREACHED */
-       return((char *)NULL);   /* dummy */
+       return "shut up gcc";
 }
 
 /*
  - fast - step through the string at top speed
- == static char *fast(register struct match *m, char *start, \
- ==    char *stop, sopno startst, sopno stopst);
+ == static const char *fast(struct match *m, const char *start, \
+ ==    const char *stop, sopno startst, sopno stopst);
  */
-static char *                  /* where tentative match ended, or NULL */
-fast(m, start, stop, startst, stopst)
-register struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char *            /* where tentative match ended, or NULL */
+fast(  struct match *m,
+       const char *start,
+       const char *stop,
+       sopno startst,
+       sopno stopst)
 {
-       register states st = m->st;
-       register states fresh = m->fresh;
-       register states tmp = m->tmp;
-       register char *p = start;
-       register int c = (start == m->beginp) ? OUT : *(start-1);
-       register int lastc;     /* previous c */
-       register int flagch;
-       register int i;
-       register char *coldp;   /* last p after which no match was underway */
+       states st = m->st;
+       states fresh = m->fresh;
+       states tmp = m->tmp;
+       const char *p = start;
+       wint_t c;
+       wint_t lastc;           /* previous c */
+       wint_t flagch;
+       int i;
+       const char *coldp;      /* last p after which no match was underway */
+       size_t clen;
 
        CLEAR(st);
        SET1(st, startst);
+       SP("fast", st, *p);
        st = step(m->g, startst, stopst, st, NOTHING, st);
        ASSIGN(fresh, st);
        SP("start", st, *p);
        coldp = NULL;
+       if (start == m->beginp)
+               c = OUT;
+       else {
+               /*
+                * XXX Wrong if the previous character was multi-byte.
+                * Newline never is (in encodings supported by FreeBSD),
+                * so this only breaks the ISWORD tests below.
+                */
+               c = (uch)*(start - 1);
+       }
        for (;;) {
                /* next character */
                lastc = c;
-               c = (p == m->endp) ? OUT : *p;
+               if (p == m->endp) {
+                       clen = 0;
+                       c = OUT;
+               } else
+                       clen = XMBRTOWC(&c, p, m->endp - p, &m->mbs, BADCHAR);
                if (EQ(st, fresh))
                        coldp = p;
 
@@ -686,7 +855,7 @@ sopno stopst;
                }
 
                /* are we done? */
-               if (ISSET(st, stopst) || p == stop)
+               if (ISSET(st, stopst) || p == stop || clen > stop - p)
                        break;          /* NOTE BREAK OUT */
 
                /* no, we must deal with this character */
@@ -696,39 +865,39 @@ sopno stopst;
                st = step(m->g, startst, stopst, tmp, c, st);
                SP("aft", st, c);
                assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
-               p++;
+               p += clen;
        }
 
        assert(coldp != NULL);
        m->coldp = coldp;
        if (ISSET(st, stopst))
-               return(p+1);
+               return(p+XMBRTOWC(NULL, p, stop - p, &m->mbs, 0));
        else
                return(NULL);
 }
 
 /*
  - slow - step through the string more deliberately
- == static char *slow(register struct match *m, char *start, \
- ==    char *stop, sopno startst, sopno stopst);
+ == static const char *slow(struct match *m, const char *start, \
+ ==    const char *stop, sopno startst, sopno stopst);
  */
-static char *                  /* where it ended */
-slow(m, start, stop, startst, stopst)
-register struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char *            /* where it ended */
+slow(  struct match *m,
+       const char *start,
+       const char *stop,
+       sopno startst,
+       sopno stopst)
 {
-       register states st = m->st;
-       register states empty = m->empty;
-       register states tmp = m->tmp;
-       register char *p = start;
-       register int c = (start == m->beginp) ? OUT : *(start-1);
-       register int lastc;     /* previous c */
-       register int flagch;
-       register int i;
-       register char *matchp;  /* last p at which a match ended */
+       states st = m->st;
+       states empty = m->empty;
+       states tmp = m->tmp;
+       const char *p = start;
+       wint_t c;
+       wint_t lastc;           /* previous c */
+       wint_t flagch;
+       int i;
+       const char *matchp;     /* last p at which a match ended */
+       size_t clen;
 
        AT("slow", start, stop, startst, stopst);
        CLEAR(st);
@@ -736,10 +905,24 @@ sopno stopst;
        SP("sstart", st, *p);
        st = step(m->g, startst, stopst, st, NOTHING, st);
        matchp = NULL;
+       if (start == m->beginp)
+               c = OUT;
+       else {
+               /*
+                * XXX Wrong if the previous character was multi-byte.
+                * Newline never is (in encodings supported by FreeBSD),
+                * so this only breaks the ISWORD tests below.
+                */
+               c = (uch)*(start - 1);
+       }
        for (;;) {
                /* next character */
                lastc = c;
-               c = (p == m->endp) ? OUT : *p;
+               if (p == m->endp) {
+                       c = OUT;
+                       clen = 0;
+               } else
+                       clen = XMBRTOWC(&c, p, m->endp - p, &m->mbs, BADCHAR);
 
                /* is there an EOL and/or BOL between lastc and c? */
                flagch = '\0';
@@ -777,7 +960,7 @@ sopno stopst;
                /* are we done? */
                if (ISSET(st, stopst))
                        matchp = p;
-               if (EQ(st, empty) || p == stop)
+               if (EQ(st, empty) || p == stop || clen > stop - p)
                        break;          /* NOTE BREAK OUT */
 
                /* no, we must deal with this character */
@@ -787,7 +970,7 @@ sopno stopst;
                st = step(m->g, startst, stopst, tmp, c, st);
                SP("saft", st, c);
                assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
-               p++;
+               p += clen;
        }
 
        return(matchp);
@@ -796,33 +979,31 @@ sopno stopst;
 
 /*
  - step - map set of states reachable before char to set reachable after
- == static states step(register struct re_guts *g, sopno start, sopno stop, \
- ==    register states bef, int ch, register states aft);
- == #define    BOL     (OUT+1)
- == #define    EOL     (BOL+1)
- == #define    BOLEOL  (BOL+2)
- == #define    NOTHING (BOL+3)
- == #define    BOW     (BOL+4)
- == #define    EOW     (BOL+5)
- == #define    CODEMAX (BOL+5)         // highest code used
- == #define    NONCHAR(c)      ((c) > CHAR_MAX)
- == #define    NNONCHAR        (CODEMAX-CHAR_MAX)
+ == static states step(struct re_guts *g, sopno start, sopno stop, \
+ ==    states bef, int ch, states aft);
+ == #define    BOL     (OUT-1)
+ == #define    EOL     (BOL-1)
+ == #define    BOLEOL  (BOL-2)
+ == #define    NOTHING (BOL-3)
+ == #define    BOW     (BOL-4)
+ == #define    EOW     (BOL-5)
+ == #define    BADCHAR (BOL-6)
+ == #define    NONCHAR(c)      ((c) <= OUT)
  */
 static states
-step(g, start, stop, bef, ch, aft)
-register struct re_guts *g;
-sopno start;                   /* start state within strip */
-sopno stop;                    /* state after stop state within strip */
-register states bef;           /* states reachable before */
-int ch;                                /* character or NONCHAR code */
-register states aft;           /* states already known reachable after */
+step(struct re_guts *g,
+       sopno start,            /* start state within strip */
+       sopno stop,             /* state after stop state within strip */
+       states bef,             /* states reachable before */
+       wint_t ch,              /* character or NONCHAR code */
+       states aft)             /* states already known reachable after */
 {
-       register cset *cs;
-       register sop s;
-       register sopno pc;
-       register onestate here;         /* note, macros know this name */
-       register sopno look;
-       register long i;
+       cset *cs;
+       sop s;
+       sopno pc;
+       onestate here;          /* note, macros know this name */
+       sopno look;
+       int i;
 
        for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
                s = g->strip[pc];
@@ -832,8 +1013,8 @@ register states aft;               /* states already known reachable after */
                        break;
                case OCHAR:
                        /* only characters can match */
-                       assert(!NONCHAR(ch) || ch != (char)OPND(s));
-                       if (ch == (char)OPND(s))
+                       assert(!NONCHAR(ch) || ch != OPND(s));
+                       if (ch == OPND(s))
                                FWD(aft, bef, 1);
                        break;
                case OBOL:
@@ -900,7 +1081,7 @@ register states aft;               /* states already known reachable after */
                                                OP(s = g->strip[pc+look]) != O_CH;
                                                look += OPND(s))
                                        assert(OP(s) == OOR2);
-                               FWD(aft, aft, look);
+                               FWD(aft, aft, look + 1);
                        }
                        break;
                case OOR2:              /* propagate OCH_'s marking */
@@ -926,21 +1107,20 @@ register states aft;             /* states already known reachable after */
 /*
  - print - print a set of states
  == #ifdef REDEBUG
- == static void print(struct match *m, char *caption, states st, \
+ == static void print(struct match *m, const char *caption, states st, \
  ==    int ch, FILE *d);
  == #endif
  */
 static void
-print(m, caption, st, ch, d)
-struct match *m;
-char *caption;
-states st;
-int ch;
-FILE *d;
+print(struct match *m,
+       const char *caption,
+       states st,
+       int ch,
+       FILE *d)
 {
-       register struct re_guts *g = m->g;
-       register int i;
-       register int first = 1;
+       struct re_guts *g = m->g;
+       int i;
+       int first = 1;
 
        if (!(m->eflags&REG_TRACE))
                return;
@@ -959,18 +1139,17 @@ FILE *d;
 /*
  - at - print current situation
  == #ifdef REDEBUG
- == static void at(struct match *m, char *title, char *start, char *stop, \
- ==                                            sopno startst, sopno stopst);
+ == static void at(struct match *m, const char *title, const char *start, \
+ ==                     const char *stop, sopno startst, sopno stopst);
  == #endif
  */
 static void
-at(m, title, start, stop, startst, stopst)
-struct match *m;
-char *title;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+at(    struct match *m,
+       const char *title,
+       const char *start,
+       const char *stop,
+       sopno startst,
+       sopno stopst)
 {
        if (!(m->eflags&REG_TRACE))
                return;
@@ -985,7 +1164,7 @@ sopno stopst;
 /*
  - pchar - make a character printable
  == #ifdef REDEBUG
- == static char *pchar(int ch);
+ == static const char *pchar(int ch);
  == #endif
  *
  * Is this identical to regchar() over in debug.c?  Well, yes.  But a
@@ -993,13 +1172,12 @@ sopno stopst;
  * a matching debug.o, and this is convenient.  It all disappears in
  * the non-debug compilation anyway, so it doesn't matter much.
  */
-static char *                  /* -> representation */
-pchar(ch)
-int ch;
+static const char *            /* -> representation */
+pchar(int ch)
 {
        static char pbuf[10];
 
-       if (isprint(ch) || ch == ' ')
+       if (isprint((uch)ch) || ch == ' ')
                sprintf(pbuf, "%c", ch);
        else
                sprintf(pbuf, "\\%o", ch);
diff --git a/winsup/cygwin/regex/engine.ih b/winsup/cygwin/regex/engine.ih
deleted file mode 100644 (file)
index cc98334..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* ========= begin header generated by ./mkh ========= */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* === engine.c === */
-static int matcher(register struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
-static char *dissect(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static char *backref(register struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);
-static char *fast(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static char *slow(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static states step(register struct re_guts *g, sopno start, sopno stop, register states bef, int ch, register states aft);
-#define        BOL     (OUT+1)
-#define        EOL     (BOL+1)
-#define        BOLEOL  (BOL+2)
-#define        NOTHING (BOL+3)
-#define        BOW     (BOL+4)
-#define        EOW     (BOL+5)
-#define        CODEMAX (BOL+5)         /* highest code used */
-#define        NONCHAR(c)      ((c) > CHAR_MAX)
-#define        NNONCHAR        (CODEMAX-CHAR_MAX)
-#ifdef REDEBUG
-static void print(struct match *m, char *caption, states st, int ch, FILE *d);
-#endif
-#ifdef REDEBUG
-static void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst);
-#endif
-#ifdef REDEBUG
-static char *pchar(int ch);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-/* ========= end header generated by ./mkh ========= */
diff --git a/winsup/cygwin/regex/mkh b/winsup/cygwin/regex/mkh
deleted file mode 100755 (executable)
index 252b246..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#! /bin/sh
-# mkh - pull headers out of C source
-PATH=/bin:/usr/bin ; export PATH
-
-# egrep pattern to pick out marked lines
-egrep='^ =([   ]|$)'
-
-# Sed program to process marked lines into lines for the header file.
-# The markers have already been removed.  Two things are done here:  removal
-# of backslashed newlines, and some fudging of comments.  The first is done
-# because -o needs to have prototypes on one line to strip them down.
-# Getting comments into the output is tricky; we turn C++-style // comments
-# into /* */ comments, after altering any existing */'s to avoid trouble.
-peel=' /\\$/N
-       /\\\n[  ]*/s///g
-       /\/\//s;\*/;* /;g
-       /\/\//s;//\(.*\);/*\1 */;'
-
-for a
-do
-       case "$a" in
-       -o)     # old (pre-function-prototype) compiler
-               # add code to comment out argument lists
-               peel="$peel
-                       "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1(/*\2*/);'
-               shift
-               ;;
-       -b)     # funny Berkeley __P macro
-               peel="$peel
-                       "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1 __P((\2));'
-               shift
-               ;;
-       -s)     # compiler doesn't like `static foo();'
-               # add code to get rid of the `static'
-               peel="$peel
-                       "'/^static[     ][^\/]*[a-zA-Z0-9_)](.*)/s;static.;;'
-               shift
-               ;;
-       -p)     # private declarations
-               egrep='^ ==([   ]|$)'
-               shift
-               ;;
-       -i)     # wrap in #ifndef, argument is name
-               ifndef="$2"
-               shift ; shift
-               ;;
-       *)      break
-               ;;
-       esac
-done
-
-if test " $ifndef" != " "
-then
-       echo "#ifndef $ifndef"
-       echo "#define   $ifndef /* never again */"
-fi
-echo "/* ========= begin header generated by $0 ========= */"
-echo '#ifdef __cplusplus'
-echo 'extern "C" {'
-echo '#endif'
-for f
-do
-       echo
-       echo "/* === $f === */"
-       egrep "$egrep" $f | sed 's/^ ==*[       ]//;s/^ ==*$//' | sed "$peel"
-       echo
-done
-echo '#ifdef __cplusplus'
-echo '}'
-echo '#endif'
-echo "/* ========= end header generated by $0 ========= */"
-if test " $ifndef" != " "
-then
-       echo "#endif"
-fi
-exit 0
index f771a1ac4d27d45c0e1112a0818012dccfbbf649..5bcaa98c38d4d96cb1b5f0c3084e29802deb4ad7 100644 (file)
@@ -1,18 +1,77 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regcomp.c   8.5 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regcomp.c  8.5 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.36 2007/06/11 03:05:54 delphij Exp $");
+
+#ifdef __CYGWIN__
 #include "winsup.h"
+#endif
 #include <sys/types.h>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <limits.h>
 #include <stdlib.h>
-#include "regex.h"
+#include <regex.h>
+#ifndef __CYGWIN__
+#include <runetype.h>
+#endif
+#include <wchar.h>
+#include <wctype.h>
+
+#ifndef __CYGWIN__
+#include "collate.h"
+#endif
 
 #include "utils.h"
 #include "regex2.h"
 
-#include "cclass.h"
 #include "cname.h"
 
+#ifdef __CYGWIN__
+/* Don't pull in windows headers just for LCID. */
+typedef unsigned long LCID;
+/* These are defined in nlsfuncs.cc. */
+extern LCID collate_lcid;
+extern char collate_charset[];
+#endif
+
 /*
  * parse structure, passed up and down to avoid global variables and
  * other clumsinesses
@@ -31,7 +90,61 @@ struct parse {
        sopno pend[NPAREN];     /* -> ) ([0] unused) */
 };
 
-#include "regcomp.ih"
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regcomp.c === */
+#ifdef __CYGWIN__ /* Defined below `int stop'.  Our gcc chokes on that. */
+static void p_ere(struct parse *p, int stop);
+#else
+static void p_ere(struct parse *p, wint_t stop);
+#endif
+static void p_ere_exp(struct parse *p);
+static void p_str(struct parse *p);
+#ifdef __CYGWIN__ /* Defined below `int end1/end2'.  Our gcc chokes on that. */
+static void p_bre(struct parse *p, int end1, int end2);
+#else
+static void p_bre(struct parse *p, wint_t end1, wint_t end2);
+#endif
+static int p_simp_re(struct parse *p, int starordinary);
+static int p_count(struct parse *p);
+static void p_bracket(struct parse *p);
+static void p_b_term(struct parse *p, cset *cs);
+static void p_b_cclass(struct parse *p, cset *cs);
+static void p_b_eclass(struct parse *p, cset *cs);
+static wint_t p_b_symbol(struct parse *p);
+static wint_t p_b_coll_elem(struct parse *p, wint_t endc);
+static wint_t othercase(wint_t ch);
+static void bothcases(struct parse *p, wint_t ch);
+static void ordinary(struct parse *p, wint_t ch);
+static void nonnewline(struct parse *p);
+static void repeat(struct parse *p, sopno start, int from, int to);
+static int seterr(struct parse *p, int e);
+static cset *allocset(struct parse *p);
+static void freeset(struct parse *p, cset *cs);
+static void CHadd(struct parse *p, cset *cs, wint_t ch);
+static void CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max);
+static void CHaddtype(struct parse *p, cset *cs, wctype_t wct);
+static wint_t singleton(cset *cs);
+static sopno dupl(struct parse *p, sopno start, sopno finish);
+static void doemit(struct parse *p, sop op, size_t opnd);
+static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
+static void dofwd(struct parse *p, sopno pos, sop value);
+static void enlarge(struct parse *p, sopno size);
+static void stripsnug(struct parse *p, struct re_guts *g);
+static void findmust(struct parse *p, struct re_guts *g);
+static int altoffset(sop *scan, int offset);
+static void computejumps(struct parse *p, struct re_guts *g);
+static void computematchjumps(struct parse *p, struct re_guts *g);
+static sopno pluscount(struct parse *p, struct re_guts *g);
+static wint_t wgetnext(struct parse *p);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
 
 static char nuls[10];          /* place to point scanner in event of error */
 
@@ -51,8 +164,9 @@ static char nuls[10];                /* place to point scanner in event of error */
 #define        NEXT2() (p->next += 2)
 #define        NEXTn(n)        (p->next += (n))
 #define        GETNEXT()       (*p->next++)
+#define        WGETNEXT()      wgetnext(p)
 #define        SETERROR(e)     seterr(p, (e))
-#define        REQUIRE(co, e)  (void) ((co) || SETERROR(e))
+#define        REQUIRE(co, e)  ((co) || SETERROR(e))
 #define        MUSTSEE(c, e)   (REQUIRE(MORE() && PEEK() == (c), e))
 #define        MUSTEAT(c, e)   (REQUIRE(MORE() && GETNEXT() == (c), e))
 #define        MUSTNOTSEE(c, e)        (REQUIRE(!MORE() || PEEK() != (c), e))
@@ -71,6 +185,9 @@ static int never = 0;                /* for use in asserts; shuts lint up */
 #define        never   0               /* some <assert.h>s have bugs too */
 #endif
 
+/* Macro used by computejump()/computematchjump() */
+#define MIN(a,b)       ((a)<(b)?(a):(b))
+
 /*
  - regcomp - interface for parser and compilation
  = extern int regcomp(regex_t *, const char *, int);
@@ -84,16 +201,15 @@ static int never = 0;              /* for use in asserts; shuts lint up */
  = #define     REG_DUMP        0200
  */
 int                            /* 0 success, otherwise REG_something */
-regcomp(preg, pattern, cflags)
-regex_t *preg;
-const char *pattern;
-int cflags;
+regcomp(regex_t * __restrict preg,
+       const char * __restrict pattern,
+       int cflags)
 {
        struct parse pa;
-       register struct re_guts *g;
-       register struct parse *p = &pa;
-       register int i;
-       register size_t len;
+       struct re_guts *g;
+       struct parse *p = &pa;
+       int i;
+       size_t len;
 #ifdef REDEBUG
 #      define  GOODFLAGS(f)    (f)
 #else
@@ -112,8 +228,7 @@ int cflags;
                len = strlen((char *)pattern);
 
        /* do the mallocs early so failure handling is easy */
-       g = (struct re_guts *)malloc(sizeof(struct re_guts) +
-                                                       (NC-1)*sizeof(cat_t));
+       g = (struct re_guts *)malloc(sizeof(struct re_guts));
        if (g == NULL)
                return(REG_ESPACE);
        p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */
@@ -134,20 +249,18 @@ int cflags;
                p->pbegin[i] = 0;
                p->pend[i] = 0;
        }
-       g->csetsize = NC;
        g->sets = NULL;
-       g->setbits = NULL;
        g->ncsets = 0;
        g->cflags = cflags;
        g->iflags = 0;
        g->nbol = 0;
        g->neol = 0;
        g->must = NULL;
+       g->moffset = -1;
+       g->charjump = NULL;
+       g->matchjump = NULL;
        g->mlen = 0;
        g->nsub = 0;
-       g->ncategories = 1;     /* category 0 is "everything else" */
-       g->categories = &g->catspace[-(CHAR_MIN)];
-       (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t));
        g->backrefs = 0;
 
        /* do it */
@@ -163,9 +276,19 @@ int cflags;
        g->laststate = THERE();
 
        /* tidy up loose ends and fill things in */
-       categorize(p, g);
        stripsnug(p, g);
        findmust(p, g);
+       /* only use Boyer-Moore algorithm if the pattern is bigger
+        * than three characters
+        */
+       if(g->mlen > 3) {
+               computejumps(p, g);
+               computematchjumps(p, g);
+               if(g->matchjump == NULL && g->charjump != NULL) {
+                       free(g->charjump);
+                       g->charjump = NULL;
+               }
+       }
        g->nplus = pluscount(p, g);
        g->magic = MAGIC2;
        preg->re_nsub = g->nsub;
@@ -185,25 +308,24 @@ int cflags;
 
 /*
  - p_ere - ERE parser top level, concatenation and alternation
- == static void p_ere(register struct parse *p, int stop);
+ == static void p_ere(struct parse *p, int stop);
  */
 static void
-p_ere(p, stop)
-register struct parse *p;
-int stop;                      /* character this ERE should end at */
+p_ere(struct parse *p,
+       int stop)               /* character this ERE should end at */
 {
-       register char c;
-       register sopno prevback = 0;
-       register sopno prevfwd = 0;
-       register sopno conc = 0;
-       register int first = 1;         /* is this the first alternative? */
+       char c;
+       sopno prevback;
+       sopno prevfwd;
+       sopno conc;
+       int first = 1;          /* is this the first alternative? */
 
        for (;;) {
                /* do a bunch of concatenated expressions */
                conc = HERE();
                while (MORE() && (c = PEEK()) != '|' && c != stop)
                        p_ere_exp(p);
-               REQUIRE(HERE() != conc, REG_EMPTY);     /* require nonempty */
+               (void)REQUIRE(HERE() != conc, REG_EMPTY);       /* require nonempty */
 
                if (!EAT('|'))
                        break;          /* NOTE BREAK OUT */
@@ -231,17 +353,17 @@ int stop;                 /* character this ERE should end at */
 
 /*
  - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
- == static void p_ere_exp(register struct parse *p);
+ == static void p_ere_exp(struct parse *p);
  */
 static void
-p_ere_exp(p)
-register struct parse *p;
+p_ere_exp(struct parse *p)
 {
-       register char c;
-       register sopno pos;
-       register int count;
-       register int count2;
-       register sopno subno;
+       char c;
+       wint_t wc;
+       sopno pos;
+       int count;
+       int count2;
+       sopno subno;
        int wascaret = 0;
 
        assert(MORE());         /* caller should have ensured this */
@@ -250,7 +372,7 @@ register struct parse *p;
        pos = HERE();
        switch (c) {
        case '(':
-               REQUIRE(MORE(), REG_EPAREN);
+               (void)REQUIRE(MORE(), REG_EPAREN);
                p->g->nsub++;
                subno = p->g->nsub;
                if (subno < NPAREN)
@@ -263,7 +385,7 @@ register struct parse *p;
                        assert(p->pend[subno] != 0);
                }
                EMIT(ORPAREN, subno);
-               MUSTEAT(')', REG_EPAREN);
+               (void)MUSTEAT(')', REG_EPAREN);
                break;
 #ifndef POSIX_MISTAKE
        case ')':               /* happens only if no current unmatched ( */
@@ -306,15 +428,33 @@ register struct parse *p;
                p_bracket(p);
                break;
        case '\\':
-               REQUIRE(MORE(), REG_EESCAPE);
-               c = GETNEXT();
-               ordinary(p, c);
+               (void)REQUIRE(MORE(), REG_EESCAPE);
+               wc = WGETNEXT();
+#ifdef __CYGWIN__
+               /* \< and \> are the GNU equivalents to [[:<:]] and [[:>:]] */
+               switch (wc)
+                 {
+                 case L'<':
+                   EMIT(OBOW, 0);
+                   break;
+                 case L'>':
+                   EMIT(OEOW, 0);
+                   break;
+                 default:
+                   ordinary(p, wc);
+                   break;
+                 }
+#else
+               ordinary(p, wc);
+#endif
                break;
        case '{':               /* okay as ordinary except if digit follows */
-               REQUIRE(!MORE() || !isdigit((unsigned char)PEEK()), REG_BADRPT);
+               (void)REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT);
                /* FALLTHROUGH */
        default:
-               ordinary(p, c);
+               p->next--;
+               wc = WGETNEXT();
+               ordinary(p, wc);
                break;
        }
 
@@ -323,11 +463,11 @@ register struct parse *p;
        c = PEEK();
        /* we call { a repetition if followed by a digit */
        if (!( c == '*' || c == '+' || c == '?' ||
-                               (c == '{' && MORE2() && isdigit((unsigned char)PEEK2())) ))
+                               (c == '{' && MORE2() && isdigit((uch)PEEK2())) ))
                return;         /* no repetition, we're done */
        NEXT();
 
-       REQUIRE(!wascaret, REG_BADRPT);
+       (void)REQUIRE(!wascaret, REG_BADRPT);
        switch (c) {
        case '*':       /* implemented as +? */
                /* this case does not require the (y|) trick, noKLUDGE */
@@ -352,9 +492,9 @@ register struct parse *p;
        case '{':
                count = p_count(p);
                if (EAT(',')) {
-                       if (isdigit((unsigned char)PEEK())) {
+                       if (isdigit((uch)PEEK())) {
                                count2 = p_count(p);
-                               REQUIRE(count <= count2, REG_BADBR);
+                               (void)REQUIRE(count <= count2, REG_BADBR);
                        } else          /* single number with comma */
                                count2 = INFINITY;
                } else          /* just a single number */
@@ -363,7 +503,7 @@ register struct parse *p;
                if (!EAT('}')) {        /* error heuristics */
                        while (MORE() && PEEK() != '}')
                                NEXT();
-                       REQUIRE(MORE(), REG_EBRACE);
+                       (void)REQUIRE(MORE(), REG_EBRACE);
                        SETERROR(REG_BADBR);
                }
                break;
@@ -373,45 +513,41 @@ register struct parse *p;
                return;
        c = PEEK();
        if (!( c == '*' || c == '+' || c == '?' ||
-                               (c == '{' && MORE2() && isdigit((unsigned char)PEEK2())) ) )
+                               (c == '{' && MORE2() && isdigit((uch)PEEK2())) ) )
                return;
        SETERROR(REG_BADRPT);
 }
 
 /*
  - p_str - string (no metacharacters) "parser"
- == static void p_str(register struct parse *p);
+ == static void p_str(struct parse *p);
  */
 static void
-p_str(p)
-register struct parse *p;
+p_str(struct parse *p)
 {
-       REQUIRE(MORE(), REG_EMPTY);
+       (void)REQUIRE(MORE(), REG_EMPTY);
        while (MORE())
-               ordinary(p, GETNEXT());
+               ordinary(p, WGETNEXT());
 }
 
 /*
  - p_bre - BRE parser top level, anchoring and concatenation
- == static void p_bre(register struct parse *p, register int end1, \
- ==    register int end2);
+ == static void p_bre(struct parse *p, int end1, \
+ ==    int end2);
  * Giving end1 as OUT essentially eliminates the end1/end2 check.
  *
  * This implementation is a bit of a kludge, in that a trailing $ is first
- * taken as an ordinary character and then revised to be an anchor.  The
- * only undesirable side effect is that '$' gets included as a character
- * category in such cases.  This is fairly harmless; not worth fixing.
+ * taken as an ordinary character and then revised to be an anchor.
  * The amount of lookahead needed to avoid this kludge is excessive.
  */
 static void
-p_bre(p, end1, end2)
-register struct parse *p;
-register int end1;             /* first terminating character */
-register int end2;             /* second terminating character */
+p_bre(struct parse *p,
+       int end1,               /* first terminating character */
+       int end2)               /* second terminating character */
 {
-       register sopno start = HERE();
-       register int first = 1;                 /* first subexpression? */
-       register int wasdollar = 0;
+       sopno start = HERE();
+       int first = 1;                  /* first subexpression? */
+       int wasdollar = 0;
 
        if (EAT('^')) {
                EMIT(OBOL, 0);
@@ -429,24 +565,24 @@ register int end2;                /* second terminating character */
                p->g->neol++;
        }
 
-       REQUIRE(HERE() != start, REG_EMPTY);    /* require nonempty */
+       (void)REQUIRE(HERE() != start, REG_EMPTY);      /* require nonempty */
 }
 
 /*
  - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
- == static int p_simp_re(register struct parse *p, int starordinary);
+ == static int p_simp_re(struct parse *p, int starordinary);
  */
 static int                     /* was the simple RE an unbackslashed $? */
-p_simp_re(p, starordinary)
-register struct parse *p;
-int starordinary;              /* is a leading * an ordinary character? */
+p_simp_re(struct parse *p,
+       int starordinary)       /* is a leading * an ordinary character? */
 {
-       register int c;
-       register int count;
-       register int count2;
-       register sopno pos;
-       register int i;
-       register sopno subno;
+       int c;
+       int count;
+       int count2;
+       sopno pos;
+       int i;
+       wint_t wc;
+       sopno subno;
 #      define  BACKSL  (1<<CHAR_BIT)
 
        pos = HERE();           /* repetion op, if any, covers from here */
@@ -454,8 +590,8 @@ int starordinary;           /* is a leading * an ordinary character? */
        assert(MORE());         /* caller should have ensured this */
        c = GETNEXT();
        if (c == '\\') {
-               REQUIRE(MORE(), REG_EESCAPE);
-               c = BACKSL | (unsigned char)GETNEXT();
+               (void)REQUIRE(MORE(), REG_EESCAPE);
+               c = BACKSL | GETNEXT();
        }
        switch (c) {
        case '.':
@@ -467,6 +603,16 @@ int starordinary;          /* is a leading * an ordinary character? */
        case '[':
                p_bracket(p);
                break;
+#ifdef __CYGWIN__
+       case BACKSL|'<':
+               /* \< is the GNU equivalents to [[:<:]] */
+               EMIT(OBOW, 0);
+               break;
+       case BACKSL|'>':
+               /* \> is the GNU equivalents to [[:>:]] */
+               EMIT(OEOW, 0);
+               break;
+#endif
        case BACKSL|'{':
                SETERROR(REG_BADRPT);
                break;
@@ -484,7 +630,7 @@ int starordinary;           /* is a leading * an ordinary character? */
                        assert(p->pend[subno] != 0);
                }
                EMIT(ORPAREN, subno);
-               REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
+               (void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
                break;
        case BACKSL|')':        /* should not get here -- must be user */
        case BACKSL|'}':
@@ -514,10 +660,12 @@ int starordinary;         /* is a leading * an ordinary character? */
                p->g->backrefs = 1;
                break;
        case '*':
-               REQUIRE(starordinary, REG_BADRPT);
+               (void)REQUIRE(starordinary, REG_BADRPT);
                /* FALLTHROUGH */
        default:
-               ordinary(p, (char)c);   /* takes off BACKSL, if any */
+               p->next--;
+               wc = WGETNEXT();
+               ordinary(p, wc);
                break;
        }
 
@@ -530,9 +678,9 @@ int starordinary;           /* is a leading * an ordinary character? */
        } else if (EATTWO('\\', '{')) {
                count = p_count(p);
                if (EAT(',')) {
-                       if (MORE() && isdigit((unsigned char)PEEK())) {
+                       if (MORE() && isdigit((uch)PEEK())) {
                                count2 = p_count(p);
-                               REQUIRE(count <= count2, REG_BADBR);
+                               (void)REQUIRE(count <= count2, REG_BADBR);
                        } else          /* single number with comma */
                                count2 = INFINITY;
                } else          /* just a single number */
@@ -541,10 +689,10 @@ int starordinary;         /* is a leading * an ordinary character? */
                if (!EATTWO('\\', '}')) {       /* error heuristics */
                        while (MORE() && !SEETWO('\\', '}'))
                                NEXT();
-                       REQUIRE(MORE(), REG_EBRACE);
+                       (void)REQUIRE(MORE(), REG_EBRACE);
                        SETERROR(REG_BADBR);
                }
-       } else if (c == (unsigned char)'$')     /* $ (but not \$) ends it */
+       } else if (c == '$')     /* $ (but not \$) ends it */
                return(1);
 
        return(0);
@@ -552,37 +700,32 @@ int starordinary;         /* is a leading * an ordinary character? */
 
 /*
  - p_count - parse a repetition count
- == static int p_count(register struct parse *p);
+ == static int p_count(struct parse *p);
  */
 static int                     /* the value */
-p_count(p)
-register struct parse *p;
+p_count(struct parse *p)
 {
-       register int count = 0;
-       register int ndigits = 0;
+       int count = 0;
+       int ndigits = 0;
 
-       while (MORE() && isdigit((unsigned char)PEEK()) && count <= DUPMAX) {
+       while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) {
                count = count*10 + (GETNEXT() - '0');
                ndigits++;
        }
 
-       REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
+       (void)REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
        return(count);
 }
 
 /*
  - p_bracket - parse a bracketed character list
- == static void p_bracket(register struct parse *p);
- *
- * Note a significant property of this code:  if the allocset() did SETERROR,
- * no set operations are done.
+ == static void p_bracket(struct parse *p);
  */
 static void
-p_bracket(p)
-register struct parse *p;
+p_bracket(struct parse *p)
 {
-       register cset *cs = allocset(p);
-       register int invert = 0;
+       cset *cs;
+       wint_t ch;
 
        /* Dept of Truly Sickening Special-Case Kludges */
        if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) {
@@ -596,69 +739,57 @@ register struct parse *p;
                return;
        }
 
+       if ((cs = allocset(p)) == NULL)
+               return;
+
+       if (p->g->cflags&REG_ICASE)
+               cs->icase = 1;
        if (EAT('^'))
-               invert++;       /* make note to invert set at end */
+               cs->invert = 1;
        if (EAT(']'))
-               CHadd(cs, ']');
+               CHadd(p, cs, ']');
        else if (EAT('-'))
-               CHadd(cs, '-');
+               CHadd(p, cs, '-');
        while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
                p_b_term(p, cs);
        if (EAT('-'))
-               CHadd(cs, '-');
-       MUSTEAT(']', REG_EBRACK);
+               CHadd(p, cs, '-');
+       (void)MUSTEAT(']', REG_EBRACK);
 
        if (p->error != 0)      /* don't mess things up further */
                return;
 
-       if (p->g->cflags&REG_ICASE) {
-               register int i;
-               register int ci;
-
-               for (i = p->g->csetsize - 1; i >= 0; i--)
-                       if (CHIN(cs, i) && isalpha(i)) {
-                               ci = othercase(i);
-                               if (ci != i)
-                                       CHadd(cs, ci);
-                       }
-               if (cs->multis != NULL)
-                       mccase(p, cs);
-       }
-       if (invert) {
-               register int i;
-
-               for (i = p->g->csetsize - 1; i >= 0; i--)
-                       if (CHIN(cs, i))
-                               CHsub(cs, i);
-                       else
-                               CHadd(cs, i);
-               if (p->g->cflags&REG_NEWLINE)
-                       CHsub(cs, '\n');
-               if (cs->multis != NULL)
-                       mcinvert(p, cs);
-       }
+       if (cs->invert && p->g->cflags&REG_NEWLINE)
+               cs->bmp['\n' >> 3] |= 1 << ('\n' & 7);
 
-       assert(cs->multis == NULL);             /* xxx */
-
-       if (nch(p, cs) == 1) {          /* optimize singleton sets */
-               ordinary(p, firstch(p, cs));
+       if ((ch = singleton(cs)) != OUT) {      /* optimize singleton sets */
+               ordinary(p, ch);
                freeset(p, cs);
        } else
-               EMIT(OANYOF, freezeset(p, cs));
+               EMIT(OANYOF, (int)(cs - p->g->sets));
 }
 
+#ifdef __CYGWIN__
+/* This function is usually part of FreeBSD's libc. */
+int
+__collate_range_cmp(int c1, int c2)
+{
+  char s1[2] = { c1, '\0' };
+  char s2[2] = { c2, '\0' };
+  return strcoll (s1, s2);
+}
+#endif
+
 /*
  - p_b_term - parse one term of a bracketed character list
- == static void p_b_term(register struct parse *p, register cset *cs);
+ == static void p_b_term(struct parse *p, cset *cs);
  */
 static void
-p_b_term(p, cs)
-register struct parse *p;
-register cset *cs;
+p_b_term(struct parse *p, cset *cs)
 {
-       register char c;
-       register char start, finish;
-       register int i;
+       char c;
+       wint_t start, finish;
+       wint_t i;
 
        /* classify what we've got */
        switch ((MORE()) ? PEEK() : '\0') {
@@ -677,24 +808,23 @@ register cset *cs;
        switch (c) {
        case ':':               /* character class */
                NEXT2();
-               REQUIRE(MORE(), REG_EBRACK);
+               (void)REQUIRE(MORE(), REG_EBRACK);
                c = PEEK();
-               REQUIRE(c != '-' && c != ']', REG_ECTYPE);
+               (void)REQUIRE(c != '-' && c != ']', REG_ECTYPE);
                p_b_cclass(p, cs);
-               REQUIRE(MORE(), REG_EBRACK);
-               REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
+               (void)REQUIRE(MORE(), REG_EBRACK);
+               (void)REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
                break;
        case '=':               /* equivalence class */
                NEXT2();
-               REQUIRE(MORE(), REG_EBRACK);
+               (void)REQUIRE(MORE(), REG_EBRACK);
                c = PEEK();
-               REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
+               (void)REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
                p_b_eclass(p, cs);
-               REQUIRE(MORE(), REG_EBRACK);
-               REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
+               (void)REQUIRE(MORE(), REG_EBRACK);
+               (void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
                break;
        default:                /* symbol, ordinary character, or range */
-/* xxx revision needed for multichar stuff */
                start = p_b_symbol(p);
                if (SEE('-') && MORE2() && PEEK2() != ']') {
                        /* range */
@@ -705,97 +835,106 @@ register cset *cs;
                                finish = p_b_symbol(p);
                } else
                        finish = start;
-/* xxx what about signed chars here... */
-               REQUIRE(start <= finish, REG_ERANGE);
-               for (i = start; i <= finish; i++)
-                       CHadd(cs, i);
+               if (start == finish)
+                       CHadd(p, cs, start);
+               else {
+#ifdef __CYGWIN__
+                       if (!collate_lcid) {
+#else
+                       if (__collate_load_error) {
+#endif
+                               (void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE);
+                               CHaddrange(p, cs, start, finish);
+                       } else {
+                               (void)REQUIRE(__collate_range_cmp(start, finish) <= 0, REG_ERANGE);
+                               for (i = 0; i <= UCHAR_MAX; i++) {
+                                       if (   __collate_range_cmp(start, i) <= 0
+                                           && __collate_range_cmp(i, finish) <= 0
+                                          )
+                                               CHadd(p, cs, i);
+                               }
+                       }
+               }
                break;
        }
 }
 
 /*
  - p_b_cclass - parse a character-class name and deal with it
- == static void p_b_cclass(register struct parse *p, register cset *cs);
+ == static void p_b_cclass(struct parse *p, cset *cs);
  */
 static void
-p_b_cclass(p, cs)
-register struct parse *p;
-register cset *cs;
+p_b_cclass(struct parse *p, cset *cs)
 {
-       register char *sp = p->next;
-       register struct cclass *cp;
-       register size_t len;
-       register const char *u;
-       register char c;
+       char *sp = p->next;
+       size_t len;
+       wctype_t wct;
+       char clname[16];
 
-       while (MORE() && isalpha((unsigned char)PEEK()))
+       while (MORE() && isalpha((uch)PEEK()))
                NEXT();
        len = p->next - sp;
-       for (cp = cclasses; cp->name != NULL; cp++)
-               if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
-                       break;
-       if (cp->name == NULL) {
-               /* oops, didn't find it */
+       if (len >= sizeof(clname) - 1) {
                SETERROR(REG_ECTYPE);
                return;
        }
-
-       u = cp->chars;
-       while ((c = *u++) != '\0')
-               CHadd(cs, c);
-       for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)
-               MCadd(p, cs, u);
+       memcpy(clname, sp, len);
+       clname[len] = '\0';
+       if ((wct = wctype(clname)) == 0) {
+               SETERROR(REG_ECTYPE);
+               return;
+       }
+       CHaddtype(p, cs, wct);
 }
 
 /*
  - p_b_eclass - parse an equivalence-class name and deal with it
- == static void p_b_eclass(register struct parse *p, register cset *cs);
+ == static void p_b_eclass(struct parse *p, cset *cs);
  *
  * This implementation is incomplete. xxx
  */
 static void
-p_b_eclass(p, cs)
-register struct parse *p;
-register cset *cs;
+p_b_eclass(struct parse *p, cset *cs)
 {
-       register char c;
+       wint_t c;
 
        c = p_b_coll_elem(p, '=');
-       CHadd(cs, c);
+       CHadd(p, cs, c);
 }
 
 /*
  - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
- == static char p_b_symbol(register struct parse *p);
+ == static char p_b_symbol(struct parse *p);
  */
-static char                    /* value of symbol */
-p_b_symbol(p)
-register struct parse *p;
+static wint_t                  /* value of symbol */
+p_b_symbol(struct parse *p)
 {
-       register char value;
+       wint_t value;
 
-       REQUIRE(MORE(), REG_EBRACK);
+       (void)REQUIRE(MORE(), REG_EBRACK);
        if (!EATTWO('[', '.'))
-               return(GETNEXT());
+               return(WGETNEXT());
 
        /* collating symbol */
        value = p_b_coll_elem(p, '.');
-       REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
+       (void)REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
        return(value);
 }
 
 /*
  - p_b_coll_elem - parse a collating-element name and look it up
- == static char p_b_coll_elem(register struct parse *p, int endc);
+ == static char p_b_coll_elem(struct parse *p, int endc);
  */
-static char                    /* value of collating element */
-p_b_coll_elem(p, endc)
-register struct parse *p;
-int endc;                      /* name ended by endc,']' */
+static wint_t                  /* value of collating element */
+p_b_coll_elem(struct parse *p,
+       wint_t endc)            /* name ended by endc,']' */
 {
-       register char *sp = p->next;
-       register struct cname *cp;
-       register int len;
+       char *sp = p->next;
+       struct cname *cp;
+       int len;
+       mbstate_t mbs;
+       wchar_t wc;
+       size_t clen;
 
        while (MORE() && !SEETWO(endc, ']'))
                NEXT();
@@ -807,9 +946,13 @@ int endc;                  /* name ended by endc,']' */
        for (cp = cnames; cp->name != NULL; cp++)
                if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
                        return(cp->code);       /* known name */
-       if (len == 1)
-               return(*sp);    /* single character */
-       SETERROR(REG_ECOLLATE);                 /* neither */
+       memset(&mbs, 0, sizeof(mbs));
+       if ((clen = mbrtowc(&wc, sp, len, &mbs)) == len)
+               return (wc);                    /* single character */
+       else if (clen == (size_t)-1 || clen == (size_t)-2)
+               SETERROR(REG_ILLSEQ);
+       else
+               SETERROR(REG_ECOLLATE);         /* neither */
        return(0);
 }
 
@@ -817,78 +960,83 @@ int endc;                 /* name ended by endc,']' */
  - othercase - return the case counterpart of an alphabetic
  == static char othercase(int ch);
  */
-static char                    /* if no counterpart, return ch */
-othercase(ch)
-int ch;
+static wint_t                  /* if no counterpart, return ch */
+othercase(wint_t ch)
 {
-       assert(isalpha(ch));
-       if (isupper(ch))
-               return(tolower(ch));
-       else if (islower(ch))
-               return(toupper(ch));
+       assert(iswalpha(ch));
+       if (iswupper(ch))
+               return(towlower(ch));
+       else if (iswlower(ch))
+               return(towupper(ch));
        else                    /* peculiar, but could happen */
                return(ch);
 }
 
 /*
  - bothcases - emit a dualcase version of a two-case character
- == static void bothcases(register struct parse *p, int ch);
+ == static void bothcases(struct parse *p, int ch);
  *
  * Boy, is this implementation ever a kludge...
  */
 static void
-bothcases(p, ch)
-register struct parse *p;
-int ch;
+bothcases(struct parse *p, wint_t ch)
 {
-       register char *oldnext = p->next;
-       register char *oldend = p->end;
-       char bracket[3];
+       char *oldnext = p->next;
+       char *oldend = p->end;
+       char bracket[3 + MB_LEN_MAX];
+       size_t n;
+       mbstate_t mbs;
 
        assert(othercase(ch) != ch);    /* p_bracket() would recurse */
        p->next = bracket;
-       p->end = bracket+2;
-       bracket[0] = ch;
-       bracket[1] = ']';
-       bracket[2] = '\0';
+       memset(&mbs, 0, sizeof(mbs));
+       n = wcrtomb(bracket, ch, &mbs);
+       assert(n != (size_t)-1);
+       bracket[n] = ']';
+       bracket[n + 1] = '\0';
+       p->end = bracket+n+1;
        p_bracket(p);
-       assert(p->next == bracket+2);
+       assert(p->next == p->end);
        p->next = oldnext;
        p->end = oldend;
 }
 
 /*
  - ordinary - emit an ordinary character
- == static void ordinary(register struct parse *p, register int ch);
+ == static void ordinary(struct parse *p, int ch);
  */
 static void
-ordinary(p, ch)
-register struct parse *p;
-register int ch;
+ordinary(struct parse *p, wint_t ch)
 {
-       register cat_t *cap = p->g->categories;
+       cset *cs;
 
-       if ((p->g->cflags&REG_ICASE) && isalpha(ch) && othercase(ch) != ch)
+       if ((p->g->cflags&REG_ICASE) && iswalpha(ch) && othercase(ch) != ch)
                bothcases(p, ch);
+       else if ((ch & OPDMASK) == ch)
+               EMIT(OCHAR, ch);
        else {
-               EMIT(OCHAR, (unsigned char)ch);
-               if (cap[ch] == 0)
-                       cap[ch] = p->g->ncategories++;
+               /*
+                * Kludge: character is too big to fit into an OCHAR operand.
+                * Emit a singleton set.
+                */
+               if ((cs = allocset(p)) == NULL)
+                       return;
+               CHadd(p, cs, ch);
+               EMIT(OANYOF, (int)(cs - p->g->sets));
        }
 }
 
 /*
  - nonnewline - emit REG_NEWLINE version of OANY
- == static void nonnewline(register struct parse *p);
+ == static void nonnewline(struct parse *p);
  *
  * Boy, is this implementation ever a kludge...
  */
 static void
-nonnewline(p)
-register struct parse *p;
+nonnewline(struct parse *p)
 {
-       register char *oldnext = p->next;
-       register char *oldend = p->end;
+       char *oldnext = p->next;
+       char *oldend = p->end;
        char bracket[4];
 
        p->next = bracket;
@@ -905,21 +1053,20 @@ register struct parse *p;
 
 /*
  - repeat - generate code for a bounded repetition, recursively if needed
- == static void repeat(register struct parse *p, sopno start, int from, int to);
+ == static void repeat(struct parse *p, sopno start, int from, int to);
  */
 static void
-repeat(p, start, from, to)
-register struct parse *p;
-sopno start;                   /* operand from here to end of strip */
-int from;                      /* repeated from this number */
-int to;                                /* to this number of times (maybe INFINITY) */
+repeat(struct parse *p,
+       sopno start,            /* operand from here to end of strip */
+       int from,               /* repeated from this number */
+       int to)                 /* to this number of times (maybe INFINITY) */
 {
-       register sopno finish = HERE();
+       sopno finish = HERE();
 #      define  N       2
 #      define  INF     3
 #      define  REP(f, t)       ((f)*8 + (t))
 #      define  MAP(n)  (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
-       register sopno copy;
+       sopno copy;
 
        if (p->error != 0)      /* head off possible runaway recursion */
                return;
@@ -975,14 +1122,36 @@ int to;                          /* to this number of times (maybe INFINITY) */
        }
 }
 
+/*
+ - wgetnext - helper function for WGETNEXT() macro. Gets the next wide
+ - character from the parse struct, signals a REG_ILLSEQ error if the
+ - character can't be converted. Returns the number of bytes consumed.
+ */
+static wint_t
+wgetnext(struct parse *p)
+{
+       mbstate_t mbs;
+       wchar_t wc;
+       size_t n;
+
+       memset(&mbs, 0, sizeof(mbs));
+       n = mbrtowc(&wc, p->next, p->end - p->next, &mbs);
+       if (n == (size_t)-1 || n == (size_t)-2) {
+               SETERROR(REG_ILLSEQ);
+               return (0);
+       }
+       if (n == 0)
+               n = 1;
+       p->next += n;
+       return (wc);
+}
+
 /*
  - seterr - set an error condition
- == static int seterr(register struct parse *p, int e);
+ == static int seterr(struct parse *p, int e);
  */
 static int                     /* useless but makes type checking happy */
-seterr(p, e)
-register struct parse *p;
-int e;
+seterr(struct parse *p, int e)
 {
        if (p->error == 0)      /* keep earliest error condition */
                p->error = e;
@@ -993,295 +1162,150 @@ int e;
 
 /*
  - allocset - allocate a set of characters for []
- == static cset *allocset(register struct parse *p);
+ == static cset *allocset(struct parse *p);
  */
 static cset *
-allocset(p)
-register struct parse *p;
+allocset(struct parse *p)
 {
-       register int no = p->g->ncsets++;
-       register size_t nc;
-       register size_t nbytes;
-       register cset *cs;
-       register size_t css = (size_t)p->g->csetsize;
-       register int i;
-
-       if (no >= p->ncsalloc) {        /* need another column of space */
-               p->ncsalloc += CHAR_BIT;
-               nc = p->ncsalloc;
-               assert(nc % CHAR_BIT == 0);
-               nbytes = nc / CHAR_BIT * css;
-               if (p->g->sets == NULL)
-                       p->g->sets = (cset *)malloc(nc * sizeof(cset));
-               else
-                       p->g->sets = (cset *)realloc((char *)p->g->sets,
-                                                       nc * sizeof(cset));
-               if (p->g->setbits == NULL)
-                       p->g->setbits = (uch *)malloc(nbytes);
-               else {
-                       p->g->setbits = (uch *)realloc((char *)p->g->setbits,
-                                                               nbytes);
-                       /* xxx this isn't right if setbits is now NULL */
-                       for (i = 0; i < no; i++)
-                               p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
-               }
-               if (p->g->sets != NULL && p->g->setbits != NULL)
-                       (void) memset((char *)p->g->setbits + (nbytes - css),
-                                                               0, css);
-               else {
-                       no = 0;
-                       SETERROR(REG_ESPACE);
-                       /* caller's responsibility not to do set ops */
-               }
-       }
+       cset *cs, *ncs;
 
-       assert(p->g->sets != NULL);     /* xxx */
-       cs = &p->g->sets[no];
-       cs->ptr = p->g->setbits + css*((no)/CHAR_BIT);
-       cs->mask = 1 << ((no) % CHAR_BIT);
-       cs->hash = 0;
-       cs->smultis = 0;
-       cs->multis = NULL;
+       ncs = realloc(p->g->sets, (p->g->ncsets + 1) * sizeof(*ncs));
+       if (ncs == NULL) {
+               SETERROR(REG_ESPACE);
+               return (NULL);
+       }
+       p->g->sets = ncs;
+       cs = &p->g->sets[p->g->ncsets++];
+       memset(cs, 0, sizeof(*cs));
 
        return(cs);
 }
 
 /*
  - freeset - free a now-unused set
- == static void freeset(register struct parse *p, register cset *cs);
+ == static void freeset(struct parse *p, cset *cs);
  */
 static void
-freeset(p, cs)
-register struct parse *p;
-register cset *cs;
+freeset(struct parse *p, cset *cs)
 {
-       register size_t i;
-       register cset *top = &p->g->sets[p->g->ncsets];
-       register size_t css = (size_t)p->g->csetsize;
+       cset *top = &p->g->sets[p->g->ncsets];
 
-       for (i = 0; i < css; i++)
-               CHsub(cs, i);
+       free(cs->wides);
+       free(cs->ranges);
+       free(cs->types);
+       memset(cs, 0, sizeof(*cs));
        if (cs == top-1)        /* recover only the easy case */
                p->g->ncsets--;
 }
 
 /*
- - freezeset - final processing on a set of characters
- == static int freezeset(register struct parse *p, register cset *cs);
- *
- * The main task here is merging identical sets.  This is usually a waste
- * of time (although the hash code minimizes the overhead), but can win
- * big if REG_ICASE is being used.  REG_ICASE, by the way, is why the hash
- * is done using addition rather than xor -- all ASCII [aA] sets xor to
- * the same value!
- */
-static int                     /* set number */
-freezeset(p, cs)
-register struct parse *p;
-register cset *cs;
-{
-       register uch h = cs->hash;
-       register size_t i;
-       register cset *top = &p->g->sets[p->g->ncsets];
-       register cset *cs2;
-       register size_t css = (size_t)p->g->csetsize;
-
-       /* look for an earlier one which is the same */
-       for (cs2 = &p->g->sets[0]; cs2 < top; cs2++)
-               if (cs2->hash == h && cs2 != cs) {
-                       /* maybe */
-                       for (i = 0; i < css; i++)
-                               if (!!CHIN(cs2, i) != !!CHIN(cs, i))
-                                       break;          /* no */
-                       if (i == css)
-                               break;                  /* yes */
-               }
-
-       if (cs2 < top) {        /* found one */
-               freeset(p, cs);
-               cs = cs2;
-       }
-
-       return((int)(cs - p->g->sets));
-}
-
-/*
- - firstch - return first character in a set (which must have at least one)
- == static int firstch(register struct parse *p, register cset *cs);
- */
-static int                     /* character; there is no "none" value */
-firstch(p, cs)
-register struct parse *p;
-register cset *cs;
-{
-       register size_t i;
-       register size_t css = (size_t)p->g->csetsize;
-
-       for (i = 0; i < css; i++)
-               if (CHIN(cs, i))
-                       return((char)i);
-       assert(never);
-       return(0);              /* arbitrary */
-}
-
-/*
- - nch - number of characters in a set
- == static int nch(register struct parse *p, register cset *cs);
+ - singleton - Determine whether a set contains only one character,
+ - returning it if so, otherwise returning OUT.
  */
-static int
-nch(p, cs)
-register struct parse *p;
-register cset *cs;
+static wint_t
+singleton(cset *cs)
 {
-       register size_t i;
-       register size_t css = (size_t)p->g->csetsize;
-       register int n = 0;
+       wint_t i, s, n;
 
-       for (i = 0; i < css; i++)
-               if (CHIN(cs, i))
+       for (i = n = 0; i < NC; i++)
+               if (CHIN(cs, i)) {
                        n++;
-       return(n);
+                       s = i;
+               }
+       if (n == 1)
+               return (s);
+       if (cs->nwides == 1 && cs->nranges == 0 && cs->ntypes == 0 &&
+           cs->icase == 0)
+               return (cs->wides[0]);
+       /* Don't bother handling the other cases. */
+       return (OUT);
 }
 
 /*
- - mcadd - add a collating element to a cset
- == static void mcadd(register struct parse *p, register cset *cs, \
- ==    register char *cp);
+ - CHadd - add character to character set.
  */
 static void
-mcadd(p, cs, cp)
-register struct parse *p;
-register cset *cs;
-register const char *cp;
+CHadd(struct parse *p, cset *cs, wint_t ch)
 {
-       register size_t oldend = cs->smultis;
-
-       cs->smultis += strlen(cp) + 1;
-       if (cs->multis == NULL)
-               cs->multis = malloc(cs->smultis);
-       else
-               cs->multis = realloc(cs->multis, cs->smultis);
-       if (cs->multis == NULL) {
-               SETERROR(REG_ESPACE);
-               return;
+       wint_t nch, *newwides;
+       assert(ch >= 0);
+       if (ch < NC)
+               cs->bmp[ch >> 3] |= 1 << (ch & 7);
+       else {
+               newwides = realloc(cs->wides, (cs->nwides + 1) *
+                   sizeof(*cs->wides));
+               if (newwides == NULL) {
+                       SETERROR(REG_ESPACE);
+                       return;
+               }
+               cs->wides = newwides;
+               cs->wides[cs->nwides++] = ch;
+       }
+       if (cs->icase) {
+               if ((nch = towlower(ch)) < NC)
+                       cs->bmp[nch >> 3] |= 1 << (nch & 7);
+               if ((nch = towupper(ch)) < NC)
+                       cs->bmp[nch >> 3] |= 1 << (nch & 7);
        }
-
-       (void) strcpy(cs->multis + oldend - 1, cp);
-       cs->multis[cs->smultis - 1] = '\0';
-}
-
-/*
- - mcinvert - invert the list of collating elements in a cset
- == static void mcinvert(register struct parse *p, register cset *cs);
- *
- * This would have to know the set of possibilities.  Implementation
- * is deferred.
- */
-static void
-mcinvert(p, cs)
-register struct parse *p;
-register cset *cs;
-{
-       assert(cs->multis == NULL);     /* xxx */
 }
 
 /*
- - mccase - add case counterparts of the list of collating elements in a cset
- == static void mccase(register struct parse *p, register cset *cs);
- *
- * This would have to know the set of possibilities.  Implementation
- * is deferred.
+ - CHaddrange - add all characters in the range [min,max] to a character set.
  */
 static void
-mccase(p, cs)
-register struct parse *p;
-register cset *cs;
-{
-       assert(cs->multis == NULL);     /* xxx */
-}
-
-/*
- - isinsets - is this character in any sets?
- == static int isinsets(register struct re_guts *g, int c);
- */
-static int                     /* predicate */
-isinsets(g, c)
-register struct re_guts *g;
-int c;
+CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max)
 {
-       register uch *col;
-       register int i;
-       register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
-       register unsigned uc = (unsigned char)c;
-
-       for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
-               if (col[uc] != 0)
-                       return(1);
-       return(0);
-}
+       crange *newranges;
 
-/*
- - samesets - are these two characters in exactly the same sets?
- == static int samesets(register struct re_guts *g, int c1, int c2);
- */
-static int                     /* predicate */
-samesets(g, c1, c2)
-register struct re_guts *g;
-int c1;
-int c2;
-{
-       register uch *col;
-       register int i;
-       register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
-       register unsigned uc1 = (unsigned char)c1;
-       register unsigned uc2 = (unsigned char)c2;
-
-       for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
-               if (col[uc1] != col[uc2])
-                       return(0);
-       return(1);
+       for (; min < NC && min <= max; min++)
+               CHadd(p, cs, min);
+       if (min >= max)
+               return;
+       newranges = realloc(cs->ranges, (cs->nranges + 1) *
+           sizeof(*cs->ranges));
+       if (newranges == NULL) {
+               SETERROR(REG_ESPACE);
+               return;
+       }
+       cs->ranges = newranges;
+       cs->ranges[cs->nranges].min = min;
+       cs->ranges[cs->nranges].min = max;
+       cs->nranges++;
 }
 
 /*
- - categorize - sort out character categories
- == static void categorize(struct parse *p, register struct re_guts *g);
+ - CHaddtype - add all characters of a certain type to a character set.
  */
 static void
-categorize(p, g)
-struct parse *p;
-register struct re_guts *g;
+CHaddtype(struct parse *p, cset *cs, wctype_t wct)
 {
-       register cat_t *cats = g->categories;
-       register int c;
-       register int c2;
-       register cat_t cat;
-
-       /* avoid making error situations worse */
-       if (p->error != 0)
+       wint_t i;
+       wctype_t *newtypes;
+
+       for (i = 0; i < NC; i++)
+               if (iswctype(i, wct))
+                       CHadd(p, cs, i);
+       newtypes = realloc(cs->types, (cs->ntypes + 1) *
+           sizeof(*cs->types));
+       if (newtypes == NULL) {
+               SETERROR(REG_ESPACE);
                return;
-
-       for (c = CHAR_MIN; c <= CHAR_MAX; c++)
-               if (cats[c] == 0 && isinsets(g, c)) {
-                       cat = g->ncategories++;
-                       cats[c] = cat;
-                       for (c2 = c+1; c2 <= CHAR_MAX; c2++)
-                               if (cats[c2] == 0 && samesets(g, c, c2))
-                                       cats[c2] = cat;
-               }
+       }
+       cs->types = newtypes;
+       cs->types[cs->ntypes++] = wct;
 }
 
 /*
  - dupl - emit a duplicate of a bunch of sops
- == static sopno dupl(register struct parse *p, sopno start, sopno finish);
+ == static sopno dupl(struct parse *p, sopno start, sopno finish);
  */
 static sopno                   /* start of duplicate */
-dupl(p, start, finish)
-register struct parse *p;
-sopno start;                   /* from here */
-sopno finish;                  /* to this less one */
+dupl(struct parse *p,
+       sopno start,            /* from here */
+       sopno finish)           /* to this less one */
 {
-       register sopno ret = HERE();
-       register sopno len = finish - start;
+       sopno ret = HERE();
+       sopno len = finish - start;
 
        assert(finish >= start);
        if (len == 0)
@@ -1296,17 +1320,14 @@ sopno finish;                   /* to this less one */
 
 /*
  - doemit - emit a strip operator
- == static void doemit(register struct parse *p, sop op, size_t opnd);
+ == static void doemit(struct parse *p, sop op, size_t opnd);
  *
  * It might seem better to implement this as a macro with a function as
  * hard-case backup, but it's just too big and messy unless there are
  * some changes to the data structures.  Maybe later.
  */
 static void
-doemit(p, op, opnd)
-register struct parse *p;
-sop op;
-size_t opnd;
+doemit(struct parse *p, sop op, size_t opnd)
 {
        /* avoid making error situations worse */
        if (p->error != 0)
@@ -1326,18 +1347,14 @@ size_t opnd;
 
 /*
  - doinsert - insert a sop into the strip
- == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
+ == static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
  */
 static void
-doinsert(p, op, opnd, pos)
-register struct parse *p;
-sop op;
-size_t opnd;
-sopno pos;
+doinsert(struct parse *p, sop op, size_t opnd, sopno pos)
 {
-       register sopno sn;
-       register sop s;
-       register int i;
+       sopno sn;
+       sop s;
+       int i;
 
        /* avoid making error situations worse */
        if (p->error != 0)
@@ -1366,13 +1383,10 @@ sopno pos;
 
 /*
  - dofwd - complete a forward reference
- == static void dofwd(register struct parse *p, sopno pos, sop value);
+ == static void dofwd(struct parse *p, sopno pos, sop value);
  */
 static void
-dofwd(p, pos, value)
-register struct parse *p;
-register sopno pos;
-sop value;
+dofwd(struct parse *p, sopno pos, sop value)
 {
        /* avoid making error situations worse */
        if (p->error != 0)
@@ -1384,14 +1398,12 @@ sop value;
 
 /*
  - enlarge - enlarge the strip
- == static void enlarge(register struct parse *p, sopno size);
+ == static void enlarge(struct parse *p, sopno size);
  */
 static void
-enlarge(p, size)
-register struct parse *p;
-register sopno size;
+enlarge(struct parse *p, sopno size)
 {
-       register sop *sp;
+       sop *sp;
 
        if (p->ssize >= size)
                return;
@@ -1407,12 +1419,10 @@ register sopno size;
 
 /*
  - stripsnug - compact the strip
- == static void stripsnug(register struct parse *p, register struct re_guts *g);
+ == static void stripsnug(struct parse *p, struct re_guts *g);
  */
 static void
-stripsnug(p, g)
-register struct parse *p;
-register struct re_guts *g;
+stripsnug(struct parse *p, struct re_guts *g)
 {
        g->nstates = p->slen;
        g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
@@ -1424,7 +1434,7 @@ register struct re_guts *g;
 
 /*
  - findmust - fill in must and mlen with longest mandatory literal string
- == static void findmust(register struct parse *p, register struct re_guts *g);
+ == static void findmust(struct parse *p, struct re_guts *g);
  *
  * This algorithm could do fancy things like analyzing the operands of |
  * for common subsequences.  Someday.  This code is simple and finds most
@@ -1433,32 +1443,53 @@ register struct re_guts *g;
  * Note that must and mlen got initialized during setup.
  */
 static void
-findmust(p, g)
-struct parse *p;
-register struct re_guts *g;
+findmust(struct parse *p, struct re_guts *g)
 {
-       register sop *scan;
-       sop *start = NULL;
-       register sop *newstart = NULL;
-       register sopno newlen;
-       register sop s;
-       register char *cp;
-       register sopno i;
+       sop *scan;
+       sop *start;
+       sop *newstart;
+       sopno newlen;
+       sop s;
+       char *cp;
+       int offset;
+       char buf[MB_LEN_MAX];
+       size_t clen;
+       mbstate_t mbs;
 
        /* avoid making error situations worse */
        if (p->error != 0)
                return;
 
+       /*
+        * It's not generally safe to do a ``char'' substring search on
+        * multibyte character strings, but it's safe for at least
+        * UTF-8 (see RFC 3629).
+        */
+       if (MB_CUR_MAX > 1 &&
+#ifdef __CYGWIN__
+           strcmp(collate_charset, "UTF-8") != 0)
+#else
+           strcmp(_CurrentRuneLocale->__encoding, "UTF-8") != 0)
+#endif
+               return;
+
        /* find the longest OCHAR sequence in strip */
        newlen = 0;
+       offset = 0;
+       g->moffset = 0;
        scan = g->strip + 1;
        do {
                s = *scan++;
                switch (OP(s)) {
                case OCHAR:             /* sequence member */
-                       if (newlen == 0)                /* new sequence */
+                       if (newlen == 0) {              /* new sequence */
+                               memset(&mbs, 0, sizeof(mbs));
                                newstart = scan - 1;
-                       newlen++;
+                       }
+                       clen = wcrtomb(buf, OPND(s), &mbs);
+                       if (clen == (size_t)-1)
+                               goto toohard;
+                       newlen += clen;
                        break;
                case OPLUS_:            /* things that don't break one */
                case OLPAREN:
@@ -1466,6 +1497,7 @@ register struct re_guts *g;
                        break;
                case OQUEST_:           /* things that must be skipped */
                case OCH_:
+                       offset = altoffset(scan, offset);
                        scan--;
                        do {
                                scan += OPND(s);
@@ -1477,51 +1509,317 @@ register struct re_guts *g;
                                        return;
                                }
                        } while (OP(s) != O_QUEST && OP(s) != O_CH);
-                       /* fallthrough */
-               default:                /* things that break a sequence */
+                       /* FALLTHROUGH */
+               case OBOW:              /* things that break a sequence */
+               case OEOW:
+               case OBOL:
+               case OEOL:
+               case O_QUEST:
+               case O_CH:
+               case OEND:
+                       if (newlen > g->mlen) {         /* ends one */
+                               start = newstart;
+                               g->mlen = newlen;
+                               if (offset > -1) {
+                                       g->moffset += offset;
+                                       offset = newlen;
+                               } else
+                                       g->moffset = offset;
+                       } else {
+                               if (offset > -1)
+                                       offset += newlen;
+                       }
+                       newlen = 0;
+                       break;
+               case OANY:
                        if (newlen > g->mlen) {         /* ends one */
                                start = newstart;
                                g->mlen = newlen;
+                               if (offset > -1) {
+                                       g->moffset += offset;
+                                       offset = newlen;
+                               } else
+                                       g->moffset = offset;
+                       } else {
+                               if (offset > -1)
+                                       offset += newlen;
                        }
+                       if (offset > -1)
+                               offset++;
+                       newlen = 0;
+                       break;
+               case OANYOF:            /* may or may not invalidate offset */
+                       /* First, everything as OANY */
+                       if (newlen > g->mlen) {         /* ends one */
+                               start = newstart;
+                               g->mlen = newlen;
+                               if (offset > -1) {
+                                       g->moffset += offset;
+                                       offset = newlen;
+                               } else
+                                       g->moffset = offset;
+                       } else {
+                               if (offset > -1)
+                                       offset += newlen;
+                       }
+                       if (offset > -1)
+                               offset++;
+                       newlen = 0;
+                       break;
+               toohard:
+               default:
+                       /* Anything here makes it impossible or too hard
+                        * to calculate the offset -- so we give up;
+                        * save the last known good offset, in case the
+                        * must sequence doesn't occur later.
+                        */
+                       if (newlen > g->mlen) {         /* ends one */
+                               start = newstart;
+                               g->mlen = newlen;
+                               if (offset > -1)
+                                       g->moffset += offset;
+                               else
+                                       g->moffset = offset;
+                       }
+                       offset = -1;
                        newlen = 0;
                        break;
                }
        } while (OP(s) != OEND);
 
-       if (g->mlen == 0)               /* there isn't one */
+       if (g->mlen == 0) {             /* there isn't one */
+               g->moffset = -1;
                return;
+       }
 
        /* turn it into a character string */
        g->must = malloc((size_t)g->mlen + 1);
        if (g->must == NULL) {          /* argh; just forget it */
                g->mlen = 0;
+               g->moffset = -1;
                return;
        }
        cp = g->must;
        scan = start;
-       for (i = g->mlen; i > 0; i--) {
+       memset(&mbs, 0, sizeof(mbs));
+       while (cp < g->must + g->mlen) {
                while (OP(s = *scan++) != OCHAR)
                        continue;
-               assert(cp < g->must + g->mlen);
-               *cp++ = (char)OPND(s);
+               clen = wcrtomb(cp, OPND(s), &mbs);
+               assert(clen != (size_t)-1);
+               cp += clen;
        }
        assert(cp == g->must + g->mlen);
        *cp++ = '\0';           /* just on general principles */
 }
 
+/*
+ - altoffset - choose biggest offset among multiple choices
+ == static int altoffset(sop *scan, int offset);
+ *
+ * Compute, recursively if necessary, the largest offset among multiple
+ * re paths.
+ */
+static int
+altoffset(sop *scan, int offset)
+{
+       int largest;
+       int try;
+       sop s;
+
+       /* If we gave up already on offsets, return */
+       if (offset == -1)
+               return -1;
+
+       largest = 0;
+       try = 0;
+       s = *scan++;
+       while (OP(s) != O_QUEST && OP(s) != O_CH) {
+               switch (OP(s)) {
+               case OOR1:
+                       if (try > largest)
+                               largest = try;
+                       try = 0;
+                       break;
+               case OQUEST_:
+               case OCH_:
+                       try = altoffset(scan, try);
+                       if (try == -1)
+                               return -1;
+                       scan--;
+                       do {
+                               scan += OPND(s);
+                               s = *scan;
+                               if (OP(s) != O_QUEST && OP(s) != O_CH &&
+                                                       OP(s) != OOR2)
+                                       return -1;
+                       } while (OP(s) != O_QUEST && OP(s) != O_CH);
+                       /* We must skip to the next position, or we'll
+                        * leave altoffset() too early.
+                        */
+                       scan++;
+                       break;
+               case OANYOF:
+               case OCHAR:
+               case OANY:
+                       try++;
+               case OBOW:
+               case OEOW:
+               case OLPAREN:
+               case ORPAREN:
+               case OOR2:
+                       break;
+               default:
+                       try = -1;
+                       break;
+               }
+               if (try == -1)
+                       return -1;
+               s = *scan++;
+       }
+
+       if (try > largest)
+               largest = try;
+
+       return largest+offset;
+}
+
+/*
+ - computejumps - compute char jumps for BM scan
+ == static void computejumps(struct parse *p, struct re_guts *g);
+ *
+ * This algorithm assumes g->must exists and is has size greater than
+ * zero. It's based on the algorithm found on Computer Algorithms by
+ * Sara Baase.
+ *
+ * A char jump is the number of characters one needs to jump based on
+ * the value of the character from the text that was mismatched.
+ */
+static void
+computejumps(struct parse *p, struct re_guts *g)
+{
+       int ch;
+       int mindex;
+
+       /* Avoid making errors worse */
+       if (p->error != 0)
+               return;
+
+       g->charjump = (int*) malloc((NC + 1) * sizeof(int));
+       if (g->charjump == NULL)        /* Not a fatal error */
+               return;
+       /* Adjust for signed chars, if necessary */
+       g->charjump = &g->charjump[-(CHAR_MIN)];
+
+       /* If the character does not exist in the pattern, the jump
+        * is equal to the number of characters in the pattern.
+        */
+       for (ch = CHAR_MIN; ch < (CHAR_MAX + 1); ch++)
+               g->charjump[ch] = g->mlen;
+
+       /* If the character does exist, compute the jump that would
+        * take us to the last character in the pattern equal to it
+        * (notice that we match right to left, so that last character
+        * is the first one that would be matched).
+        */
+       for (mindex = 0; mindex < g->mlen; mindex++)
+               g->charjump[(int)g->must[mindex]] = g->mlen - mindex - 1;
+}
+
+/*
+ - computematchjumps - compute match jumps for BM scan
+ == static void computematchjumps(struct parse *p, struct re_guts *g);
+ *
+ * This algorithm assumes g->must exists and is has size greater than
+ * zero. It's based on the algorithm found on Computer Algorithms by
+ * Sara Baase.
+ *
+ * A match jump is the number of characters one needs to advance based
+ * on the already-matched suffix.
+ * Notice that all values here are minus (g->mlen-1), because of the way
+ * the search algorithm works.
+ */
+static void
+computematchjumps(struct parse *p, struct re_guts *g)
+{
+       int mindex;             /* General "must" iterator */
+       int suffix;             /* Keeps track of matching suffix */
+       int ssuffix;            /* Keeps track of suffixes' suffix */
+       int* pmatches;          /* pmatches[k] points to the next i
+                                * such that i+1...mlen is a substring
+                                * of k+1...k+mlen-i-1
+                                */
+
+       /* Avoid making errors worse */
+       if (p->error != 0)
+               return;
+
+       pmatches = (int*) malloc(g->mlen * sizeof(unsigned int));
+       if (pmatches == NULL) {
+               g->matchjump = NULL;
+               return;
+       }
+
+       g->matchjump = (int*) malloc(g->mlen * sizeof(unsigned int));
+       if (g->matchjump == NULL)       /* Not a fatal error */
+               return;
+
+       /* Set maximum possible jump for each character in the pattern */
+       for (mindex = 0; mindex < g->mlen; mindex++)
+               g->matchjump[mindex] = 2*g->mlen - mindex - 1;
+
+       /* Compute pmatches[] */
+       for (mindex = g->mlen - 1, suffix = g->mlen; mindex >= 0;
+           mindex--, suffix--) {
+               pmatches[mindex] = suffix;
+
+               /* If a mismatch is found, interrupting the substring,
+                * compute the matchjump for that position. If no
+                * mismatch is found, then a text substring mismatched
+                * against the suffix will also mismatch against the
+                * substring.
+                */
+               while (suffix < g->mlen
+                   && g->must[mindex] != g->must[suffix]) {
+                       g->matchjump[suffix] = MIN(g->matchjump[suffix],
+                           g->mlen - mindex - 1);
+                       suffix = pmatches[suffix];
+               }
+       }
+
+       /* Compute the matchjump up to the last substring found to jump
+        * to the beginning of the largest must pattern prefix matching
+        * it's own suffix.
+        */
+       for (mindex = 0; mindex <= suffix; mindex++)
+               g->matchjump[mindex] = MIN(g->matchjump[mindex],
+                   g->mlen + suffix - mindex);
+
+        ssuffix = pmatches[suffix];
+        while (suffix < g->mlen) {
+                while (suffix <= ssuffix && suffix < g->mlen) {
+                        g->matchjump[suffix] = MIN(g->matchjump[suffix],
+                           g->mlen + ssuffix - suffix);
+                        suffix++;
+                }
+               if (suffix < g->mlen)
+                       ssuffix = pmatches[ssuffix];
+        }
+
+       free(pmatches);
+}
+
 /*
  - pluscount - count + nesting
- == static sopno pluscount(register struct parse *p, register struct re_guts *g);
+ == static sopno pluscount(struct parse *p, struct re_guts *g);
  */
 static sopno                   /* nesting depth */
-pluscount(p, g)
-struct parse *p;
-register struct re_guts *g;
+pluscount(struct parse *p, struct re_guts *g)
 {
-       register sop *scan;
-       register sop s;
-       register sopno plusnest = 0;
-       register sopno maxnest = 0;
+       sop *scan;
+       sop s;
+       sopno plusnest = 0;
+       sopno maxnest = 0;
 
        if (p->error != 0)
                return(0);      /* there may not be an OEND */
diff --git a/winsup/cygwin/regex/regcomp.ih b/winsup/cygwin/regex/regcomp.ih
deleted file mode 100644 (file)
index e16d5ab..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* ========= begin header generated by ./mkh ========= */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* === regcomp.c === */
-static void p_ere(register struct parse *p, int stop);
-static void p_ere_exp(register struct parse *p);
-static void p_str(register struct parse *p);
-static void p_bre(register struct parse *p, register int end1, register int end2);
-static int p_simp_re(register struct parse *p, int starordinary);
-static int p_count(register struct parse *p);
-static void p_bracket(register struct parse *p);
-static void p_b_term(register struct parse *p, register cset *cs);
-static void p_b_cclass(register struct parse *p, register cset *cs);
-static void p_b_eclass(register struct parse *p, register cset *cs);
-static char p_b_symbol(register struct parse *p);
-static char p_b_coll_elem(register struct parse *p, int endc);
-static char othercase(int ch);
-static void bothcases(register struct parse *p, int ch);
-static void ordinary(register struct parse *p, register int ch);
-static void nonnewline(register struct parse *p);
-static void repeat(register struct parse *p, sopno start, int from, int to);
-static int seterr(register struct parse *p, int e);
-static cset *allocset(register struct parse *p);
-static void freeset(register struct parse *p, register cset *cs);
-static int freezeset(register struct parse *p, register cset *cs);
-static int firstch(register struct parse *p, register cset *cs);
-static int nch(register struct parse *p, register cset *cs);
-static void mcadd(register struct parse *p, register cset *cs, register const char *cp);
-static void mcinvert(register struct parse *p, register cset *cs);
-static void mccase(register struct parse *p, register cset *cs);
-static int isinsets(register struct re_guts *g, int c);
-static int samesets(register struct re_guts *g, int c1, int c2);
-static void categorize(struct parse *p, register struct re_guts *g);
-static sopno dupl(register struct parse *p, sopno start, sopno finish);
-static void doemit(register struct parse *p, sop op, size_t opnd);
-static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
-static void dofwd(register struct parse *p, sopno pos, sop value);
-static void enlarge(register struct parse *p, sopno size);
-static void stripsnug(register struct parse *p, register struct re_guts *g);
-static void findmust(register struct parse *p, register struct re_guts *g);
-static sopno pluscount(register struct parse *p, register struct re_guts *g);
-
-#ifdef __cplusplus
-}
-#endif
-/* ========= end header generated by ./mkh ========= */
index 42b045bae9d39dc403aca3fd63a17f539fb93b5b..7e88be5cbcaea045b6715ce8525e26383a2058e8 100644 (file)
@@ -1,17 +1,66 @@
-#include "winsup.h"
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regerror.c  8.4 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/regex/regerror.c,v 1.11 2007/06/11 03:05:54 delphij Exp $");
+
 #include <sys/types.h>
 #include <stdio.h>
 #include <string.h>
-#include <ctype.h>
 #include <limits.h>
 #include <stdlib.h>
-#include "regex.h"
+#include <regex.h>
 
 #include "utils.h"
-#include "regerror.ih"
 
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regerror.c === */
+static char *regatoi(const regex_t *preg, char *localbuf);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
 /*
- = #define     REG_OKAY         0
  = #define     REG_NOMATCH      1
  = #define     REG_BADPAT       2
  = #define     REG_ECOLLATE     3
  = #define     REG_EMPTY       14
  = #define     REG_ASSERT      15
  = #define     REG_INVARG      16
+ = #define     REG_ILLSEQ      17
  = #define     REG_ATOI        255     // convert name to number (!)
  = #define     REG_ITOA        0400    // convert number to name (!)
  */
 static struct rerr {
        int code;
+#ifdef __CYGWIN__ /* Avoid whining compiler */
        const char *name;
        const char *explain;
+#else
+       char *name;
+       char *explain;
+#endif
 } rerrs[] = {
-       {REG_OKAY,      "REG_OKAY",     "no errors detected"},
        {REG_NOMATCH,   "REG_NOMATCH",  "regexec() failed to match"},
        {REG_BADPAT,    "REG_BADPAT",   "invalid regular expression"},
        {REG_ECOLLATE,  "REG_ECOLLATE", "invalid collating element"},
@@ -53,7 +107,8 @@ static struct rerr {
        {REG_EMPTY,     "REG_EMPTY",    "empty (sub)expression"},
        {REG_ASSERT,    "REG_ASSERT",   "\"can't happen\" -- you found a bug"},
        {REG_INVARG,    "REG_INVARG",   "invalid argument to regex routine"},
-       {-1,            "",             "*** unknown regexp error code ***"},
+       {REG_ILLSEQ,    "REG_ILLSEQ",   "illegal byte sequence"},
+       {0,             "",             "*** unknown regexp error code ***"}
 };
 
 /*
@@ -62,27 +117,30 @@ static struct rerr {
  */
 /* ARGSUSED */
 size_t
-regerror(errcode, preg, errbuf, errbuf_size)
-int errcode;
-const regex_t *preg;
-char *errbuf;
-size_t errbuf_size;
+regerror(int errcode,
+        const regex_t * __restrict preg,
+        char * __restrict errbuf,
+        size_t errbuf_size)
 {
-       register struct rerr *r;
-       register size_t len;
-       register int target = errcode &~ REG_ITOA;
-       register const char *s;
+       struct rerr *r;
+       size_t len;
+       int target = errcode &~ REG_ITOA;
+#ifdef __CYGWIN__ /* Avoid whining compiler */
+       const char *s;
+#else
+       char *s;
+#endif
        char convbuf[50];
 
        if (errcode == REG_ATOI)
                s = regatoi(preg, convbuf);
        else {
-               for (r = rerrs; r->code >= 0; r++)
+               for (r = rerrs; r->code != 0; r++)
                        if (r->code == target)
                                break;
 
                if (errcode&REG_ITOA) {
-                       if (r->code >= 0)
+                       if (r->code != 0)
                                (void) strcpy(convbuf, r->name);
                        else
                                sprintf(convbuf, "REG_0x%x", target);
@@ -109,18 +167,23 @@ size_t errbuf_size;
  - regatoi - internal routine to implement REG_ATOI
  == static char *regatoi(const regex_t *preg, char *localbuf);
  */
-static const char *
-regatoi(preg, localbuf)
-const regex_t *preg;
-char *localbuf;
+static char *
+regatoi(const regex_t *preg, char *localbuf)
 {
-       register struct rerr *r;
+       struct rerr *r;
 
-       for (r = rerrs; r->code >= 0; r++)
+       for (r = rerrs; r->code != 0; r++)
                if (strcmp(r->name, preg->re_endp) == 0)
                        break;
-       if (r->code < 0)
+       if (r->code == 0)
+#ifdef __CYGWIN__ /* Avoid whining compiler */
+           {
+               static const char null[] = "0";
+               return null;
+           }
+#else
                return("0");
+#endif
 
        sprintf(localbuf, "%d", r->code);
        return(localbuf);
diff --git a/winsup/cygwin/regex/regerror.ih b/winsup/cygwin/regex/regerror.ih
deleted file mode 100644 (file)
index d428544..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* ========= begin header generated by ./mkh ========= */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* === regerror.c === */
-static const char *regatoi(const regex_t *preg, char *localbuf);
-
-#ifdef __cplusplus
-}
-#endif
-/* ========= end header generated by ./mkh ========= */
index bc747096d65b0db4a034baba2e1f754de8c8d333..f848d66c3a3c52cd3c6ff8298d2e14eb177867bf 100644 (file)
-.TH REGEX 3 "25 Sept 1997"
-.BY "Henry Spencer"
-.de ZR
-.\" one other place knows this name:  the SEE ALSO section
-.IR regex (7) \\$1
-..
-.SH NAME
-regcomp, regexec, regerror, regfree \- regular-expression library
-.SH SYNOPSIS
-.ft B
-.\".na
-#include <sys/types.h>
-.br
-#include <regex.h>
-.HP 10
-int regcomp(regex_t\ *preg, const\ char\ *pattern, int\ cflags);
-.HP
-int\ regexec(const\ regex_t\ *preg, const\ char\ *string,
-size_t\ nmatch, regmatch_t\ pmatch[], int\ eflags);
-.HP
-size_t\ regerror(int\ errcode, const\ regex_t\ *preg,
-char\ *errbuf, size_t\ errbuf_size);
-.HP
-void\ regfree(regex_t\ *preg);
-.\".ad
-.ft
-.SH DESCRIPTION
-These routines implement POSIX 1003.2 regular expressions (``RE''s);
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)regex.3     8.4 (Berkeley) 3/20/94
+.\" $FreeBSD: src/lib/libc/regex/regex.3,v 1.21 2007/01/09 00:28:04 imp Exp $
+.\"
+.Dd August 17, 2005
+.Dt REGEX 3
+.Os
+.Sh NAME
+.Nm regcomp ,
+.Nm regexec ,
+.Nm regerror ,
+.Nm regfree
+.Nd regular-expression library
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In regex.h
+.Ft int
+.Fo regcomp
+.Fa "regex_t * restrict preg" "const char * restrict pattern" "int cflags"
+.Fc
+.Ft int
+.Fo regexec
+.Fa "const regex_t * restrict preg" "const char * restrict string"
+.Fa "size_t nmatch" "regmatch_t pmatch[restrict]" "int eflags"
+.Fc
+.Ft size_t
+.Fo regerror
+.Fa "int errcode" "const regex_t * restrict preg"
+.Fa "char * restrict errbuf" "size_t errbuf_size"
+.Fc
+.Ft void
+.Fn regfree "regex_t *preg"
+.Sh DESCRIPTION
+These routines implement
+.St -p1003.2
+regular expressions
+.Pq Do RE Dc Ns s ;
 see
-.ZR .
-.I Regcomp
+.Xr re_format 7 .
+The
+.Fn regcomp
+function
 compiles an RE written as a string into an internal form,
-.I regexec
+.Fn regexec
 matches that internal form against a string and reports results,
-.I regerror
+.Fn regerror
 transforms error codes from either into human-readable messages,
 and
-.I regfree
+.Fn regfree
 frees any dynamically-allocated storage used by the internal form
 of an RE.
-.PP
+.Pp
 The header
-.I <regex.h>
+.In regex.h
 declares two structure types,
-.I regex_t
+.Ft regex_t
 and
-.IR regmatch_t ,
+.Ft regmatch_t ,
 the former for compiled internal forms and the latter for match reporting.
 It also declares the four functions,
 a type
-.IR regoff_t ,
-and a number of constants with names starting with ``REG_''.
-.PP
-.I Regcomp
+.Ft regoff_t ,
+and a number of constants with names starting with
+.Dq Dv REG_ .
+.Pp
+The
+.Fn regcomp
+function
 compiles the regular expression contained in the
-.I pattern
+.Fa pattern
 string,
 subject to the flags in
-.IR cflags ,
+.Fa cflags ,
 and places the results in the
-.I regex_t
+.Ft regex_t
 structure pointed to by
-.IR preg .
-.I Cflags
+.Fa preg .
+The
+.Fa cflags
+argument
 is the bitwise OR of zero or more of the following flags:
-.IP REG_EXTENDED \w'REG_EXTENDED'u+2n
-Compile modern (``extended'') REs,
-rather than the obsolete (``basic'') REs that
+.Bl -tag -width REG_EXTENDED
+.It Dv REG_EXTENDED
+Compile modern
+.Pq Dq extended
+REs,
+rather than the obsolete
+.Pq Dq basic
+REs that
 are the default.
-.IP REG_BASIC
+.It Dv REG_BASIC
 This is a synonym for 0,
-provided as a counterpart to REG_EXTENDED to improve readability.
-This is an extension,
-compatible with but not specified by POSIX 1003.2,
-and should be used with
-caution in software intended to be portable to other systems.
-.IP REG_NOSPEC
+provided as a counterpart to
+.Dv REG_EXTENDED
+to improve readability.
+.It Dv REG_NOSPEC
 Compile with recognition of all special characters turned off.
 All characters are thus considered ordinary,
-so the ``RE'' is a literal string.
+so the
+.Dq RE
+is a literal string.
 This is an extension,
-compatible with but not specified by POSIX 1003.2,
+compatible with but not specified by
+.St -p1003.2 ,
 and should be used with
 caution in software intended to be portable to other systems.
-REG_EXTENDED and REG_NOSPEC may not be used
+.Dv REG_EXTENDED
+and
+.Dv REG_NOSPEC
+may not be used
 in the same call to
-.IR regcomp .
-.IP REG_ICASE
+.Fn regcomp .
+.It Dv REG_ICASE
 Compile for matching that ignores upper/lower case distinctions.
 See
-.ZR .
-.IP REG_NOSUB
+.Xr re_format 7 .
+.It Dv REG_NOSUB
 Compile for matching that need only report success or failure,
 not what was matched.
-.IP REG_NEWLINE
+.It Dv REG_NEWLINE
 Compile for newline-sensitive matching.
 By default, newline is a completely ordinary character with no special
 meaning in either REs or strings.
 With this flag,
-`[^' bracket expressions and `.' never match newline,
-a `^' anchor matches the null string after any newline in the string
+.Ql [^
+bracket expressions and
+.Ql .\&
+never match newline,
+a
+.Ql ^\&
+anchor matches the null string after any newline in the string
 in addition to its normal function,
-and the `$' anchor matches the null string before any newline in the
+and the
+.Ql $\&
+anchor matches the null string before any newline in the
 string in addition to its normal function.
-.IP REG_PEND
+.It Dv REG_PEND
 The regular expression ends,
 not at the first NUL,
 but just before the character pointed to by the
-.I re_endp
+.Va re_endp
 member of the structure pointed to by
-.IR preg .
+.Fa preg .
 The
-.I re_endp
+.Va re_endp
 member is of type
-.IR const\ char\ * .
+.Ft "const char *" .
 This flag permits inclusion of NULs in the RE;
 they are considered ordinary characters.
 This is an extension,
-compatible with but not specified by POSIX 1003.2,
+compatible with but not specified by
+.St -p1003.2 ,
 and should be used with
 caution in software intended to be portable to other systems.
-.PP
+.El
+.Pp
 When successful,
-.I regcomp
+.Fn regcomp
 returns 0 and fills in the structure pointed to by
-.IR preg .
+.Fa preg .
 One member of that structure
 (other than
-.IR re_endp )
+.Va re_endp )
 is publicized:
-.IR re_nsub ,
+.Va re_nsub ,
 of type
-.IR size_t ,
+.Ft size_t ,
 contains the number of parenthesized subexpressions within the RE
 (except that the value of this member is undefined if the
-REG_NOSUB flag was used).
+.Dv REG_NOSUB
+flag was used).
 If
-.I regcomp
+.Fn regcomp
 fails, it returns a non-zero error code;
-see DIAGNOSTICS.
-.PP
-.I Regexec
+see
+.Sx DIAGNOSTICS .
+.Pp
+The
+.Fn regexec
+function
 matches the compiled RE pointed to by
-.I preg
+.Fa preg
 against the
-.IR string ,
+.Fa string ,
 subject to the flags in
-.IR eflags ,
+.Fa eflags ,
 and reports results using
-.IR nmatch ,
-.IR pmatch ,
+.Fa nmatch ,
+.Fa pmatch ,
 and the returned value.
 The RE must have been compiled by a previous invocation of
-.IR regcomp .
+.Fn regcomp .
 The compiled form is not altered during execution of
-.IR regexec ,
+.Fn regexec ,
 so a single compiled RE can be used simultaneously by multiple threads.
-.PP
+.Pp
 By default,
 the NUL-terminated string pointed to by
-.I string
-is considered to be the text of an entire line,
-with the NUL indicating the end of the line.
-(That is,
-any other end-of-line marker is considered to have been removed
-and replaced by the NUL.)
+.Fa string
+is considered to be the text of an entire line, minus any terminating
+newline.
 The
-.I eflags
+.Fa eflags
 argument is the bitwise OR of zero or more of the following flags:
-.IP REG_NOTBOL \w'REG_STARTEND'u+2n
+.Bl -tag -width REG_STARTEND
+.It Dv REG_NOTBOL
 The first character of
 the string
-is not the beginning of a line, so the `^' anchor should not match before it.
-This does not affect the behavior of newlines under REG_NEWLINE.
-.IP REG_NOTEOL
+is not the beginning of a line, so the
+.Ql ^\&
+anchor should not match before it.
+This does not affect the behavior of newlines under
+.Dv REG_NEWLINE .
+.It Dv REG_NOTEOL
 The NUL terminating
 the string
-does not end a line, so the `$' anchor should not match before it.
-This does not affect the behavior of newlines under REG_NEWLINE.
-.IP REG_STARTEND
+does not end a line, so the
+.Ql $\&
+anchor should not match before it.
+This does not affect the behavior of newlines under
+.Dv REG_NEWLINE .
+.It Dv REG_STARTEND
 The string is considered to start at
-\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_so\fR
+.Fa string
++
+.Fa pmatch Ns [0]. Ns Va rm_so
 and to have a terminating NUL located at
-\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_eo\fR
+.Fa string
++
+.Fa pmatch Ns [0]. Ns Va rm_eo
 (there need not actually be a NUL at that location),
 regardless of the value of
-.IR nmatch .
+.Fa nmatch .
 See below for the definition of
-.IR pmatch
+.Fa pmatch
 and
-.IR nmatch .
+.Fa nmatch .
 This is an extension,
-compatible with but not specified by POSIX 1003.2,
+compatible with but not specified by
+.St -p1003.2 ,
 and should be used with
 caution in software intended to be portable to other systems.
-Note that a non-zero \fIrm_so\fR does not imply REG_NOTBOL;
-REG_STARTEND affects only the location of the string,
+Note that a non-zero
+.Va rm_so
+does not imply
+.Dv REG_NOTBOL ;
+.Dv REG_STARTEND
+affects only the location of the string,
 not how it is matched.
-.PP
+.El
+.Pp
 See
-.ZR
+.Xr re_format 7
 for a discussion of what is matched in situations where an RE or a
 portion thereof could match any of several substrings of
-.IR string .
-.PP
+.Fa string .
+.Pp
 Normally,
-.I regexec
-returns 0 for success and the non-zero code REG_NOMATCH for failure.
+.Fn regexec
+returns 0 for success and the non-zero code
+.Dv REG_NOMATCH
+for failure.
 Other non-zero error codes may be returned in exceptional situations;
-see DIAGNOSTICS.
-.PP
-If REG_NOSUB was specified in the compilation of the RE,
+see
+.Sx DIAGNOSTICS .
+.Pp
+If
+.Dv REG_NOSUB
+was specified in the compilation of the RE,
 or if
-.I nmatch
+.Fa nmatch
 is 0,
-.I regexec
+.Fn regexec
 ignores the
-.I pmatch
-argument (but see below for the case where REG_STARTEND is specified).
+.Fa pmatch
+argument (but see below for the case where
+.Dv REG_STARTEND
+is specified).
 Otherwise,
-.I pmatch
+.Fa pmatch
 points to an array of
-.I nmatch
+.Fa nmatch
 structures of type
-.IR regmatch_t .
+.Ft regmatch_t .
 Such a structure has at least the members
-.I rm_so
+.Va rm_so
 and
-.IR rm_eo ,
+.Va rm_eo ,
 both of type
-.I regoff_t
+.Ft regoff_t
 (a signed arithmetic type at least as large as an
-.I off_t
+.Ft off_t
 and a
-.IR ssize_t ),
+.Ft ssize_t ) ,
 containing respectively the offset of the first character of a substring
 and the offset of the first character after the end of the substring.
 Offsets are measured from the beginning of the
-.I string
+.Fa string
 argument given to
-.IR regexec .
+.Fn regexec .
 An empty substring is denoted by equal offsets,
 both indicating the character following the empty substring.
-.PP
+.Pp
 The 0th member of the
-.I pmatch
+.Fa pmatch
 array is filled in to indicate what substring of
-.I string
+.Fa string
 was matched by the entire RE.
 Remaining members report what substring was matched by parenthesized
 subexpressions within the RE;
 member
-.I i
+.Va i
 reports subexpression
-.IR i ,
+.Va i ,
 with subexpressions counted (starting at 1) by the order of their opening
 parentheses in the RE, left to right.
-Unused entries in the array\(emcorresponding either to subexpressions that
+Unused entries in the array (corresponding either to subexpressions that
 did not participate in the match at all, or to subexpressions that do not
-exist in the RE (that is, \fIi\fR\ > \fIpreg\fR\->\fIre_nsub\fR)\(emhave both
-.I rm_so
+exist in the RE (that is,
+.Va i
+>
+.Fa preg Ns -> Ns Va re_nsub ) )
+have both
+.Va rm_so
 and
-.I rm_eo
-set to \-1.
+.Va rm_eo
+set to -1.
 If a subexpression participated in the match several times,
 the reported substring is the last one it matched.
-(Note, as an example in particular, that when the RE `(b*)+' matches `bbb',
-the parenthesized subexpression matches the three `b's and then
-an infinite number of empty strings following the last `b',
+(Note, as an example in particular, that when the RE
+.Ql "(b*)+"
+matches
+.Ql bbb ,
+the parenthesized subexpression matches each of the three
+.So Li b Sc Ns s
+and then
+an infinite number of empty strings following the last
+.Ql b ,
 so the reported substring is one of the empties.)
-.PP
-If REG_STARTEND is specified,
-.I pmatch
+.Pp
+If
+.Dv REG_STARTEND
+is specified,
+.Fa pmatch
 must point to at least one
-.I regmatch_t
+.Ft regmatch_t
 (even if
-.I nmatch
-is 0 or REG_NOSUB was specified),
-to hold the input offsets for REG_STARTEND.
+.Fa nmatch
+is 0 or
+.Dv REG_NOSUB
+was specified),
+to hold the input offsets for
+.Dv REG_STARTEND .
 Use for output is still entirely controlled by
-.IR nmatch ;
+.Fa nmatch ;
 if
-.I nmatch
-is 0 or REG_NOSUB was specified,
+.Fa nmatch
+is 0 or
+.Dv REG_NOSUB
+was specified,
 the value of
-.IR pmatch [0]
+.Fa pmatch Ns [0]
 will not be changed by a successful
-.IR regexec .
-.PP
-.I Regerror
+.Fn regexec .
+.Pp
+The
+.Fn regerror
+function
 maps a non-zero
-.I errcode
+.Fa errcode
 from either
-.I regcomp
+.Fn regcomp
 or
-.I regexec
+.Fn regexec
 to a human-readable, printable message.
 If
-.I preg
-is non-NULL,
+.Fa preg
+is
+.No non\- Ns Dv NULL ,
 the error code should have arisen from use of
 the
-.I regex_t
+.Ft regex_t
 pointed to by
-.IR preg ,
+.Fa preg ,
 and if the error code came from
-.IR regcomp ,
+.Fn regcomp ,
 it should have been the result from the most recent
-.I regcomp
+.Fn regcomp
 using that
-.IR regex_t .
-.RI ( Regerror
+.Ft regex_t .
+The
+.Fn ( regerror
 may be able to supply a more detailed message using information
 from the
-.IR regex_t .)
-.I Regerror
+.Ft regex_t . )
+The
+.Fn regerror
+function
 places the NUL-terminated message into the buffer pointed to by
-.IR errbuf ,
+.Fa errbuf ,
 limiting the length (including the NUL) to at most
-.I errbuf_size
+.Fa errbuf_size
 bytes.
-If the whole message won't fit,
+If the whole message will not fit,
 as much of it as will fit before the terminating NUL is supplied.
 In any case,
 the returned value is the size of buffer needed to hold the whole
 message (including terminating NUL).
 If
-.I errbuf_size
+.Fa errbuf_size
 is 0,
-.I errbuf
+.Fa errbuf
 is ignored but the return value is still correct.
-.PP
+.Pp
 If the
-.I errcode
+.Fa errcode
 given to
-.I regerror
-is first ORed with REG_ITOA,
-the ``message'' that results is the printable name of the error code,
-e.g. ``REG_NOMATCH'',
+.Fn regerror
+is first ORed with
+.Dv REG_ITOA ,
+the
+.Dq message
+that results is the printable name of the error code,
+e.g.\&
+.Dq Dv REG_NOMATCH ,
 rather than an explanation thereof.
 If
-.I errcode
-is REG_ATOI,
+.Fa errcode
+is
+.Dv REG_ATOI ,
 then
-.I preg
-shall be non-NULL and the
-.I re_endp
+.Fa preg
+shall be
+.No non\- Ns Dv NULL
+and the
+.Va re_endp
 member of the structure it points to
 must point to the printable name of an error code;
 in this case, the result in
-.I errbuf
+.Fa errbuf
 is the decimal digits of
 the numeric value of the error code
 (0 if the name is not recognized).
-REG_ITOA and REG_ATOI are intended primarily as debugging facilities;
+.Dv REG_ITOA
+and
+.Dv REG_ATOI
+are intended primarily as debugging facilities;
 they are extensions,
-compatible with but not specified by POSIX 1003.2,
+compatible with but not specified by
+.St -p1003.2 ,
 and should be used with
 caution in software intended to be portable to other systems.
 Be warned also that they are considered experimental and changes are possible.
-.PP
-.I Regfree
+.Pp
+The
+.Fn regfree
+function
 frees any dynamically-allocated storage associated with the compiled RE
 pointed to by
-.IR preg .
+.Fa preg .
 The remaining
-.I regex_t
+.Ft regex_t
 is no longer a valid compiled RE
 and the effect of supplying it to
-.I regexec
+.Fn regexec
 or
-.I regerror
+.Fn regerror
 is undefined.
-.PP
+.Pp
 None of these functions references global variables except for tables
 of constants;
 all are safe for use from multiple threads if the arguments are safe.
-.SH IMPLEMENTATION CHOICES
-There are a number of decisions that 1003.2 leaves up to the implementor,
-either by explicitly saying ``undefined'' or by virtue of them being
+.Sh IMPLEMENTATION CHOICES
+There are a number of decisions that
+.St -p1003.2
+leaves up to the implementor,
+either by explicitly saying
+.Dq undefined
+or by virtue of them being
 forbidden by the RE grammar.
 This implementation treats them as follows.
-.PP
+.Pp
 See
-.ZR
+.Xr re_format 7
 for a discussion of the definition of case-independent matching.
-.PP
+.Pp
 There is no particular limit on the length of REs,
 except insofar as memory is limited.
 Memory usage is approximately linear in RE size, and largely insensitive
 to RE complexity, except for bounded repetitions.
-See BUGS for one short RE using them
+See
+.Sx BUGS
+for one short RE using them
 that will run almost any system out of memory.
-.PP
+.Pp
 A backslashed character other than one specifically given a magic meaning
-by 1003.2 (such magic meanings occur only in obsolete [``basic''] REs)
+by
+.St -p1003.2
+(such magic meanings occur only in obsolete
+.Bq Dq basic
+REs)
 is taken as an ordinary character.
-.PP
-Any unmatched [ is a REG_EBRACK error.
-.PP
+.Pp
+Any unmatched
+.Ql [\&
+is a
+.Dv REG_EBRACK
+error.
+.Pp
 Equivalence classes cannot begin or end bracket-expression ranges.
 The endpoint of one range cannot begin another.
-.PP
-RE_DUP_MAX, the limit on repetition counts in bounded repetitions, is 255.
-.PP
-A repetition operator (?, *, +, or bounds) cannot follow another
+.Pp
+.Dv RE_DUP_MAX ,
+the limit on repetition counts in bounded repetitions, is 255.
+.Pp
+A repetition operator
+.Ql ( ?\& ,
+.Ql *\& ,
+.Ql +\& ,
+or bounds)
+cannot follow another
 repetition operator.
 A repetition operator cannot begin an expression or subexpression
-or follow `^' or `|'.
-.PP
-`|' cannot appear first or last in a (sub)expression or after another `|',
-i.e. an operand of `|' cannot be an empty subexpression.
-An empty parenthesized subexpression, `()', is legal and matches an
+or follow
+.Ql ^\&
+or
+.Ql |\& .
+.Pp
+.Ql |\&
+cannot appear first or last in a (sub)expression or after another
+.Ql |\& ,
+i.e., an operand of
+.Ql |\&
+cannot be an empty subexpression.
+An empty parenthesized subexpression,
+.Ql "()" ,
+is legal and matches an
 empty (sub)string.
 An empty string is not a legal RE.
-.PP
-A `{' followed by a digit is considered the beginning of bounds for a
+.Pp
+A
+.Ql {\&
+followed by a digit is considered the beginning of bounds for a
 bounded repetition, which must then follow the syntax for bounds.
-A `{' \fInot\fR followed by a digit is considered an ordinary character.
-.PP
-`^' and `$' beginning and ending subexpressions in obsolete (``basic'')
-REs are anchors, not ordinary characters.
-.SH SEE ALSO
-grep(1), regex(7)
-.PP
-POSIX 1003.2, sections 2.8 (Regular Expression Notation)
+A
+.Ql {\&
+.Em not
+followed by a digit is considered an ordinary character.
+.Pp
+.Ql ^\&
 and
-B.5 (C Binding for Regular Expression Matching).
-.SH DIAGNOSTICS
+.Ql $\&
+beginning and ending subexpressions in obsolete
+.Pq Dq basic
+REs are anchors, not ordinary characters.
+.Sh DIAGNOSTICS
 Non-zero error codes from
-.I regcomp
+.Fn regcomp
 and
-.I regexec
+.Fn regexec
 include the following:
-.PP
-.nf
-.ta \w'REG_ECOLLATE'u+3n
-REG_NOMATCH    regexec() failed to match
-REG_BADPAT     invalid regular expression
-REG_ECOLLATE   invalid collating element
-REG_ECTYPE     invalid character class
-REG_EESCAPE    \e applied to unescapable character
-REG_ESUBREG    invalid backreference number
-REG_EBRACK     brackets [ ] not balanced
-REG_EPAREN     parentheses ( ) not balanced
-REG_EBRACE     braces { } not balanced
-REG_BADBR      invalid repetition count(s) in { }
-REG_ERANGE     invalid character range in [ ]
-REG_ESPACE     ran out of memory
-REG_BADRPT     ?, *, or + operand invalid
-REG_EMPTY      empty (sub)expression
-REG_ASSERT     ``can't happen''\(emyou found a bug
-REG_INVARG     invalid argument, e.g. negative-length string
-.fi
-.SH HISTORY
-Written by Henry Spencer,
-henry@zoo.toronto.edu.
-.SH BUGS
+.Pp
+.Bl -tag -width REG_ECOLLATE -compact
+.It Dv REG_NOMATCH
+The
+.Fn regexec
+function
+failed to match
+.It Dv REG_BADPAT
+invalid regular expression
+.It Dv REG_ECOLLATE
+invalid collating element
+.It Dv REG_ECTYPE
+invalid character class
+.It Dv REG_EESCAPE
+.Ql \e
+applied to unescapable character
+.It Dv REG_ESUBREG
+invalid backreference number
+.It Dv REG_EBRACK
+brackets
+.Ql "[ ]"
+not balanced
+.It Dv REG_EPAREN
+parentheses
+.Ql "( )"
+not balanced
+.It Dv REG_EBRACE
+braces
+.Ql "{ }"
+not balanced
+.It Dv REG_BADBR
+invalid repetition count(s) in
+.Ql "{ }"
+.It Dv REG_ERANGE
+invalid character range in
+.Ql "[ ]"
+.It Dv REG_ESPACE
+ran out of memory
+.It Dv REG_BADRPT
+.Ql ?\& ,
+.Ql *\& ,
+or
+.Ql +\&
+operand invalid
+.It Dv REG_EMPTY
+empty (sub)expression
+.It Dv REG_ASSERT
+cannot happen - you found a bug
+.It Dv REG_INVARG
+invalid argument, e.g.\& negative-length string
+.It Dv REG_ILLSEQ
+illegal byte sequence (bad multibyte character)
+.El
+.Sh SEE ALSO
+.Xr grep 1 ,
+.Xr re_format 7
+.Pp
+.St -p1003.2 ,
+sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
+.Sh HISTORY
+Originally written by
+.An Henry Spencer .
+Altered for inclusion in the
+.Bx 4.4
+distribution.
+.Sh BUGS
 This is an alpha release with known defects.
 Please report problems.
-.PP
-There is one known functionality bug.
-The implementation of internationalization is incomplete:
-the locale is always assumed to be the default one of 1003.2,
-and only the collating elements etc. of that locale are available.
-.PP
+.Pp
 The back-reference code is subtle and doubts linger about its correctness
 in complex cases.
-.PP
-.I Regexec
+.Pp
+The
+.Fn regexec
+function
 performance is poor.
 This will improve with later releases.
-.I Nmatch
+The
+.Fa nmatch
+argument
 exceeding 0 is expensive;
-.I nmatch
+.Fa nmatch
 exceeding 1 is worse.
-.I Regexec
-is largely insensitive to RE complexity \fIexcept\fR that back
+The
+.Fn regexec
+function
+is largely insensitive to RE complexity
+.Em except
+that back
 references are massively expensive.
 RE length does matter; in particular, there is a strong speed bonus
 for keeping RE length under about 30 characters,
 with most special characters counting roughly double.
-.PP
-.I Regcomp
+.Pp
+The
+.Fn regcomp
+function
 implements bounded repetitions by macro expansion,
 which is costly in time and space if counts are large
 or bounded repetitions are nested.
 An RE like, say,
-`((((a{1,100}){1,100}){1,100}){1,100}){1,100}'
+.Ql "((((a{1,100}){1,100}){1,100}){1,100}){1,100}"
 will (eventually) run almost any existing machine out of swap space.
-.PP
+.Pp
 There are suspected problems with response to obscure error conditions.
 Notably,
 certain kinds of internal overflow,
 produced only by truly enormous REs or by multiply nested bounded repetitions,
 are probably not handled well.
-.PP
-Due to a mistake in 1003.2, things like `a)b' are legal REs because `)' is
-a special character only in the presence of a previous unmatched `('.
-This can't be fixed until the spec is fixed.
-.PP
+.Pp
+Due to a mistake in
+.St -p1003.2 ,
+things like
+.Ql "a)b"
+are legal REs because
+.Ql )\&
+is
+a special character only in the presence of a previous unmatched
+.Ql (\& .
+This cannot be fixed until the spec is fixed.
+.Pp
 The standard's definition of back references is vague.
 For example, does
-`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?
+.Ql "a\e(\e(b\e)*\e2\e)*d"
+match
+.Ql "abbbd" ?
 Until the standard is clarified,
 behavior in such cases should not be relied on.
-.PP
+.Pp
 The implementation of word-boundary matching is a bit of a kludge,
 and bugs may lurk in combinations of word-boundary matching and anchoring.
+.Pp
+Word-boundary matching does not work properly in multibyte locales.
index dc53e8c47f685a72f3ed8fd5b965189744e03942..79fecc19751976ee823204be764faa63a582e1b4 100644 (file)
-.TH REGEX 7 "25 Oct 1995"
-.BY "Henry Spencer"
-.SH NAME
-regex \- POSIX 1003.2 regular expressions
-.SH DESCRIPTION
-Regular expressions (``RE''s),
-as defined in POSIX 1003.2, come in two forms:
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)re_format.7 8.3 (Berkeley) 3/20/94
+.\" $FreeBSD: src/lib/libc/regex/re_format.7,v 1.12 2008/09/05 17:41:20 keramida Exp $
+.\"
+.Dd March 20, 1994
+.Dt RE_FORMAT 7
+.Os
+.Sh NAME
+.Nm re_format
+.Nd POSIX 1003.2 regular expressions
+.Sh DESCRIPTION
+Regular expressions
+.Pq Dq RE Ns s ,
+as defined in
+.St -p1003.2 ,
+come in two forms:
 modern REs (roughly those of
-.IR egrep ;
-1003.2 calls these ``extended'' REs)
+.Xr egrep 1 ;
+1003.2 calls these
+.Dq extended
+REs)
 and obsolete REs (roughly those of
-.IR ed ;
-1003.2 ``basic'' REs).
+.Xr ed 1 ;
+1003.2
+.Dq basic
+REs).
 Obsolete REs mostly exist for backward compatibility in some old programs;
 they will be discussed at the end.
-1003.2 leaves some aspects of RE syntax and semantics open;
-`\(dg' marks decisions on these aspects that
-may not be fully portable to other 1003.2 implementations.
-.PP
-A (modern) RE is one\(dg or more non-empty\(dg \fIbranches\fR,
-separated by `|'.
+.St -p1003.2
+leaves some aspects of RE syntax and semantics open;
+`\(dd' marks decisions on these aspects that
+may not be fully portable to other
+.St -p1003.2
+implementations.
+.Pp
+A (modern) RE is one\(dd or more non-empty\(dd
+.Em branches ,
+separated by
+.Ql \&| .
 It matches anything that matches one of the branches.
-.PP
-A branch is one\(dg or more \fIpieces\fR, concatenated.
+.Pp
+A branch is one\(dd or more
+.Em pieces ,
+concatenated.
 It matches a match for the first, followed by a match for the second, etc.
-.PP
-A piece is an \fIatom\fR possibly followed
-by a single\(dg `*', `+', `?', or \fIbound\fR.
-An atom followed by `*' matches a sequence of 0 or more matches of the atom.
-An atom followed by `+' matches a sequence of 1 or more matches of the atom.
-An atom followed by `?' matches a sequence of 0 or 1 matches of the atom.
-.PP
-A \fIbound\fR is `{' followed by an unsigned decimal integer,
-possibly followed by `,'
+.Pp
+A piece is an
+.Em atom
+possibly followed
+by a single\(dd
+.Ql \&* ,
+.Ql \&+ ,
+.Ql \&? ,
+or
+.Em bound .
+An atom followed by
+.Ql \&*
+matches a sequence of 0 or more matches of the atom.
+An atom followed by
+.Ql \&+
+matches a sequence of 1 or more matches of the atom.
+An atom followed by
+.Ql ?\&
+matches a sequence of 0 or 1 matches of the atom.
+.Pp
+A
+.Em bound
+is
+.Ql \&{
+followed by an unsigned decimal integer,
+possibly followed by
+.Ql \&,
 possibly followed by another unsigned decimal integer,
-always followed by `}'.
-The integers must lie between 0 and RE_DUP_MAX (255\(dg) inclusive,
+always followed by
+.Ql \&} .
+The integers must lie between 0 and
+.Dv RE_DUP_MAX
+(255\(dd) inclusive,
 and if there are two of them, the first may not exceed the second.
-An atom followed by a bound containing one integer \fIi\fR
+An atom followed by a bound containing one integer
+.Em i
 and no comma matches
-a sequence of exactly \fIi\fR matches of the atom.
+a sequence of exactly
+.Em i
+matches of the atom.
 An atom followed by a bound
-containing one integer \fIi\fR and a comma matches
-a sequence of \fIi\fR or more matches of the atom.
+containing one integer
+.Em i
+and a comma matches
+a sequence of
+.Em i
+or more matches of the atom.
 An atom followed by a bound
-containing two integers \fIi\fR and \fIj\fR matches
-a sequence of \fIi\fR through \fIj\fR (inclusive) matches of the atom.
-.PP
-An atom is a regular expression enclosed in `()' (matching a match for the
+containing two integers
+.Em i
+and
+.Em j
+matches
+a sequence of
+.Em i
+through
+.Em j
+(inclusive) matches of the atom.
+.Pp
+An atom is a regular expression enclosed in
+.Ql ()
+(matching a match for the
 regular expression),
-an empty set of `()' (matching the null string)\(dg,
-a \fIbracket expression\fR (see below), `.'
-(matching any single character), `^' (matching the null string at the
-beginning of a line), `$' (matching the null string at the
-end of a line), a `\e' followed by one of the characters
-`^.[$()|*+?{\e'
+an empty set of
+.Ql ()
+(matching the null string)\(dd,
+a
+.Em bracket expression
+(see below),
+.Ql .\&
+(matching any single character),
+.Ql \&^
+(matching the null string at the beginning of a line),
+.Ql \&$
+(matching the null string at the end of a line), a
+.Ql \e
+followed by one of the characters
+.Ql ^.[$()|*+?{\e
 (matching that character taken as an ordinary character),
-a `\e' followed by any other character\(dg
+a
+.Ql \e
+followed by any other character\(dd
 (matching that character taken as an ordinary character,
-as if the `\e' had not been present\(dg),
+as if the
+.Ql \e
+had not been present\(dd),
 or a single character with no other significance (matching that character).
-A `{' followed by a character other than a digit is an ordinary
-character, not the beginning of a bound\(dg.
-It is illegal to end an RE with `\e'.
-.PP
-A \fIbracket expression\fR is a list of characters enclosed in `[]'.
+A
+.Ql \&{
+followed by a character other than a digit is an ordinary
+character, not the beginning of a bound\(dd.
+It is illegal to end an RE with
+.Ql \e .
+.Pp
+A
+.Em bracket expression
+is a list of characters enclosed in
+.Ql [] .
 It normally matches any single character from the list (but see below).
-If the list begins with `^',
+If the list begins with
+.Ql \&^ ,
 it matches any single character
-(but see below) \fInot\fR from the rest of the list.
-If two characters in the list are separated by `\-', this is shorthand
-for the full \fIrange\fR of characters between those two (inclusive) in the
+(but see below)
+.Em not
+from the rest of the list.
+If two characters in the list are separated by
+.Ql \&- ,
+this is shorthand
+for the full
+.Em range
+of characters between those two (inclusive) in the
 collating sequence,
-e.g. `[0\-9]' in ASCII matches any decimal digit.
-It is illegal\(dg for two ranges to share an
-endpoint, e.g. `a\-c\-e'.
+.No e.g. Ql [0-9]
+in ASCII matches any decimal digit.
+It is illegal\(dd for two ranges to share an
+endpoint,
+.No e.g. Ql a-c-e .
 Ranges are very collating-sequence-dependent,
 and portable programs should avoid relying on them.
-.PP
-To include a literal `]' in the list, make it the first character
-(following a possible `^').
-To include a literal `\-', make it the first or last character,
+.Pp
+To include a literal
+.Ql \&]
+in the list, make it the first character
+(following a possible
+.Ql \&^ ) .
+To include a literal
+.Ql \&- ,
+make it the first or last character,
 or the second endpoint of a range.
-To use a literal `\-' as the first endpoint of a range,
-enclose it in `[.' and `.]' to make it a collating element (see below).
-With the exception of these and some combinations using `[' (see next
-paragraphs), all other special characters, including `\e', lose their
-special significance within a bracket expression.
-.PP
+To use a literal
+.Ql \&-
+as the first endpoint of a range,
+enclose it in
+.Ql [.\&
+and
+.Ql .]\&
+to make it a collating element (see below).
+With the exception of these and some combinations using
+.Ql \&[
+(see next paragraphs), all other special characters, including
+.Ql \e ,
+lose their special significance within a bracket expression.
+.Pp
 Within a bracket expression, a collating element (a character,
 a multi-character sequence that collates as if it were a single character,
 or a collating-sequence name for either)
-enclosed in `[.' and `.]' stands for the
+enclosed in
+.Ql [.\&
+and
+.Ql .]\&
+stands for the
 sequence of characters of that collating element.
 The sequence is a single element of the bracket expression's list.
 A bracket expression containing a multi-character collating element
 can thus match more than one character,
-e.g. if the collating sequence includes a `ch' collating element,
-then the RE `[[.ch.]]*c' matches the first five characters
-of `chchcc'.
-.PP
-Within a bracket expression, a collating element enclosed in `[=' and
-`=]' is an equivalence class, standing for the sequences of characters
+e.g.\& if the collating sequence includes a
+.Ql ch
+collating element,
+then the RE
+.Ql [[.ch.]]*c
+matches the first five characters
+of
+.Ql chchcc .
+.Pp
+Within a bracket expression, a collating element enclosed in
+.Ql [=
+and
+.Ql =]
+is an equivalence class, standing for the sequences of characters
 of all collating elements equivalent to that one, including itself.
 (If there are no other equivalent collating elements,
-the treatment is as if the enclosing delimiters were `[.' and `.]'.)
-For example, if o and \o'o^' are the members of an equivalence class,
-then `[[=o=]]', `[[=\o'o^'=]]', and `[o\o'o^']' are all synonymous.
-An equivalence class may not\(dg be an endpoint
+the treatment is as if the enclosing delimiters were
+.Ql [.\&
+and
+.Ql .] . )
+For example, if
+.Ql x
+and
+.Ql y
+are the members of an equivalence class,
+then
+.Ql [[=x=]] ,
+.Ql [[=y=]] ,
+and
+.Ql [xy]
+are all synonymous.
+An equivalence class may not\(dd be an endpoint
 of a range.
-.PP
-Within a bracket expression, the name of a \fIcharacter class\fR enclosed
-in `[:' and `:]' stands for the list of all characters belonging to that
+.Pp
+Within a bracket expression, the name of a
+.Em character class
+enclosed in
+.Ql [:
+and
+.Ql :]
+stands for the list of all characters belonging to that
 class.
 Standard character class names are:
-.PP
-.RS
-.nf
-.ta 3c 6c 9c
-alnum  digit   punct
-alpha  graph   space
-blank  lower   upper
-cntrl  print   xdigit
-.fi
-.RE
-.PP
+.Pp
+.Bl -column "alnum" "digit" "xdigit" -offset indent
+.It Em "alnum  digit   punct"
+.It Em "alpha  graph   space"
+.It Em "blank  lower   upper"
+.It Em "cntrl  print   xdigit"
+.El
+.Pp
 These stand for the character classes defined in
-.IR ctype (3).
+.Xr ctype 3 .
 A locale may provide others.
 A character class may not be used as an endpoint of a range.
-.PP
-There are two special cases\(dg of bracket expressions:
-the bracket expressions `[[:<:]]' and `[[:>:]]' match the null string at
-the beginning and end of a word respectively.
-A word is defined as a sequence of
-word characters
+.Pp
+A bracketed expression like
+.Ql [[:class:]]
+can be used to match a single character that belongs to a character
+class.
+The reverse, matching any character that does not belong to a specific
+class, the negation operator of bracket expressions may be used:
+.Ql [^[:class:]] .
+.Pp
+There are two special cases\(dd of bracket expressions:
+the bracket expressions
+.Ql [[:<:]]
+and
+.Ql [[:>:]]
+match the null string at the beginning and end of a word respectively.
+A word is defined as a sequence of word characters
 which is neither preceded nor followed by
 word characters.
 A word character is an
-.I alnum
+.Em alnum
 character (as defined by
-.IR ctype (3))
+.Xr ctype 3 )
 or an underscore.
 This is an extension,
-compatible with but not specified by POSIX 1003.2,
+compatible with but not specified by
+.St -p1003.2 ,
 and should be used with
 caution in software intended to be portable to other systems.
-.PP
+.Pp
 In the event that an RE could match more than one substring of a given
 string,
 the RE matches the one starting earliest in the string.
@@ -157,79 +323,158 @@ with subexpressions starting earlier in the RE taking priority over
 ones starting later.
 Note that higher-level subexpressions thus take priority over
 their lower-level component subexpressions.
-.PP
+.Pp
 Match lengths are measured in characters, not collating elements.
 A null string is considered longer than no match at all.
 For example,
-`bb*' matches the three middle characters of `abbbc',
-`(wee|week)(knights|nights)' matches all ten characters of `weeknights',
-when `(.*).*' is matched against `abc' the parenthesized subexpression
+.Ql bb*
+matches the three middle characters of
+.Ql abbbc ,
+.Ql (wee|week)(knights|nights)
+matches all ten characters of
+.Ql weeknights ,
+when
+.Ql (.*).*\&
+is matched against
+.Ql abc
+the parenthesized subexpression
 matches all three characters, and
-when `(a*)*' is matched against `bc' both the whole RE and the parenthesized
+when
+.Ql (a*)*
+is matched against
+.Ql bc
+both the whole RE and the parenthesized
 subexpression match the null string.
-.PP
+.Pp
 If case-independent matching is specified,
 the effect is much as if all case distinctions had vanished from the
 alphabet.
 When an alphabetic that exists in multiple cases appears as an
 ordinary character outside a bracket expression, it is effectively
 transformed into a bracket expression containing both cases,
-e.g. `x' becomes `[xX]'.
+.No e.g. Ql x
+becomes
+.Ql [xX] .
 When it appears inside a bracket expression, all case counterparts
-of it are added to the bracket expression, so that (e.g.) `[x]'
-becomes `[xX]' and `[^x]' becomes `[^xX]'.
-.PP
-No particular limit is imposed on the length of REs\(dg.
+of it are added to the bracket expression, so that (e.g.)
+.Ql [x]
+becomes
+.Ql [xX]
+and
+.Ql [^x]
+becomes
+.Ql [^xX] .
+.Pp
+No particular limit is imposed on the length of REs\(dd.
 Programs intended to be portable should not employ REs longer
 than 256 bytes,
 as an implementation can refuse to accept such REs and remain
 POSIX-compliant.
-.PP
-Obsolete (``basic'') regular expressions differ in several respects.
-`|', `+', and `?' are ordinary characters and there is no equivalent
-for their functionality.
-The delimiters for bounds are `\e{' and `\e}',
-with `{' and `}' by themselves ordinary characters.
-The parentheses for nested subexpressions are `\e(' and `\e)',
-with `(' and `)' by themselves ordinary characters.
-`^' is an ordinary character except at the beginning of the
-RE or\(dg the beginning of a parenthesized subexpression,
-`$' is an ordinary character except at the end of the
-RE or\(dg the end of a parenthesized subexpression,
-and `*' is an ordinary character if it appears at the beginning of the
+.Pp
+Obsolete
+.Pq Dq basic
+regular expressions differ in several respects.
+.Ql \&|
+is an ordinary character and there is no equivalent
+for its functionality.
+.Ql \&+
+and
+.Ql ?\&
+are ordinary characters, and their functionality
+can be expressed using bounds
+.No ( Ql {1,}
+or
+.Ql {0,1}
+respectively).
+Also note that
+.Ql x+
+in modern REs is equivalent to
+.Ql xx* .
+The delimiters for bounds are
+.Ql \e{
+and
+.Ql \e} ,
+with
+.Ql \&{
+and
+.Ql \&}
+by themselves ordinary characters.
+The parentheses for nested subexpressions are
+.Ql \e(
+and
+.Ql \e) ,
+with
+.Ql \&(
+and
+.Ql \&)
+by themselves ordinary characters.
+.Ql \&^
+is an ordinary character except at the beginning of the
+RE or\(dd the beginning of a parenthesized subexpression,
+.Ql \&$
+is an ordinary character except at the end of the
+RE or\(dd the end of a parenthesized subexpression,
+and
+.Ql \&*
+is an ordinary character if it appears at the beginning of the
 RE or the beginning of a parenthesized subexpression
-(after a possible leading `^').
-Finally, there is one new type of atom, a \fIback reference\fR:
-`\e' followed by a non-zero decimal digit \fId\fR
+(after a possible leading
+.Ql \&^ ) .
+Finally, there is one new type of atom, a
+.Em back reference :
+.Ql \e
+followed by a non-zero decimal digit
+.Em d
 matches the same sequence of characters
-matched by the \fId\fRth parenthesized subexpression
+matched by the
+.Em d Ns th
+parenthesized subexpression
 (numbering subexpressions by the positions of their opening parentheses,
 left to right),
-so that (e.g.) `\e([bc]\e)\e1' matches `bb' or `cc' but not `bc'.
-.SH SEE ALSO
-regex(3)
-.PP
-POSIX 1003.2, section 2.8 (Regular Expression Notation).
-.SH HISTORY
-Written by Henry Spencer, based on the 1003.2 spec.
-.SH BUGS
+so that (e.g.)
+.Ql \e([bc]\e)\e1
+matches
+.Ql bb
+or
+.Ql cc
+but not
+.Ql bc .
+.Sh SEE ALSO
+.Xr regex 3
+.Rs
+.%T Regular Expression Notation
+.%R IEEE Std
+.%N 1003.2
+.%P section 2.8
+.Re
+.Sh BUGS
 Having two kinds of REs is a botch.
-.PP
-The current 1003.2 spec says that `)' is an ordinary character in
-the absence of an unmatched `(';
+.Pp
+The current
+.St -p1003.2
+spec says that
+.Ql \&)
+is an ordinary character in
+the absence of an unmatched
+.Ql \&( ;
 this was an unintentional result of a wording error,
 and change is likely.
 Avoid relying on it.
-.PP
+.Pp
 Back references are a dreadful botch,
 posing major problems for efficient implementations.
 They are also somewhat vaguely defined
 (does
-`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?).
+.Ql a\e(\e(b\e)*\e2\e)*d
+match
+.Ql abbbd ? ) .
 Avoid using them.
-.PP
-1003.2's specification of case-independent matching is vague.
-The ``one case implies all cases'' definition given above
+.Pp
+.St -p1003.2
+specification of case-independent matching is vague.
+The
+.Dq one case implies all cases
+definition given above
 is current consensus among implementors as to the right interpretation.
-.PP
+.Pp
 The syntax for word boundaries is incredibly ugly.
diff --git a/winsup/cygwin/regex/regex.h b/winsup/cygwin/regex/regex.h
deleted file mode 100644 (file)
index 03a1825..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _REGEX_H_
-#define        _REGEX_H_       /* never again */
-#include <sys/types.h>
-/* ========= begin header generated by ./mkh ========= */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* === regex2.h === */
-typedef _off_t regoff_t;
-typedef struct {
-       int re_magic;
-       size_t re_nsub;         /* number of parenthesized subexpressions */
-       const char *re_endp;    /* end pointer for REG_PEND */
-       struct re_guts *re_g;   /* none of your business :-) */
-} regex_t;
-typedef struct {
-       regoff_t rm_so;         /* start of match */
-       regoff_t rm_eo;         /* end of match */
-} regmatch_t;
-
-
-/* === regcomp.c === */
-extern int regcomp(regex_t *, const char *, int);
-#define        REG_BASIC       0000
-#define        REG_EXTENDED    0001
-#define        REG_ICASE       0002
-#define        REG_NOSUB       0004
-#define        REG_NEWLINE     0010
-#define        REG_NOSPEC      0020
-#define        REG_PEND        0040
-#define        REG_DUMP        0200
-
-
-/* === regerror.c === */
-#define        REG_OKAY         0
-#define        REG_NOMATCH      1
-#define        REG_BADPAT       2
-#define        REG_ECOLLATE     3
-#define        REG_ECTYPE       4
-#define        REG_EESCAPE      5
-#define        REG_ESUBREG      6
-#define        REG_EBRACK       7
-#define        REG_EPAREN       8
-#define        REG_EBRACE       9
-#define        REG_BADBR       10
-#define        REG_ERANGE      11
-#define        REG_ESPACE      12
-#define        REG_BADRPT      13
-#define        REG_EMPTY       14
-#define        REG_ASSERT      15
-#define        REG_INVARG      16
-#define        REG_ATOI        255     /* convert name to number (!) */
-#define        REG_ITOA        0400    /* convert number to name (!) */
-extern size_t regerror(int, const regex_t *, char *, size_t);
-
-
-/* === regexec.c === */
-extern int regexec(const regex_t *, const char *, size_t, regmatch_t [], int);
-#define        REG_NOTBOL      00001
-#define        REG_NOTEOL      00002
-#define        REG_STARTEND    00004
-#define        REG_TRACE       00400   /* tracing of execution */
-#define        REG_LARGE       01000   /* force large representation */
-#define        REG_BACKR       02000   /* force use of backref code */
-
-
-/* === regfree.c === */
-extern void regfree(regex_t *);
-
-
-#ifdef __cplusplus
-}
-#endif
-/* ========= end header generated by ./mkh ========= */
-#endif
index 176038ab00b643ef10c420d53c1aafcedd51069b..13bbf64a73c07ea38b8c482660df5ce1644a4b5f 100644 (file)
@@ -1,6 +1,42 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regex2.h    8.4 (Berkeley) 3/20/94
+ * $FreeBSD: src/lib/libc/regex/regex2.h,v 1.11 2007/01/09 00:28:04 imp Exp $
+ */
+
 /*
  * First, the stuff that ends up in the outside-world include file
- = typedef _off_t regoff_t;
+ = typedef off_t regoff_t;
  = typedef struct {
  =     int re_magic;
  =     size_t re_nsub;         // number of parenthesized subexpressions
  * In state representations, an operator's bit is on to signify a state
  * immediately *preceding* "execution" of that operator.
  */
-typedef long sop;              /* strip operator */
+typedef unsigned long sop;     /* strip operator */
 typedef long sopno;
-#define        OPRMASK 0x7c000000
-#define        OPDMASK 0x03ffffff
-#define        OPSHIFT (26)
+#define        OPRMASK 0xf8000000L
+#define        OPDMASK 0x07ffffffL
+#define        OPSHIFT ((unsigned)27)
 #define        OP(n)   ((n)&OPRMASK)
 #define        OPND(n) ((n)&OPDMASK)
 #define        SOP(op, opnd)   ((op)|(opnd))
 /* operators                      meaning      operand                 */
 /*                                             (back, fwd are offsets) */
-#define        OEND    (1<<OPSHIFT)    /* endmarker    -                       */
-#define        OCHAR   (2<<OPSHIFT)    /* character    unsigned char           */
-#define        OBOL    (3<<OPSHIFT)    /* left anchor  -                       */
-#define        OEOL    (4<<OPSHIFT)    /* right anchor -                       */
-#define        OANY    (5<<OPSHIFT)    /* .            -                       */
-#define        OANYOF  (6<<OPSHIFT)    /* [...]        set number              */
-#define        OBACK_  (7<<OPSHIFT)    /* begin \d     paren number            */
-#define        O_BACK  (8<<OPSHIFT)    /* end \d       paren number            */
-#define        OPLUS_  (9<<OPSHIFT)    /* + prefix     fwd to suffix           */
-#define        O_PLUS  (10<<OPSHIFT)   /* + suffix     back to prefix          */
-#define        OQUEST_ (11<<OPSHIFT)   /* ? prefix     fwd to suffix           */
-#define        O_QUEST (12<<OPSHIFT)   /* ? suffix     back to prefix          */
-#define        OLPAREN (13<<OPSHIFT)   /* (            fwd to )                */
-#define        ORPAREN (14<<OPSHIFT)   /* )            back to (               */
-#define        OCH_    (15<<OPSHIFT)   /* begin choice fwd to OOR2             */
-#define        OOR1    (16<<OPSHIFT)   /* | pt. 1      back to OOR1 or OCH_    */
-#define        OOR2    (17<<OPSHIFT)   /* | pt. 2      fwd to OOR2 or O_CH     */
-#define        O_CH    (18<<OPSHIFT)   /* end choice   back to OOR1            */
-#define        OBOW    (19<<OPSHIFT)   /* begin word   -                       */
-#define        OEOW    (20<<OPSHIFT)   /* end word     -                       */
+#define        OEND    (1L<<OPSHIFT)   /* endmarker    -                       */
+#define        OCHAR   (2L<<OPSHIFT)   /* character    wide character          */
+#define        OBOL    (3L<<OPSHIFT)   /* left anchor  -                       */
+#define        OEOL    (4L<<OPSHIFT)   /* right anchor -                       */
+#define        OANY    (5L<<OPSHIFT)   /* .            -                       */
+#define        OANYOF  (6L<<OPSHIFT)   /* [...]        set number              */
+#define        OBACK_  (7L<<OPSHIFT)   /* begin \d     paren number            */
+#define        O_BACK  (8L<<OPSHIFT)   /* end \d       paren number            */
+#define        OPLUS_  (9L<<OPSHIFT)   /* + prefix     fwd to suffix           */
+#define        O_PLUS  (10L<<OPSHIFT)  /* + suffix     back to prefix          */
+#define        OQUEST_ (11L<<OPSHIFT)  /* ? prefix     fwd to suffix           */
+#define        O_QUEST (12L<<OPSHIFT)  /* ? suffix     back to prefix          */
+#define        OLPAREN (13L<<OPSHIFT)  /* (            fwd to )                */
+#define        ORPAREN (14L<<OPSHIFT)  /* )            back to (               */
+#define        OCH_    (15L<<OPSHIFT)  /* begin choice fwd to OOR2             */
+#define        OOR1    (16L<<OPSHIFT)  /* | pt. 1      back to OOR1 or OCH_    */
+#define        OOR2    (17L<<OPSHIFT)  /* | pt. 2      fwd to OOR2 or O_CH     */
+#define        O_CH    (18L<<OPSHIFT)  /* end choice   back to OOR1            */
+#define        OBOW    (19L<<OPSHIFT)  /* begin word   -                       */
+#define        OEOW    (20L<<OPSHIFT)  /* end word     -                       */
 
 /*
- * Structure for [] character-set representation.  Character sets are
- * done as bit vectors, grouped 8 to a byte vector for compactness.
- * The individual set therefore has both a pointer to the byte vector
- * and a mask to pick out the relevant bit of each byte.  A hash code
- * simplifies testing whether two sets could be identical.
- *
- * This will get trickier for multicharacter collating elements.  As
- * preliminary hooks for dealing with such things, we also carry along
- * a string of multi-character elements, and decide the size of the
- * vectors at run time.
+ * Structures for [] character-set representation.
  */
 typedef struct {
-       uch *ptr;               /* -> uch [csetsize] */
-       uch mask;               /* bit within array */
-       uch hash;               /* hash code */
-       size_t smultis;
-       char *multis;           /* -> char[smulti]  ab\0cd\0ef\0\0 */
+       wint_t          min;
+       wint_t          max;
+} crange;
+typedef struct {
+       unsigned char   bmp[NC / 8];
+       wctype_t        *types;
+       int             ntypes;
+       wint_t          *wides;
+       int             nwides;
+       crange          *ranges;
+       int             nranges;
+       int             invert;
+       int             icase;
 } cset;
-/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */
-#define        CHadd(cs, c)    ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c))
-#define        CHsub(cs, c)    ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c))
-#define        CHIN(cs, c)     ((cs)->ptr[(uch)(c)] & (cs)->mask)
-#define        MCadd(p, cs, cp)        mcadd(p, cs, cp)        /* regcomp() internal fns */
-#define        MCsub(p, cs, cp)        mcsub(p, cs, cp)
-#define        MCin(p, cs, cp) mcin(p, cs, cp)
 
-/* stuff for character categories */
-typedef unsigned char cat_t;
+static int
+CHIN1(cset *cs, wint_t ch)
+{
+       int i;
+
+       assert(ch >= 0);
+       if (ch < NC)
+               return (((cs->bmp[ch >> 3] & (1 << (ch & 7))) != 0) ^
+                   cs->invert);
+       for (i = 0; i < cs->nwides; i++)
+               if (ch == cs->wides[i])
+                       return (!cs->invert);
+       for (i = 0; i < cs->nranges; i++)
+               if (cs->ranges[i].min <= ch && ch <= cs->ranges[i].max)
+                       return (!cs->invert);
+       for (i = 0; i < cs->ntypes; i++)
+               if (iswctype(ch, cs->types[i]))
+                       return (!cs->invert);
+       return (cs->invert);
+}
+
+static __inline int
+CHIN(cset *cs, wint_t ch)
+{
+
+       assert(ch >= 0);
+       if (ch < NC)
+               return (((cs->bmp[ch >> 3] & (1 << (ch & 7))) != 0) ^
+                   cs->invert);
+       else if (cs->icase)
+               return (CHIN1(cs, ch) || CHIN1(cs, towlower(ch)) ||
+                   CHIN1(cs, towupper(ch)));
+       else
+               return (CHIN1(cs, ch));
+}
 
 /*
  * main compiled-expression structure
@@ -104,10 +165,8 @@ struct re_guts {
        int magic;
 #              define  MAGIC2  ((('R'^0200)<<8)|'E')
        sop *strip;             /* malloced area for strip */
-       int csetsize;           /* number of bits in a cset vector */
        int ncsets;             /* number of csets in use */
        cset *sets;             /* -> cset [ncsets] */
-       uch *setbits;           /* -> uch[csetsize][ncsets/CHAR_BIT] */
        int cflags;             /* copy of regcomp() cflags argument */
        sopno nstates;          /* = number of sops */
        sopno firststate;       /* the initial OEND (normally 0) */
@@ -118,17 +177,16 @@ struct re_guts {
 #              define  BAD     04      /* something wrong */
        int nbol;               /* number of ^ used */
        int neol;               /* number of $ used */
-       int ncategories;        /* how many character categories */
-       cat_t *categories;      /* ->catspace[-CHAR_MIN] */
        char *must;             /* match must contain this string */
+       int moffset;            /* latest point at which must may be located */
+       int *charjump;          /* Boyer-Moore char jump table */
+       int *matchjump;         /* Boyer-Moore match jump table */
        int mlen;               /* length of must */
        size_t nsub;            /* copy of re_nsub */
        int backrefs;           /* does it use back references? */
        sopno nplus;            /* how deep does it nest +s? */
-       /* catspace must be last */
-       cat_t catspace[1];      /* actually [NC] */
 };
 
 /* misc utilities */
-#define        OUT     (CHAR_MAX+1)    /* a non-character value */
-#define        ISWORD(c)       (isalnum((unsigned char)c) || (c) == '_')
+#define        OUT     (CHAR_MIN - 1)  /* a non-character value */
+#define ISWORD(c)       (iswalnum((uch)(c)) || (c) == '_')
index 35b99c2727805e5dc4faf5e49ea2451d3227c117..6195e508c4a130dbfb7f8f58760c1f283ae092e3 100644 (file)
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regexec.c   8.3 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regexec.c  8.3 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/regex/regexec.c,v 1.8 2007/06/11 03:05:54 delphij Exp $");
+
 /*
  * the outer shell of regexec()
  *
- * This file includes engine.c *twice*, after muchos fiddling with the
+ * This file includes engine.c three times, after muchos fiddling with the
  * macros that code uses.  This lets the same code operate on two different
- * representations for state sets.
+ * representations for state sets and characters.
  */
+#ifdef __CYGWIN__
 #include "winsup.h"
+#endif
 #include <sys/types.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
 #include <ctype.h>
-#include "regex.h"
+#include <regex.h>
+#include <wchar.h>
+#include <wctype.h>
 
 #include "utils.h"
 #include "regex2.h"
 
-#ifdef lint
-static int nope = 0;           /* for use in asserts; shuts lint up */
+#ifdef __CYGWIN__
+#define __unused       __attribute__ ((unused))
 #endif
 
+static int nope __unused = 0;  /* for use in asserts; shuts lint up */
+
+static __inline size_t
+xmbrtowc(wint_t *wi, const char *s, size_t n, mbstate_t *mbs, wint_t dummy)
+{
+       size_t nr;
+       wchar_t wc;
+
+       nr = mbrtowc(&wc, s, n, mbs);
+       if (wi != NULL)
+               *wi = wc;
+       if (nr == 0)
+               return (1);
+       else if (nr == (size_t)-1 || nr == (size_t)-2) {
+               memset(mbs, 0, sizeof(*mbs));
+               if (wi != NULL)
+                       *wi = dummy;
+               return (1);
+       } else
+                return (nr);
+}
+
+static __inline size_t
+xmbrtowc_dummy(wint_t *wi,
+               const char *s,
+               size_t n __unused,
+               mbstate_t *mbs __unused,
+               wint_t dummy __unused)
+{
+
+       if (wi != NULL)
+               *wi = (unsigned char)*s;
+       return (1);
+}
+
 /* macros for manipulating states, small version */
-#define        states  unsigned
-#define        states1 unsigned        /* for later use in regexec() decision */
+#define        states  long
+#define        states1 states          /* for later use in regexec() decision */
 #define        CLEAR(v)        ((v) = 0)
-#define        SET0(v, n)      ((v) &= ~((unsigned)1 << (n)))
-#define        SET1(v, n)      ((v) |= (unsigned)1 << (n))
-#define        ISSET(v, n)     ((v) & ((unsigned)1 << (n)))
+#define        SET0(v, n)      ((v) &= ~((unsigned long)1 << (n)))
+#define        SET1(v, n)      ((v) |= (unsigned long)1 << (n))
+#define        ISSET(v, n)     (((v) & ((unsigned long)1 << (n))) != 0)
 #define        ASSIGN(d, s)    ((d) = (s))
 #define        EQ(a, b)        ((a) == (b))
-#define        STATEVARS       int dummy       /* dummy version */
+#define        STATEVARS       long dummy      /* dummy version */
 #define        STATESETUP(m, n)        /* nothing */
 #define        STATETEARDOWN(m)        /* nothing */
 #define        SETUP(v)        ((v) = 0)
-#define        onestate        unsigned
-#define        INIT(o, n)      ((o) = (unsigned)1 << (n))
+#define        onestate        long
+#define        INIT(o, n)      ((o) = (unsigned long)1 << (n))
 #define        INC(o)  ((o) <<= 1)
-#define        ISSTATEIN(v, o) ((v) & (o))
+#define        ISSTATEIN(v, o) (((v) & (o)) != 0)
 /* some abbreviations; note that some of these know variable names! */
 /* do "if I'm here, I can also be there" etc without branches */
-#define        FWD(dst, src, n)        ((dst) |= ((unsigned)(src)&(here)) << (n))
-#define        BACK(dst, src, n)       ((dst) |= ((unsigned)(src)&(here)) >> (n))
-#define        ISSETBACK(v, n) ((v) & ((unsigned)here >> (n)))
+#define        FWD(dst, src, n)        ((dst) |= ((unsigned long)(src)&(here)) << (n))
+#define        BACK(dst, src, n)       ((dst) |= ((unsigned long)(src)&(here)) >> (n))
+#define        ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0)
+/* no multibyte support */
+#define        XMBRTOWC        xmbrtowc_dummy
+#define        ZAPSTATE(mbs)   ((void)(mbs))
 /* function names */
 #define SNAMES                 /* engine.c looks after details */
 
@@ -68,6 +151,8 @@ static int nope = 0;         /* for use in asserts; shuts lint up */
 #undef BACK
 #undef ISSETBACK
 #undef SNAMES
+#undef XMBRTOWC
+#undef ZAPSTATE
 
 /* macros for manipulating states, large version */
 #define        states  char *
@@ -77,13 +162,13 @@ static int nope = 0;               /* for use in asserts; shuts lint up */
 #define        ISSET(v, n)     ((v)[n])
 #define        ASSIGN(d, s)    memcpy(d, s, m->g->nstates)
 #define        EQ(a, b)        (memcmp(a, b, m->g->nstates) == 0)
-#define        STATEVARS       int vn; char *space
+#define        STATEVARS       long vn; char *space
 #define        STATESETUP(m, nv)       { (m)->space = malloc((nv)*(m)->g->nstates); \
                                if ((m)->space == NULL) return(REG_ESPACE); \
                                (m)->vn = 0; }
 #define        STATETEARDOWN(m)        { free((m)->space); }
 #define        SETUP(v)        ((v) = &m->space[m->vn++ * m->g->nstates])
-#define        onestate        int
+#define        onestate        long
 #define        INIT(o, n)      ((o) = (n))
 #define        INC(o)  ((o)++)
 #define        ISSTATEIN(v, o) ((v)[o])
@@ -92,11 +177,24 @@ static int nope = 0;               /* for use in asserts; shuts lint up */
 #define        FWD(dst, src, n)        ((dst)[here+(n)] |= (src)[here])
 #define        BACK(dst, src, n)       ((dst)[here-(n)] |= (src)[here])
 #define        ISSETBACK(v, n) ((v)[here - (n)])
+/* no multibyte support */
+#define        XMBRTOWC        xmbrtowc_dummy
+#define        ZAPSTATE(mbs)   ((void)(mbs))
 /* function names */
 #define        LNAMES                  /* flag */
 
 #include "engine.c"
 
+/* multibyte character & large states version */
+#undef LNAMES
+#undef XMBRTOWC
+#undef ZAPSTATE
+#define        XMBRTOWC        xmbrtowc
+#define        ZAPSTATE(mbs)   memset((mbs), 0, sizeof(*(mbs)))
+#define        MNAMES
+
+#include "engine.c"
+
 /*
  - regexec - interface for matching
  = extern int regexec(const regex_t *, const char *, size_t, \
@@ -113,14 +211,13 @@ static int nope = 0;              /* for use in asserts; shuts lint up */
  * have been prototyped.
  */
 int                            /* 0 success, REG_NOMATCH failure */
-regexec(preg, string, nmatch, pmatch, eflags)
-const regex_t *preg;
-const char *string;
-size_t nmatch;
-regmatch_t pmatch[];
-int eflags;
+regexec(const regex_t * __restrict preg,
+       const char * __restrict string,
+       size_t nmatch,
+       regmatch_t pmatch[__restrict],
+       int eflags)
 {
-       register struct re_guts *g = preg->re_g;
+       struct re_guts *g = preg->re_g;
 #ifdef REDEBUG
 #      define  GOODFLAGS(f)    (f)
 #else
@@ -134,7 +231,9 @@ int eflags;
                return(REG_BADPAT);
        eflags = GOODFLAGS(eflags);
 
-       if ((unsigned) g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))
+       if (MB_CUR_MAX > 1)
+               return(mmatcher(g, (char *)string, nmatch, pmatch, eflags));
+       else if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))
                return(smatcher(g, (char *)string, nmatch, pmatch, eflags));
        else
                return(lmatcher(g, (char *)string, nmatch, pmatch, eflags));
index b8be143d882ca6c71a603ca90185395d3cf07ac0..aa795fa783dcc145e449ca889f2d65e02437b740 100644 (file)
@@ -1,8 +1,51 @@
-#include "winsup.h"
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regfree.c   8.3 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regfree.c  8.3 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/regex/regfree.c,v 1.8 2007/06/11 03:05:54 delphij Exp $");
+
 #include <sys/types.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include "regex.h"
+#include <limits.h>
+#include <regex.h>
+#include <wchar.h>
+#include <wctype.h>
 
 #include "utils.h"
 #include "regex2.h"
  = extern void regfree(regex_t *);
  */
 void
-regfree(preg)
-regex_t *preg;
+regfree(regex_t *preg)
 {
-       register struct re_guts *g;
+       struct re_guts *g;
+       int i;
 
        if (preg->re_magic != MAGIC1)   /* oops */
                return;                 /* nice to complain, but hard */
@@ -28,11 +71,19 @@ regex_t *preg;
 
        if (g->strip != NULL)
                free((char *)g->strip);
-       if (g->sets != NULL)
+       if (g->sets != NULL) {
+               for (i = 0; i < g->ncsets; i++) {
+                       free(g->sets[i].ranges);
+                       free(g->sets[i].wides);
+                       free(g->sets[i].types);
+               }
                free((char *)g->sets);
-       if (g->setbits != NULL)
-               free((char *)g->setbits);
+       }
        if (g->must != NULL)
                free(g->must);
+       if (g->charjump != NULL)
+               free(&g->charjump[CHAR_MIN]);
+       if (g->matchjump != NULL)
+               free(g->matchjump);
        free((char *)g);
 }
diff --git a/winsup/cygwin/regex/tests b/winsup/cygwin/regex/tests
deleted file mode 100644 (file)
index e4d928d..0000000
+++ /dev/null
@@ -1,477 +0,0 @@
-# regular expression test set
-# Lines are at least three fields, separated by one or more tabs.  "" stands
-# for an empty field.  First field is an RE.  Second field is flags.  If
-# C flag given, regcomp() is expected to fail, and the third field is the
-# error name (minus the leading REG_).
-#
-# Otherwise it is expected to succeed, and the third field is the string to
-# try matching it against.  If there is no fourth field, the match is
-# expected to fail.  If there is a fourth field, it is the substring that
-# the RE is expected to match.  If there is a fifth field, it is a comma-
-# separated list of what the subexpressions should match, with - indicating
-# no match for that one.  In both the fourth and fifth fields, a (sub)field
-# starting with @ indicates that the (sub)expression is expected to match
-# a null string followed by the stuff after the @; this provides a way to
-# test where null strings match.  The character `N' in REs and strings
-# is newline, `S' is space, `T' is tab, `Z' is NUL.
-#
-# The full list of flags:
-#      -       placeholder, does nothing
-#      b       RE is a BRE, not an ERE
-#      &       try it as both an ERE and a BRE
-#      C       regcomp() error expected, third field is error name
-#      i       REG_ICASE
-#      m       ("mundane") REG_NOSPEC
-#      s       REG_NOSUB (not really testable)
-#      n       REG_NEWLINE
-#      ^       REG_NOTBOL
-#      $       REG_NOTEOL
-#      #       REG_STARTEND (see below)
-#      p       REG_PEND
-#
-# For REG_STARTEND, the start/end offsets are those of the substring
-# enclosed in ().
-
-# basics
-a              &       a       a
-abc            &       abc     abc
-abc|de         -       abc     abc
-a|b|c          -       abc     a
-
-# parentheses and perversions thereof
-a(b)c          -       abc     abc
-a\(b\)c                b       abc     abc
-a(             C       EPAREN
-a(             b       a(      a(
-a\(            -       a(      a(
-a\(            bC      EPAREN
-a\(b           bC      EPAREN
-a(b            C       EPAREN
-a(b            b       a(b     a(b
-# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly)
-a)             -       a)      a)
-)              -       )       )
-# end gagging (in a just world, those *should* give EPAREN)
-a)             b       a)      a)
-a\)            bC      EPAREN
-\)             bC      EPAREN
-a()b           -       ab      ab
-a\(\)b         b       ab      ab
-
-# anchoring and REG_NEWLINE
-^abc$          &       abc     abc
-a^b            -       a^b
-a^b            b       a^b     a^b
-a$b            -       a$b
-a$b            b       a$b     a$b
-^              &       abc     @abc
-$              &       abc     @
-^$             &       ""      @
-$^             -       ""      @
-\($\)\(^\)     b       ""      @
-# stop retching, those are legitimate (although disgusting)
-^^             -       ""      @
-$$             -       ""      @
-b$             &       abNc
-b$             &n      abNc    b
-^b$            &       aNbNc
-^b$            &n      aNbNc   b
-^$             &n      aNNb    @Nb
-^$             n       abc
-^$             n       abcN    @
-$^             n       aNNb    @Nb
-\($\)\(^\)     bn      aNNb    @Nb
-^^             n^      aNNb    @Nb
-$$             n       aNNb    @NN
-^a             ^       a
-a$             $       a
-^a             ^n      aNb
-^b             ^n      aNb     b
-a$             $n      bNa
-b$             $n      bNa     b
-a*(^b$)c*      -       b       b
-a*\(^b$\)c*    b       b       b
-
-# certain syntax errors and non-errors
-|              C       EMPTY
-|              b       |       |
-*              C       BADRPT
-*              b       *       *
-+              C       BADRPT
-?              C       BADRPT
-""             &C      EMPTY
-()             -       abc     @abc
-\(\)           b       abc     @abc
-a||b           C       EMPTY
-|ab            C       EMPTY
-ab|            C       EMPTY
-(|a)b          C       EMPTY
-(a|)b          C       EMPTY
-(*a)           C       BADRPT
-(+a)           C       BADRPT
-(?a)           C       BADRPT
-({1}a)         C       BADRPT
-\(\{1\}a\)     bC      BADRPT
-(a|*b)         C       BADRPT
-(a|+b)         C       BADRPT
-(a|?b)         C       BADRPT
-(a|{1}b)       C       BADRPT
-^*             C       BADRPT
-^*             b       *       *
-^+             C       BADRPT
-^?             C       BADRPT
-^{1}           C       BADRPT
-^\{1\}         bC      BADRPT
-
-# metacharacters, backslashes
-a.c            &       abc     abc
-a[bc]d         &       abd     abd
-a\*c           &       a*c     a*c
-a\\b           &       a\b     a\b
-a\\\*b         &       a\*b    a\*b
-a\bc           &       abc     abc
-a\             &C      EESCAPE
-a\\bc          &       a\bc    a\bc
-\{             bC      BADRPT
-a\[b           &       a[b     a[b
-a[b            &C      EBRACK
-# trailing $ is a peculiar special case for the BRE code
-a$             &       a       a
-a$             &       a$
-a\$            &       a
-a\$            &       a$      a$
-a\\$           &       a
-a\\$           &       a$
-a\\$           &       a\$
-a\\$           &       a\      a\
-
-# back references, ugh
-a\(b\)\2c      bC      ESUBREG
-a\(b\1\)c      bC      ESUBREG
-a\(b*\)c\1d    b       abbcbbd abbcbbd bb
-a\(b*\)c\1d    b       abbcbd
-a\(b*\)c\1d    b       abbcbbbd
-^\(.\)\1       b       abc
-a\([bc]\)\1d   b       abcdabbd        abbd    b
-a\(\([bc]\)\2\)*d      b       abbccd  abbccd
-a\(\([bc]\)\2\)*d      b       abbcbd
-# actually, this next one probably ought to fail, but the spec is unclear
-a\(\(b\)*\2\)*d                b       abbbd   abbbd
-# here is a case that no NFA implementation does right
-\(ab*\)[ab]*\1 b       ababaaa ababaaa a
-# check out normal matching in the presence of back refs
-\(a\)\1bcd     b       aabcd   aabcd
-\(a\)\1bc*d    b       aabcd   aabcd
-\(a\)\1bc*d    b       aabd    aabd
-\(a\)\1bc*d    b       aabcccd aabcccd
-\(a\)\1bc*[ce]d        b       aabcccd aabcccd
-^\(a\)\1b\(c\)*cd$     b       aabcccd aabcccd
-
-# ordinary repetitions
-ab*c           &       abc     abc
-ab+c           -       abc     abc
-ab?c           -       abc     abc
-a\(*\)b                b       a*b     a*b
-a\(**\)b       b       ab      ab
-a\(***\)b      bC      BADRPT
-*a             b       *a      *a
-**a            b       a       a
-***a           bC      BADRPT
-
-# the dreaded bounded repetitions
-{              &       {       {
-{abc           &       {abc    {abc
-{1             C       BADRPT
-{1}            C       BADRPT
-a{b            &       a{b     a{b
-a{1}b          -       ab      ab
-a\{1\}b                b       ab      ab
-a{1,}b         -       ab      ab
-a\{1,\}b       b       ab      ab
-a{1,2}b                -       aab     aab
-a\{1,2\}b      b       aab     aab
-a{1            C       EBRACE
-a\{1           bC      EBRACE
-a{1a           C       EBRACE
-a\{1a          bC      EBRACE
-a{1a}          C       BADBR
-a\{1a\}                bC      BADBR
-a{,2}          -       a{,2}   a{,2}
-a\{,2\}                bC      BADBR
-a{,}           -       a{,}    a{,}
-a\{,\}         bC      BADBR
-a{1,x}         C       BADBR
-a\{1,x\}       bC      BADBR
-a{1,x          C       EBRACE
-a\{1,x         bC      EBRACE
-a{300}         C       BADBR
-a\{300\}       bC      BADBR
-a{1,0}         C       BADBR
-a\{1,0\}       bC      BADBR
-ab{0,0}c       -       abcac   ac
-ab\{0,0\}c     b       abcac   ac
-ab{0,1}c       -       abcac   abc
-ab\{0,1\}c     b       abcac   abc
-ab{0,3}c       -       abbcac  abbc
-ab\{0,3\}c     b       abbcac  abbc
-ab{1,1}c       -       acabc   abc
-ab\{1,1\}c     b       acabc   abc
-ab{1,3}c       -       acabc   abc
-ab\{1,3\}c     b       acabc   abc
-ab{2,2}c       -       abcabbc abbc
-ab\{2,2\}c     b       abcabbc abbc
-ab{2,4}c       -       abcabbc abbc
-ab\{2,4\}c     b       abcabbc abbc
-((a{1,10}){1,10}){1,10}        -       a       a       a,a
-
-# multiple repetitions
-a**            &C      BADRPT
-a++            C       BADRPT
-a??            C       BADRPT
-a*+            C       BADRPT
-a*?            C       BADRPT
-a+*            C       BADRPT
-a+?            C       BADRPT
-a?*            C       BADRPT
-a?+            C       BADRPT
-a{1}{1}                C       BADRPT
-a*{1}          C       BADRPT
-a+{1}          C       BADRPT
-a?{1}          C       BADRPT
-a{1}*          C       BADRPT
-a{1}+          C       BADRPT
-a{1}?          C       BADRPT
-a*{b}          -       a{b}    a{b}
-a\{1\}\{1\}    bC      BADRPT
-a*\{1\}                bC      BADRPT
-a\{1\}*                bC      BADRPT
-
-# brackets, and numerous perversions thereof
-a[b]c          &       abc     abc
-a[ab]c         &       abc     abc
-a[^ab]c                &       adc     adc
-a[]b]c         &       a]c     a]c
-a[[b]c         &       a[c     a[c
-a[-b]c         &       a-c     a-c
-a[^]b]c                &       adc     adc
-a[^-b]c                &       adc     adc
-a[b-]c         &       a-c     a-c
-a[b            &C      EBRACK
-a[]            &C      EBRACK
-a[1-3]c                &       a2c     a2c
-a[3-1]c                &C      ERANGE
-a[1-3-5]c      &C      ERANGE
-a[[.-.]--]c    &       a-c     a-c
-a[1-           &C      ERANGE
-a[[.           &C      EBRACK
-a[[.x          &C      EBRACK
-a[[.x.         &C      EBRACK
-a[[.x.]                &C      EBRACK
-a[[.x.]]       &       ax      ax
-a[[.x,.]]      &C      ECOLLATE
-a[[.one.]]b    &       a1b     a1b
-a[[.notdef.]]b &C      ECOLLATE
-a[[.].]]b      &       a]b     a]b
-a[[:alpha:]]c  &       abc     abc
-a[[:notdef:]]c &C      ECTYPE
-a[[:           &C      EBRACK
-a[[:alpha      &C      EBRACK
-a[[:alpha:]    &C      EBRACK
-a[[:alpha,:]   &C      ECTYPE
-a[[:]:]]b      &C      ECTYPE
-a[[:-:]]b      &C      ECTYPE
-a[[:alph:]]    &C      ECTYPE
-a[[:alphabet:]]        &C      ECTYPE
-[[:alnum:]]+   -       -%@a0X- a0X
-[[:alpha:]]+   -       -%@aX0- aX
-[[:blank:]]+   -       aSSTb   SST
-[[:cntrl:]]+   -       aNTb    NT
-[[:digit:]]+   -       a019b   019
-[[:graph:]]+   -       Sa%bS   a%b
-[[:lower:]]+   -       AabC    ab
-[[:print:]]+   -       NaSbN   aSb
-[[:punct:]]+   -       S%-&T   %-&
-[[:space:]]+   -       aSNTb   SNT
-[[:upper:]]+   -       aBCd    BC
-[[:xdigit:]]+  -       p0f3Cq  0f3C
-a[[=b=]]c      &       abc     abc
-a[[=           &C      EBRACK
-a[[=b          &C      EBRACK
-a[[=b=         &C      EBRACK
-a[[=b=]                &C      EBRACK
-a[[=b,=]]      &C      ECOLLATE
-a[[=one=]]b    &       a1b     a1b
-
-# complexities
-a(((b)))c      -       abc     abc
-a(b|(c))d      -       abd     abd
-a(b*|c)d       -       abbd    abbd
-# just gotta have one DFA-buster, of course
-a[ab]{20}      -       aaaaabaaaabaaaabaaaab   aaaaabaaaabaaaabaaaab
-# and an inline expansion in case somebody gets tricky
-a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab]      -       aaaaabaaaabaaaabaaaab   aaaaabaaaabaaaabaaaab
-# and in case somebody just slips in an NFA...
-a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night)     -       aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights
-# fish for anomalies as the number of states passes 32
-12345678901234567890123456789  -       a12345678901234567890123456789b 12345678901234567890123456789
-123456789012345678901234567890 -       a123456789012345678901234567890b        123456789012345678901234567890
-1234567890123456789012345678901        -       a1234567890123456789012345678901b       1234567890123456789012345678901
-12345678901234567890123456789012       -       a12345678901234567890123456789012b      12345678901234567890123456789012
-123456789012345678901234567890123      -       a123456789012345678901234567890123b     123456789012345678901234567890123
-# and one really big one, beyond any plausible word width
-1234567890123456789012345678901234567890123456789012345678901234567890 -       a1234567890123456789012345678901234567890123456789012345678901234567890b        1234567890123456789012345678901234567890123456789012345678901234567890
-# fish for problems as brackets go past 8
-[ab][cd][ef][gh][ij][kl][mn]   -       xacegikmoq      acegikm
-[ab][cd][ef][gh][ij][kl][mn][op]       -       xacegikmoq      acegikmo
-[ab][cd][ef][gh][ij][kl][mn][op][qr]   -       xacegikmoqy     acegikmoq
-[ab][cd][ef][gh][ij][kl][mn][op][q]    -       xacegikmoqy     acegikmoq
-
-# subtleties of matching
-abc            &       xabcy   abc
-a\(b\)?c\1d    b       acd
-aBc            i       Abc     Abc
-a[Bc]*d                i       abBCcd  abBCcd
-0[[:upper:]]1  &i      0a1     0a1
-0[[:lower:]]1  &i      0A1     0A1
-a[^b]c         &i      abc
-a[^b]c         &i      aBc
-a[^b]c         &i      adc     adc
-[a]b[c]                -       abc     abc
-[a]b[a]                -       aba     aba
-[abc]b[abc]    -       abc     abc
-[abc]b[abd]    -       abd     abd
-a(b?c)+d       -       accd    accd
-(wee|week)(knights|night)      -       weeknights      weeknights
-(we|wee|week|frob)(knights|night|day)  -       weeknights      weeknights
-a[bc]d         -       xyzaaabcaababdacd       abd
-a[ab]c         -       aaabc   abc
-abc            s       abc     abc
-a*             &       b       @b
-
-# Let's have some fun -- try to match a C comment.
-# first the obvious, which looks okay at first glance...
-/\*.*\*/       -       /*x*/   /*x*/
-# but...
-/\*.*\*/       -       /*x*/y/*z*/     /*x*/y/*z*/
-# okay, we must not match */ inside; try to do that...
-/\*([^*]|\*[^/])*\*/   -       /*x*/   /*x*/
-/\*([^*]|\*[^/])*\*/   -       /*x*/y/*z*/     /*x*/
-# but...
-/\*([^*]|\*[^/])*\*/   -       /*x**/y/*z*/    /*x**/y/*z*/
-# and a still fancier version, which does it right (I think)...
-/\*([^*]|\*+[^*/])*\*+/        -       /*x*/   /*x*/
-/\*([^*]|\*+[^*/])*\*+/        -       /*x*/y/*z*/     /*x*/
-/\*([^*]|\*+[^*/])*\*+/        -       /*x**/y/*z*/    /*x**/
-/\*([^*]|\*+[^*/])*\*+/        -       /*x****/y/*z*/  /*x****/
-/\*([^*]|\*+[^*/])*\*+/        -       /*x**x*/y/*z*/  /*x**x*/
-/\*([^*]|\*+[^*/])*\*+/        -       /*x***x/y/*z*/  /*x***x/y/*z*/
-
-# subexpressions
-.*             -       abc     abc     -
-a(b)(c)d       -       abcd    abcd    b,c
-a(((b)))c      -       abc     abc     b,b,b
-a(b|(c))d      -       abd     abd     b,-
-a(b*|c|e)d     -       abbd    abbd    bb
-a(b*|c|e)d     -       acd     acd     c
-a(b*|c|e)d     -       ad      ad      @d
-a(b?)c         -       abc     abc     b
-a(b?)c         -       ac      ac      @c
-a(b+)c         -       abc     abc     b
-a(b+)c         -       abbbc   abbbc   bbb
-a(b*)c         -       ac      ac      @c
-(a|ab)(bc([de]+)f|cde) -       abcdef  abcdef  a,bcdef,de
-# the regression tester only asks for 9 subexpressions
-a(b)(c)(d)(e)(f)(g)(h)(i)(j)k  -       abcdefghijk     abcdefghijk     b,c,d,e,f,g,h,i,j
-a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l       -       abcdefghijkl    abcdefghijkl    b,c,d,e,f,g,h,i,j,k
-a([bc]?)c      -       abc     abc     b
-a([bc]?)c      -       ac      ac      @c
-a([bc]+)c      -       abc     abc     b
-a([bc]+)c      -       abcc    abcc    bc
-a([bc]+)bc     -       abcbc   abcbc   bc
-a(bb+|b)b      -       abb     abb     b
-a(bbb+|bb+|b)b -       abb     abb     b
-a(bbb+|bb+|b)b -       abbb    abbb    bb
-a(bbb+|bb+|b)bb        -       abbb    abbb    b
-(.*).*         -       abcdef  abcdef  abcdef
-(a*)*          -       bc      @b      @b
-
-# do we get the right subexpression when it is used more than once?
-a(b|c)*d       -       ad      ad      -
-a(b|c)*d       -       abcd    abcd    c
-a(b|c)+d       -       abd     abd     b
-a(b|c)+d       -       abcd    abcd    c
-a(b|c?)+d      -       ad      ad      @d
-a(b|c?)+d      -       abcd    abcd    @d
-a(b|c){0,0}d   -       ad      ad      -
-a(b|c){0,1}d   -       ad      ad      -
-a(b|c){0,1}d   -       abd     abd     b
-a(b|c){0,2}d   -       ad      ad      -
-a(b|c){0,2}d   -       abcd    abcd    c
-a(b|c){0,}d    -       ad      ad      -
-a(b|c){0,}d    -       abcd    abcd    c
-a(b|c){1,1}d   -       abd     abd     b
-a(b|c){1,1}d   -       acd     acd     c
-a(b|c){1,2}d   -       abd     abd     b
-a(b|c){1,2}d   -       abcd    abcd    c
-a(b|c){1,}d    -       abd     abd     b
-a(b|c){1,}d    -       abcd    abcd    c
-a(b|c){2,2}d   -       acbd    acbd    b
-a(b|c){2,2}d   -       abcd    abcd    c
-a(b|c){2,4}d   -       abcd    abcd    c
-a(b|c){2,4}d   -       abcbd   abcbd   b
-a(b|c){2,4}d   -       abcbcd  abcbcd  c
-a(b|c){2,}d    -       abcd    abcd    c
-a(b|c){2,}d    -       abcbd   abcbd   b
-a(b+|((c)*))+d -       abd     abd     @d,@d,-
-a(b+|((c)*))+d -       abcd    abcd    @d,@d,-
-
-# check out the STARTEND option
-[abc]          &#      a(b)c   b
-[abc]          &#      a(d)c
-[abc]          &#      a(bc)d  b
-[abc]          &#      a(dc)d  c
-.              &#      a()c
-b.*c           &#      b(bc)c  bc
-b.*            &#      b(bc)c  bc
-.*c            &#      b(bc)c  bc
-
-# plain strings, with the NOSPEC flag
-abc            m       abc     abc
-abc            m       xabcy   abc
-abc            m       xyz
-a*b            m       aba*b   a*b
-a*b            m       ab
-""             mC      EMPTY
-
-# cases involving NULs
-aZb            &       a       a
-aZb            &p      a
-aZb            &p#     (aZb)   aZb
-aZ*b           &p#     (ab)    ab
-a.b            &#      (aZb)   aZb
-a.*            &#      (aZb)c  aZb
-
-# word boundaries (ick)
-[[:<:]]a       &       a       a
-[[:<:]]a       &       ba
-[[:<:]]a       &       -a      a
-a[[:>:]]       &       a       a
-a[[:>:]]       &       ab
-a[[:>:]]       &       a-      a
-[[:<:]]a.c[[:>:]]      &       axcd-dayc-dazce-abc     abc
-[[:<:]]a.c[[:>:]]      &       axcd-dayc-dazce-abc-q   abc
-[[:<:]]a.c[[:>:]]      &       axc-dayc-dazce-abc      axc
-[[:<:]]b.c[[:>:]]      &       a_bxc-byc_d-bzc-q       bzc
-[[:<:]].x..[[:>:]]     &       y_xa_-_xb_y-_xc_-axdc   _xc_
-[[:<:]]a_b[[:>:]]      &       x_a_b
-
-# past problems, and suspected problems
-(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A])  -       A1      A1
-abcdefghijklmnop       i       abcdefghijklmnop        abcdefghijklmnop
-abcdefghijklmnopqrstuv i       abcdefghijklmnopqrstuv  abcdefghijklmnopqrstuv
-(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN])    -       CC11    CC11
-CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a   -       CC11    CC11
-Char \([a-z0-9_]*\)\[.*        b       Char xyz[k      Char xyz[k      xyz
-a?b    -       ab      ab
--\{0,1\}[0-9]*$        b       -5      -5
-a*a*a*a*a*a*a* &       aaaaaa  aaaaaa
index 1a997ac8fc166de4ce162938b67c10464982a489..2a2ed9694de53a1de7440bbd4faa13afa602e249 100644 (file)
@@ -1,9 +1,41 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)utils.h     8.3 (Berkeley) 3/20/94
+ * $FreeBSD: src/lib/libc/regex/utils.h,v 1.3 2007/01/09 00:28:04 imp Exp $
+ */
+
 /* utility definitions */
-#ifdef _POSIX2_RE_DUP_MAX
-#define        DUPMAX  _POSIX2_RE_DUP_MAX
-#else
-#define        DUPMAX  255
-#endif
+#define        DUPMAX          _POSIX2_RE_DUP_MAX      /* xxx is this right? */
 #define        INFINITY        (DUPMAX + 1)
 #define        NC              (CHAR_MAX - CHAR_MIN + 1)
 typedef unsigned char uch;
index 820519af5a416506b9d95542efa3488192b34f06..fbeb04c70419a5eadd9c7705244e451fb8d49c15 100644 (file)
@@ -49,6 +49,7 @@ extern char *__locale_charset ();
 #endif
 
 #ifdef __INSIDE_CYGWIN__
+#ifdef __cplusplus
 size_t __stdcall sys_cp_wcstombs (wctomb_p, const char *, char *, size_t,
                                  const wchar_t *, size_t = (size_t) -1)
        __attribute__ ((regparm(3)));
@@ -68,6 +69,7 @@ size_t __stdcall sys_mbstowcs (wchar_t * dst, size_t dlen, const char *src,
 size_t __stdcall sys_mbstowcs_alloc (wchar_t **, int, const char *,
                                     size_t = (size_t) -1)
        __attribute__ ((regparm(3)));
+#endif /* __cplusplus */
 #endif /* __INSIDE_CYGWIN__ */
 
 #endif /* _CYGWIN_WCHAR_H */
This page took 0.206807 seconds and 5 git commands to generate.