aboutsummaryrefslogtreecommitdiff
path: root/posix
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2004-11-26 13:48:49 +0000
committerJakub Jelinek <jakub@redhat.com>2004-11-26 13:48:49 +0000
commitf94203900a978cda33df395c36827a17d171f98e (patch)
treef60c591eb4acb7c1ca6977b86b1b86e3fecd8532 /posix
parent945a6124b6aa3047e3d144da4fb47cbbf5da70ee (diff)
downloadglibc-f94203900a978cda33df395c36827a17d171f98e.tar
glibc-f94203900a978cda33df395c36827a17d171f98e.tar.gz
glibc-f94203900a978cda33df395c36827a17d171f98e.tar.bz2
glibc-f94203900a978cda33df395c36827a17d171f98e.zip
Updated to fedora-glibc-20041126T1318cvs/fedora-glibc-2_3_3-85
Diffstat (limited to 'posix')
-rw-r--r--posix/Makefile21
-rw-r--r--posix/PCRE.tests19
-rw-r--r--posix/confstr.c193
-rw-r--r--posix/getconf.c73
-rw-r--r--posix/getconf.speclist.h15
-rw-r--r--posix/regcomp.c79
-rw-r--r--posix/regex_internal.c25
-rw-r--r--posix/regex_internal.h2
8 files changed, 323 insertions, 104 deletions
diff --git a/posix/Makefile b/posix/Makefile
index c89cfc0b41..5a3534a6ad 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -91,6 +91,7 @@ tests += wordexp-test tst-exec tst-spawn
endif
others := getconf
install-bin := getconf
+install-others := $(inst_libexecdir)/getconf
before-compile := testcases.h ptestcases.h
@@ -101,7 +102,8 @@ generated := $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
bug-regex21-mem bug-regex21.mtrace \
tst-rxspencer-mem tst-rxspencer.mtrace tst-getconf.out \
tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \
- bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem
+ bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem \
+ getconf.speclist
include ../Rules
@@ -138,7 +140,7 @@ CFLAGS-waitid.c = -fexceptions
CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-getopt.c = -fexceptions
CFLAGS-wordexp.c = -fexceptions
-CFLAGS-sysconf.c = -fexceptions
+CFLAGS-sysconf.c = -fexceptions -DGETCONF_DIR='"$(libexecdir)/getconf"'
CFLAGS-pathconf.c = -fexceptions
CFLAGS-fpathconf.c = -fexceptions
CFLAGS-spawn.c = -fexceptions
@@ -147,6 +149,7 @@ CFLAGS-spawni.c = -fexceptions
CFLAGS-pause.c = -fexceptions
CFLAGS-glob.c = $(uses-callbacks) -fexceptions
CFLAGS-glob64.c = $(uses-callbacks) -fexceptions
+CFLAGS-getconf.c = -DGETCONF_DIR='"$(libexecdir)/getconf"'
tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \
--none random --col --color --colour
@@ -260,3 +263,17 @@ bug-glob2-ENV = MALLOC_TRACE=$(objpfx)bug-glob2.mtrace
$(objpfx)bug-glob2-mem: $(objpfx)bug-glob2.out
$(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@
+
+$(inst_libexecdir)/getconf: $(objpfx)getconf $(objpfx)getconf.speclist FORCE
+ $(addprefix $(..)./scripts/mkinstalldirs ,\
+ $(filter-out $(wildcard $@),$@))
+ for spec in `cat $(objpfx)getconf.speclist`; do \
+ $(INSTALL_PROGRAM) $< $@/$$spec.new; \
+ mv -f $@/$$spec.new $@/$$spec; \
+ done
+
+$(objpfx)getconf.speclist: getconf.speclist.h
+ $(CC) -E $(CFLAGS) $(CPPFLAGS) $< \
+ | sed -n -e '/START_OF_STRINGS/,$${/_POSIX_V6_/{s/^[^"]*"//;s/".*$$//;p}}' \
+ > $@.new
+ mv -f $@.new $@
diff --git a/posix/PCRE.tests b/posix/PCRE.tests
index 7ea5b9e70c..0fb9cadafc 100644
--- a/posix/PCRE.tests
+++ b/posix/PCRE.tests
@@ -2365,3 +2365,22 @@ No match
0: bc123bc
1: bc
2: bc
+
+/^a{2,5}$/
+ aa
+ 0: aa
+ aaa
+ 0: aaa
+ aaaa
+ 0: aaaa
+ aaaaa
+ 0: aaaaa
+ *** Failers
+No match
+ a
+No match
+ b
+No match
+ aaaaab
+No match
+ aaaaaa
diff --git a/posix/confstr.c b/posix/confstr.c
index 212ec72311..6b0dcf0c20 100644
--- a/posix/confstr.c
+++ b/posix/confstr.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991,96,97,2000-2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1996, 1997, 2000-2002, 2003, 2004
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -32,8 +33,8 @@ confstr (name, buf, len)
char *buf;
size_t len;
{
- const char *string;
- size_t string_len;
+ const char *string = "";
+ size_t string_len = 1;
switch (name)
{
@@ -54,66 +55,175 @@ confstr (name, buf, len)
Currently this means all environment which the system allows. */
{
- static const char restenvs[] =
-#if _POSIX_V6_ILP32_OFF32 > 0
- "_POSIX_V6_ILP32_OFF32"
+ char restenvs[4 * sizeof "_POSIX_V6_LPBIG_OFFBIG"];
+
+ string_len = 0;
+#ifndef _POSIX_V6_ILP32_OFF32
+ if (__sysconf (_SC_V6_ILP32_OFF32) > 0)
#endif
-#if _POSIX_V6_ILP32_OFFBIG > 0
-# if _POSIX_V6_ILP32_OFF32 > 0
- "\n"
-# endif
- "_POSIX_V6_ILP32_OFFBIG"
+#if !defined _POSIX_V6_ILP32_OFF32 || _POSIX_V6_ILP32_OFF32 > 0
+ {
+ memcpy (restenvs + string_len, "_POSIX_V6_ILP32_OFF32",
+ sizeof "_POSIX_V6_ILP32_OFF32" - 1);
+ string_len += sizeof "_POSIX_V6_ILP32_OFF32" - 1;
+ }
#endif
-#if _POSIX_V6_LP64_OFF64 > 0
-# if _POSIX_V6_ILP32_OFF32 > 0 || _POSIX_V6_ILP32_OFFBIG > 0
- "\n"
-# endif
- "_POSIX_V6_LP64_OFF64"
+#ifndef _POSIX_V6_ILP32_OFFBIG
+ if (__sysconf (_SC_V6_ILP32_OFFBIG) > 0)
#endif
-#if _POSIX_V6_LPBIG_OFFBIG > 0
-# if _POSIX_V6_ILP32_OFF32 > 0 || _POSIX_V6_ILP32_OFFBIG > 0 \
- || _POSIX_V6_LP64_OFF64 > 0
- "\n"
-# endif
- "_POSIX_V6_LPBIG_OFFBIG"
+#if !defined _POSIX_V6_ILP32_OFFBIG || _POSIX_V6_ILP32_OFFBIG > 0
+ {
+ if (string_len)
+ restenvs[string_len++] = '\n';
+ memcpy (restenvs + string_len, "_POSIX_V6_ILP32_OFFBIG",
+ sizeof "_POSIX_V6_ILP32_OFFBIG" - 1);
+ string_len += sizeof "_POSIX_V6_ILP32_OFFBIG" - 1;
+ }
+#endif
+#ifndef _POSIX_V6_LP64_OFF64
+ if (__sysconf (_SC_V6_LP64_OFF64) > 0)
+#endif
+#if !defined _POSIX_V6_LP64_OFF64 || _POSIX_V6_LP64_OFF64 > 0
+ {
+ if (string_len)
+ restenvs[string_len++] = '\n';
+ memcpy (restenvs + string_len, "_POSIX_V6_LP64_OFF64",
+ sizeof "_POSIX_V6_LP64_OFF64" - 1);
+ string_len += sizeof "_POSIX_V6_LP64_OFF64" - 1;
+ }
+#endif
+#ifndef _POSIX_V6_LPBIG_OFFBIG
+ if (__sysconf (_SC_V6_LPBIG_OFFBIG) > 0)
+#endif
+#if !defined _POSIX_V6_LPBIG_OFFBIG || _POSIX_V6_LPBIG_OFFBIG > 0
+ {
+ if (string_len)
+ restenvs[string_len++] = '\n';
+ memcpy (restenvs + string_len, "_POSIX_V6_LPBIG_OFFBIG",
+ sizeof "_POSIX_V6_LPBIG_OFFBIG" - 1);
+ string_len += sizeof "_POSIX_V6_LPBIG_OFFBIG" - 1;
+ }
#endif
- ;
+ restenvs[string_len++] = '\0';
string = restenvs;
- string_len = sizeof (restenvs);
}
break;
+ case _CS_XBS5_ILP32_OFF32_CFLAGS:
+ case _CS_POSIX_V6_ILP32_OFF32_CFLAGS:
+#ifdef __ILP32_OFF32_CFLAGS
+# if _POSIX_V6_ILP32_OFF32 == -1
+# error __ILP32_OFF32_CFLAGS shouldn't be defined
+# elif !defined _POSIX_V6_ILP32_OFF32
+ if (__sysconf (_SC_V6_ILP32_OFF32) < 0)
+ break;
+# endif
+ string = __ILP32_OFF32_CFLAGS;
+ string_len = sizeof (__ILP32_OFF32_CFLAGS);
+#endif
+ break;
+
case _CS_XBS5_ILP32_OFFBIG_CFLAGS:
case _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS:
- case _CS_LFS_CFLAGS:
-#if _XBS5_LP64_OFF64 == -1 && _XBS5_LPBIG_OFFBIG == -1 && _XBS5_ILP32_OFFBIG == 1
- /* Signal that we want the new ABI. */
- {
- static const char file_offset[] = "-D_FILE_OFFSET_BITS=64";
- string = file_offset;
- string_len = sizeof (file_offset);
- }
+#ifdef __ILP32_OFFBIG_CFLAGS
+# if _POSIX_V6_ILP32_OFFBIG == -1
+# error __ILP32_OFFBIG_CFLAGS shouldn't be defined
+# elif !defined _POSIX_V6_ILP32_OFFBIG
+ if (__sysconf (_SC_V6_ILP32_OFFBIG) < 0)
+ break;
+# endif
+ string = __ILP32_OFFBIG_CFLAGS;
+ string_len = sizeof (__ILP32_OFFBIG_CFLAGS);
+#endif
+ break;
+
+ case _CS_XBS5_LP64_OFF64_CFLAGS:
+ case _CS_POSIX_V6_LP64_OFF64_CFLAGS:
+#ifdef __LP64_OFF64_CFLAGS
+# if _POSIX_V6_LP64_OFF64 == -1
+# error __LP64_OFF64_CFLAGS shouldn't be defined
+# elif !defined _POSIX_V6_LP64_OFF64
+ if (__sysconf (_SC_V6_LP64_OFF64) < 0)
+ break;
+# endif
+ string = __LP64_OFF64_CFLAGS;
+ string_len = sizeof (__LP64_OFF64_CFLAGS);
+#endif
break;
+
+ case _CS_XBS5_ILP32_OFF32_LDFLAGS:
+ case _CS_POSIX_V6_ILP32_OFF32_LDFLAGS:
+#ifdef __ILP32_OFF32_LDFLAGS
+# if _POSIX_V6_ILP32_OFF32 == -1
+# error __ILP32_OFF32_LDFLAGS shouldn't be defined
+# elif !defined _POSIX_V6_ILP32_OFF32
+ if (__sysconf (_SC_V6_ILP32_OFF32) < 0)
+ break;
+# endif
+ string = __ILP32_OFF32_LDFLAGS;
+ string_len = sizeof (__ILP32_OFF32_LDFLAGS);
#endif
- /* FALLTHROUGH */
+ break;
+ case _CS_XBS5_ILP32_OFFBIG_LDFLAGS:
+ case _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS:
+#ifdef __ILP32_OFFBIG_LDFLAGS
+# if _POSIX_V6_ILP32_OFFBIG == -1
+# error __ILP32_OFFBIG_LDFLAGS shouldn't be defined
+# elif !defined _POSIX_V6_ILP32_OFFBIG
+ if (__sysconf (_SC_V6_ILP32_OFFBIG) < 0)
+ break;
+# endif
+ string = __ILP32_OFFBIG_LDFLAGS;
+ string_len = sizeof (__ILP32_OFFBIG_LDFLAGS);
+#endif
+ break;
+
+ case _CS_XBS5_LP64_OFF64_LDFLAGS:
+ case _CS_POSIX_V6_LP64_OFF64_LDFLAGS:
+#ifdef __LP64_OFF64_LDFLAGS
+# if _POSIX_V6_LP64_OFF64 == -1
+# error __LP64_OFF64_LDFLAGS shouldn't be defined
+# elif !defined _POSIX_V6_LP64_OFF64
+ if (__sysconf (_SC_V6_LP64_OFF64) < 0)
+ break;
+# endif
+ string = __LP64_OFF64_LDFLAGS;
+ string_len = sizeof (__LP64_OFF64_LDFLAGS);
+#endif
+ break;
+
+ case _CS_LFS_CFLAGS:
case _CS_LFS_LINTFLAGS:
+#if _POSIX_V6_ILP32_OFF32 == 1 && _POSIX_V6_ILP32_OFFBIG == 1
+# define __LFS_CFLAGS "-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+ /* Signal that we want the new ABI. */
+ string = __LFS_CFLAGS;
+ string_len = sizeof (__LFS_CFLAGS);
+#endif
+ break;
+
case _CS_LFS_LDFLAGS:
case _CS_LFS_LIBS:
+ /* No special libraries or linker flags needed. */
+ break;
+
case _CS_LFS64_CFLAGS:
case _CS_LFS64_LINTFLAGS:
+#define __LFS64_CFLAGS "-D_LARGEFILE64_SOURCE"
+ string = __LFS64_CFLAGS;
+ string_len = sizeof (__LFS64_CFLAGS);
+ break;
+
case _CS_LFS64_LDFLAGS:
case _CS_LFS64_LIBS:
+ /* No special libraries or linker flags needed. */
+ break;
- case _CS_XBS5_ILP32_OFF32_CFLAGS:
- case _CS_XBS5_ILP32_OFF32_LDFLAGS:
case _CS_XBS5_ILP32_OFF32_LIBS:
case _CS_XBS5_ILP32_OFF32_LINTFLAGS:
- case _CS_XBS5_ILP32_OFFBIG_LDFLAGS:
case _CS_XBS5_ILP32_OFFBIG_LIBS:
case _CS_XBS5_ILP32_OFFBIG_LINTFLAGS:
- case _CS_XBS5_LP64_OFF64_CFLAGS:
- case _CS_XBS5_LP64_OFF64_LDFLAGS:
case _CS_XBS5_LP64_OFF64_LIBS:
case _CS_XBS5_LP64_OFF64_LINTFLAGS:
case _CS_XBS5_LPBIG_OFFBIG_CFLAGS:
@@ -121,15 +231,10 @@ confstr (name, buf, len)
case _CS_XBS5_LPBIG_OFFBIG_LIBS:
case _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS:
- case _CS_POSIX_V6_ILP32_OFF32_CFLAGS:
- case _CS_POSIX_V6_ILP32_OFF32_LDFLAGS:
case _CS_POSIX_V6_ILP32_OFF32_LIBS:
case _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS:
- case _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS:
case _CS_POSIX_V6_ILP32_OFFBIG_LIBS:
case _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS:
- case _CS_POSIX_V6_LP64_OFF64_CFLAGS:
- case _CS_POSIX_V6_LP64_OFF64_LDFLAGS:
case _CS_POSIX_V6_LP64_OFF64_LIBS:
case _CS_POSIX_V6_LP64_OFF64_LINTFLAGS:
case _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS:
@@ -137,8 +242,6 @@ confstr (name, buf, len)
case _CS_POSIX_V6_LPBIG_OFFBIG_LIBS:
case _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS:
/* GNU libc does not require special actions to use LFS functions. */
- string = "";
- string_len = 1;
break;
case _CS_GNU_LIBC_VERSION:
diff --git a/posix/getconf.c b/posix/getconf.c
index 2f68003ff3..6175dfec26 100644
--- a/posix/getconf.c
+++ b/posix/getconf.c
@@ -917,12 +917,12 @@ static const struct conf vars[] =
};
-static const char *specs[] =
+static struct { const char *name; int num; } specs[] =
{
- "POSIX_V6_ILP32_OFF32",
- "POSIX_V6_ILP32_OFFBIG",
- "POSIX_V6_LP64_OFF64",
- "POSIX_V6_LPBIG_OFFBIG"
+ { "POSIX_V6_ILP32_OFF32", _SC_V6_ILP32_OFF32 },
+ { "POSIX_V6_ILP32_OFFBIG", _SC_V6_ILP32_OFFBIG },
+ { "POSIX_V6_LP64_OFF64", _SC_V6_LP64_OFF64 },
+ { "POSIX_V6_LPBIG_OFFBIG", _SC_V6_LPBIG_OFFBIG }
};
static const int nspecs = sizeof (specs) / sizeof (specs[0]);
@@ -963,11 +963,14 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
return 0;
}
+ const char *getconf_dir = getenv ("GETCONF_DIR") ?: GETCONF_DIR;
+ size_t getconf_dirlen = strlen (getconf_dir);
+
+ const char *spec = NULL;
+ char buf[sizeof "POSIX_V6_LPBIG_OFFBIG"];
+ char *argv0 = argv[0];
if (argc > 1 && strncmp (argv[1], "-v", 2) == 0)
{
- const char *spec;
- int i;
-
if (argv[1][2] == '\0')
{
if (argc < 3)
@@ -983,18 +986,62 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
argv += 1;
argc += 1;
}
+ }
+ else
+ {
+ char default_name[getconf_dirlen + sizeof "/default"];
+ memcpy (mempcpy (default_name, getconf_dir, getconf_dirlen),
+ "/default", sizeof "/default");
+ int len = readlink (default_name, buf, sizeof buf - 1);
+ if (len > 0)
+ {
+ buf[len] = '\0';
+ spec = buf;
+ }
+ }
- /* Check for the specifications we know. This is simple in the
- moment. */
+ /* Check for the specifications we know. */
+ if (spec != NULL)
+ {
+ int i;
for (i = 0; i < nspecs; ++i)
- if (strcmp (spec, specs[i]) == 0)
+ if (strcmp (spec, specs[i].name) == 0)
break;
if (i == nspecs)
error (2, 0, _("unknown specification \"%s\""), spec);
- /* And now we forget the specification. We don't do anything different
- with or without it. */
+ switch (specs[i].num)
+ {
+#ifndef _POSIX_V6_ILP32_OFF32
+ case _SC_V6_ILP32_OFF32:
+#endif
+#ifndef _POSIX_V6_ILP32_OFFBIG
+ case _SC_V6_ILP32_OFFBIG:
+#endif
+#ifndef _POSIX_V6_LP64_OFF64
+ case _SC_V6_LP64_OFF64:
+#endif
+#ifndef _POSIX_V6_LPBIG_OFFBIG
+ case _SC_V6_LPBIG_OFFBIG:
+#endif
+ {
+ const char *args[argc + 3];
+ size_t spec_len = strlen (spec);
+ char getconf_name[getconf_dirlen + 2 + spec_len + 1];
+ memcpy (mempcpy (mempcpy (getconf_name, getconf_dir,
+ getconf_dirlen),
+ "/_", 2), spec, spec_len + 1);
+ args[0] = argv0;
+ args[1] = "-v";
+ args[2] = spec;
+ memcpy (&args[3], &argv[1], argc * sizeof (argv[1]));
+ execv (getconf_name, (char * const *) args);
+ error (4, errno, _("Couldn't execute %s"), getconf_name);
+ }
+ default:
+ break;
+ }
}
if (argc < 2 || argc > 3)
diff --git a/posix/getconf.speclist.h b/posix/getconf.speclist.h
new file mode 100644
index 0000000000..943c0de606
--- /dev/null
+++ b/posix/getconf.speclist.h
@@ -0,0 +1,15 @@
+#include <unistd.h>
+const char *START_OF_STRINGS =
+#if _POSIX_V6_ILP32_OFF32 == 1
+"_POSIX_V6_ILP32_OFF32"
+#endif
+#if _POSIX_V6_ILP32_OFFBIG == 1
+"_POSIX_V6_ILP32_OFFBIG"
+#endif
+#if _POSIX_V6_LP64_OFF64 == 1
+"_POSIX_V6_LP64_OFF64"
+#endif
+#if _POSIX_V6_LPBIG_OFFBIG == 1
+"_POSIX_V6_LPBIG_OFFBIG"
+#endif
+"";
diff --git a/posix/regcomp.c b/posix/regcomp.c
index dafad9bd0c..675f816f60 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -1269,8 +1269,8 @@ analyze_tree (dfa, node)
calc_first (dfa, node);
if (node->next == -1)
calc_next (dfa, node);
- if (node->eclosure.nelem == 0)
- calc_epsdest (dfa, node);
+ calc_epsdest (dfa, node);
+
/* Calculate "first" etc. for the left child. */
if (node->left != NULL)
{
@@ -1626,7 +1626,7 @@ calc_inveclosure (dfa)
for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
{
dest = dfa->eclosures[src].elems[idx];
- re_node_set_insert (dfa->inveclosures + dest, src);
+ re_node_set_insert_last (dfa->inveclosures + dest, src);
}
}
}
@@ -2538,7 +2538,7 @@ parse_dup_op (elem, regexp, dfa, token, syntax, err)
reg_errcode_t *err;
{
re_token_t dup_token;
- bin_tree_t *tree = NULL;
+ bin_tree_t *tree = NULL, *old_tree = NULL;
int i, start, end, start_idx = re_string_cur_idx (regexp);
re_token_t start_token = *token;
@@ -2598,12 +2598,14 @@ parse_dup_op (elem, regexp, dfa, token, syntax, err)
end = (token->type == OP_DUP_QUESTION) ? 1 : -1;
}
+ fetch_token (token, regexp, syntax);
+
/* Treat "<re>{0}*" etc. as "<re>{0}". */
- if (BE (elem == NULL, 0))
- start = end = 0;
+ if (BE (elem == NULL || (start == 0 && end == 0), 0))
+ return NULL;
/* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */
- else if (BE (start > 0, 0))
+ if (BE (start > 0, 0))
{
tree = elem;
for (i = 2; i <= start; ++i)
@@ -2613,52 +2615,41 @@ parse_dup_op (elem, regexp, dfa, token, syntax, err)
if (BE (elem == NULL || tree == NULL, 0))
goto parse_dup_op_espace;
}
- }
- if (BE (end != start, 1))
- {
- dup_token.type = (end == -1 ? OP_DUP_ASTERISK : OP_DUP_QUESTION);
- if (BE (start > 0, 0))
- {
- elem = duplicate_tree (elem, dfa);
- if (BE (elem == NULL, 0))
- goto parse_dup_op_espace;
+ if (start == end)
+ return tree;
- /* This subexpression will be marked as optional, so that
- empty matches do not touch the registers. */
- mark_opt_subexp (elem, dfa);
+ /* Duplicate ELEM before it is marked optional. */
+ elem = duplicate_tree (elem, dfa);
+ old_tree = tree;
+ }
+ else
+ old_tree = NULL;
- /* Prepare the tree with the modifier. */
- elem = re_dfa_add_tree_node (dfa, elem, NULL, &dup_token);
- tree = create_tree (dfa, tree, elem, CONCAT, 0);
- }
- else
- {
- /* We do not need to duplicate the tree because we have not
- created it yet. */
- mark_opt_subexp (elem, dfa);
- tree = elem = re_dfa_add_tree_node (dfa, elem, NULL, &dup_token);
- }
+ mark_opt_subexp (elem, dfa);
+ dup_token.type = (end == -1 ? OP_DUP_ASTERISK : OP_DUP_QUESTION);
+ tree = re_dfa_add_tree_node (dfa, elem, NULL, &dup_token);
+ if (BE (tree == NULL, 0))
+ goto parse_dup_op_espace;
+ /* This loop is actually executed only when end != -1,
+ to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?... We have
+ already created the start+1-th copy. */
+ for (i = start + 2; i <= end; ++i)
+ {
+ elem = duplicate_tree (elem, dfa);
+ tree = create_tree (dfa, tree, elem, CONCAT, 0);
if (BE (elem == NULL || tree == NULL, 0))
goto parse_dup_op_espace;
- /* This loop is actually executed only when end != -1,
- to rewrite <re>{0,n} as <re>?<re>?<re>?... We have
- already created the start+1-th copy. */
- for (i = start + 2; i <= end; ++i)
- {
- elem = duplicate_tree (elem, dfa);
- tree = create_tree (dfa, tree, elem, CONCAT, 0);
- if (BE (elem == NULL || tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- }
+ tree = re_dfa_add_tree_node (dfa, tree, NULL, &dup_token);
+ if (BE (tree == NULL, 0))
+ goto parse_dup_op_espace;
}
- fetch_token (token, regexp, syntax);
+ if (old_tree)
+ tree = create_tree (dfa, old_tree, tree, CONCAT, 0);
+
return tree;
parse_dup_op_espace:
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index bb1d73d9a0..cb439e5d7c 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -1250,6 +1250,31 @@ re_node_set_insert (set, elem)
return 1;
}
+/* Insert the new element ELEM to the re_node_set* SET.
+ SET should not already have any element greater than or equal to ELEM.
+ Return -1 if an error is occured, return 1 otherwise. */
+
+static int
+re_node_set_insert_last (set, elem)
+ re_node_set *set;
+ int elem;
+{
+ /* Realloc if we need. */
+ if (set->alloc == set->nelem)
+ {
+ int *new_array;
+ set->alloc = (set->alloc + 1) * 2;
+ new_array = re_realloc (set->elems, int, set->alloc);
+ if (BE (new_array == NULL, 0))
+ return -1;
+ set->elems = new_array;
+ }
+
+ /* Insert the new element. */
+ set->elems[set->nelem++] = elem;
+ return 1;
+}
+
/* Compare two node sets SET1 and SET2.
return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */
diff --git a/posix/regex_internal.h b/posix/regex_internal.h
index a778032d77..703d409eb8 100644
--- a/posix/regex_internal.h
+++ b/posix/regex_internal.h
@@ -668,6 +668,8 @@ static reg_errcode_t re_node_set_init_union (re_node_set *dest,
static reg_errcode_t re_node_set_merge (re_node_set *dest,
const re_node_set *src) internal_function;
static int re_node_set_insert (re_node_set *set, int elem) internal_function;
+static int re_node_set_insert_last (re_node_set *set,
+ int elem) internal_function;
static int re_node_set_compare (const re_node_set *set1,
const re_node_set *set2) internal_function;
static int re_node_set_contains (const re_node_set *set, int elem) internal_function;