[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/build/uClibc/libc/misc/Makefile b/ap/build/uClibc/libc/misc/Makefile
new file mode 100644
index 0000000..11f362a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../
+top_builddir=../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/Makefile.in b/ap/build/uClibc/libc/misc/Makefile.in
new file mode 100644
index 0000000..e01b3dc
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/Makefile.in
@@ -0,0 +1,36 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+#DIRS:=assert ctype dirent error file fnmatch ftw glob gnu internals intl locale mntent \
+#	pthread regex search statfs syslog sysvipc time ttyent utmp wchar wctype wordexp
+
+include $(top_srcdir)libc/misc/assert/Makefile.in
+include $(top_srcdir)libc/misc/ctype/Makefile.in
+include $(top_srcdir)libc/misc/dirent/Makefile.in
+include $(top_srcdir)libc/misc/error/Makefile.in
+include $(top_srcdir)libc/misc/elf/Makefile.in
+include $(top_srcdir)libc/misc/file/Makefile.in
+include $(top_srcdir)libc/misc/fnmatch/Makefile.in
+include $(top_srcdir)libc/misc/ftw/Makefile.in
+include $(top_srcdir)libc/misc/fts/Makefile.in
+include $(top_srcdir)libc/misc/glob/Makefile.in
+include $(top_srcdir)libc/misc/gnu/Makefile.in
+include $(top_srcdir)libc/misc/internals/Makefile.in
+include $(top_srcdir)libc/misc/locale/Makefile.in
+include $(top_srcdir)libc/misc/mntent/Makefile.in
+include $(top_srcdir)libc/misc/pthread/Makefile.in
+include $(top_srcdir)libc/misc/regex/Makefile.in
+include $(top_srcdir)libc/misc/search/Makefile.in
+include $(top_srcdir)libc/misc/statfs/Makefile.in
+include $(top_srcdir)libc/misc/syslog/Makefile.in
+include $(top_srcdir)libc/misc/sysvipc/Makefile.in
+include $(top_srcdir)libc/misc/time/Makefile.in
+include $(top_srcdir)libc/misc/ttyent/Makefile.in
+include $(top_srcdir)libc/misc/utmp/Makefile.in
+include $(top_srcdir)libc/misc/wchar/Makefile.in
+include $(top_srcdir)libc/misc/wctype/Makefile.in
+include $(top_srcdir)libc/misc/wordexp/Makefile.in
diff --git a/ap/build/uClibc/libc/misc/assert/.indent.pro b/ap/build/uClibc/libc/misc/assert/.indent.pro
new file mode 100644
index 0000000..492ecf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/assert/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/ap/build/uClibc/libc/misc/assert/Makefile b/ap/build/uClibc/libc/misc/assert/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/assert/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/assert/Makefile.in b/ap/build/uClibc/libc/misc/assert/Makefile.in
new file mode 100644
index 0000000..a49e00d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/assert/Makefile.in
@@ -0,0 +1,23 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/assert
+
+CSRC := __assert.c
+
+MISC_ASSERT_DIR := $(top_srcdir)libc/misc/assert
+MISC_ASSERT_OUT := $(top_builddir)libc/misc/assert
+
+MISC_ASSERT_SRC := $(MISC_ASSERT_DIR)/__assert.c
+MISC_ASSERT_OBJ := $(MISC_ASSERT_OUT)/__assert.o
+
+libc-y += $(MISC_ASSERT_OBJ)
+
+objclean-y += CLEAN_libc/misc/assert
+
+CLEAN_libc/misc/assert:
+	$(do_rm) $(addprefix $(MISC_ASSERT_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/assert/__assert.c b/ap/build/uClibc/libc/misc/assert/__assert.c
new file mode 100644
index 0000000..8afde52
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/assert/__assert.c
@@ -0,0 +1,66 @@
+/*  Copyright (C) 2002     Manuel Novoa III
+ *  An __assert() function compatible with the modified glibc assert.h
+ *  that is used by uClibc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Oct 28, 2002
+ *
+ * ANSI/ISO C99 requires assert() to write to stderr.  This means that
+ * writing to STDERR_FILENO is insufficient, as the user could freopen
+ * stderr.  It is also insufficient to output to fileno(stderr) since
+ * this would fail in the custom stream case.  I didn't remove the
+ * old code though, as it doesn't use stdio stream functionality
+ * and is useful in debugging the stdio code.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Get the prototype from assert.h as a double-check. */
+#undef NDEBUG
+#include <assert.h>
+#undef assert
+
+
+#define ASSERT_SHOW_PROGNAME 1
+
+static smallint in_assert;			/* bss inits to 0. */
+
+void __assert(const char *assertion, const char * filename,
+	      unsigned int linenumber, register const char * function)
+{
+	if (!in_assert) {
+		in_assert = 1;
+
+		fprintf(stderr,
+#ifdef ASSERT_SHOW_PROGNAME
+				"%s: %s: %d: %s: Assertion `%s' failed.\n", __uclibc_progname,
+#else
+				"%s: %d: %s: Assertion `%s' failed.\n",
+#endif
+				filename,
+				linenumber,
+				/* Function name isn't available with some compilers. */
+				((function == NULL) ? "?function?" : function),
+				assertion
+				);
+	}
+	/* shouldn't we? fflush(stderr); */
+	abort();
+}
+libc_hidden_def(__assert)
diff --git a/ap/build/uClibc/libc/misc/ctype/.indent.pro b/ap/build/uClibc/libc/misc/ctype/.indent.pro
new file mode 100644
index 0000000..492ecf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/ap/build/uClibc/libc/misc/ctype/Makefile b/ap/build/uClibc/libc/misc/ctype/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/ctype/Makefile.in b/ap/build/uClibc/libc/misc/ctype/Makefile.in
new file mode 100644
index 0000000..125d916
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/Makefile.in
@@ -0,0 +1,42 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/ctype
+
+# multi source ctype.c
+COM_SRC := \
+	isalnum.c isalpha.c iscntrl.c isdigit.c \
+	isgraph.c islower.c isprint.c ispunct.c isspace.c \
+	isupper.c isxdigit.c tolower.c toupper.c \
+	isblank.c
+ifeq ($(UCLIBC_SUSV4_LEGACY),y)
+COM_SRC += isascii.c toascii.c
+endif
+CSRC := $(COM_SRC)
+
+ifeq ($(UCLIBC_HAS_CTYPE_TABLES),y)
+CSRC +=	__C_ctype_b.c __C_ctype_tolower.c __C_ctype_toupper.c \
+	__ctype_b_loc.c __ctype_tolower_loc.c __ctype_toupper_loc.c \
+	__ctype_assert.c isctype.c
+endif
+
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+CSRC += $(patsubst %.c,%_l.c,$(COM_SRC))
+endif
+
+MISC_CTYPE_DIR := $(top_srcdir)libc/misc/ctype
+MISC_CTYPE_OUT := $(top_builddir)libc/misc/ctype
+
+MISC_CTYPE_SRC := $(patsubst %.c,$(MISC_CTYPE_DIR)/%.c,$(CSRC))
+MISC_CTYPE_OBJ := $(patsubst %.c,$(MISC_CTYPE_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_CTYPE_OBJ)
+
+objclean-y += CLEAN_libc/misc/ctype
+
+CLEAN_libc/misc/ctype:
+	$(do_rm) $(addprefix $(MISC_CTYPE_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/ctype/__C_ctype_b.c b/ap/build/uClibc/libc/misc/ctype/__C_ctype_b.c
new file mode 100644
index 0000000..d22359f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/__C_ctype_b.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___C_ctype_b
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/__C_ctype_tolower.c b/ap/build/uClibc/libc/misc/ctype/__C_ctype_tolower.c
new file mode 100644
index 0000000..fc6027f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/__C_ctype_tolower.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___C_ctype_tolower
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/__C_ctype_toupper.c b/ap/build/uClibc/libc/misc/ctype/__C_ctype_toupper.c
new file mode 100644
index 0000000..ec42fbf
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/__C_ctype_toupper.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___C_ctype_toupper
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/__ctype_assert.c b/ap/build/uClibc/libc/misc/ctype/__ctype_assert.c
new file mode 100644
index 0000000..fe45945
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/__ctype_assert.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___ctype_assert
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/__ctype_b_loc.c b/ap/build/uClibc/libc/misc/ctype/__ctype_b_loc.c
new file mode 100644
index 0000000..11d5046
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/__ctype_b_loc.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___ctype_b_loc
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/__ctype_tolower_loc.c b/ap/build/uClibc/libc/misc/ctype/__ctype_tolower_loc.c
new file mode 100644
index 0000000..54037a5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/__ctype_tolower_loc.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___ctype_tolower_loc
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/__ctype_toupper_loc.c b/ap/build/uClibc/libc/misc/ctype/__ctype_toupper_loc.c
new file mode 100644
index 0000000..e511d0f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/__ctype_toupper_loc.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___ctype_toupper_loc
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/ctype.c b/ap/build/uClibc/libc/misc/ctype/ctype.c
new file mode 100644
index 0000000..1c40b24
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/ctype.c
@@ -0,0 +1,1083 @@
+/*  Copyright (C) 2003     Manuel Novoa III
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!
+ *
+ *  Besides uClibc, I'm using this code in my libc for elks, which is
+ *  a 16-bit environment with a fairly limited compiler.  It would make
+ *  things much easier for me if this file isn't modified unnecessarily.
+ *  In particular, please put any new or replacement functions somewhere
+ *  else, and modify the makefile to use your version instead.
+ *  Thanks.  Manuel
+ *
+ *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */
+
+#define __NO_CTYPE
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+#include <assert.h>
+#include <locale.h>
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+# include <xlocale.h>
+#endif
+
+/**********************************************************************/
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+
+#if EOF >= CHAR_MIN
+#define CTYPE_DOMAIN_CHECK(C) \
+	(((unsigned int)((C) - CHAR_MIN)) <= (UCHAR_MAX - CHAR_MIN))
+#else
+#define CTYPE_DOMAIN_CHECK(C) \
+	((((unsigned int)((C) - CHAR_MIN)) <= (UCHAR_MAX - CHAR_MIN)) || ((C) == EOF))
+#endif
+
+#else  /* __UCLIBC_HAS_CTYPE_SIGNED__ */
+
+#if EOF == -1
+#define CTYPE_DOMAIN_CHECK(C) \
+	(((unsigned int)((C) - EOF)) <= (UCHAR_MAX - EOF))
+#else
+#define CTYPE_DOMAIN_CHECK(C) \
+	((((unsigned int)(C)) <= UCHAR_MAX) || ((C) == EOF))
+#endif
+
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__ */
+
+#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
+/**********************************************************************/
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_isspace
+/* emit only once */
+#warning CONSIDER: Should we assert when debugging and __UCLIBC_HAS_CTYPE_CHECKED?
+#warning TODO: Fix asserts in to{upper|lower}{_l}.
+#warning TODO: Optimize the isx*() funcs.
+#endif
+#endif /* __UCLIBC_MJN3_ONLY__ */
+/**********************************************************************/
+#undef PASTE2
+#define PASTE2(X,Y)    X ## Y
+
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+
+#undef CTYPE_NAME
+#undef ISCTYPE
+#undef CTYPE_ALIAS
+#undef CTYPE_DEF
+#ifdef __UCLIBC_DO_XLOCALE
+#define CTYPE_NAME(X)  __is ## X ## _l
+#define ISCTYPE(C,F)   __isctype_l( C, F, locale_arg)
+#define CTYPE_ALIAS(NAME)   strong_alias( __is ## NAME ## _l , is ## NAME ## _l)
+#define CTYPE_DEF(NAME) libc_hidden_def(is ## NAME ## _l)
+#else
+#define CTYPE_NAME(X)  is ## X
+#define ISCTYPE(C,F)   __isctype( C, F )
+#define CTYPE_ALIAS(NAME)
+#define CTYPE_DEF(NAME) libc_hidden_def(is ## NAME)
+#endif
+
+
+#undef CTYPE_BODY
+
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+/* Make sure assert is active for to*() funcs below. */
+#undef NDEBUG
+#include <assert.h>
+
+extern void __isctype_assert(int c, int mask) __attribute__ ((__noreturn__)) attribute_hidden;
+
+#define CTYPE_BODY(NAME,C,MASK) \
+	if (CTYPE_DOMAIN_CHECK(C)) { \
+		return ISCTYPE(C, MASK); \
+	} \
+	__isctype_assert(C, MASK);
+
+#elif defined(__UCLIBC_HAS_CTYPE_CHECKED__)
+
+#define CTYPE_BODY(NAME,C,MASK) \
+	return CTYPE_DOMAIN_CHECK(C) \
+		? ISCTYPE(C, MASK) \
+		: 0;
+
+#elif defined(__UCLIBC_HAS_CTYPE_UNSAFE__)
+
+#define CTYPE_BODY(NAME,C,MASK) \
+	return ISCTYPE(C, MASK);
+
+
+#else  /* No checking done. */
+
+#error Unknown type of ctype checking!
+
+#endif
+
+
+
+#define IS_FUNC_BODY(NAME) \
+int CTYPE_NAME(NAME) (int c  __LOCALE_PARAM ); \
+int CTYPE_NAME(NAME) (int c  __LOCALE_PARAM ) \
+{ \
+	CTYPE_BODY(NAME,c,PASTE2(_IS,NAME)) \
+} \
+CTYPE_DEF(NAME) \
+CTYPE_ALIAS(NAME)
+
+#else  /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+#define C_MACRO(X)		PASTE2(__C_is,X)(c)
+#define CTYPE_NAME(X)  is ## X
+#define CTYPE_DEF(NAME) libc_hidden_def(is ## NAME)
+
+#define IS_FUNC_BODY(NAME) \
+int CTYPE_NAME(NAME) (int c) \
+{ \
+	return C_MACRO(NAME); \
+}
+
+#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
+/**********************************************************************/
+#ifdef L___ctype_assert
+#ifdef __UCLIBC_HAS_CTYPE_ENFORCED__
+
+
+attribute_hidden void __isctype_assert(int c, int mask)
+{
+	fprintf(stderr,	"%s: __is*{_l}(%d,%#x {locale})\n", __uclibc_progname, c, mask);
+	abort();
+}
+
+#endif
+#endif
+/**********************************************************************/
+#if defined(L_isalnum) || defined(L_isalnum_l)
+
+IS_FUNC_BODY(alnum);
+
+#endif
+/**********************************************************************/
+#if defined(L_isalpha) || defined(L_isalpha_l)
+
+IS_FUNC_BODY(alpha);
+
+#endif
+/**********************************************************************/
+#if defined(L_isblank) || defined(L_isblank_l)
+
+IS_FUNC_BODY(blank);
+
+#endif
+/**********************************************************************/
+#if defined(L_iscntrl) || defined(L_iscntrl_l)
+
+IS_FUNC_BODY(cntrl);
+
+#endif
+/**********************************************************************/
+#if defined(L_isdigit) || defined(L_isdigit_l)
+
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+
+/* The standards require EOF < 0. */
+#if EOF >= CHAR_MIN
+#define __isdigit_char_or_EOF(C)   __isdigit_char((C))
+#else
+#define __isdigit_char_or_EOF(C)   __isdigit_int((C))
+#endif
+
+int CTYPE_NAME(digit) (int C   __LOCALE_PARAM);
+int CTYPE_NAME(digit) (int C   __LOCALE_PARAM)
+{
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+	if (CTYPE_DOMAIN_CHECK(C)) {
+		return __isdigit_char_or_EOF(C); /* C is (unsigned) char or EOF. */
+	}
+	__isctype_assert(C, _ISdigit);
+#else
+	return __isdigit_int(C);	/* C could be invalid. */
+#endif
+}
+CTYPE_DEF(digit)
+CTYPE_ALIAS(digit)
+
+#else  /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+IS_FUNC_BODY(digit);
+
+#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+#endif
+/**********************************************************************/
+#if defined(L_isgraph) || defined(L_isgraph_l)
+
+IS_FUNC_BODY(graph);
+
+#endif
+/**********************************************************************/
+#if defined(L_islower) || defined(L_islower_l)
+
+IS_FUNC_BODY(lower);
+
+#endif
+/**********************************************************************/
+#if defined(L_isprint) || defined(L_isprint_l)
+
+IS_FUNC_BODY(print);
+
+#endif
+/**********************************************************************/
+#if defined(L_ispunct) || defined(L_ispunct_l)
+
+IS_FUNC_BODY(punct);
+
+#endif
+/**********************************************************************/
+#if defined(L_isspace) || defined(L_isspace_l)
+
+IS_FUNC_BODY(space);
+
+#endif
+/**********************************************************************/
+#if defined(L_isupper) || defined(L_isupper_l)
+
+IS_FUNC_BODY(upper);
+
+#endif
+/**********************************************************************/
+#if defined(L_isxdigit) || defined(L_isxdigit_l)
+
+IS_FUNC_BODY(xdigit);
+
+#endif
+/**********************************************************************/
+#ifdef L_tolower
+
+#undef tolower
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+
+int tolower(int c)
+{
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+	assert(CTYPE_DOMAIN_CHECK(c));
+#endif
+	return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? (__UCLIBC_CTYPE_TOLOWER)[c] : c;
+}
+
+#else  /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+int tolower(int c)
+{
+	return __C_tolower(c);
+}
+
+#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
+libc_hidden_def(tolower)
+
+#endif
+/**********************************************************************/
+#ifdef L_tolower_l
+
+#undef tolower_l
+int tolower_l(int c, __locale_t l)
+{
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+	assert(CTYPE_DOMAIN_CHECK(c));
+#endif
+	return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? l->__ctype_tolower[c] : c;
+}
+libc_hidden_def(tolower_l)
+
+#endif
+/**********************************************************************/
+#ifdef L_toupper
+
+#undef toupper
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+
+int toupper(int c)
+{
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+	assert(CTYPE_DOMAIN_CHECK(c));
+#endif
+	return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? (__UCLIBC_CTYPE_TOUPPER)[c] : c;
+}
+
+#else  /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+int toupper(int c)
+{
+	return __C_toupper(c);
+}
+
+#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
+libc_hidden_def(toupper)
+
+#endif
+/**********************************************************************/
+#ifdef L_toupper_l
+
+#undef toupper_l
+int toupper_l(int c, __locale_t l)
+{
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+	assert(CTYPE_DOMAIN_CHECK(c));
+#endif
+	return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? l->__ctype_toupper[c] : c;
+}
+
+#endif
+/**********************************************************************/
+#if defined(L_isascii) || defined(L_isascii_l)
+
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+
+int __XL_NPP(isascii)(int c);
+int __XL_NPP(isascii)(int c)
+{
+	return __isascii(c);		/* locale-independent */
+}
+
+#else  /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+int isascii(int c)
+{
+	return __isascii(c);		/* locale-independent */
+}
+
+#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
+CTYPE_DEF(ascii)
+
+
+#endif
+/**********************************************************************/
+#if defined(L_toascii) || defined(L_toascii_l)
+
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+
+int __XL_NPP(toascii)(int c);
+int __XL_NPP(toascii)(int c)
+{
+	return __toascii(c);		/* locale-independent */
+}
+
+#else  /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+int toascii(int c)
+{
+	return __toascii(c);		/* locale-independent */
+}
+
+#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+#endif
+/**********************************************************************/
+/* glibc extensions */
+/**********************************************************************/
+#ifdef L_isctype
+
+int isctype(int c, int mask)
+{
+	CTYPE_BODY(NAME,c,mask)
+}
+
+#endif
+/**********************************************************************/
+#ifdef L___ctype_b_loc
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+
+const __ctype_mask_t **__ctype_b_loc(void)
+{
+	return &(__UCLIBC_CURLOCALE->__ctype_b);
+}
+
+libc_hidden_def(__ctype_b_loc)
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L___ctype_tolower_loc
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+
+const __ctype_touplow_t **__ctype_tolower_loc(void)
+{
+	return &(__UCLIBC_CURLOCALE->__ctype_tolower);
+}
+libc_hidden_def(__ctype_tolower_loc)
+
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L___ctype_toupper_loc
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+
+const __ctype_touplow_t **__ctype_toupper_loc(void)
+{
+	return &(__UCLIBC_CURLOCALE->__ctype_toupper);
+}
+libc_hidden_def(__ctype_toupper_loc)
+
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L___C_ctype_b
+
+static const __ctype_mask_t __C_ctype_b_data[] = {
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+	/* -128  M-^@ */ 0,
+	/* -127  M-^A */ 0,
+	/* -126  M-^B */ 0,
+	/* -125  M-^C */ 0,
+	/* -124  M-^D */ 0,
+	/* -123  M-^E */ 0,
+	/* -122  M-^F */ 0,
+	/* -121  M-^G */ 0,
+	/* -120  M-^H */ 0,
+	/* -119  M-^I */ 0,
+	/* -118  M-^J */ 0,
+	/* -117  M-^K */ 0,
+	/* -116  M-^L */ 0,
+	/* -115  M-^M */ 0,
+	/* -114  M-^N */ 0,
+	/* -113  M-^O */ 0,
+	/* -112  M-^P */ 0,
+	/* -111  M-^Q */ 0,
+	/* -110  M-^R */ 0,
+	/* -109  M-^S */ 0,
+	/* -108  M-^T */ 0,
+	/* -107  M-^U */ 0,
+	/* -106  M-^V */ 0,
+	/* -105  M-^W */ 0,
+	/* -104  M-^X */ 0,
+	/* -103  M-^Y */ 0,
+	/* -102  M-^Z */ 0,
+	/* -101  M-^[ */ 0,
+	/* -100  M-^\ */ 0,
+	/*  -99  M-^] */ 0,
+	/*  -98  M-^^ */ 0,
+	/*  -97  M-^_ */ 0,
+	/*  -96  M-   */ 0,
+	/*  -95  M-!  */ 0,
+	/*  -94  M-"  */ 0,
+	/*  -93  M-#  */ 0,
+	/*  -92  M-$  */ 0,
+	/*  -91  M-%  */ 0,
+	/*  -90  M-&  */ 0,
+	/*  -89  M-'  */ 0,
+	/*  -88  M-(  */ 0,
+	/*  -87  M-)  */ 0,
+	/*  -86  M-*  */ 0,
+	/*  -85  M-+  */ 0,
+	/*  -84  M-,  */ 0,
+	/*  -83  M--  */ 0,
+	/*  -82  M-.  */ 0,
+	/*  -81  M-/  */ 0,
+	/*  -80  M-0  */ 0,
+	/*  -79  M-1  */ 0,
+	/*  -78  M-2  */ 0,
+	/*  -77  M-3  */ 0,
+	/*  -76  M-4  */ 0,
+	/*  -75  M-5  */ 0,
+	/*  -74  M-6  */ 0,
+	/*  -73  M-7  */ 0,
+	/*  -72  M-8  */ 0,
+	/*  -71  M-9  */ 0,
+	/*  -70  M-:  */ 0,
+	/*  -69  M-;  */ 0,
+	/*  -68  M-<  */ 0,
+	/*  -67  M-=  */ 0,
+	/*  -66  M->  */ 0,
+	/*  -65  M-?  */ 0,
+	/*  -64  M-@  */ 0,
+	/*  -63  M-A  */ 0,
+	/*  -62  M-B  */ 0,
+	/*  -61  M-C  */ 0,
+	/*  -60  M-D  */ 0,
+	/*  -59  M-E  */ 0,
+	/*  -58  M-F  */ 0,
+	/*  -57  M-G  */ 0,
+	/*  -56  M-H  */ 0,
+	/*  -55  M-I  */ 0,
+	/*  -54  M-J  */ 0,
+	/*  -53  M-K  */ 0,
+	/*  -52  M-L  */ 0,
+	/*  -51  M-M  */ 0,
+	/*  -50  M-N  */ 0,
+	/*  -49  M-O  */ 0,
+	/*  -48  M-P  */ 0,
+	/*  -47  M-Q  */ 0,
+	/*  -46  M-R  */ 0,
+	/*  -45  M-S  */ 0,
+	/*  -44  M-T  */ 0,
+	/*  -43  M-U  */ 0,
+	/*  -42  M-V  */ 0,
+	/*  -41  M-W  */ 0,
+	/*  -40  M-X  */ 0,
+	/*  -39  M-Y  */ 0,
+	/*  -38  M-Z  */ 0,
+	/*  -37  M-[  */ 0,
+	/*  -36  M-\  */ 0,
+	/*  -35  M-]  */ 0,
+	/*  -34  M-^  */ 0,
+	/*  -33  M-_  */ 0,
+	/*  -32  M-`  */ 0,
+	/*  -31  M-a  */ 0,
+	/*  -30  M-b  */ 0,
+	/*  -29  M-c  */ 0,
+	/*  -28  M-d  */ 0,
+	/*  -27  M-e  */ 0,
+	/*  -26  M-f  */ 0,
+	/*  -25  M-g  */ 0,
+	/*  -24  M-h  */ 0,
+	/*  -23  M-i  */ 0,
+	/*  -22  M-j  */ 0,
+	/*  -21  M-k  */ 0,
+	/*  -20  M-l  */ 0,
+	/*  -19  M-m  */ 0,
+	/*  -18  M-n  */ 0,
+	/*  -17  M-o  */ 0,
+	/*  -16  M-p  */ 0,
+	/*  -15  M-q  */ 0,
+	/*  -14  M-r  */ 0,
+	/*  -13  M-s  */ 0,
+	/*  -12  M-t  */ 0,
+	/*  -11  M-u  */ 0,
+	/*  -10  M-v  */ 0,
+	/*   -9  M-w  */ 0,
+	/*   -8  M-x  */ 0,
+	/*   -7  M-y  */ 0,
+	/*   -6  M-z  */ 0,
+	/*   -5  M-{  */ 0,
+	/*   -4  M-|  */ 0,
+	/*   -3  M-}  */ 0,
+	/*   -2  M-~  */ 0,
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/
+	/*   -1  M-^? */ 0,
+	/*    0  ^@   */ _IScntrl,
+	/*    1  ^A   */ _IScntrl,
+	/*    2  ^B   */ _IScntrl,
+	/*    3  ^C   */ _IScntrl,
+	/*    4  ^D   */ _IScntrl,
+	/*    5  ^E   */ _IScntrl,
+	/*    6  ^F   */ _IScntrl,
+	/*    7  ^G   */ _IScntrl,
+	/*    8  ^H   */ _IScntrl,
+	/*    9  ^I   */ _ISspace|_ISblank|_IScntrl,
+	/*   10  ^J   */ _ISspace|_IScntrl,
+	/*   11  ^K   */ _ISspace|_IScntrl,
+	/*   12  ^L   */ _ISspace|_IScntrl,
+	/*   13  ^M   */ _ISspace|_IScntrl,
+	/*   14  ^N   */ _IScntrl,
+	/*   15  ^O   */ _IScntrl,
+	/*   16  ^P   */ _IScntrl,
+	/*   17  ^Q   */ _IScntrl,
+	/*   18  ^R   */ _IScntrl,
+	/*   19  ^S   */ _IScntrl,
+	/*   20  ^T   */ _IScntrl,
+	/*   21  ^U   */ _IScntrl,
+	/*   22  ^V   */ _IScntrl,
+	/*   23  ^W   */ _IScntrl,
+	/*   24  ^X   */ _IScntrl,
+	/*   25  ^Y   */ _IScntrl,
+	/*   26  ^Z   */ _IScntrl,
+	/*   27  ^[   */ _IScntrl,
+	/*   28  ^\   */ _IScntrl,
+	/*   29  ^]   */ _IScntrl,
+	/*   30  ^^   */ _IScntrl,
+	/*   31  ^_   */ _IScntrl,
+	/*   32       */ _ISspace|_ISprint|_ISblank,
+	/*   33  !    */ _ISprint|_ISgraph|_ISpunct,
+	/*   34  "    */ _ISprint|_ISgraph|_ISpunct,
+	/*   35  #    */ _ISprint|_ISgraph|_ISpunct,
+	/*   36  $    */ _ISprint|_ISgraph|_ISpunct,
+	/*   37  %    */ _ISprint|_ISgraph|_ISpunct,
+	/*   38  &    */ _ISprint|_ISgraph|_ISpunct,
+	/*   39  '    */ _ISprint|_ISgraph|_ISpunct,
+	/*   40  (    */ _ISprint|_ISgraph|_ISpunct,
+	/*   41  )    */ _ISprint|_ISgraph|_ISpunct,
+	/*   42  *    */ _ISprint|_ISgraph|_ISpunct,
+	/*   43  +    */ _ISprint|_ISgraph|_ISpunct,
+	/*   44  ,    */ _ISprint|_ISgraph|_ISpunct,
+	/*   45  -    */ _ISprint|_ISgraph|_ISpunct,
+	/*   46  .    */ _ISprint|_ISgraph|_ISpunct,
+	/*   47  /    */ _ISprint|_ISgraph|_ISpunct,
+	/*   48  0    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   49  1    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   50  2    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   51  3    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   52  4    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   53  5    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   54  6    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   55  7    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   56  8    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   57  9    */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   58  :    */ _ISprint|_ISgraph|_ISpunct,
+	/*   59  ;    */ _ISprint|_ISgraph|_ISpunct,
+	/*   60  <    */ _ISprint|_ISgraph|_ISpunct,
+	/*   61  =    */ _ISprint|_ISgraph|_ISpunct,
+	/*   62  >    */ _ISprint|_ISgraph|_ISpunct,
+	/*   63  ?    */ _ISprint|_ISgraph|_ISpunct,
+	/*   64  @    */ _ISprint|_ISgraph|_ISpunct,
+	/*   65  A    */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   66  B    */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   67  C    */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   68  D    */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   69  E    */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   70  F    */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   71  G    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   72  H    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   73  I    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   74  J    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   75  K    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   76  L    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   77  M    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   78  N    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   79  O    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   80  P    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   81  Q    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   82  R    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   83  S    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   84  T    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   85  U    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   86  V    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   87  W    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   88  X    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   89  Y    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   90  Z    */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*   91  [    */ _ISprint|_ISgraph|_ISpunct,
+	/*   92  \    */ _ISprint|_ISgraph|_ISpunct,
+	/*   93  ]    */ _ISprint|_ISgraph|_ISpunct,
+	/*   94  ^    */ _ISprint|_ISgraph|_ISpunct,
+	/*   95  _    */ _ISprint|_ISgraph|_ISpunct,
+	/*   96  `    */ _ISprint|_ISgraph|_ISpunct,
+	/*   97  a    */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   98  b    */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*   99  c    */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*  100  d    */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*  101  e    */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*  102  f    */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+	/*  103  g    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  104  h    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  105  i    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  106  j    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  107  k    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  108  l    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  109  m    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  110  n    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  111  o    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  112  p    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  113  q    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  114  r    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  115  s    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  116  t    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  117  u    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  118  v    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  119  w    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  120  x    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  121  y    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  122  z    */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+	/*  123  {    */ _ISprint|_ISgraph|_ISpunct,
+	/*  124  |    */ _ISprint|_ISgraph|_ISpunct,
+	/*  125  }    */ _ISprint|_ISgraph|_ISpunct,
+	/*  126  ~    */ _ISprint|_ISgraph|_ISpunct,
+	/*  127  ^?   */ _IScntrl,
+	/*  128  M-^@ */ 0,
+	/*  129  M-^A */ 0,
+	/*  130  M-^B */ 0,
+	/*  131  M-^C */ 0,
+	/*  132  M-^D */ 0,
+	/*  133  M-^E */ 0,
+	/*  134  M-^F */ 0,
+	/*  135  M-^G */ 0,
+	/*  136  M-^H */ 0,
+	/*  137  M-^I */ 0,
+	/*  138  M-^J */ 0,
+	/*  139  M-^K */ 0,
+	/*  140  M-^L */ 0,
+	/*  141  M-^M */ 0,
+	/*  142  M-^N */ 0,
+	/*  143  M-^O */ 0,
+	/*  144  M-^P */ 0,
+	/*  145  M-^Q */ 0,
+	/*  146  M-^R */ 0,
+	/*  147  M-^S */ 0,
+	/*  148  M-^T */ 0,
+	/*  149  M-^U */ 0,
+	/*  150  M-^V */ 0,
+	/*  151  M-^W */ 0,
+	/*  152  M-^X */ 0,
+	/*  153  M-^Y */ 0,
+	/*  154  M-^Z */ 0,
+	/*  155  M-^[ */ 0,
+	/*  156  M-^\ */ 0,
+	/*  157  M-^] */ 0,
+	/*  158  M-^^ */ 0,
+	/*  159  M-^_ */ 0,
+	/*  160  M-   */ 0,
+	/*  161  M-!  */ 0,
+	/*  162  M-"  */ 0,
+	/*  163  M-#  */ 0,
+	/*  164  M-$  */ 0,
+	/*  165  M-%  */ 0,
+	/*  166  M-&  */ 0,
+	/*  167  M-'  */ 0,
+	/*  168  M-(  */ 0,
+	/*  169  M-)  */ 0,
+	/*  170  M-*  */ 0,
+	/*  171  M-+  */ 0,
+	/*  172  M-,  */ 0,
+	/*  173  M--  */ 0,
+	/*  174  M-.  */ 0,
+	/*  175  M-/  */ 0,
+	/*  176  M-0  */ 0,
+	/*  177  M-1  */ 0,
+	/*  178  M-2  */ 0,
+	/*  179  M-3  */ 0,
+	/*  180  M-4  */ 0,
+	/*  181  M-5  */ 0,
+	/*  182  M-6  */ 0,
+	/*  183  M-7  */ 0,
+	/*  184  M-8  */ 0,
+	/*  185  M-9  */ 0,
+	/*  186  M-:  */ 0,
+	/*  187  M-;  */ 0,
+	/*  188  M-<  */ 0,
+	/*  189  M-=  */ 0,
+	/*  190  M->  */ 0,
+	/*  191  M-?  */ 0,
+	/*  192  M-@  */ 0,
+	/*  193  M-A  */ 0,
+	/*  194  M-B  */ 0,
+	/*  195  M-C  */ 0,
+	/*  196  M-D  */ 0,
+	/*  197  M-E  */ 0,
+	/*  198  M-F  */ 0,
+	/*  199  M-G  */ 0,
+	/*  200  M-H  */ 0,
+	/*  201  M-I  */ 0,
+	/*  202  M-J  */ 0,
+	/*  203  M-K  */ 0,
+	/*  204  M-L  */ 0,
+	/*  205  M-M  */ 0,
+	/*  206  M-N  */ 0,
+	/*  207  M-O  */ 0,
+	/*  208  M-P  */ 0,
+	/*  209  M-Q  */ 0,
+	/*  210  M-R  */ 0,
+	/*  211  M-S  */ 0,
+	/*  212  M-T  */ 0,
+	/*  213  M-U  */ 0,
+	/*  214  M-V  */ 0,
+	/*  215  M-W  */ 0,
+	/*  216  M-X  */ 0,
+	/*  217  M-Y  */ 0,
+	/*  218  M-Z  */ 0,
+	/*  219  M-[  */ 0,
+	/*  220  M-\  */ 0,
+	/*  221  M-]  */ 0,
+	/*  222  M-^  */ 0,
+	/*  223  M-_  */ 0,
+	/*  224  M-`  */ 0,
+	/*  225  M-a  */ 0,
+	/*  226  M-b  */ 0,
+	/*  227  M-c  */ 0,
+	/*  228  M-d  */ 0,
+	/*  229  M-e  */ 0,
+	/*  230  M-f  */ 0,
+	/*  231  M-g  */ 0,
+	/*  232  M-h  */ 0,
+	/*  233  M-i  */ 0,
+	/*  234  M-j  */ 0,
+	/*  235  M-k  */ 0,
+	/*  236  M-l  */ 0,
+	/*  237  M-m  */ 0,
+	/*  238  M-n  */ 0,
+	/*  239  M-o  */ 0,
+	/*  240  M-p  */ 0,
+	/*  241  M-q  */ 0,
+	/*  242  M-r  */ 0,
+	/*  243  M-s  */ 0,
+	/*  244  M-t  */ 0,
+	/*  245  M-u  */ 0,
+	/*  246  M-v  */ 0,
+	/*  247  M-w  */ 0,
+	/*  248  M-x  */ 0,
+	/*  249  M-y  */ 0,
+	/*  250  M-z  */ 0,
+	/*  251  M-{  */ 0,
+	/*  252  M-|  */ 0,
+	/*  253  M-}  */ 0,
+	/*  254  M-~  */ 0,
+	/*  255  M-^? */ 0
+};
+
+const __ctype_mask_t *__C_ctype_b = __C_ctype_b_data + __UCLIBC_CTYPE_B_TBL_OFFSET;
+libc_hidden_data_def(__C_ctype_b)
+
+#ifndef __UCLIBC_HAS_XLOCALE__
+
+const __ctype_mask_t *__ctype_b = __C_ctype_b_data + __UCLIBC_CTYPE_B_TBL_OFFSET;
+libc_hidden_data_def(__ctype_b)
+
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L___C_ctype_tolower
+
+static const __ctype_touplow_t __C_ctype_tolower_data[] = {
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+	-128,         -127,         -126,         -125,
+	-124,         -123,         -122,         -121,
+	-120,         -119,         -118,         -117,
+	-116,         -115,         -114,         -113,
+	-112,         -111,         -110,         -109,
+	-108,         -107,         -106,         -105,
+	-104,         -103,         -102,         -101,
+	-100,          -99,          -98,          -97,
+	 -96,          -95,          -94,          -93,
+	 -92,          -91,          -90,          -89,
+	 -88,          -87,          -86,          -85,
+	 -84,          -83,          -82,          -81,
+	 -80,          -79,          -78,          -77,
+	 -76,          -75,          -74,          -73,
+	 -72,          -71,          -70,          -69,
+	 -68,          -67,          -66,          -65,
+	 -64,          -63,          -62,          -61,
+	 -60,          -59,          -58,          -57,
+	 -56,          -55,          -54,          -53,
+	 -52,          -51,          -50,          -49,
+	 -48,          -47,          -46,          -45,
+	 -44,          -43,          -42,          -41,
+	 -40,          -39,          -38,          -37,
+	 -36,          -35,          -34,          -33,
+	 -32,          -31,          -30,          -29,
+	 -28,          -27,          -26,          -25,
+	 -24,          -23,          -22,          -21,
+	 -20,          -19,          -18,          -17,
+	 -16,          -15,          -14,          -13,
+	 -12,          -11,          -10,           -9,
+	  -8,           -7,           -6,           -5,
+	  -4,           -3,           -2,           -1,
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/
+	   0,            1,            2,            3,
+	   4,            5,            6,            7,
+	   8,            9,           10,           11,
+	  12,           13,           14,           15,
+	  16,           17,           18,           19,
+	  20,           21,           22,           23,
+	  24,           25,           26,           27,
+	  28,           29,           30,           31,
+	  32,           33,           34,           35,
+	  36,           37,           38,           39,
+	  40,           41,           42,           43,
+	  44,           45,           46,           47,
+	  48,           49,           50,           51,
+	  52,           53,           54,           55,
+	  56,           57,           58,           59,
+	  60,           61,           62,           63,
+	  64,           97 /* a */,   98 /* b */,   99 /* c */,
+	 100 /* d */,  101 /* e */,  102 /* f */,  103 /* g */,
+	 104 /* h */,  105 /* i */,  106 /* j */,  107 /* k */,
+	 108 /* l */,  109 /* m */,  110 /* n */,  111 /* o */,
+	 112 /* p */,  113 /* q */,  114 /* r */,  115 /* s */,
+	 116 /* t */,  117 /* u */,  118 /* v */,  119 /* w */,
+	 120 /* x */,  121 /* y */,  122 /* z */,   91,
+	  92,           93,           94,           95,
+	  96,           97,           98,           99,
+	 100,          101,          102,          103,
+	 104,          105,          106,          107,
+	 108,          109,          110,          111,
+	 112,          113,          114,          115,
+	 116,          117,          118,          119,
+	 120,          121,          122,          123,
+	 124,          125,          126,          127,
+	 128,          129,          130,          131,
+	 132,          133,          134,          135,
+	 136,          137,          138,          139,
+	 140,          141,          142,          143,
+	 144,          145,          146,          147,
+	 148,          149,          150,          151,
+	 152,          153,          154,          155,
+	 156,          157,          158,          159,
+	 160,          161,          162,          163,
+	 164,          165,          166,          167,
+	 168,          169,          170,          171,
+	 172,          173,          174,          175,
+	 176,          177,          178,          179,
+	 180,          181,          182,          183,
+	 184,          185,          186,          187,
+	 188,          189,          190,          191,
+	 192,          193,          194,          195,
+	 196,          197,          198,          199,
+	 200,          201,          202,          203,
+	 204,          205,          206,          207,
+	 208,          209,          210,          211,
+	 212,          213,          214,          215,
+	 216,          217,          218,          219,
+	 220,          221,          222,          223,
+	 224,          225,          226,          227,
+	 228,          229,          230,          231,
+	 232,          233,          234,          235,
+	 236,          237,          238,          239,
+	 240,          241,          242,          243,
+	 244,          245,          246,          247,
+	 248,          249,          250,          251,
+	 252,          253,          254,          255
+};
+
+const __ctype_touplow_t *__C_ctype_tolower =
+		__C_ctype_tolower_data + __UCLIBC_CTYPE_TO_TBL_OFFSET;
+libc_hidden_data_def(__C_ctype_tolower)
+
+#ifndef __UCLIBC_HAS_XLOCALE__
+
+const __ctype_touplow_t *__ctype_tolower =
+		__C_ctype_tolower_data + __UCLIBC_CTYPE_TO_TBL_OFFSET;
+libc_hidden_data_def(__ctype_tolower)
+
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L___C_ctype_toupper
+
+static const __ctype_touplow_t __C_ctype_toupper_data[] = {
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+	-128,         -127,         -126,         -125,
+	-124,         -123,         -122,         -121,
+	-120,         -119,         -118,         -117,
+	-116,         -115,         -114,         -113,
+	-112,         -111,         -110,         -109,
+	-108,         -107,         -106,         -105,
+	-104,         -103,         -102,         -101,
+	-100,          -99,          -98,          -97,
+	 -96,          -95,          -94,          -93,
+	 -92,          -91,          -90,          -89,
+	 -88,          -87,          -86,          -85,
+	 -84,          -83,          -82,          -81,
+	 -80,          -79,          -78,          -77,
+	 -76,          -75,          -74,          -73,
+	 -72,          -71,          -70,          -69,
+	 -68,          -67,          -66,          -65,
+	 -64,          -63,          -62,          -61,
+	 -60,          -59,          -58,          -57,
+	 -56,          -55,          -54,          -53,
+	 -52,          -51,          -50,          -49,
+	 -48,          -47,          -46,          -45,
+	 -44,          -43,          -42,          -41,
+	 -40,          -39,          -38,          -37,
+	 -36,          -35,          -34,          -33,
+	 -32,          -31,          -30,          -29,
+	 -28,          -27,          -26,          -25,
+	 -24,          -23,          -22,          -21,
+	 -20,          -19,          -18,          -17,
+	 -16,          -15,          -14,          -13,
+	 -12,          -11,          -10,           -9,
+	  -8,           -7,           -6,           -5,
+	  -4,           -3,           -2,           -1,
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/
+	   0,            1,            2,            3,
+	   4,            5,            6,            7,
+	   8,            9,           10,           11,
+	  12,           13,           14,           15,
+	  16,           17,           18,           19,
+	  20,           21,           22,           23,
+	  24,           25,           26,           27,
+	  28,           29,           30,           31,
+	  32,           33,           34,           35,
+	  36,           37,           38,           39,
+	  40,           41,           42,           43,
+	  44,           45,           46,           47,
+	  48,           49,           50,           51,
+	  52,           53,           54,           55,
+	  56,           57,           58,           59,
+	  60,           61,           62,           63,
+	  64,           65,           66,           67,
+	  68,           69,           70,           71,
+	  72,           73,           74,           75,
+	  76,           77,           78,           79,
+	  80,           81,           82,           83,
+	  84,           85,           86,           87,
+	  88,           89,           90,           91,
+	  92,           93,           94,           95,
+	  96,           65 /* A */,   66 /* B */,   67 /* C */,
+	  68 /* D */,   69 /* E */,   70 /* F */,   71 /* G */,
+	  72 /* H */,   73 /* I */,   74 /* J */,   75 /* K */,
+	  76 /* L */,   77 /* M */,   78 /* N */,   79 /* O */,
+	  80 /* P */,   81 /* Q */,   82 /* R */,   83 /* S */,
+	  84 /* T */,   85 /* U */,   86 /* V */,   87 /* W */,
+	  88 /* X */,   89 /* Y */,   90 /* Z */,  123,
+	 124,          125,          126,          127,
+	 128,          129,          130,          131,
+	 132,          133,          134,          135,
+	 136,          137,          138,          139,
+	 140,          141,          142,          143,
+	 144,          145,          146,          147,
+	 148,          149,          150,          151,
+	 152,          153,          154,          155,
+	 156,          157,          158,          159,
+	 160,          161,          162,          163,
+	 164,          165,          166,          167,
+	 168,          169,          170,          171,
+	 172,          173,          174,          175,
+	 176,          177,          178,          179,
+	 180,          181,          182,          183,
+	 184,          185,          186,          187,
+	 188,          189,          190,          191,
+	 192,          193,          194,          195,
+	 196,          197,          198,          199,
+	 200,          201,          202,          203,
+	 204,          205,          206,          207,
+	 208,          209,          210,          211,
+	 212,          213,          214,          215,
+	 216,          217,          218,          219,
+	 220,          221,          222,          223,
+	 224,          225,          226,          227,
+	 228,          229,          230,          231,
+	 232,          233,          234,          235,
+	 236,          237,          238,          239,
+	 240,          241,          242,          243,
+	 244,          245,          246,          247,
+	 248,          249,          250,          251,
+	 252,          253,          254,          255
+};
+
+const __ctype_touplow_t *__C_ctype_toupper =
+		__C_ctype_toupper_data + __UCLIBC_CTYPE_TO_TBL_OFFSET;
+libc_hidden_data_def(__C_ctype_toupper)
+
+#ifndef __UCLIBC_HAS_XLOCALE__
+
+const __ctype_touplow_t *__ctype_toupper =
+		__C_ctype_toupper_data + __UCLIBC_CTYPE_TO_TBL_OFFSET;
+libc_hidden_data_def(__ctype_toupper)
+
+#endif
+
+#endif
+/**********************************************************************/
diff --git a/ap/build/uClibc/libc/misc/ctype/isalnum.c b/ap/build/uClibc/libc/misc/ctype/isalnum.c
new file mode 100644
index 0000000..8bc8ad6
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isalnum.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isalnum
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isalnum_l.c b/ap/build/uClibc/libc/misc/ctype/isalnum_l.c
new file mode 100644
index 0000000..8ecd9d5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isalnum_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isalnum_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isalpha.c b/ap/build/uClibc/libc/misc/ctype/isalpha.c
new file mode 100644
index 0000000..22f23d9
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isalpha.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isalpha
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isalpha_l.c b/ap/build/uClibc/libc/misc/ctype/isalpha_l.c
new file mode 100644
index 0000000..10a2ecf
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isalpha_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isalpha_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isascii.c b/ap/build/uClibc/libc/misc/ctype/isascii.c
new file mode 100644
index 0000000..84f701f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isascii.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isascii
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isascii_l.c b/ap/build/uClibc/libc/misc/ctype/isascii_l.c
new file mode 100644
index 0000000..7fe5545
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isascii_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isascii_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isblank.c b/ap/build/uClibc/libc/misc/ctype/isblank.c
new file mode 100644
index 0000000..d11fe26
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isblank.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isblank
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isblank_l.c b/ap/build/uClibc/libc/misc/ctype/isblank_l.c
new file mode 100644
index 0000000..144cd93
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isblank_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isblank_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/iscntrl.c b/ap/build/uClibc/libc/misc/ctype/iscntrl.c
new file mode 100644
index 0000000..4a0c09d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/iscntrl.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iscntrl
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/iscntrl_l.c b/ap/build/uClibc/libc/misc/ctype/iscntrl_l.c
new file mode 100644
index 0000000..fbee951
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/iscntrl_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iscntrl_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isctype.c b/ap/build/uClibc/libc/misc/ctype/isctype.c
new file mode 100644
index 0000000..a2d0b3d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isctype.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isctype
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isdigit.c b/ap/build/uClibc/libc/misc/ctype/isdigit.c
new file mode 100644
index 0000000..e185c89
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isdigit.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isdigit
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isdigit_l.c b/ap/build/uClibc/libc/misc/ctype/isdigit_l.c
new file mode 100644
index 0000000..5b764f1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isdigit_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isdigit_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isgraph.c b/ap/build/uClibc/libc/misc/ctype/isgraph.c
new file mode 100644
index 0000000..c4ad1b7
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isgraph.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isgraph
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isgraph_l.c b/ap/build/uClibc/libc/misc/ctype/isgraph_l.c
new file mode 100644
index 0000000..005e19f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isgraph_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isgraph_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/islower.c b/ap/build/uClibc/libc/misc/ctype/islower.c
new file mode 100644
index 0000000..aff65dd
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/islower.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_islower
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/islower_l.c b/ap/build/uClibc/libc/misc/ctype/islower_l.c
new file mode 100644
index 0000000..dd08557
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/islower_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_islower_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isprint.c b/ap/build/uClibc/libc/misc/ctype/isprint.c
new file mode 100644
index 0000000..b6f7d6c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isprint.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isprint
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isprint_l.c b/ap/build/uClibc/libc/misc/ctype/isprint_l.c
new file mode 100644
index 0000000..32f9b3f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isprint_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isprint_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/ispunct.c b/ap/build/uClibc/libc/misc/ctype/ispunct.c
new file mode 100644
index 0000000..08f7b19
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/ispunct.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_ispunct
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/ispunct_l.c b/ap/build/uClibc/libc/misc/ctype/ispunct_l.c
new file mode 100644
index 0000000..513bb52
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/ispunct_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_ispunct_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isspace.c b/ap/build/uClibc/libc/misc/ctype/isspace.c
new file mode 100644
index 0000000..c8ff567
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isspace.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isspace
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isspace_l.c b/ap/build/uClibc/libc/misc/ctype/isspace_l.c
new file mode 100644
index 0000000..97e0c99
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isspace_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isspace_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isupper.c b/ap/build/uClibc/libc/misc/ctype/isupper.c
new file mode 100644
index 0000000..36d6e6e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isupper.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isupper
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isupper_l.c b/ap/build/uClibc/libc/misc/ctype/isupper_l.c
new file mode 100644
index 0000000..8aa4dbd
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isupper_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isupper_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isxdigit.c b/ap/build/uClibc/libc/misc/ctype/isxdigit.c
new file mode 100644
index 0000000..40919f7
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isxdigit.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isxdigit
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/isxdigit_l.c b/ap/build/uClibc/libc/misc/ctype/isxdigit_l.c
new file mode 100644
index 0000000..5dce7f1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/isxdigit_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_isxdigit_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/toascii.c b/ap/build/uClibc/libc/misc/ctype/toascii.c
new file mode 100644
index 0000000..a63b993
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/toascii.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_toascii
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/toascii_l.c b/ap/build/uClibc/libc/misc/ctype/toascii_l.c
new file mode 100644
index 0000000..6179526
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/toascii_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_toascii_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/tolower.c b/ap/build/uClibc/libc/misc/ctype/tolower.c
new file mode 100644
index 0000000..3673642
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/tolower.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_tolower
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/tolower_l.c b/ap/build/uClibc/libc/misc/ctype/tolower_l.c
new file mode 100644
index 0000000..327e63c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/tolower_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_tolower_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/toupper.c b/ap/build/uClibc/libc/misc/ctype/toupper.c
new file mode 100644
index 0000000..a9d8aab
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/toupper.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_toupper
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/ctype/toupper_l.c b/ap/build/uClibc/libc/misc/ctype/toupper_l.c
new file mode 100644
index 0000000..c91d791
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ctype/toupper_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2003-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_toupper_l
+#define __UCLIBC_DO_XLOCALE
+#include "ctype.c"
diff --git a/ap/build/uClibc/libc/misc/dirent/Makefile b/ap/build/uClibc/libc/misc/dirent/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/dirent/Makefile.in b/ap/build/uClibc/libc/misc/dirent/Makefile.in
new file mode 100644
index 0000000..d42dfeb
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/Makefile.in
@@ -0,0 +1,28 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/dirent
+
+CSRC :=	alphasort.c closedir.c dirfd.c opendir.c readdir.c rewinddir.c \
+	scandir.c seekdir.c telldir.c readdir_r.c versionsort.c
+
+ifeq ($(UCLIBC_HAS_LFS),y)
+CSRC +=	readdir64.c alphasort64.c scandir64.c readdir64_r.c versionsort64.c
+endif
+
+MISC_DIRENT_DIR := $(top_srcdir)libc/misc/dirent
+MISC_DIRENT_OUT := $(top_builddir)libc/misc/dirent
+
+MISC_DIRENT_SRC := $(patsubst %.c,$(MISC_DIRENT_DIR)/%.c,$(CSRC))
+MISC_DIRENT_OBJ := $(patsubst %.c,$(MISC_DIRENT_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_DIRENT_OBJ)
+
+objclean-y += CLEAN_libc/misc/dirent
+
+CLEAN_libc/misc/dirent:
+	$(do_rm) $(addprefix $(MISC_DIRENT_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/dirent/alphasort.c b/ap/build/uClibc/libc/misc/dirent/alphasort.c
new file mode 100644
index 0000000..eb0dbf2
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/alphasort.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <dirent.h>
+#include <string.h>
+#include "dirstream.h"
+
+int alphasort(const struct dirent **a, const struct dirent **b)
+{
+	return strcmp((*a)->d_name, (*b)->d_name);
+}
+
diff --git a/ap/build/uClibc/libc/misc/dirent/alphasort64.c b/ap/build/uClibc/libc/misc/dirent/alphasort64.c
new file mode 100644
index 0000000..d65b596
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/alphasort64.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <_lfs_64.h>
+
+#include <dirent.h>
+#include <string.h>
+#include "dirstream.h"
+
+int alphasort64(const struct dirent64 **a, const struct dirent64 **b)
+{
+	return strcmp((*a)->d_name, (*b)->d_name);
+}
diff --git a/ap/build/uClibc/libc/misc/dirent/closedir.c b/ap/build/uClibc/libc/misc/dirent/closedir.c
new file mode 100644
index 0000000..dfb53f8
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/closedir.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "dirstream.h"
+#include <not-cancel.h>
+
+
+int closedir(DIR * dir)
+{
+	int fd;
+
+	if (!dir) {
+		__set_errno(EBADF);
+		return -1;
+	}
+
+	/* We need to check dd_fd. */
+	if (dir->dd_fd == -1) {
+		__set_errno(EBADF);
+		return -1;
+	}
+	__UCLIBC_MUTEX_LOCK(dir->dd_lock);
+	fd = dir->dd_fd;
+	dir->dd_fd = -1;
+	__UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+	free(dir->dd_buf);
+	free(dir);
+	return close_not_cancel(fd);
+}
+libc_hidden_def(closedir)
diff --git a/ap/build/uClibc/libc/misc/dirent/dirfd.c b/ap/build/uClibc/libc/misc/dirent/dirfd.c
new file mode 100644
index 0000000..649dd4a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/dirfd.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include "dirstream.h"
+
+
+int dirfd(DIR * dir)
+{
+	if (!dir || dir->dd_fd == -1) {
+		__set_errno(EBADF);
+		return -1;
+	}
+
+	return dir->dd_fd;
+}
+libc_hidden_def(dirfd)
diff --git a/ap/build/uClibc/libc/misc/dirent/dirstream.h b/ap/build/uClibc/libc/misc/dirent/dirstream.h
new file mode 100644
index 0000000..370886a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/dirstream.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/*
+ *	POSIX Standard: 5.1.2 Directory Operations	<dirent.h>
+ */
+
+#ifndef	_DIRSTREAM_H
+
+#define	_DIRSTREAM_H	1
+
+#include <features.h>
+#include <sys/types.h>
+
+#include <bits/uClibc_mutex.h>
+
+/* For now, syscall readdir () only supports one entry at a time. It
+ * will be changed in the future.
+#define NUMENT		3
+*/
+#ifndef NUMENT
+#define NUMENT		1
+#endif
+
+#define SINGLE_READDIR	11
+#define MULTI_READDIR	12
+#define NEW_READDIR	13
+
+/* Directory stream type.  */
+struct __dirstream {
+  /* file descriptor */
+  int dd_fd;
+
+  /* offset of the next dir entry in buffer */
+  size_t dd_nextloc;
+
+  /* bytes of valid entries in buffer */
+  size_t dd_size;
+
+  /* -> directory buffer */
+  void *dd_buf;
+
+  /* offset of the next dir entry in directory. */
+  off_t dd_nextoff;
+
+  /* total size of buffer */
+  size_t dd_max;
+
+  /* lock */
+  __UCLIBC_MUTEX(dd_lock);
+};				/* stream data from opendir() */
+
+
+extern ssize_t __getdents(int fd, char *buf, size_t count) attribute_hidden;
+#ifdef __UCLIBC_HAS_LFS__
+extern ssize_t __getdents64 (int fd, char *buf, size_t count) attribute_hidden;
+#endif
+
+#endif /* dirent.h  */
diff --git a/ap/build/uClibc/libc/misc/dirent/opendir.c b/ap/build/uClibc/libc/misc/dirent/opendir.c
new file mode 100644
index 0000000..66a5cc9
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/opendir.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include <not-cancel.h>
+#include <dirent.h>
+#include "dirstream.h"
+
+static DIR *fd_to_DIR(int fd, __blksize_t size)
+{
+	DIR *ptr;
+
+	ptr = malloc(sizeof(*ptr));
+	if (!ptr)
+		return NULL;
+
+	ptr->dd_fd = fd;
+	ptr->dd_nextloc = ptr->dd_size = ptr->dd_nextoff = 0;
+	ptr->dd_max = size;
+	if (ptr->dd_max < 512)
+		ptr->dd_max = 512;
+
+	ptr->dd_buf = calloc(1, ptr->dd_max);
+	if (!ptr->dd_buf) {
+		free(ptr);
+		return NULL;
+	}
+	__UCLIBC_MUTEX_INIT_VAR(ptr->dd_lock);
+
+	return ptr;
+}
+
+DIR *fdopendir(int fd)
+{
+	int flags;
+	struct stat st;
+
+	if (fstat(fd, &st))
+		return NULL;
+	if (!S_ISDIR(st.st_mode)) {
+		__set_errno(ENOTDIR);
+		return NULL;
+	}
+
+	flags = fcntl(fd, F_GETFL);
+	if (flags == -1)
+		return NULL;
+	if ((flags & O_ACCMODE) == O_WRONLY) {
+		__set_errno(EINVAL);
+		return NULL;
+	}
+
+	return fd_to_DIR(fd, st.st_blksize);
+}
+
+/* opendir just makes an open() call - it return NULL if it fails
+ * (open sets errno), otherwise it returns a DIR * pointer.
+ */
+DIR *opendir(const char *name)
+{
+	int fd;
+	struct stat statbuf;
+	DIR *ptr;
+
+#ifndef O_DIRECTORY
+	/* O_DIRECTORY is linux specific and has been around since like 2.1.x */
+	if (stat(name, &statbuf))
+		return NULL;
+	if (!S_ISDIR(statbuf.st_mode)) {
+		__set_errno(ENOTDIR);
+		return NULL;
+	}
+# define O_DIRECTORY 0
+#endif
+	fd = open_not_cancel_2(name, O_RDONLY|O_NDELAY|O_DIRECTORY|O_CLOEXEC);
+	if (fd < 0)
+		return NULL;
+	/* Note: we should check to make sure that between the stat() and open()
+	 * call, 'name' didnt change on us, but that's only if O_DIRECTORY isnt
+	 * defined and since Linux has supported it for like ever, i'm not going
+	 * to worry about it right now (if ever). */
+
+	if (fstat(fd, &statbuf) < 0) {
+		/* this close() never fails
+		 *int saved_errno;
+		 *saved_errno = errno; */
+		close_not_cancel_no_status(fd);
+		/*__set_errno(saved_errno);*/
+		return NULL;
+	}
+
+	/* According to POSIX, directory streams should be closed when
+	 * exec. From "Anna Pluzhnikov" <besp@midway.uchicago.edu>.
+	 */
+#ifndef __ASSUME_O_CLOEXEC
+	fcntl_not_cancel(fd, F_SETFD, FD_CLOEXEC);
+#endif
+
+	ptr = fd_to_DIR(fd, statbuf.st_blksize);
+
+	if (!ptr) {
+		close_not_cancel_no_status(fd);
+		__set_errno(ENOMEM);
+	}
+	return ptr;
+}
+libc_hidden_def(opendir)
diff --git a/ap/build/uClibc/libc/misc/dirent/readdir.c b/ap/build/uClibc/libc/misc/dirent/readdir.c
new file mode 100644
index 0000000..4fcd1cc
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/readdir.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <features.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "dirstream.h"
+
+
+struct dirent *readdir(DIR * dir)
+{
+	ssize_t bytes;
+	struct dirent *de;
+
+	if (!dir) {
+		__set_errno(EBADF);
+		return NULL;
+	}
+
+	__UCLIBC_MUTEX_LOCK(dir->dd_lock);
+
+	do {
+	    if (dir->dd_size <= dir->dd_nextloc) {
+		/* read dir->dd_max bytes of directory entries. */
+		bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
+		if (bytes <= 0) {
+		    de = NULL;
+		    goto all_done;
+		}
+		dir->dd_size = bytes;
+		dir->dd_nextloc = 0;
+	    }
+
+	    de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+
+	    /* Am I right? H.J. */
+	    dir->dd_nextloc += de->d_reclen;
+
+	    /* We have to save the next offset here. */
+	    dir->dd_nextoff = de->d_off;
+
+	    /* Skip deleted files.  */
+	} while (de->d_ino == 0);
+
+all_done:
+	__UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+	return de;
+}
+libc_hidden_def(readdir)
diff --git a/ap/build/uClibc/libc/misc/dirent/readdir64.c b/ap/build/uClibc/libc/misc/dirent/readdir64.c
new file mode 100644
index 0000000..1264c38
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/readdir64.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <_lfs_64.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "dirstream.h"
+
+struct dirent64 *readdir64(DIR * dir)
+{
+	ssize_t bytes;
+	struct dirent64 *de;
+
+	if (!dir) {
+		__set_errno(EBADF);
+		return NULL;
+	}
+
+	__UCLIBC_MUTEX_LOCK(dir->dd_lock);
+
+	do {
+	    if (dir->dd_size <= dir->dd_nextloc) {
+		/* read dir->dd_max bytes of directory entries. */
+		bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max);
+		if (bytes <= 0) {
+		    de = NULL;
+		    goto all_done;
+		}
+		dir->dd_size = bytes;
+		dir->dd_nextloc = 0;
+	    }
+
+	    de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+
+	    /* Am I right? H.J. */
+	    dir->dd_nextloc += de->d_reclen;
+
+	    /* We have to save the next offset here. */
+	    dir->dd_nextoff = de->d_off;
+
+	    /* Skip deleted files.  */
+	} while (de->d_ino == 0);
+
+all_done:
+	__UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+
+	return de;
+}
+libc_hidden_def(readdir64)
diff --git a/ap/build/uClibc/libc/misc/dirent/readdir64_r.c b/ap/build/uClibc/libc/misc/dirent/readdir64_r.c
new file mode 100644
index 0000000..ba72600
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/readdir64_r.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <_lfs_64.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "dirstream.h"
+
+
+int readdir64_r(DIR *dir, struct dirent64 *entry, struct dirent64 **result)
+{
+	int ret;
+	ssize_t bytes;
+	struct dirent64 *de;
+
+	if (!dir) {
+	    __set_errno(EBADF);
+	    return(EBADF);
+	}
+	de = NULL;
+
+	__UCLIBC_MUTEX_LOCK(dir->dd_lock);
+
+	do {
+	    if (dir->dd_size <= dir->dd_nextloc) {
+		/* read dir->dd_max bytes of directory entries. */
+		bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max);
+		if (bytes <= 0) {
+		    *result = NULL;
+		    ret = (bytes==0)? 0 : errno;
+		    goto all_done;
+		}
+		dir->dd_size = bytes;
+		dir->dd_nextloc = 0;
+	    }
+
+	    de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+
+	    /* Am I right? H.J. */
+	    dir->dd_nextloc += de->d_reclen;
+
+	    /* We have to save the next offset here. */
+	    dir->dd_nextoff = de->d_off;
+	    /* Skip deleted files.  */
+	} while (de->d_ino == 0);
+
+	if (de == NULL) {
+	    *result = NULL;
+	} else {
+	    *result = memcpy (entry, de, de->d_reclen);
+	}
+	ret = 0;
+
+all_done:
+
+	__UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+        return((de != NULL)? 0 : ret);
+}
+libc_hidden_def(readdir64_r)
diff --git a/ap/build/uClibc/libc/misc/dirent/readdir_r.c b/ap/build/uClibc/libc/misc/dirent/readdir_r.c
new file mode 100644
index 0000000..d08997f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/readdir_r.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "dirstream.h"
+
+
+int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result)
+{
+	int ret;
+	ssize_t bytes;
+	struct dirent *de;
+
+	if (!dir) {
+	    __set_errno(EBADF);
+	    return(EBADF);
+	}
+	de = NULL;
+
+	__UCLIBC_MUTEX_LOCK(dir->dd_lock);
+
+	do {
+	    if (dir->dd_size <= dir->dd_nextloc) {
+		/* read dir->dd_max bytes of directory entries. */
+		bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
+		if (bytes <= 0) {
+		    *result = NULL;
+		    ret = (bytes==0)? 0 : errno;
+		    goto all_done;
+		}
+		dir->dd_size = bytes;
+		dir->dd_nextloc = 0;
+	    }
+
+	    de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+
+	    /* Am I right? H.J. */
+	    dir->dd_nextloc += de->d_reclen;
+
+	    /* We have to save the next offset here. */
+	    dir->dd_nextoff = de->d_off;
+	    /* Skip deleted files.  */
+	} while (de->d_ino == 0);
+
+	if (de == NULL) {
+	    *result = NULL;
+	} else {
+	    *result = memcpy (entry, de, de->d_reclen);
+	}
+	ret = 0;
+
+all_done:
+
+	__UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+	return((de != NULL)? 0 : ret);
+}
+libc_hidden_def(readdir_r)
diff --git a/ap/build/uClibc/libc/misc/dirent/rewinddir.c b/ap/build/uClibc/libc/misc/dirent/rewinddir.c
new file mode 100644
index 0000000..0a8f147
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/rewinddir.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include "dirstream.h"
+
+
+/* rewinddir() just does an lseek(fd,0,0) - see close for comments */
+void rewinddir(DIR * dir)
+{
+	if (!dir) {
+		__set_errno(EBADF);
+		return;
+	}
+	__UCLIBC_MUTEX_LOCK(dir->dd_lock);
+	lseek(dir->dd_fd, 0, SEEK_SET);
+	dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0;
+	__UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+}
diff --git a/ap/build/uClibc/libc/misc/dirent/scandir.c b/ap/build/uClibc/libc/misc/dirent/scandir.c
new file mode 100644
index 0000000..bb42564
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/scandir.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include "dirstream.h"
+
+int scandir(const char *dir, struct dirent ***namelist,
+	int (*selector) (const struct dirent *),
+	int (*compar) (const struct dirent **, const struct dirent **))
+{
+    DIR *dp = opendir (dir);
+    struct dirent *current;
+    struct dirent **names = NULL;
+    size_t names_size = 0, pos;
+    int save;
+
+    if (dp == NULL)
+	return -1;
+
+    save = errno;
+    __set_errno (0);
+
+    pos = 0;
+    while ((current = readdir (dp)) != NULL) {
+	int use_it = selector == NULL;
+
+	if (! use_it)
+	{
+	    use_it = (*selector) (current);
+	    /* The selector function might have changed errno.
+	     * It was zero before and it need to be again to make
+	     * the latter tests work.  */
+	    if (! use_it)
+		__set_errno (0);
+	}
+	if (use_it)
+	{
+	    struct dirent *vnew;
+	    size_t dsize;
+
+	    /* Ignore errors from selector or readdir */
+	    __set_errno (0);
+
+	    if (unlikely(pos == names_size))
+	    {
+		struct dirent **new;
+		if (names_size == 0)
+		    names_size = 10;
+		else
+		    names_size *= 2;
+		new = (struct dirent **) realloc (names,
+					names_size * sizeof (struct dirent *));
+		if (new == NULL)
+		    break;
+		names = new;
+	    }
+
+	    dsize = &current->d_name[_D_ALLOC_NAMLEN(current)] - (char*)current;
+	    vnew = (struct dirent *) malloc (dsize);
+	    if (vnew == NULL)
+		break;
+
+	    names[pos++] = (struct dirent *) memcpy (vnew, current, dsize);
+	}
+    }
+
+    if (unlikely(errno != 0))
+    {
+	save = errno;
+	closedir (dp);
+	while (pos > 0)
+	    free (names[--pos]);
+	free (names);
+	__set_errno (save);
+	return -1;
+    }
+
+    closedir (dp);
+    __set_errno (save);
+
+    /* Sort the list if we have a comparison function to sort with.  */
+    if (compar != NULL)
+	qsort (names, pos, sizeof (struct dirent *), (comparison_fn_t) compar);
+    *namelist = names;
+    return pos;
+}
diff --git a/ap/build/uClibc/libc/misc/dirent/scandir64.c b/ap/build/uClibc/libc/misc/dirent/scandir64.c
new file mode 100644
index 0000000..3d2a250
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/scandir64.c
@@ -0,0 +1,111 @@
+/* Copyright (C) 1992-1998, 2000 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+   */
+
+/* Modified for uClibc by Erik Andersen
+   */
+
+#include <_lfs_64.h>
+
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include "dirstream.h"
+
+int scandir64(const char *dir, struct dirent64 ***namelist,
+	int (*selector) (const struct dirent64 *),
+	int (*compar) (const struct dirent64 **, const struct dirent64 **))
+{
+    DIR *dp = opendir (dir);
+    struct dirent64 *current;
+    struct dirent64 **names = NULL;
+    size_t names_size = 0, pos;
+    int save;
+
+    if (dp == NULL)
+	return -1;
+
+    save = errno;
+    __set_errno (0);
+
+    pos = 0;
+    while ((current = readdir64 (dp)) != NULL) {
+	int use_it = selector == NULL;
+
+	if (! use_it)
+	{
+	    use_it = (*selector) (current);
+	    /* The selector function might have changed errno.
+	     * It was zero before and it need to be again to make
+	     * the latter tests work.  */
+	    if (! use_it)
+		__set_errno (0);
+	}
+	if (use_it)
+	{
+	    struct dirent64 *vnew;
+	    size_t dsize;
+
+	    /* Ignore errors from selector or readdir64 */
+	    __set_errno (0);
+
+	    if (unlikely(pos == names_size))
+	    {
+		struct dirent64 **new;
+		if (names_size == 0)
+		    names_size = 10;
+		else
+		    names_size *= 2;
+		new = (struct dirent64 **) realloc (names,
+				      names_size * sizeof (struct dirent64 *));
+		if (new == NULL)
+		    break;
+		names = new;
+	    }
+
+	    dsize = &current->d_name[_D_ALLOC_NAMLEN(current)] - (char*)current;
+	    vnew = (struct dirent64 *) malloc (dsize);
+	    if (vnew == NULL)
+		break;
+
+	    names[pos++] = (struct dirent64 *) memcpy (vnew, current, dsize);
+	}
+    }
+    if (unlikely(errno != 0))
+    {
+	save = errno;
+	closedir (dp);
+	while (pos > 0)
+	    free (names[--pos]);
+	free (names);
+	__set_errno (save);
+	return -1;
+    }
+
+    closedir (dp);
+    __set_errno (save);
+
+    /* Sort the list if we have a comparison function to sort with.  */
+    if (compar != NULL)
+	qsort (names, pos, sizeof (struct dirent64 *), (comparison_fn_t) compar);
+    *namelist = names;
+    return pos;
+}
diff --git a/ap/build/uClibc/libc/misc/dirent/seekdir.c b/ap/build/uClibc/libc/misc/dirent/seekdir.c
new file mode 100644
index 0000000..eaf447e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/seekdir.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include "dirstream.h"
+
+
+void seekdir(DIR * dir, long int offset)
+{
+	if (!dir) {
+		__set_errno(EBADF);
+		return;
+	}
+	__UCLIBC_MUTEX_LOCK(dir->dd_lock);
+	dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET);
+	dir->dd_size = dir->dd_nextloc = 0;
+	__UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+}
diff --git a/ap/build/uClibc/libc/misc/dirent/telldir.c b/ap/build/uClibc/libc/misc/dirent/telldir.c
new file mode 100644
index 0000000..3c5deca
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/telldir.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include "dirstream.h"
+
+
+long int telldir(DIR * dir)
+{
+	if (!dir) {
+		__set_errno(EBADF);
+		return -1;
+	}
+
+	/* The next entry. */
+	return dir->dd_nextoff;
+}
diff --git a/ap/build/uClibc/libc/misc/dirent/versionsort.c b/ap/build/uClibc/libc/misc/dirent/versionsort.c
new file mode 100644
index 0000000..d84da1f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/versionsort.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2008-2009 Hai Zaar, Codefidence Ltd <haizaar@codefidence.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <dirent.h>
+#include <string.h>
+#include "dirstream.h"
+
+int versionsort(const struct dirent **a, const struct dirent **b)
+{
+	return strverscmp((*a)->d_name, (*b)->d_name);
+}
diff --git a/ap/build/uClibc/libc/misc/dirent/versionsort64.c b/ap/build/uClibc/libc/misc/dirent/versionsort64.c
new file mode 100644
index 0000000..af9689e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/dirent/versionsort64.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2008-2009 Hai Zaar, Codefidence Ltd <haizaar@codefidence.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <_lfs_64.h>
+
+#include <dirent.h>
+#include <string.h>
+#include "dirstream.h"
+
+int versionsort64(const struct dirent64 **a, const struct dirent64 **b)
+{
+	return strverscmp((*a)->d_name, (*b)->d_name);
+}
diff --git a/ap/build/uClibc/libc/misc/elf/Makefile b/ap/build/uClibc/libc/misc/elf/Makefile
new file mode 100644
index 0000000..4bb6872
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/elf/Makefile
@@ -0,0 +1,12 @@
+# Copyright (C) 2008 STMicroelectronics Ltd.
+# Author: Carmelo Amoroso <carmelo.amoroso@st.com>
+
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/elf/Makefile.in b/ap/build/uClibc/libc/misc/elf/Makefile.in
new file mode 100644
index 0000000..1b4bd8b
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/elf/Makefile.in
@@ -0,0 +1,22 @@
+# Copyright (C) 2008 STMicroelectronics Ltd.
+# Author: Carmelo Amoroso <carmelo.amoroso@st.com>
+
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/elf
+
+libc_a_CSRC = dl-support.c dl-core.c dl-iterate-phdr.c
+CFLAGS-dl-iterate-phdr.c=-D_GNU_SOURCE -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include
+CFLAGS-dl-core.c=-I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include
+
+MISC_ELF_OUT:=$(top_builddir)libc/misc/elf
+MISC_ELF_OBJ:=$(patsubst %.c,$(MISC_ELF_OUT)/%.o,$(libc_a_CSRC))
+
+libc-static-y += $(MISC_ELF_OBJ)
+libc-shared-y += $(MISC_ELF_OUT)/dl-iterate-phdr.oS
+
+objclean-y+= CLEAN_libc/misc/elf
+
+CLEAN_libc/misc/elf:
+	$(do_rm) $(addprefix $(MISC_ELF_OUT)/*., o os oS)
diff --git a/ap/build/uClibc/libc/misc/elf/dl-core.c b/ap/build/uClibc/libc/misc/elf/dl-core.c
new file mode 100644
index 0000000..b32dcf8
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/elf/dl-core.c
@@ -0,0 +1,20 @@
+/*
+ * This contains all symbols and functions to support
+ * dynamic linking into static libc.
+
+ * Copyright (c) 2008  STMicroelectronics Ltd
+ * Author: Carmelo Amoroso <carmelo.amoroso@st.com>
+ *
+ * Based on draft work by Peter S. Mazinger <ps.m@gmx.net>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ */
+
+#ifdef SHARED
+#error "This file is not suitable for linking into dynamic libc"
+#else
+/* Include ldso symbols and functions used into static libc */
+#include "../../../ldso/ldso/dl-symbols.c"
+#endif
+
diff --git a/ap/build/uClibc/libc/misc/elf/dl-iterate-phdr.c b/ap/build/uClibc/libc/misc/elf/dl-iterate-phdr.c
new file mode 100644
index 0000000..f0233ca
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/elf/dl-iterate-phdr.c
@@ -0,0 +1,85 @@
+/* Get loaded objects program headers.
+
+  Based on GNU C library (file: libc/elf/dl-iteratephdr.c)
+
+  Copyright (C) 2001,2002,2003,2004,2006,2007 Free Software Foundation, Inc.
+  Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
+
+  Copyright (C) 2008 STMicroelectronics Ltd.
+  Author: Carmelo Amoroso <carmelo.amoroso@st.com>
+
+  Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+*/
+
+
+#include <link.h>
+#include <ldso.h>
+
+/* we want this in libc but nowhere else */
+#ifdef __USE_GNU
+
+extern __typeof(dl_iterate_phdr) __dl_iterate_phdr;
+
+hidden_proto(__dl_iterate_phdr)
+int
+__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data)
+{
+	int ret = 0;
+#ifndef __ARCH_HAS_NO_SHARED__
+	struct elf_resolve *l;
+	struct dl_phdr_info info;
+
+	for (l = _dl_loaded_modules; l != NULL; l = l->next) {
+		info.dlpi_addr = l->loadaddr;
+		info.dlpi_name = l->libname;
+		info.dlpi_phdr = l->ppnt;
+		info.dlpi_phnum = l->n_phent;
+		ret = callback (&info, sizeof (struct dl_phdr_info), data);
+		if (ret)
+			break;
+	}
+#endif
+	return ret;
+}
+hidden_def (__dl_iterate_phdr)
+
+# ifdef SHARED
+
+weak_alias(__dl_iterate_phdr, dl_iterate_phdr)
+
+# else
+
+/* dl-support.c defines these and initializes them early on.  */
+extern ElfW(Phdr) *_dl_phdr;
+extern size_t _dl_phnum;
+
+int
+dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
+                                  size_t size, void *data), void *data)
+{
+  if (_dl_phnum != 0)
+    {
+      /* This entry describes this statically-linked program itself.  */
+      struct dl_phdr_info info;
+      int ret;
+#if defined(__FDPIC__)
+      info.dlpi_addr.map = NULL;
+      info.dlpi_addr.got_value = NULL;
+#elif defined(__DSBT__)
+      info.dlpi_addr.map = NULL;
+#else
+      info.dlpi_addr = 0;
+#endif
+      info.dlpi_name = "";
+      info.dlpi_phdr = _dl_phdr;
+      info.dlpi_phnum = _dl_phnum;
+      ret = (*callback) (&info, sizeof (struct dl_phdr_info), data);
+      if (ret)
+        return ret;
+    }
+   /* Then invoke callback on loaded modules, if any */
+  return __dl_iterate_phdr (callback, data);
+}
+
+# endif
+#endif
diff --git a/ap/build/uClibc/libc/misc/elf/dl-support.c b/ap/build/uClibc/libc/misc/elf/dl-support.c
new file mode 100644
index 0000000..f194692
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/elf/dl-support.c
@@ -0,0 +1,70 @@
+/*
+ * Support for dynamic linking code in static libc.
+ * Copyright (C) 1996-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ *
+ * Partially based on GNU C Library (file: libc/elf/dl-support.c)
+ *
+ * Copyright (C) 2008 STMicroelectronics Ltd.
+ * Author: Carmelo Amoroso <carmelo.amoroso@st.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ */
+
+#include <link.h>
+#include <elf.h>
+#if defined(USE_TLS) && USE_TLS
+#include <assert.h>
+#include <tls.h>
+#include <ldsodefs.h>
+#include <string.h>
+#endif
+
+#if defined(USE_TLS) && USE_TLS
+
+void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
+
+#endif
+
+ElfW(Phdr) *_dl_phdr;
+size_t _dl_phnum;
+
+void internal_function _dl_aux_init (ElfW(auxv_t) *av);
+void internal_function _dl_aux_init (ElfW(auxv_t) *av)
+{
+   /* Get the program headers base address from the aux vect */
+   _dl_phdr = (ElfW(Phdr) *) av[AT_PHDR].a_un.a_val;
+
+   /* Get the number of program headers from the aux vect */
+   _dl_phnum = (size_t) av[AT_PHNUM].a_un.a_val;
+}
+
+#if defined(USE_TLS) && USE_TLS
+/* Initialize static TLS area and DTV for current (only) thread.
+   libpthread implementations should provide their own hook
+   to handle all threads.  */
+void
+attribute_hidden
+_dl_nothread_init_static_tls (struct link_map *map)
+{
+# if defined(TLS_TCB_AT_TP)
+  void *dest = (char *) THREAD_SELF - map->l_tls_offset;
+# elif defined(TLS_DTV_AT_TP)
+  void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
+# else
+#  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+  /* Fill in the DTV slot so that a later LD/GD access will find it.  */
+  dtv_t *dtv = THREAD_DTV ();
+  assert (map->l_tls_modid <= dtv[-1].counter);
+  dtv[map->l_tls_modid].pointer.val = dest;
+  dtv[map->l_tls_modid].pointer.is_static = true;
+
+  /* Initialize the memory.  */
+  memset (mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
+}
+
+#endif
+
diff --git a/ap/build/uClibc/libc/misc/error/Makefile b/ap/build/uClibc/libc/misc/error/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/error/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/error/Makefile.in b/ap/build/uClibc/libc/misc/error/Makefile.in
new file mode 100644
index 0000000..b76a0df
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/error/Makefile.in
@@ -0,0 +1,29 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/error
+
+CSRC :=
+ifeq ($(UCLIBC_HAS_BSD_ERR),y)
+CSRC += err.c
+endif
+ifeq ($(UCLIBC_HAS_GNU_ERROR),y)
+CSRC += error.c
+endif
+
+MISC_ERROR_DIR := $(top_srcdir)libc/misc/error
+MISC_ERROR_OUT := $(top_builddir)libc/misc/error
+
+MISC_ERROR_SRC := $(patsubst %.c,$(MISC_ERROR_DIR)/%.c,$(CSRC))
+MISC_ERROR_OBJ := $(patsubst %.c,$(MISC_ERROR_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_ERROR_OBJ)
+
+objclean-y += CLEAN_libc/misc/error
+
+CLEAN_libc/misc/error:
+	$(do_rm) $(addprefix $(MISC_ERROR_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/error/err.c b/ap/build/uClibc/libc/misc/error/err.c
new file mode 100644
index 0000000..9ddb596
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/error/err.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org>
+ *
+ * GNU Library General Public License (LGPL) version 2 or later.
+ *
+ * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <err.h>
+#ifdef __UCLIBC_HAS_THREADS__
+#include <pthread.h>
+#endif
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: Deal with wide oriented stderr case.
+#endif
+
+#if defined __USE_BSD
+
+
+
+static void vwarn_work(const char *format, va_list args, int showerr)
+{
+	/*                         0123 45678 9 a b*/
+	static const char fmt[] = "%s: \0: %s\n\0\n";
+	const char *f;
+	char buf[64];
+	__STDIO_AUTO_THREADLOCK_VAR;
+
+	/* Do this first, in case something below changes errno. */
+	f = fmt + 11;				/* At 11. */
+	if (showerr) {
+		f -= 4;					/* At 7. */
+		__xpg_strerror_r(errno, buf, sizeof(buf));
+	}
+
+	__STDIO_AUTO_THREADLOCK(stderr);
+
+	fprintf(stderr, fmt, __uclibc_progname);
+	if (format) {
+		vfprintf(stderr, format, args);
+		f -= 2;					/* At 5 (showerr) or 9. */
+	}
+	fprintf(stderr, f, buf);
+
+	__STDIO_AUTO_THREADUNLOCK(stderr);
+}
+
+void vwarn(const char *format, va_list args)
+{
+	vwarn_work(format, args, 1);
+}
+libc_hidden_def(vwarn)
+
+void warn(const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	vwarn(format, args);
+	va_end(args);
+}
+
+void vwarnx(const char *format, va_list args)
+{
+	vwarn_work(format, args, 0);
+}
+libc_hidden_def(vwarnx)
+
+void warnx(const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	vwarnx(format, args);
+	va_end(args);
+}
+
+void verr(int status, const char *format, va_list args)
+{
+	vwarn(format, args);
+	exit(status);
+}
+libc_hidden_def(verr)
+
+void attribute_noreturn err(int status, const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	verr(status, format, args);
+	/* This should get optimized away.  We'll leave it now for safety. */
+	/* The loop is added only to keep gcc happy. */
+	while(1)
+		va_end(args);
+}
+
+void verrx(int status, const char *format, va_list args)
+{
+	vwarnx(format, args);
+	exit(status);
+}
+libc_hidden_def(verrx)
+
+void attribute_noreturn errx(int status, const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	verrx(status, format, args);
+	/* This should get optimized away.  We'll leave it now for safety. */
+	/* The loop is added only to keep gcc happy. */
+	while(1)
+		va_end(args);
+}
+#endif
diff --git a/ap/build/uClibc/libc/misc/error/error.c b/ap/build/uClibc/libc/misc/error/error.c
new file mode 100644
index 0000000..a30a4de
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/error/error.c
@@ -0,0 +1,106 @@
+/* Error handler for noninteractive utilities
+   Copyright (C) 1990-1998, 2000-2004, 2005 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
+/* Adjusted slightly by Erik Andersen <andersen@uclibc.org> */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <error.h>
+
+
+/* This variable is incremented each time `error' is called.  */
+unsigned int error_message_count = 0;
+/* Sometimes we want to have at most one error per line.  This
+   variable controls whether this mode is selected or not.  */
+int error_one_per_line;
+/* If NULL, error will flush stdout, then print on stderr the program
+   name, a colon and a space.  Otherwise, error will call this
+   function without parameters instead.  */
+void (*error_print_progname) (void) = NULL;
+
+extern __typeof(error) __error attribute_hidden;
+void __error (int status, int errnum, const char *message, ...)
+{
+    va_list args;
+
+    fflush (stdout);
+
+    if (error_print_progname)
+	(*error_print_progname) ();
+    else
+	fprintf (stderr, "%s: ", __uclibc_progname);
+
+    va_start (args, message);
+    vfprintf (stderr, message, args);
+    va_end (args);
+    ++error_message_count;
+    if (errnum) {
+	fprintf (stderr, ": %s", strerror (errnum));
+    }
+    putc ('\n', stderr);
+    if (status)
+	exit (status);
+}
+weak_alias(__error,error)
+
+extern __typeof(error_at_line) __error_at_line attribute_hidden;
+void __error_at_line (int status, int errnum, const char *file_name,
+	       unsigned int line_number, const char *message, ...)
+{
+    va_list args;
+
+    if (error_one_per_line) {
+	static const char *old_file_name;
+	static unsigned int old_line_number;
+
+	if (old_line_number == line_number &&
+		(file_name == old_file_name || !strcmp (old_file_name, file_name)))
+	    /* Simply return and print nothing.  */
+	    return;
+
+	old_file_name = file_name;
+	old_line_number = line_number;
+    }
+
+    fflush (stdout);
+
+    if (error_print_progname)
+	(*error_print_progname) ();
+    else
+	fprintf (stderr, "%s:", __uclibc_progname);
+
+    if (file_name != NULL)
+	fprintf (stderr, "%s:%d: ", file_name, line_number);
+
+    va_start (args, message);
+    vfprintf (stderr, message, args);
+    va_end (args);
+
+    ++error_message_count;
+    if (errnum) {
+	fprintf (stderr, ": %s", strerror (errnum));
+    }
+    putc ('\n', stderr);
+    if (status)
+	exit (status);
+}
+weak_alias(__error_at_line,error_at_line)
diff --git a/ap/build/uClibc/libc/misc/file/Makefile b/ap/build/uClibc/libc/misc/file/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/file/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/file/Makefile.in b/ap/build/uClibc/libc/misc/file/Makefile.in
new file mode 100644
index 0000000..ace9db0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/file/Makefile.in
@@ -0,0 +1,26 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/file
+
+MISC_FILE_DIR := $(top_srcdir)libc/misc/file
+MISC_FILE_OUT := $(top_builddir)libc/misc/file
+
+MISC_FILE_SRC := $(wildcard $(MISC_FILE_DIR)/*.c)
+ifneq ($(UCLIBC_HAS_LFS),y)
+MISC_FILE_SRC := $(filter-out $(MISC_FILE_DIR)/lockf64.c,$(MISC_FILE_SRC))
+endif
+MISC_FILE_OBJ := $(patsubst $(MISC_FILE_DIR)/%.c,$(MISC_FILE_OUT)/%.o,$(MISC_FILE_SRC))
+
+libc-y += $(MISC_FILE_OBJ)
+
+libc-nomulti-$(UCLIBC_HAS_LFS) += $(MISC_FILE_OUT)/lockf64.o
+
+objclean-y += CLEAN_libc/misc/file
+
+CLEAN_libc/misc/file:
+	$(do_rm) $(addprefix $(MISC_FILE_OUT)/*., o os oS)
diff --git a/ap/build/uClibc/libc/misc/file/lockf.c b/ap/build/uClibc/libc/misc/file/lockf.c
new file mode 100644
index 0000000..b37ace4
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/file/lockf.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1994, 1996, 1997, 1998, 2000 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <features.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+
+
+/* lockf is a simplified interface to fcntl's locking facilities.  */
+
+int lockf (int fd, int cmd, off_t len)
+{
+    struct flock fl;
+
+    memset ((char *) &fl, '\0', sizeof (fl));
+
+    /* lockf is always relative to the current file position.  */
+    fl.l_whence = SEEK_CUR;
+    fl.l_start = 0;
+    fl.l_len = len;
+
+    switch (cmd)
+    {
+	case F_TEST:
+	    /* Test the lock: return 0 if FD is unlocked or locked by this process;
+	       return -1, set errno to EACCES, if another process holds the lock.  */
+	    fl.l_type = F_RDLCK;
+	    if (fcntl (fd, F_GETLK, &fl) < 0)
+		return -1;
+	    if (fl.l_type == F_UNLCK || fl.l_pid == getpid ())
+		return 0;
+	    __set_errno(EACCES);
+	    return -1;
+
+	case F_ULOCK:
+	    fl.l_type = F_UNLCK;
+	    cmd = F_SETLK;
+	    break;
+	case F_LOCK:
+	    fl.l_type = F_WRLCK;
+	    cmd = F_SETLKW;
+	    break;
+	case F_TLOCK:
+	    fl.l_type = F_WRLCK;
+	    cmd = F_SETLK;
+	    break;
+
+	default:
+	    __set_errno(EINVAL);
+	    return -1;
+    }
+
+    return fcntl(fd, cmd, &fl);
+}
+libc_hidden_def(lockf)
diff --git a/ap/build/uClibc/libc/misc/file/lockf64.c b/ap/build/uClibc/libc/misc/file/lockf64.c
new file mode 100644
index 0000000..1779424
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/file/lockf64.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 1994, 1996, 1997, 1998, 2000 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <_lfs_64.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/syscall.h>
+
+#ifdef __NR_fcntl64
+#define flock flock64
+#define fcntl fcntl64
+#undef F_GETLK
+#define F_GETLK F_GETLK64
+#undef F_SETLK
+#define F_SETLK F_SETLK64
+#else
+#endif
+
+
+/* lockf is a simplified interface to fcntl's locking facilities.  */
+
+int lockf64 (int fd, int cmd, off64_t len64)
+{
+    struct flock fl;
+    off_t len = (off_t) len64;
+
+    if (len64 != (off64_t) len)
+    {
+	/* We can't represent the length.  */
+	__set_errno(EOVERFLOW);
+	return -1;
+    }
+
+    memset((char *) &fl, '\0', sizeof (fl));
+
+    /* lockf is always relative to the current file position.  */
+    fl.l_whence = SEEK_CUR;
+    fl.l_start = 0;
+    fl.l_len = len;
+
+    switch (cmd)
+    {
+	case F_TEST:
+	    /* Test the lock: return 0 if FD is unlocked or locked by this process;
+	       return -1, set errno to EACCES, if another process holds the lock.  */
+	    fl.l_type = F_RDLCK;
+	    if (fcntl (fd, F_GETLK, &fl) < 0)
+		return -1;
+	    if (fl.l_type == F_UNLCK || fl.l_pid == getpid ())
+		return 0;
+	    __set_errno(EACCES);
+	    return -1;
+
+	case F_ULOCK:
+	    fl.l_type = F_UNLCK;
+	    cmd = F_SETLK;
+	    break;
+	case F_LOCK:
+	    fl.l_type = F_WRLCK;
+	    cmd = F_SETLKW;
+	    break;
+	case F_TLOCK:
+	    fl.l_type = F_WRLCK;
+	    cmd = F_SETLK;
+	    break;
+
+	default:
+	    __set_errno(EINVAL);
+	    return -1;
+    }
+
+    return fcntl(fd, cmd, &fl);
+}
+libc_hidden_def(lockf64)
diff --git a/ap/build/uClibc/libc/misc/fnmatch/.indent.pro b/ap/build/uClibc/libc/misc/fnmatch/.indent.pro
new file mode 100644
index 0000000..492ecf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fnmatch/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/ap/build/uClibc/libc/misc/fnmatch/Makefile b/ap/build/uClibc/libc/misc/fnmatch/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fnmatch/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/fnmatch/Makefile.in b/ap/build/uClibc/libc/misc/fnmatch/Makefile.in
new file mode 100644
index 0000000..2557b5a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fnmatch/Makefile.in
@@ -0,0 +1,27 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/fnmatch
+
+ifeq ($(UCLIBC_HAS_FNMATCH_OLD),y)
+CSRC := fnmatch_old.c
+else
+CSRC := fnmatch.c
+endif
+
+MISC_FNMATCH_DIR := $(top_srcdir)libc/misc/fnmatch
+MISC_FNMATCH_OUT := $(top_builddir)libc/misc/fnmatch
+
+MISC_FNMATCH_SRC := $(patsubst %.c,$(MISC_FNMATCH_DIR)/%.c,$(CSRC))
+MISC_FNMATCH_OBJ := $(patsubst %.c,$(MISC_FNMATCH_OUT)/%.o,$(CSRC))
+
+libc-$(UCLIBC_HAS_FNMATCH) += $(MISC_FNMATCH_OBJ)
+
+objclean-y += CLEAN_libc/misc/fnmatch
+
+CLEAN_libc/misc/fnmatch:
+	$(do_rm) $(addprefix $(MISC_FNMATCH_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/fnmatch/fnmatch.c b/ap/build/uClibc/libc/misc/fnmatch/fnmatch.c
new file mode 100644
index 0000000..2874413
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fnmatch/fnmatch.c
@@ -0,0 +1,435 @@
+/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003
+	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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* unistd.h must be included with _LIBC defined: we need smallint */
+#include <unistd.h>
+#include <features.h>
+#ifdef __UCLIBC__
+# undef _LIBC
+# define HAVE_STRING_H 1
+# define STDC_HEADERS
+# define HAVE___STRCHRNUL 1
+# ifdef __UCLIBC_HAS_WCHAR__
+#  define HAVE_WCHAR_H 1
+#  define HAVE_WCTYPE_H 1
+#  ifdef __UCLIBC_HAS_LOCALE__
+#   define HAVE_MBSTATE_T 1
+#   define HAVE_MBSRTOWCS 1
+#  endif
+# endif
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fnmatch.h>
+#include <ctype.h>
+
+#if HAVE_STRING_H || defined _LIBC
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+#endif
+
+#ifdef __UCLIBC__
+# define __memset memset
+#endif
+
+/* For platform which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+# include <wchar.h>
+# include <wctype.h>
+#endif
+
+/* We need some of the locale data (the collation sequence information)
+   but there is no interface to get this information in general.  Therefore
+   we support a correct implementation only in glibc.  */
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# include "../locale/elem-hash.h"
+# include "../locale/coll-lookup.h"
+# include <shlib-compat.h>
+
+# define CONCAT(a,b) __CONCAT(a,b)
+# define mbsrtowcs __mbsrtowcs
+# define fnmatch __fnmatch
+extern int fnmatch (const char *pattern, const char *string, int flags);
+#endif
+
+/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set.  */
+#define NO_LEADING_PERIOD(flags) \
+  ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined _LIBC || !defined __GNU_LIBRARY__
+
+
+# if defined STDC_HEADERS || !defined isascii
+#  define ISASCII(c) 1
+# else
+#  define ISASCII(c) isascii(c)
+# endif
+
+# ifdef isblank
+#  define ISBLANK(c) (ISASCII (c) && isblank (c))
+# else
+#  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# endif
+# ifdef isgraph
+#  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+# else
+#  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+# endif
+
+# define ISPRINT(c) (ISASCII (c) && isprint (c))
+# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+# define ISALNUM(c) (ISASCII (c) && isalnum (c))
+# define ISALPHA(c) (ISASCII (c) && isalpha (c))
+# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+# define ISLOWER(c) (ISASCII (c) && islower (c))
+# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+# define ISSPACE(c) (ISASCII (c) && isspace (c))
+# define ISUPPER(c) (ISASCII (c) && isupper (c))
+# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* The GNU C library provides support for user-defined character classes
+   and the functions from ISO C amendement 1.  */
+#  ifdef CHARCLASS_NAME_MAX
+#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+#  else
+/* This shouldn't happen but some implementation might still have this
+   problem.  Use a reasonable default value.  */
+#   define CHAR_CLASS_MAX_LENGTH 256
+#  endif
+
+#  ifdef _LIBC
+#   define IS_CHAR_CLASS(string) __wctype (string)
+#  else
+#   define IS_CHAR_CLASS(string) wctype (string)
+#  endif
+
+#  ifdef _LIBC
+#   define ISWCTYPE(WC, WT)	__iswctype (WC, WT)
+#  else
+#   define ISWCTYPE(WC, WT)	iswctype (WC, WT)
+#  endif
+
+#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
+/* In this case we are implementing the multibyte character handling.  */
+#   define HANDLE_MULTIBYTE	1
+#  endif
+
+# else
+#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#  define IS_CHAR_CLASS(string)						      \
+   (STREQ (string, "alpha") || STREQ (string, "upper")			      \
+    || STREQ (string, "lower") || STREQ (string, "digit")		      \
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")		      \
+    || STREQ (string, "space") || STREQ (string, "print")		      \
+    || STREQ (string, "punct") || STREQ (string, "graph")		      \
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+# endif
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+# if !defined _LIBC && !defined getenv && !defined __UCLIBC__
+extern char *getenv ();
+# endif
+
+# ifndef errno
+extern int errno;
+# endif
+
+/* Global variable.  */
+static smallint posixly_correct;
+
+/* This function doesn't exist on most systems.  */
+
+# if !defined HAVE___STRCHRNUL && !defined _LIBC
+static char *
+__strchrnul (s, c)
+     const char *s;
+     int c;
+{
+  char *result = strchr (s, c);
+  if (result == NULL)
+    result = strchr (s, '\0');
+  return result;
+}
+# endif
+
+# if HANDLE_MULTIBYTE && !defined HAVE___STRCHRNUL && !defined _LIBC
+static wchar_t *
+__wcschrnul (s, c)
+     const wchar_t *s;
+     wint_t c;
+{
+  wchar_t *result = wcschr (s, c);
+  if (result == NULL)
+    result = wcschr (s, '\0');
+  return result;
+}
+# endif
+
+# ifndef internal_function
+/* Inside GNU libc we mark some function in a special way.  In other
+   environments simply ignore the marking.  */
+#  define internal_function
+# endif
+
+/* Note that this evaluates C many times.  */
+# ifdef _LIBC
+#  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+# else
+#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+# endif
+# define CHAR	char
+# define UCHAR	unsigned char
+# define INT	int
+# define FCT	internal_fnmatch
+# define EXT	ext_match
+# define END	end_pattern
+# define L(CS)	CS
+# ifdef _LIBC
+#  define BTOWC(C)	__btowc (C)
+# else
+#  define BTOWC(C)	btowc (C)
+# endif
+# define STRLEN(S) strlen (S)
+# define STRCAT(D, S) strcat (D, S)
+# define MEMPCPY(D, S, N) mempcpy (D, S, N)
+# define MEMCHR(S, C, N) memchr (S, C, N)
+# define STRCOLL(S1, S2) strcoll (S1, S2)
+# include "fnmatch_loop.c"
+
+
+# if HANDLE_MULTIBYTE
+/* Note that this evaluates C many times.  */
+#  ifdef _LIBC
+#   define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
+#  else
+#   define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? towlower (c) : (c))
+#  endif
+#  define CHAR	wchar_t
+#  define UCHAR	wint_t
+#  define INT	wint_t
+#  define FCT	internal_fnwmatch
+#  define EXT	ext_wmatch
+# define END	end_wpattern
+#  define L(CS)	L##CS
+#  define BTOWC(C)	(C)
+#  define STRLEN(S) wcslen (S)
+#  define STRCAT(D, S) wcscat (D, S)
+#  define MEMPCPY(D, S, N) wmempcpy (D, S, N)
+#  define MEMCHR(S, C, N) wmemchr (S, C, N)
+#  define STRCOLL(S1, S2) wcscoll (S1, S2)
+#  ifndef __UCLIBC__
+#  define WIDE_CHAR_VERSION 1
+#  endif
+
+#  undef IS_CHAR_CLASS
+/* We have to convert the wide character string in a multibyte string.  But
+   we know that the character class names consist of alphanumeric characters
+   from the portable character set, and since the wide character encoding
+   for a member of the portable character set is the same code point as
+   its single-byte encoding, we can use a simplified method to convert the
+   string to a multibyte character string.  */
+static wctype_t
+is_char_class (const wchar_t *wcs)
+{
+  char s[CHAR_CLASS_MAX_LENGTH + 1];
+  char *cp = s;
+
+  do
+    {
+      /* Test for a printable character from the portable character set.  */
+#  if defined _LIBC || defined __UCLIBC__
+      if (*wcs < 0x20 || *wcs > 0x7e
+	  || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
+	return (wctype_t) 0;
+#  else
+      switch (*wcs)
+	{
+	case L' ': case L'!': case L'"': case L'#': case L'%':
+	case L'&': case L'\'': case L'(': case L')': case L'*':
+	case L'+': case L',': case L'-': case L'.': case L'/':
+	case L'0': case L'1': case L'2': case L'3': case L'4':
+	case L'5': case L'6': case L'7': case L'8': case L'9':
+	case L':': case L';': case L'<': case L'=': case L'>':
+	case L'?':
+	case L'A': case L'B': case L'C': case L'D': case L'E':
+	case L'F': case L'G': case L'H': case L'I': case L'J':
+	case L'K': case L'L': case L'M': case L'N': case L'O':
+	case L'P': case L'Q': case L'R': case L'S': case L'T':
+	case L'U': case L'V': case L'W': case L'X': case L'Y':
+	case L'Z':
+	case L'[': case L'\\': case L']': case L'^': case L'_':
+	case L'a': case L'b': case L'c': case L'd': case L'e':
+	case L'f': case L'g': case L'h': case L'i': case L'j':
+	case L'k': case L'l': case L'm': case L'n': case L'o':
+	case L'p': case L'q': case L'r': case L's': case L't':
+	case L'u': case L'v': case L'w': case L'x': case L'y':
+	case L'z': case L'{': case L'|': case L'}': case L'~':
+	  break;
+	default:
+	  return (wctype_t) 0;
+	}
+#  endif
+
+      /* Avoid overrunning the buffer.  */
+      if (cp == s + CHAR_CLASS_MAX_LENGTH)
+	return (wctype_t) 0;
+
+      *cp++ = (char) *wcs++;
+    }
+  while (*wcs != L'\0');
+
+  *cp = '\0';
+
+#  ifdef _LIBC
+  return __wctype (s);
+#  else
+  return wctype (s);
+#  endif
+}
+#  define IS_CHAR_CLASS(string) is_char_class (string)
+
+#  include "fnmatch_loop.c"
+# endif
+
+int
+fnmatch (const char *pattern, const char *string, int flags)
+{
+# if HANDLE_MULTIBYTE
+  if (__builtin_expect (MB_CUR_MAX, 1) != 1)
+    {
+      mbstate_t ps;
+      size_t n;
+      const char *p;
+      wchar_t *wpattern = NULL;
+      wchar_t *wstring = NULL;
+
+      /* Convert the strings into wide characters.  */
+      __memset (&ps, '\0', sizeof (ps));
+      p = pattern;
+#ifdef _LIBC
+      n = strnlen (pattern, 1024);
+#else
+      n = strlen (pattern);
+#endif
+      if (__builtin_expect (n < 1024, 1))
+	{
+	  wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
+	  n = mbsrtowcs (wpattern, &p, n + 1, &ps);
+	  if (__builtin_expect (n == (size_t) -1, 0))
+	    /* Something wrong.
+	       XXX Do we have to set `errno' to something which mbsrtows hasn't
+	       already done?  */
+	    return -1;
+	  if (p)
+	    __memset (&ps, '\0', sizeof (ps));
+	}
+      if (__builtin_expect (p != NULL, 0))
+	{
+	  n = mbsrtowcs (NULL, &pattern, 0, &ps);
+	  if (__builtin_expect (n == (size_t) -1, 0))
+	    /* Something wrong.
+	       XXX Do we have to set `errno' to something which mbsrtows hasn't
+	       already done?  */
+	    return -1;
+	  wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
+	  assert (mbsinit (&ps));
+	  (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
+	}
+
+      assert (mbsinit (&ps));
+#ifdef _LIBC
+      n = strnlen (string, 1024);
+#else
+      n = strlen (string);
+#endif
+      p = string;
+      if (__builtin_expect (n < 1024, 1))
+	{
+	  wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
+	  n = mbsrtowcs (wstring, &p, n + 1, &ps);
+	  if (__builtin_expect (n == (size_t) -1, 0))
+	    /* Something wrong.
+	       XXX Do we have to set `errno' to something which mbsrtows hasn't
+	       already done?  */
+	    return -1;
+	  if (p)
+	    __memset (&ps, '\0', sizeof (ps));
+	}
+      if (__builtin_expect (p != NULL, 0))
+	{
+	  n = mbsrtowcs (NULL, &string, 0, &ps);
+	  if (__builtin_expect (n == (size_t) -1, 0))
+	    /* Something wrong.
+	       XXX Do we have to set `errno' to something which mbsrtows hasn't
+	       already done?  */
+	    return -1;
+	  wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
+	  assert (mbsinit (&ps));
+	  (void) mbsrtowcs (wstring, &string, n + 1, &ps);
+	}
+
+      return internal_fnwmatch (wpattern, wstring, wstring + n,
+				flags & FNM_PERIOD, flags);
+    }
+# endif  /* mbstate_t and mbsrtowcs or _LIBC.  */
+
+  return internal_fnmatch (pattern, string, string + strlen (string),
+			   flags & FNM_PERIOD, flags);
+}
+
+# ifdef _LIBC
+#  undef fnmatch
+versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
+#  if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
+strong_alias (__fnmatch, __fnmatch_old)
+compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
+#  endif
+libc_hidden_ver (__fnmatch, fnmatch)
+# else
+libc_hidden_def(fnmatch)
+# endif
+
+#endif	/* _LIBC or not __GNU_LIBRARY__.  */
diff --git a/ap/build/uClibc/libc/misc/fnmatch/fnmatch_loop.c b/ap/build/uClibc/libc/misc/fnmatch/fnmatch_loop.c
new file mode 100644
index 0000000..af41727
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fnmatch/fnmatch_loop.c
@@ -0,0 +1,1205 @@
+/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2003,2004,2005
+   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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, nonzero if not.  */
+static int FCT (const CHAR *pattern, const CHAR *string,
+		const CHAR *string_end, int no_leading_period, int flags)
+     internal_function;
+static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
+		const CHAR *string_end, int no_leading_period, int flags)
+     internal_function;
+static const CHAR *END (const CHAR *patternp) internal_function;
+
+static int
+internal_function
+FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+     int no_leading_period, int flags)
+{
+  register const CHAR *p = pattern, *n = string;
+  register UCHAR c;
+#ifdef _LIBC
+# if WIDE_CHAR_VERSION
+  const char *collseq = (const char *)
+    _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+# else
+  const UCHAR *collseq = (const UCHAR *)
+    _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+# endif
+#endif
+
+  while ((c = *p++) != L('\0'))
+    {
+      int new_no_leading_period = 0;
+      c = FOLD (c);
+
+      switch (c)
+	{
+	case L('?'):
+	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+	    {
+	      int res;
+
+	      res = EXT (c, p, n, string_end, no_leading_period,
+			 flags);
+	      if (res != -1)
+		return res;
+	    }
+
+	  if (n == string_end)
+	    return FNM_NOMATCH;
+	  else if (*n == L('/') && (flags & FNM_FILE_NAME))
+	    return FNM_NOMATCH;
+	  else if (*n == L('.') && no_leading_period)
+	    return FNM_NOMATCH;
+	  break;
+
+	case L('\\'):
+	  if (!(flags & FNM_NOESCAPE))
+	    {
+	      c = *p++;
+	      if (c == L('\0'))
+		/* Trailing \ loses.  */
+		return FNM_NOMATCH;
+	      c = FOLD (c);
+	    }
+	  if (n == string_end || FOLD ((UCHAR) *n) != c)
+	    return FNM_NOMATCH;
+	  break;
+
+	case L('*'):
+	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+	    {
+	      int res;
+
+	      res = EXT (c, p, n, string_end, no_leading_period,
+			 flags);
+	      if (res != -1)
+		return res;
+	    }
+
+	  if (n != string_end && *n == L('.') && no_leading_period)
+	    return FNM_NOMATCH;
+
+	  for (c = *p++; c == L('?') || c == L('*'); c = *p++)
+	    {
+	      if (*p == L('(') && (flags & FNM_EXTMATCH) != 0)
+		{
+		  const CHAR *endp = END (p);
+		  if (endp != p)
+		    {
+		      /* This is a pattern.  Skip over it.  */
+		      p = endp;
+		      continue;
+		    }
+		}
+
+	      if (c == L('?'))
+		{
+		  /* A ? needs to match one character.  */
+		  if (n == string_end)
+		    /* There isn't another character; no match.  */
+		    return FNM_NOMATCH;
+		  else if (*n == L('/')
+			   && __builtin_expect (flags & FNM_FILE_NAME, 0))
+		    /* A slash does not match a wildcard under
+		       FNM_FILE_NAME.  */
+		    return FNM_NOMATCH;
+		  else
+		    /* One character of the string is consumed in matching
+		       this ? wildcard, so *??? won't match if there are
+		       less than three characters.  */
+		    ++n;
+		}
+	    }
+
+	  if (c == L('\0'))
+	    /* The wildcard(s) is/are the last element of the pattern.
+	       If the name is a file name and contains another slash
+	       this means it cannot match, unless the FNM_LEADING_DIR
+	       flag is set.  */
+	    {
+	      int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
+
+	      if (flags & FNM_FILE_NAME)
+		{
+		  if (flags & FNM_LEADING_DIR)
+		    result = 0;
+		  else
+		    {
+		      if (MEMCHR (n, L('/'), string_end - n) == NULL)
+			result = 0;
+		    }
+		}
+
+	      return result;
+	    }
+	  else
+	    {
+	      const CHAR *endp;
+
+	      endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'),
+			     string_end - n);
+	      if (endp == NULL)
+		endp = string_end;
+
+	      if (c == L('[')
+		  || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
+		      && (c == L('@') || c == L('+') || c == L('!'))
+		      && *p == L('(')))
+		{
+		  int flags2 = ((flags & FNM_FILE_NAME)
+				? flags : (flags & ~FNM_PERIOD));
+		  int no_leading_period2 = no_leading_period;
+
+		  for (--p; n < endp; ++n, no_leading_period2 = 0)
+		    if (FCT (p, n, string_end, no_leading_period2, flags2)
+			== 0)
+		      return 0;
+		}
+	      else if (c == L('/') && (flags & FNM_FILE_NAME))
+		{
+		  while (n < string_end && *n != L('/'))
+		    ++n;
+		  if (n < string_end && *n == L('/')
+		      && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags)
+			  == 0))
+		    return 0;
+		}
+	      else
+		{
+		  int flags2 = ((flags & FNM_FILE_NAME)
+				? flags : (flags & ~FNM_PERIOD));
+		  int no_leading_period2 = no_leading_period;
+
+		  if (c == L('\\') && !(flags & FNM_NOESCAPE))
+		    c = *p;
+		  c = FOLD (c);
+		  for (--p; n < endp; ++n, no_leading_period2 = 0)
+		    if (FOLD ((UCHAR) *n) == c
+			&& (FCT (p, n, string_end, no_leading_period2, flags2)
+			    == 0))
+		      return 0;
+		}
+	    }
+
+	  /* If we come here no match is possible with the wildcard.  */
+	  return FNM_NOMATCH;
+
+	case L('['):
+	  {
+	    /* Nonzero if the sense of the character class is inverted.  */
+	    register int not;
+	    CHAR cold;
+	    UCHAR fn;
+
+	    if (posixly_correct == 0)
+	      posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+	    if (n == string_end)
+	      return FNM_NOMATCH;
+
+	    if (*n == L('.') && no_leading_period)
+	      return FNM_NOMATCH;
+
+	    if (*n == L('/') && (flags & FNM_FILE_NAME))
+	      /* `/' cannot be matched.  */
+	      return FNM_NOMATCH;
+
+	    not = (*p == L('!') || (posixly_correct < 0 && *p == L('^')));
+	    if (not)
+	      ++p;
+
+	    fn = FOLD ((UCHAR) *n);
+
+	    c = *p++;
+	    for (;;)
+	      {
+		if (!(flags & FNM_NOESCAPE) && c == L('\\'))
+		  {
+		    if (*p == L('\0'))
+		      return FNM_NOMATCH;
+		    c = FOLD ((UCHAR) *p);
+		    ++p;
+
+		    goto normal_bracket;
+		  }
+		else if (c == L('[') && *p == L(':'))
+		  {
+		    /* Leave room for the null.  */
+		    CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
+		    size_t c1 = 0;
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+		    wctype_t wt;
+#endif
+		    const CHAR *startp = p;
+
+		    for (;;)
+		      {
+			if (c1 == CHAR_CLASS_MAX_LENGTH)
+			  /* The name is too long and therefore the pattern
+			     is ill-formed.  */
+			  return FNM_NOMATCH;
+
+			c = *++p;
+			if (c == L(':') && p[1] == L(']'))
+			  {
+			    p += 2;
+			    break;
+			  }
+			if (c < L('a') || c >= L('z'))
+			  {
+			    /* This cannot possibly be a character class name.
+			       Match it as a normal range.  */
+			    p = startp;
+			    c = L('[');
+			    goto normal_bracket;
+			  }
+			str[c1++] = c;
+		      }
+		    str[c1] = L('\0');
+
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+		    wt = IS_CHAR_CLASS (str);
+		    if (wt == 0)
+		      /* Invalid character class name.  */
+		      return FNM_NOMATCH;
+
+# if defined _LIBC && ! WIDE_CHAR_VERSION
+		    /* The following code is glibc specific but does
+		       there a good job in speeding up the code since
+		       we can avoid the btowc() call.  */
+		    if (_ISCTYPE ((UCHAR) *n, wt))
+		      goto matched;
+# else
+		    if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
+		      goto matched;
+# endif
+#else
+		    if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n))
+			|| (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n))
+			|| (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n))
+			|| (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n))
+			|| (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n))
+			|| (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n))
+			|| (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n))
+			|| (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n))
+			|| (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n))
+			|| (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n))
+			|| (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n))
+			|| (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n)))
+		      goto matched;
+#endif
+		    c = *p++;
+		  }
+#ifdef _LIBC
+		else if (c == L('[') && *p == L('='))
+		  {
+		    UCHAR str[1];
+		    uint32_t nrules =
+		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+		    const CHAR *startp = p;
+
+		    c = *++p;
+		    if (c == L('\0'))
+		      {
+			p = startp;
+			c = L('[');
+			goto normal_bracket;
+		      }
+		    str[0] = c;
+
+		    c = *++p;
+		    if (c != L('=') || p[1] != L(']'))
+		      {
+			p = startp;
+			c = L('[');
+			goto normal_bracket;
+		      }
+		    p += 2;
+
+		    if (nrules == 0)
+		      {
+			if ((UCHAR) *n == str[0])
+			  goto matched;
+		      }
+		    else
+		      {
+			const int32_t *table;
+# if WIDE_CHAR_VERSION
+			const int32_t *weights;
+			const int32_t *extra;
+# else
+			const unsigned char *weights;
+			const unsigned char *extra;
+# endif
+			const int32_t *indirect;
+			int32_t idx;
+			const UCHAR *cp = (const UCHAR *) str;
+
+			/* This #include defines a local function!  */
+# if WIDE_CHAR_VERSION
+#  include <locale/weightwc.h>
+# else
+#  include <locale/weight.h>
+# endif
+
+# if WIDE_CHAR_VERSION
+			table = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
+			weights = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
+			extra = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
+			indirect = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
+# else
+			table = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+			weights = (const unsigned char *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+			extra = (const unsigned char *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+			indirect = (const int32_t *)
+			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+# endif
+
+			idx = findidx (&cp);
+			if (idx != 0)
+			  {
+			    /* We found a table entry.  Now see whether the
+			       character we are currently at has the same
+			       equivalance class value.  */
+			    int len = weights[idx];
+			    int32_t idx2;
+			    const UCHAR *np = (const UCHAR *) n;
+
+			    idx2 = findidx (&np);
+			    if (idx2 != 0 && len == weights[idx2])
+			      {
+				int cnt = 0;
+
+				while (cnt < len
+				       && (weights[idx + 1 + cnt]
+					   == weights[idx2 + 1 + cnt]))
+				  ++cnt;
+
+				if (cnt == len)
+				  goto matched;
+			      }
+			  }
+		      }
+
+		    c = *p++;
+		  }
+#endif
+		else if (c == L('\0'))
+		  /* [ (unterminated) loses.  */
+		  return FNM_NOMATCH;
+		else
+		  {
+		    int is_range = 0;
+
+#ifdef _LIBC
+		    int is_seqval = 0;
+
+		    if (c == L('[') && *p == L('.'))
+		      {
+			uint32_t nrules =
+			  _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+			const CHAR *startp = p;
+			size_t c1 = 0;
+
+			while (1)
+			  {
+			    c = *++p;
+			    if (c == L('.') && p[1] == L(']'))
+			      {
+				p += 2;
+				break;
+			      }
+			    if (c == '\0')
+			      return FNM_NOMATCH;
+			    ++c1;
+			  }
+
+			/* We have to handling the symbols differently in
+			   ranges since then the collation sequence is
+			   important.  */
+			is_range = *p == L('-') && p[1] != L('\0');
+
+			if (nrules == 0)
+			  {
+			    /* There are no names defined in the collation
+			       data.  Therefore we only accept the trivial
+			       names consisting of the character itself.  */
+			    if (c1 != 1)
+			      return FNM_NOMATCH;
+
+			    if (!is_range && *n == startp[1])
+			      goto matched;
+
+			    cold = startp[1];
+			    c = *p++;
+			  }
+			else
+			  {
+			    int32_t table_size;
+			    const int32_t *symb_table;
+# ifdef WIDE_CHAR_VERSION
+			    char str[c1];
+			    unsigned int strcnt;
+# else
+#  define str (startp + 1)
+# endif
+			    const unsigned char *extra;
+			    int32_t idx;
+			    int32_t elem;
+			    int32_t second;
+			    int32_t hash;
+
+# ifdef WIDE_CHAR_VERSION
+			    /* We have to convert the name to a single-byte
+			       string.  This is possible since the names
+			       consist of ASCII characters and the internal
+			       representation is UCS4.  */
+			    for (strcnt = 0; strcnt < c1; ++strcnt)
+			      str[strcnt] = startp[1 + strcnt];
+#endif
+
+			    table_size =
+			      _NL_CURRENT_WORD (LC_COLLATE,
+						_NL_COLLATE_SYMB_HASH_SIZEMB);
+			    symb_table = (const int32_t *)
+			      _NL_CURRENT (LC_COLLATE,
+					   _NL_COLLATE_SYMB_TABLEMB);
+			    extra = (const unsigned char *)
+			      _NL_CURRENT (LC_COLLATE,
+					   _NL_COLLATE_SYMB_EXTRAMB);
+
+			    /* Locate the character in the hashing table.  */
+			    hash = elem_hash (str, c1);
+
+			    idx = 0;
+			    elem = hash % table_size;
+			    if (symb_table[2 * elem] != 0)
+			      {
+				second = hash % (table_size - 2) + 1;
+
+				do
+				  {
+				    /* First compare the hashing value.  */
+				    if (symb_table[2 * elem] == hash
+					&& (c1
+					    == extra[symb_table[2 * elem + 1]])
+					&& __memcmp (str,
+						   &extra[symb_table[2 * elem
+								     + 1]
+							  + 1], c1) == 0)
+				      {
+					/* Yep, this is the entry.  */
+					idx = symb_table[2 * elem + 1];
+					idx += 1 + extra[idx];
+					break;
+				      }
+
+				    /* Next entry.  */
+				    elem += second;
+				  }
+				while (symb_table[2 * elem] != 0);
+			      }
+
+			    if (symb_table[2 * elem] != 0)
+			      {
+				/* Compare the byte sequence but only if
+				   this is not part of a range.  */
+# ifdef WIDE_CHAR_VERSION
+				int32_t *wextra;
+
+				idx += 1 + extra[idx];
+				/* Adjust for the alignment.  */
+				idx = (idx + 3) & ~3;
+
+				wextra = (int32_t *) &extra[idx + 4];
+# endif
+
+				if (! is_range)
+				  {
+# ifdef WIDE_CHAR_VERSION
+				    for (c1 = 0;
+					 (int32_t) c1 < wextra[idx];
+					 ++c1)
+				      if (n[c1] != wextra[1 + c1])
+					break;
+
+				    if ((int32_t) c1 == wextra[idx])
+				      goto matched;
+# else
+				    for (c1 = 0; c1 < extra[idx]; ++c1)
+				      if (n[c1] != extra[1 + c1])
+					break;
+
+				    if (c1 == extra[idx])
+				      goto matched;
+# endif
+				  }
+
+				/* Get the collation sequence value.  */
+				is_seqval = 1;
+# ifdef WIDE_CHAR_VERSION
+				cold = wextra[1 + wextra[idx]];
+# else
+				/* Adjust for the alignment.  */
+				idx += 1 + extra[idx];
+				idx = (idx + 3) & ~4;
+				cold = *((int32_t *) &extra[idx]);
+# endif
+
+				c = *p++;
+			      }
+			    else if (c1 == 1)
+			      {
+				/* No valid character.  Match it as a
+				   single byte.  */
+				if (!is_range && *n == str[0])
+				  goto matched;
+
+				cold = str[0];
+				c = *p++;
+			      }
+			    else
+			      return FNM_NOMATCH;
+			  }
+		      }
+		    else
+# undef str
+#endif
+		      {
+			c = FOLD (c);
+		      normal_bracket:
+
+			/* We have to handling the symbols differently in
+			   ranges since then the collation sequence is
+			   important.  */
+			is_range = (*p == L('-') && p[1] != L('\0')
+				    && p[1] != L(']'));
+
+			if (!is_range && c == fn)
+			  goto matched;
+
+			/* This is needed if we goto normal_bracket; from
+			   outside of is_seqval's scope.  */
+#ifndef __UCLIBC__ /* this should be probably ifdef _LIBC*/
+			is_seqval = 0;
+#endif
+			cold = c;
+			c = *p++;
+		      }
+
+		    if (c == L('-') && *p != L(']'))
+		      {
+#if _LIBC
+			/* We have to find the collation sequence
+			   value for C.  Collation sequence is nothing
+			   we can regularly access.  The sequence
+			   value is defined by the order in which the
+			   definitions of the collation values for the
+			   various characters appear in the source
+			   file.  A strange concept, nowhere
+			   documented.  */
+			uint32_t fcollseq;
+			uint32_t lcollseq;
+			UCHAR cend = *p++;
+
+# ifdef WIDE_CHAR_VERSION
+			/* Search in the `names' array for the characters.  */
+			fcollseq = __collseq_table_lookup (collseq, fn);
+			if (fcollseq == ~((uint32_t) 0))
+			  /* XXX We don't know anything about the character
+			     we are supposed to match.  This means we are
+			     failing.  */
+			  goto range_not_matched;
+
+			if (is_seqval)
+			  lcollseq = cold;
+			else
+			  lcollseq = __collseq_table_lookup (collseq, cold);
+# else
+			fcollseq = collseq[fn];
+			lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
+# endif
+
+			is_seqval = 0;
+			if (cend == L('[') && *p == L('.'))
+			  {
+			    uint32_t nrules =
+			      _NL_CURRENT_WORD (LC_COLLATE,
+						_NL_COLLATE_NRULES);
+			    const CHAR *startp = p;
+			    size_t c1 = 0;
+
+			    while (1)
+			      {
+				c = *++p;
+				if (c == L('.') && p[1] == L(']'))
+				  {
+				    p += 2;
+				    break;
+				  }
+				if (c == '\0')
+				  return FNM_NOMATCH;
+				++c1;
+			      }
+
+			    if (nrules == 0)
+			      {
+				/* There are no names defined in the
+				   collation data.  Therefore we only
+				   accept the trivial names consisting
+				   of the character itself.  */
+				if (c1 != 1)
+				  return FNM_NOMATCH;
+
+				cend = startp[1];
+			      }
+			    else
+			      {
+				int32_t table_size;
+				const int32_t *symb_table;
+# ifdef WIDE_CHAR_VERSION
+				char str[c1];
+				unsigned int strcnt;
+# else
+#  define str (startp + 1)
+# endif
+				const unsigned char *extra;
+				int32_t idx;
+				int32_t elem;
+				int32_t second;
+				int32_t hash;
+
+# ifdef WIDE_CHAR_VERSION
+				/* We have to convert the name to a single-byte
+				   string.  This is possible since the names
+				   consist of ASCII characters and the internal
+				   representation is UCS4.  */
+				for (strcnt = 0; strcnt < c1; ++strcnt)
+				  str[strcnt] = startp[1 + strcnt];
+# endif
+
+				table_size =
+				  _NL_CURRENT_WORD (LC_COLLATE,
+						    _NL_COLLATE_SYMB_HASH_SIZEMB);
+				symb_table = (const int32_t *)
+				  _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_SYMB_TABLEMB);
+				extra = (const unsigned char *)
+				  _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_SYMB_EXTRAMB);
+
+				/* Locate the character in the hashing
+                                   table.  */
+				hash = elem_hash (str, c1);
+
+				idx = 0;
+				elem = hash % table_size;
+				if (symb_table[2 * elem] != 0)
+				  {
+				    second = hash % (table_size - 2) + 1;
+
+				    do
+				      {
+					/* First compare the hashing value.  */
+					if (symb_table[2 * elem] == hash
+					    && (c1
+						== extra[symb_table[2 * elem + 1]])
+					    && __memcmp (str,
+						       &extra[symb_table[2 * elem + 1]
+							      + 1], c1) == 0)
+					  {
+					    /* Yep, this is the entry.  */
+					    idx = symb_table[2 * elem + 1];
+					    idx += 1 + extra[idx];
+					    break;
+					  }
+
+					/* Next entry.  */
+					elem += second;
+				      }
+				    while (symb_table[2 * elem] != 0);
+				  }
+
+				if (symb_table[2 * elem] != 0)
+				  {
+				    /* Compare the byte sequence but only if
+				       this is not part of a range.  */
+# ifdef WIDE_CHAR_VERSION
+				    int32_t *wextra;
+
+				    idx += 1 + extra[idx];
+				    /* Adjust for the alignment.  */
+				    idx = (idx + 3) & ~4;
+
+				    wextra = (int32_t *) &extra[idx + 4];
+# endif
+				    /* Get the collation sequence value.  */
+				    is_seqval = 1;
+# ifdef WIDE_CHAR_VERSION
+				    cend = wextra[1 + wextra[idx]];
+# else
+				    /* Adjust for the alignment.  */
+				    idx += 1 + extra[idx];
+				    idx = (idx + 3) & ~4;
+				    cend = *((int32_t *) &extra[idx]);
+# endif
+				  }
+				else if (symb_table[2 * elem] != 0 && c1 == 1)
+				  {
+				    cend = str[0];
+				    c = *p++;
+				  }
+				else
+				  return FNM_NOMATCH;
+			      }
+# undef str
+			  }
+			else
+			  {
+			    if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
+			      cend = *p++;
+			    if (cend == L('\0'))
+			      return FNM_NOMATCH;
+			    cend = FOLD (cend);
+			  }
+
+			/* XXX It is not entirely clear to me how to handle
+			   characters which are not mentioned in the
+			   collation specification.  */
+			if (
+# ifdef WIDE_CHAR_VERSION
+			    lcollseq == 0xffffffff ||
+# endif
+			    lcollseq <= fcollseq)
+			  {
+			    /* We have to look at the upper bound.  */
+			    uint32_t hcollseq;
+
+			    if (is_seqval)
+			      hcollseq = cend;
+			    else
+			      {
+# ifdef WIDE_CHAR_VERSION
+				hcollseq =
+				  __collseq_table_lookup (collseq, cend);
+				if (hcollseq == ~((uint32_t) 0))
+				  {
+				    /* Hum, no information about the upper
+				       bound.  The matching succeeds if the
+				       lower bound is matched exactly.  */
+				    if (lcollseq != fcollseq)
+				      goto range_not_matched;
+
+				    goto matched;
+				  }
+# else
+				hcollseq = collseq[cend];
+# endif
+			      }
+
+			    if (lcollseq <= hcollseq && fcollseq <= hcollseq)
+			      goto matched;
+			  }
+# ifdef WIDE_CHAR_VERSION
+		      range_not_matched:
+# endif
+#else
+			/* We use a boring value comparison of the character
+			   values.  This is better than comparing using
+			   `strcoll' since the latter would have surprising
+			   and sometimes fatal consequences.  */
+			UCHAR cend = *p++;
+
+			if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
+			  cend = *p++;
+			if (cend == L('\0'))
+			  return FNM_NOMATCH;
+
+			/* It is a range.  */
+			if (cold <= fn && fn <= cend)
+			  goto matched;
+#endif
+
+			c = *p++;
+		      }
+		  }
+
+		if (c == L(']'))
+		  break;
+	      }
+
+	    if (!not)
+	      return FNM_NOMATCH;
+	    break;
+
+	  matched:
+	    /* Skip the rest of the [...] that already matched.  */
+	    do
+	      {
+	      ignore_next:
+		c = *p++;
+
+		if (c == L('\0'))
+		  /* [... (unterminated) loses.  */
+		  return FNM_NOMATCH;
+
+		if (!(flags & FNM_NOESCAPE) && c == L('\\'))
+		  {
+		    if (*p == L('\0'))
+		      return FNM_NOMATCH;
+		    /* XXX 1003.2d11 is unclear if this is right.  */
+		    ++p;
+		  }
+		else if (c == L('[') && *p == L(':'))
+		  {
+		    int c1 = 0;
+		    const CHAR *startp = p;
+
+		    while (1)
+		      {
+			c = *++p;
+			if (++c1 == CHAR_CLASS_MAX_LENGTH)
+			  return FNM_NOMATCH;
+
+			if (*p == L(':') && p[1] == L(']'))
+			  break;
+
+			if (c < L('a') || c >= L('z'))
+			  {
+			    p = startp;
+			    goto ignore_next;
+			  }
+		      }
+		    p += 2;
+		    c = *p++;
+		  }
+		else if (c == L('[') && *p == L('='))
+		  {
+		    c = *++p;
+		    if (c == L('\0'))
+		      return FNM_NOMATCH;
+		    c = *++p;
+		    if (c != L('=') || p[1] != L(']'))
+		      return FNM_NOMATCH;
+		    p += 2;
+		    c = *p++;
+		  }
+		else if (c == L('[') && *p == L('.'))
+		  {
+		    ++p;
+		    while (1)
+		      {
+			c = *++p;
+			if (c == '\0')
+			  return FNM_NOMATCH;
+
+			if (*p == L('.') && p[1] == L(']'))
+			  break;
+		      }
+		    p += 2;
+		    c = *p++;
+		  }
+	      }
+	    while (c != L(']'));
+	    if (not)
+	      return FNM_NOMATCH;
+	  }
+	  break;
+
+	case L('+'):
+	case L('@'):
+	case L('!'):
+	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+	    {
+	      int res;
+
+	      res = EXT (c, p, n, string_end, no_leading_period, flags);
+	      if (res != -1)
+		return res;
+	    }
+	  goto normal_match;
+
+	case L('/'):
+	  if (NO_LEADING_PERIOD (flags))
+	    {
+	      if (n == string_end || c != (UCHAR) *n)
+		return FNM_NOMATCH;
+
+	      new_no_leading_period = 1;
+	      break;
+	    }
+	  /* FALLTHROUGH */
+	default:
+	normal_match:
+	  if (n == string_end || c != FOLD ((UCHAR) *n))
+	    return FNM_NOMATCH;
+	}
+
+      no_leading_period = new_no_leading_period;
+      ++n;
+    }
+
+  if (n == string_end)
+    return 0;
+
+  if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/'))
+    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+    return 0;
+
+  return FNM_NOMATCH;
+}
+
+
+static const CHAR *
+internal_function
+END (const CHAR *pattern)
+{
+  const CHAR *p = pattern;
+
+  while (1)
+    if (*++p == L('\0'))
+      /* This is an invalid pattern.  */
+      return pattern;
+    else if (*p == L('['))
+      {
+	/* Handle brackets special.  */
+	if (posixly_correct == 0)
+	  posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+	/* Skip the not sign.  We have to recognize it because of a possibly
+	   following ']'.  */
+	if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
+	  ++p;
+	/* A leading ']' is recognized as such.  */
+	if (*p == L(']'))
+	  ++p;
+	/* Skip over all characters of the list.  */
+	while (*p != L(']'))
+	  if (*p++ == L('\0'))
+	    /* This is no valid pattern.  */
+	    return pattern;
+      }
+    else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
+	      || *p == L('!')) && p[1] == L('('))
+      p = END (p + 1);
+    else if (*p == L(')'))
+      break;
+
+  return p + 1;
+}
+
+
+static int
+internal_function
+EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+     int no_leading_period, int flags)
+{
+  const CHAR *startp;
+  int level;
+  struct patternlist
+  {
+    struct patternlist *next;
+    CHAR str[0];
+  } *list = NULL;
+  struct patternlist **lastp = &list;
+  size_t pattern_len = STRLEN (pattern);
+  const CHAR *p;
+  const CHAR *rs;
+
+  /* Parse the pattern.  Store the individual parts in the list.  */
+  level = 0;
+  for (startp = p = pattern + 1; level >= 0; ++p)
+    if (*p == L('\0'))
+      /* This is an invalid pattern.  */
+      return -1;
+    else if (*p == L('['))
+      {
+	/* Handle brackets special.  */
+	if (posixly_correct == 0)
+	  posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+	/* Skip the not sign.  We have to recognize it because of a possibly
+	   following ']'.  */
+	if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
+	  ++p;
+	/* A leading ']' is recognized as such.  */
+	if (*p == L(']'))
+	  ++p;
+	/* Skip over all characters of the list.  */
+	while (*p != L(']'))
+	  if (*p++ == L('\0'))
+	    /* This is no valid pattern.  */
+	    return -1;
+      }
+    else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
+	      || *p == L('!')) && p[1] == L('('))
+      /* Remember the nesting level.  */
+      ++level;
+    else if (*p == L(')'))
+      {
+	if (level-- == 0)
+	  {
+	    /* This means we found the end of the pattern.  */
+#define NEW_PATTERN \
+	    struct patternlist *newp;					      \
+									      \
+	    if (opt == L('?') || opt == L('@'))				      \
+	      newp = alloca (sizeof (struct patternlist)		      \
+			     + (pattern_len * sizeof (CHAR)));		      \
+	    else							      \
+	      newp = alloca (sizeof (struct patternlist)		      \
+			     + ((p - startp + 1) * sizeof (CHAR)));	      \
+	    *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0');    \
+	    newp->next = NULL;						      \
+	    *lastp = newp;						      \
+	    lastp = &newp->next
+	    NEW_PATTERN;
+	  }
+      }
+    else if (*p == L('|'))
+      {
+	if (level == 0)
+	  {
+	    NEW_PATTERN;
+	    startp = p + 1;
+	  }
+      }
+  assert (list != NULL);
+  assert (p[-1] == L(')'));
+#undef NEW_PATTERN
+
+  switch (opt)
+    {
+    case L('*'):
+      if (FCT (p, string, string_end, no_leading_period, flags) == 0)
+	return 0;
+      /* FALLTHROUGH */
+
+    case L('+'):
+      do
+	{
+	  for (rs = string; rs <= string_end; ++rs)
+	    /* First match the prefix with the current pattern with the
+	       current pattern.  */
+	    if (FCT (list->str, string, rs, no_leading_period,
+		     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0
+		/* This was successful.  Now match the rest with the rest
+		   of the pattern.  */
+		&& (FCT (p, rs, string_end,
+			 rs == string
+			 ? no_leading_period
+			 : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
+			 flags & FNM_FILE_NAME
+			 ? flags : flags & ~FNM_PERIOD) == 0
+		    /* This didn't work.  Try the whole pattern.  */
+		    || (rs != string
+			&& FCT (pattern - 1, rs, string_end,
+				rs == string
+				? no_leading_period
+				: (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
+				   ? 1 : 0),
+				flags & FNM_FILE_NAME
+				? flags : flags & ~FNM_PERIOD) == 0)))
+	      /* It worked.  Signal success.  */
+	      return 0;
+	}
+      while ((list = list->next) != NULL);
+
+      /* None of the patterns lead to a match.  */
+      return FNM_NOMATCH;
+
+    case L('?'):
+      if (FCT (p, string, string_end, no_leading_period, flags) == 0)
+	return 0;
+      /* FALLTHROUGH */
+
+    case L('@'):
+      do
+	/* I cannot believe it but `strcat' is actually acceptable
+	   here.  Match the entire string with the prefix from the
+	   pattern list and the rest of the pattern following the
+	   pattern list.  */
+	if (FCT (STRCAT (list->str, p), string, string_end,
+		 no_leading_period,
+		 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
+	  /* It worked.  Signal success.  */
+	  return 0;
+      while ((list = list->next) != NULL);
+
+      /* None of the patterns lead to a match.  */
+      return FNM_NOMATCH;
+
+    case L('!'):
+      for (rs = string; rs <= string_end; ++rs)
+	{
+	  struct patternlist *runp;
+
+	  for (runp = list; runp != NULL; runp = runp->next)
+	    if (FCT (runp->str, string, rs,  no_leading_period,
+		     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
+	      break;
+
+	  /* If none of the patterns matched see whether the rest does.  */
+	  if (runp == NULL
+	      && (FCT (p, rs, string_end,
+		       rs == string
+		       ? no_leading_period
+		       : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
+		       flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
+		  == 0))
+	    /* This is successful.  */
+	    return 0;
+	}
+
+      /* None of the patterns together with the rest of the pattern
+	 lead to a match.  */
+      return FNM_NOMATCH;
+
+    default:
+      assert (! "Invalid extended matching operator");
+      break;
+    }
+
+  return -1;
+}
+
+
+#undef FOLD
+#undef CHAR
+#undef UCHAR
+#undef INT
+#undef FCT
+#undef EXT
+#undef END
+#undef MEMPCPY
+#undef MEMCHR
+#undef STRCOLL
+#undef STRLEN
+#undef STRCAT
+#undef L
+#undef BTOWC
diff --git a/ap/build/uClibc/libc/misc/fnmatch/fnmatch_old.c b/ap/build/uClibc/libc/misc/fnmatch/fnmatch_old.c
new file mode 100644
index 0000000..2dece85
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fnmatch/fnmatch_old.c
@@ -0,0 +1,220 @@
+/* Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fnmatch.h>
+#include <ctype.h>
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+# if defined (STDC_HEADERS) || !defined (isascii)
+#  define ISASCII(c) 1
+# else
+#  define ISASCII(c) isascii(c)
+# endif
+
+# define ISUPPER(c) (ISASCII (c) && isupper (c))
+
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, nonzero if not.  */
+int fnmatch(const char *pattern, const char *string, int flags)
+{
+	register const char *p = pattern, *n = string;
+	register char c;
+
+/* Note that this evaluates C many times.  */
+# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+
+	while ((c = *p++) != '\0') {
+		c = FOLD(c);
+
+		switch (c) {
+		case '?':
+			if (*n == '\0')
+				return FNM_NOMATCH;
+			else if ((flags & FNM_FILE_NAME) && *n == '/')
+				return FNM_NOMATCH;
+			else if ((flags & FNM_PERIOD) && *n == '.' &&
+					 (n == string
+					  || ((flags & FNM_FILE_NAME)
+						  && n[-1] == '/'))) return FNM_NOMATCH;
+			break;
+
+		case '\\':
+			if (!(flags & FNM_NOESCAPE)) {
+				c = *p++;
+				if (c == '\0')
+					/* Trailing \ loses.  */
+					return FNM_NOMATCH;
+				c = FOLD(c);
+			}
+			if (FOLD(*n) != c)
+				return FNM_NOMATCH;
+			break;
+
+		case '*':
+			if ((flags & FNM_PERIOD) && *n == '.' &&
+				(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+				return FNM_NOMATCH;
+
+			for (c = *p++; c == '?' || c == '*'; c = *p++) {
+				if ((flags & FNM_FILE_NAME) && *n == '/')
+					/* A slash does not match a wildcard under FNM_FILE_NAME.  */
+					return FNM_NOMATCH;
+				else if (c == '?') {
+					/* A ? needs to match one character.  */
+					if (*n == '\0')
+						/* There isn't another character; no match.  */
+						return FNM_NOMATCH;
+					else
+						/* One character of the string is consumed in matching
+						   this ? wildcard, so *??? won't match if there are
+						   less than three characters.  */
+						++n;
+				}
+			}
+
+			if (c == '\0')
+				return 0;
+
+			{
+				char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+
+				c1 = FOLD(c1);
+				for (--p; *n != '\0'; ++n)
+					if ((c == '[' || FOLD(*n) == c1) &&
+						fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
+						return 0;
+				return FNM_NOMATCH;
+			}
+
+		case '[':
+		{
+			/* Nonzero if the sense of the character class is inverted.  */
+			register int not;
+
+			if (*n == '\0')
+				return FNM_NOMATCH;
+
+			if ((flags & FNM_PERIOD) && *n == '.' &&
+				(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+				return FNM_NOMATCH;
+
+			not = (*p == '!' || *p == '^');
+			if (not)
+				++p;
+
+			c = *p++;
+			for (;;) {
+				register char cstart = c, cend = c;
+
+				if (!(flags & FNM_NOESCAPE) && c == '\\') {
+					if (*p == '\0')
+						return FNM_NOMATCH;
+					cstart = cend = *p++;
+				}
+
+				cstart = cend = FOLD(cstart);
+
+				if (c == '\0')
+					/* [ (unterminated) loses.  */
+					return FNM_NOMATCH;
+
+				c = *p++;
+				c = FOLD(c);
+
+				if ((flags & FNM_FILE_NAME) && c == '/')
+					/* [/] can never match.  */
+					return FNM_NOMATCH;
+
+				if (c == '-' && *p != ']') {
+					cend = *p++;
+					if (!(flags & FNM_NOESCAPE) && cend == '\\')
+						cend = *p++;
+					if (cend == '\0')
+						return FNM_NOMATCH;
+					cend = FOLD(cend);
+
+					c = *p++;
+				}
+
+				if (FOLD(*n) >= cstart && FOLD(*n) <= cend)
+					goto matched;
+
+				if (c == ']')
+					break;
+			}
+			if (!not)
+				return FNM_NOMATCH;
+			break;
+
+		  matched:;
+			/* Skip the rest of the [...] that already matched.  */
+			while (c != ']') {
+				if (c == '\0')
+					/* [... (unterminated) loses.  */
+					return FNM_NOMATCH;
+
+				c = *p++;
+				if (!(flags & FNM_NOESCAPE) && c == '\\') {
+					if (*p == '\0')
+						return FNM_NOMATCH;
+					/* XXX 1003.2d11 is unclear if this is right.  */
+					++p;
+				}
+			}
+			if (not)
+				return FNM_NOMATCH;
+		}
+			break;
+
+		default:
+			if (c != FOLD(*n))
+				return FNM_NOMATCH;
+		}
+
+		++n;
+	}
+
+	if (*n == '\0')
+		return 0;
+
+	if ((flags & FNM_LEADING_DIR) && *n == '/')
+		/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+		return 0;
+
+	return FNM_NOMATCH;
+
+# undef FOLD
+}
+libc_hidden_def(fnmatch)
+#endif							/* _LIBC or not __GNU_LIBRARY__.  */
diff --git a/ap/build/uClibc/libc/misc/fts/Makefile b/ap/build/uClibc/libc/misc/fts/Makefile
new file mode 100644
index 0000000..1361db3
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fts/Makefile
@@ -0,0 +1,14 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2009 STMicroelectronics Ltd.
+# Author: Salvatore Cro <salvatore.cro at st.com>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/fts/Makefile.in b/ap/build/uClibc/libc/misc/fts/Makefile.in
new file mode 100644
index 0000000..a1d0efa
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fts/Makefile.in
@@ -0,0 +1,23 @@
+# FTS Makefile for uClibc
+#
+# Copyright (C) 2009 STMicroelectronics Ltd.
+# Author: Salvatore Cro <salvatore.cro at st.com>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/fts
+CSRC := fts.c
+
+MISC_FTS_DIR := $(top_srcdir)libc/misc/fts
+MISC_FTS_OUT := $(top_builddir)libc/misc/fts
+
+MISC_FTS_SRC := $(patsubst %.c,$(MISC_FTS_DIR)/%.c,$(CSRC))
+MISC_FTS_OBJ := $(patsubst %.c,$(MISC_FTS_OUT)/%.o,$(CSRC))
+
+libc-$(UCLIBC_HAS_FTS) += $(MISC_FTS_OBJ)
+
+objclean-y += CLEAN_libc/misc/fts
+
+CLEAN_libc/misc/fts:
+	$(do_rm) $(addprefix $(MISC_FTS_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/fts/fts.c b/ap/build/uClibc/libc/misc/fts/fts.c
new file mode 100644
index 0000000..deb8f4a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/fts/fts.c
@@ -0,0 +1,1113 @@
+/*-
+ * Copyright (c) 1990, 1993, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fts.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __UCLIBC_HAS_LFS__
+# include <_lfs_64.h>
+#else
+# define stat64 stat
+# define fstat64 fstat
+#endif
+
+/* Largest alignment size needed, minus one.
+   Usually long double is the worst case.  */
+#ifndef ALIGNBYTES
+#define ALIGNBYTES	(__alignof__ (long double) - 1)
+#endif
+/* Align P to that size.  */
+#ifndef ALIGN
+#define	ALIGN(p)	(((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
+#endif
+
+
+static FTSENT	*fts_alloc (FTS *, const char *, size_t) internal_function;
+static FTSENT	*fts_build (FTS *, int) internal_function;
+static void	 fts_lfree (FTSENT *) internal_function;
+static void	 fts_load (FTS *, FTSENT *) internal_function;
+static size_t	 fts_maxarglen (char * const *) internal_function;
+static void	 fts_padjust (FTS *, FTSENT *) internal_function;
+static int	 fts_palloc (FTS *, size_t) internal_function;
+static FTSENT	*fts_sort (FTS *, FTSENT *, int) internal_function;
+static u_short	 fts_stat (FTS *, FTSENT *, int) internal_function;
+static int      fts_safe_changedir (FTS *, FTSENT *, int, const char *)
+     internal_function;
+
+#ifndef MAX
+#define MAX(a, b)	({ __typeof__ (a) _a = (a); \
+			   __typeof__ (b) _b = (b); \
+			   _a > _b ? _a : _b; })
+#endif
+
+#define	ISDOT(a)	(a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+#define CLR(opt)	(sp->fts_options &= ~(opt))
+#define	ISSET(opt)	(sp->fts_options & (opt))
+#define	SET(opt)	(sp->fts_options |= (opt))
+
+#define	FCHDIR(sp, fd)	(!ISSET(FTS_NOCHDIR) && fchdir(fd))
+
+/* fts_build flags */
+#define	BCHILD		1		/* fts_children */
+#define	BNAMES		2		/* fts_children, names only */
+#define	BREAD		3		/* fts_read */
+
+FTS *
+fts_open( char * const *argv, register int options,
+		int (*compar) (const FTSENT **, const FTSENT **))
+{
+	register FTS *sp;
+	register FTSENT *p, *root;
+	register int nitems;
+	FTSENT *parent = NULL;
+	FTSENT *tmp = NULL;
+
+	/* Options check. */
+	if (options & ~FTS_OPTIONMASK) {
+		__set_errno (EINVAL);
+		return (NULL);
+	}
+
+	/* Allocate/initialize the stream */
+	if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
+		return (NULL);
+	memset(sp, 0, sizeof(FTS));
+	sp->fts_compar = (int (*) (const void *, const void *)) compar;
+	sp->fts_options = options;
+
+	/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+	if (ISSET(FTS_LOGICAL))
+		SET(FTS_NOCHDIR);
+
+	/*
+	 * Start out with 1K of path space, and enough, in any case,
+	 * to hold the user's paths.
+	 */
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+	size_t maxarglen = fts_maxarglen(argv);
+	if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
+		goto mem1;
+
+	/* Allocate/initialize root's parent. */
+	if (*argv != NULL) {
+		if ((parent = fts_alloc(sp, "", 0)) == NULL)
+			goto mem2;
+		parent->fts_level = FTS_ROOTPARENTLEVEL;
+	  }
+
+	/* Allocate/initialize root(s). */
+	for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
+		/* Don't allow zero-length paths. */
+		size_t len = strlen(*argv);
+		if (len == 0) {
+			__set_errno (ENOENT);
+			goto mem3;
+		}
+
+		p = fts_alloc(sp, *argv, len);
+		p->fts_level = FTS_ROOTLEVEL;
+		p->fts_parent = parent;
+		p->fts_accpath = p->fts_name;
+		p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+
+		/* Command-line "." and ".." are real directories. */
+		if (p->fts_info == FTS_DOT)
+			p->fts_info = FTS_D;
+
+		/*
+		 * If comparison routine supplied, traverse in sorted
+		 * order; otherwise traverse in the order specified.
+		 */
+		if (compar) {
+			p->fts_link = root;
+			root = p;
+		} else {
+			p->fts_link = NULL;
+			if (root == NULL)
+				tmp = root = p;
+			else {
+				tmp->fts_link = p;
+				tmp = p;
+			}
+		}
+	}
+	if (compar && nitems > 1)
+		root = fts_sort(sp, root, nitems);
+
+	/*
+	 * Allocate a dummy pointer and make fts_read think that we've just
+	 * finished the node before the root(s); set p->fts_info to FTS_INIT
+	 * so that everything about the "current" node is ignored.
+	 */
+	if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+		goto mem3;
+	sp->fts_cur->fts_link = root;
+	sp->fts_cur->fts_info = FTS_INIT;
+
+	/*
+	 * If using chdir(2), grab a file descriptor pointing to dot to ensure
+	 * that we can get back here; this could be avoided for some paths,
+	 * but almost certainly not worth the effort.  Slashes, symbolic links,
+	 * and ".." are all fairly nasty problems.  Note, if we can't get the
+	 * descriptor we run anyway, just more slowly.
+	 */
+	if (!ISSET(FTS_NOCHDIR)
+	    && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
+		SET(FTS_NOCHDIR);
+
+	return (sp);
+
+mem3:	fts_lfree(root);
+	free(parent);
+mem2:	free(sp->fts_path);
+mem1:	free(sp);
+	return (NULL);
+}
+
+static void
+internal_function
+fts_load(FTS *sp, register FTSENT *p)
+{
+	register int len;
+	register char *cp;
+
+	/*
+	 * Load the stream structure for the next traversal.  Since we don't
+	 * actually enter the directory until after the preorder visit, set
+	 * the fts_accpath field specially so the chdir gets done to the right
+	 * place and the user can access the first node.  From fts_open it's
+	 * known that the path will fit.
+	 */
+	len = p->fts_pathlen = p->fts_namelen;
+	memmove(sp->fts_path, p->fts_name, len + 1);
+	if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+		len = strlen(++cp);
+		memmove(p->fts_name, cp, len + 1);
+		p->fts_namelen = len;
+	}
+	p->fts_accpath = p->fts_path = sp->fts_path;
+	sp->fts_dev = p->fts_dev;
+}
+
+int
+fts_close(FTS *sp)
+{
+	register FTSENT *freep, *p;
+	int saved_errno;
+
+	/*
+	 * This still works if we haven't read anything -- the dummy structure
+	 * points to the root list, so we step through to the end of the root
+	 * list which has a valid parent pointer.
+	 */
+	if (sp->fts_cur) {
+		for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+			freep = p;
+			p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
+			free(freep);
+		}
+		free(p);
+	}
+
+	/* Free up child linked list, sort array, path buffer. */
+	if (sp->fts_child)
+		fts_lfree(sp->fts_child);
+	free(sp->fts_array);
+	free(sp->fts_path);
+
+	/* Return to original directory, save errno if necessary. */
+	if (!ISSET(FTS_NOCHDIR)) {
+		saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
+		(void)close(sp->fts_rfd);
+
+		/* Set errno and return. */
+		if (saved_errno != 0) {
+			/* Free up the stream pointer. */
+			free(sp);
+			__set_errno (saved_errno);
+			return (-1);
+		}
+	}
+
+	/* Free up the stream pointer. */
+	free(sp);
+	return (0);
+}
+
+/*
+ * Special case of "/" at the end of the path so that slashes aren't
+ * appended which would cause paths to be written as "....//foo".
+ */
+#define	NAPPEND(p)							\
+	(p->fts_path[p->fts_pathlen - 1] == '/'				\
+	    ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+FTSENT *
+fts_read(register FTS *sp)
+{
+	register FTSENT *p, *tmp;
+	register int instr;
+	register char *t;
+	int saved_errno;
+
+	/* If finished or unrecoverable error, return NULL. */
+	if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+		return (NULL);
+
+	/* Set current node pointer. */
+	p = sp->fts_cur;
+
+	/* Save and zero out user instructions. */
+	instr = p->fts_instr;
+	p->fts_instr = FTS_NOINSTR;
+
+	/* Any type of file may be re-visited; re-stat and re-turn. */
+	if (instr == FTS_AGAIN) {
+		p->fts_info = fts_stat(sp, p, 0);
+		return (p);
+	}
+
+	/*
+	 * Following a symlink -- SLNONE test allows application to see
+	 * SLNONE and recover.  If indirecting through a symlink, have
+	 * keep a pointer to current location.  If unable to get that
+	 * pointer, follow fails.
+	 */
+	if (instr == FTS_FOLLOW &&
+	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+		p->fts_info = fts_stat(sp, p, 1);
+		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+			if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
+				p->fts_errno = errno;
+				p->fts_info = FTS_ERR;
+			} else
+				p->fts_flags |= FTS_SYMFOLLOW;
+		}
+		return (p);
+	}
+
+	/* Directory in pre-order. */
+	if (p->fts_info == FTS_D) {
+		/* If skipped or crossed mount point, do post-order visit. */
+		if (instr == FTS_SKIP ||
+		    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
+			if (p->fts_flags & FTS_SYMFOLLOW)
+				(void)close(p->fts_symfd);
+			if (sp->fts_child) {
+				fts_lfree(sp->fts_child);
+				sp->fts_child = NULL;
+			}
+			p->fts_info = FTS_DP;
+			return (p);
+		}
+
+		/* Rebuild if only read the names and now traversing. */
+		if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
+			CLR(FTS_NAMEONLY);
+			fts_lfree(sp->fts_child);
+			sp->fts_child = NULL;
+		}
+
+		/*
+		 * Cd to the subdirectory.
+		 *
+		 * If have already read and now fail to chdir, whack the list
+		 * to make the names come out right, and set the parent errno
+		 * so the application will eventually get an error condition.
+		 * Set the FTS_DONTCHDIR flag so that when we logically change
+		 * directories back to the parent we don't do a chdir.
+		 *
+		 * If haven't read do so.  If the read fails, fts_build sets
+		 * FTS_STOP or the fts_info field of the node.
+		 */
+		if (sp->fts_child != NULL) {
+			if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+				p->fts_errno = errno;
+				p->fts_flags |= FTS_DONTCHDIR;
+				for (p = sp->fts_child; p != NULL;
+				     p = p->fts_link)
+					p->fts_accpath =
+					    p->fts_parent->fts_accpath;
+			}
+		} else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+			if (ISSET(FTS_STOP))
+				return (NULL);
+			return (p);
+		}
+		p = sp->fts_child;
+		sp->fts_child = NULL;
+		sp->fts_cur = p;
+		goto name;
+	}
+
+	/* Move to the next node on this level. */
+next:	tmp = p;
+	if ((p = p->fts_link) != NULL) {
+		sp->fts_cur = p;
+		free(tmp);
+
+		/*
+		 * If reached the top, return to the original directory (or
+		 * the root of the tree), and load the paths for the next root.
+		 */
+		if (p->fts_level == FTS_ROOTLEVEL) {
+			if (FCHDIR(sp, sp->fts_rfd)) {
+				SET(FTS_STOP);
+				return (NULL);
+			}
+			fts_load(sp, p);
+			return p;
+		}
+
+		/*
+		 * User may have called fts_set on the node.  If skipped,
+		 * ignore.  If followed, get a file descriptor so we can
+		 * get back if necessary.
+		 */
+		if (p->fts_instr == FTS_SKIP)
+			goto next;
+		if (p->fts_instr == FTS_FOLLOW) {
+			p->fts_info = fts_stat(sp, p, 1);
+			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+				if ((p->fts_symfd =
+				    open(".", O_RDONLY, 0)) < 0) {
+					p->fts_errno = errno;
+					p->fts_info = FTS_ERR;
+				} else
+					p->fts_flags |= FTS_SYMFOLLOW;
+			}
+			p->fts_instr = FTS_NOINSTR;
+		}
+
+name:		t = sp->fts_path + NAPPEND(p->fts_parent);
+		*t++ = '/';
+		memmove(t, p->fts_name, p->fts_namelen + 1);
+		return p;
+	}
+
+	/* Move up to the parent node. */
+	p = tmp->fts_parent;
+	sp->fts_cur = p;
+	free(tmp);
+
+	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+		/*
+		 * Done; free everything up and set errno to 0 so the user
+		 * can distinguish between error and EOF.
+		 */
+		free(p);
+		__set_errno (0);
+		return (sp->fts_cur = NULL);
+	}
+
+	/* NUL terminate the pathname. */
+	sp->fts_path[p->fts_pathlen] = '\0';
+
+	/*
+	 * Return to the parent directory.  If at a root node or came through
+	 * a symlink, go back through the file descriptor.  Otherwise, cd up
+	 * one directory.
+	 */
+	if (p->fts_level == FTS_ROOTLEVEL) {
+		if (FCHDIR(sp, sp->fts_rfd)) {
+			SET(FTS_STOP);
+			return (NULL);
+		}
+	} else if (p->fts_flags & FTS_SYMFOLLOW) {
+		if (FCHDIR(sp, p->fts_symfd)) {
+			saved_errno = errno;
+			(void)close(p->fts_symfd);
+			__set_errno (saved_errno);
+			SET(FTS_STOP);
+			return (NULL);
+		}
+		(void)close(p->fts_symfd);
+	} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+		   fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+		SET(FTS_STOP);
+		return (NULL);
+	}
+	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+	return p;
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set.  An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+fts_set(FTS *sp, FTSENT *p, int instr)
+{
+	if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
+		__set_errno (EINVAL);
+		return (1);
+	}
+	p->fts_instr = instr;
+	return (0);
+}
+
+FTSENT *
+fts_children(register FTS *sp, int instr)
+{
+	register FTSENT *p;
+	int fd;
+
+	if (instr != 0 && instr != FTS_NAMEONLY) {
+		__set_errno (EINVAL);
+		return (NULL);
+	}
+
+	/* Set current node pointer. */
+	p = sp->fts_cur;
+
+	/*
+	 * Errno set to 0 so user can distinguish empty directory from
+	 * an error.
+	 */
+	__set_errno (0);
+
+	/* Fatal errors stop here. */
+	if (ISSET(FTS_STOP))
+		return (NULL);
+
+	/* Return logical hierarchy of user's arguments. */
+	if (p->fts_info == FTS_INIT)
+		return (p->fts_link);
+
+	/*
+	 * If not a directory being visited in pre-order, stop here.  Could
+	 * allow FTS_DNR, assuming the user has fixed the problem, but the
+	 * same effect is available with FTS_AGAIN.
+	 */
+	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+		return (NULL);
+
+	/* Free up any previous child list. */
+	if (sp->fts_child != NULL)
+		fts_lfree(sp->fts_child);
+
+	if (instr == FTS_NAMEONLY) {
+		SET(FTS_NAMEONLY);
+		instr = BNAMES;
+	} else
+		instr = BCHILD;
+
+	/*
+	 * If using chdir on a relative path and called BEFORE fts_read does
+	 * its chdir to the root of a traversal, we can lose -- we need to
+	 * chdir into the subdirectory, and we don't know where the current
+	 * directory is, so we can't get back so that the upcoming chdir by
+	 * fts_read will work.
+	 */
+	if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
+	    ISSET(FTS_NOCHDIR))
+		return (sp->fts_child = fts_build(sp, instr));
+
+	if ((fd = open(".", O_RDONLY, 0)) < 0)
+		return (NULL);
+	sp->fts_child = fts_build(sp, instr);
+	if (fchdir(fd))
+		return (NULL);
+	(void)close(fd);
+	return (sp->fts_child);
+}
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here.  The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read.  There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly.  First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry.  Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls.  The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT *
+internal_function
+fts_build(register FTS *sp, int type)
+{
+	register struct dirent *dp;
+	register FTSENT *p, *head;
+	register int nitems;
+	FTSENT *cur, *tail;
+	DIR *dirp;
+	void *oldaddr;
+	int cderrno, descend, len, level, nlinks, saved_errno,
+	    nostat, doadjust;
+	size_t maxlen;
+	char *cp;
+
+	/* Set current node pointer. */
+	cur = sp->fts_cur;
+
+	/*
+	 * Open the directory for reading.  If this fails, we're done.
+	 * If being called from fts_read, set the fts_info field.
+	 */
+#if defined FTS_WHITEOUT && 0
+	if (ISSET(FTS_WHITEOUT))
+		oflag = DTF_NODUP|DTF_REWIND;
+	else
+		oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
+#else
+# define opendir2(path, flag) opendir(path)
+#endif
+       if ((dirp = opendir2(cur->fts_accpath, oflag)) == NULL) {
+		if (type == BREAD) {
+			cur->fts_info = FTS_DNR;
+			cur->fts_errno = errno;
+		}
+		return (NULL);
+	}
+
+	/*
+	 * Nlinks is the number of possible entries of type directory in the
+	 * directory if we're cheating on stat calls, 0 if we're not doing
+	 * any stat calls at all, -1 if we're doing stats on everything.
+	 */
+	if (type == BNAMES) {
+		nlinks = 0;
+		/* Be quiet about nostat, GCC. */
+		nostat = 0;
+	} else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+		nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+		nostat = 1;
+	} else {
+		nlinks = -1;
+		nostat = 0;
+	}
+
+#ifdef notdef
+	(void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
+	(void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
+	    ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
+#endif
+	/*
+	 * If we're going to need to stat anything or we want to descend
+	 * and stay in the directory, chdir.  If this fails we keep going,
+	 * but set a flag so we don't chdir after the post-order visit.
+	 * We won't be able to stat anything, but we can still return the
+	 * names themselves.  Note, that since fts_read won't be able to
+	 * chdir into the directory, it will have to return different path
+	 * names than before, i.e. "a/b" instead of "b".  Since the node
+	 * has already been visited in pre-order, have to wait until the
+	 * post-order visit to return the error.  There is a special case
+	 * here, if there was nothing to stat then it's not an error to
+	 * not be able to stat.  This is all fairly nasty.  If a program
+	 * needed sorted entries or stat information, they had better be
+	 * checking FTS_NS on the returned nodes.
+	 */
+	cderrno = 0;
+	if (nlinks || type == BREAD) {
+		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
+			if (nlinks && type == BREAD)
+				cur->fts_errno = errno;
+			cur->fts_flags |= FTS_DONTCHDIR;
+			descend = 0;
+			cderrno = errno;
+			(void)closedir(dirp);
+			dirp = NULL;
+		} else
+			descend = 1;
+	} else
+		descend = 0;
+
+	/*
+	 * Figure out the max file name length that can be stored in the
+	 * current path -- the inner loop allocates more path as necessary.
+	 * We really wouldn't have to do the maxlen calculations here, we
+	 * could do them in fts_read before returning the path, but it's a
+	 * lot easier here since the length is part of the dirent structure.
+	 *
+	 * If not changing directories set a pointer so that can just append
+	 * each new name into the path.
+	 */
+	len = NAPPEND(cur);
+	if (ISSET(FTS_NOCHDIR)) {
+		cp = sp->fts_path + len;
+		*cp++ = '/';
+	} else {
+		/* GCC, you're too verbose. */
+		cp = NULL;
+	}
+	len++;
+	maxlen = sp->fts_pathlen - len;
+
+	level = cur->fts_level + 1;
+
+	/* Read the directory, attaching each entry to the `link' pointer. */
+	doadjust = 0;
+	for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
+		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+			continue;
+
+		if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL)
+			goto mem1;
+		if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */
+			oldaddr = sp->fts_path;
+			if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) {
+				/*
+				 * No more memory for path or structures.  Save
+				 * errno, free up the current structure and the
+				 * structures already allocated.
+				 */
+mem1:				saved_errno = errno;
+				free(p);
+				fts_lfree(head);
+				(void)closedir(dirp);
+				cur->fts_info = FTS_ERR;
+				SET(FTS_STOP);
+				__set_errno (saved_errno);
+				return (NULL);
+			}
+			/* Did realloc() change the pointer? */
+			if (oldaddr != sp->fts_path) {
+				doadjust = 1;
+				if (ISSET(FTS_NOCHDIR))
+					cp = sp->fts_path + len;
+			}
+			maxlen = sp->fts_pathlen - len;
+		}
+
+		if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) {
+			/*
+			 * In an FTSENT, fts_pathlen is a u_short so it is
+			 * possible to wraparound here.  If we do, free up
+			 * the current structure and the structures already
+			 * allocated, then error out with ENAMETOOLONG.
+			 */
+			free(p);
+			fts_lfree(head);
+			(void)closedir(dirp);
+			cur->fts_info = FTS_ERR;
+			SET(FTS_STOP);
+			__set_errno (ENAMETOOLONG);
+			return (NULL);
+		}
+		p->fts_level = level;
+		p->fts_parent = sp->fts_cur;
+		p->fts_pathlen = len + _D_EXACT_NAMLEN (dp);
+
+#if defined FTS_WHITEOUT && 0
+		if (dp->d_type == DT_WHT)
+			p->fts_flags |= FTS_ISW;
+#endif
+
+#if 0
+		/* Unreachable code.  cderrno is only ever set to a nonnull
+		   value if dirp is closed at the same time.  But then we
+		   cannot enter this loop.  */
+		if (cderrno) {
+			if (nlinks) {
+				p->fts_info = FTS_NS;
+				p->fts_errno = cderrno;
+			} else
+				p->fts_info = FTS_NSOK;
+			p->fts_accpath = cur->fts_accpath;
+		} else
+#endif
+		if (nlinks == 0
+#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE
+			   || (nostat &&
+			       dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+#endif
+		    ) {
+			p->fts_accpath =
+			    ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
+			p->fts_info = FTS_NSOK;
+		} else {
+			/* Build a file name for fts_stat to stat. */
+			if (ISSET(FTS_NOCHDIR)) {
+				p->fts_accpath = p->fts_path;
+				memmove(cp, p->fts_name, p->fts_namelen + 1);
+			} else
+				p->fts_accpath = p->fts_name;
+			/* Stat it. */
+			p->fts_info = fts_stat(sp, p, 0);
+
+			/* Decrement link count if applicable. */
+			if (nlinks > 0 && (p->fts_info == FTS_D ||
+			    p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+				--nlinks;
+		}
+
+		/* We walk in directory order so "ls -f" doesn't get upset. */
+		p->fts_link = NULL;
+		if (head == NULL)
+			head = tail = p;
+		else {
+			tail->fts_link = p;
+			tail = p;
+		}
+		++nitems;
+	}
+	if (dirp)
+		(void)closedir(dirp);
+
+	/*
+	 * If realloc() changed the address of the path, adjust the
+	 * addresses for the rest of the tree and the dir list.
+	 */
+	if (doadjust)
+		fts_padjust(sp, head);
+
+	/*
+	 * If not changing directories, reset the path back to original
+	 * state.
+	 */
+	if (ISSET(FTS_NOCHDIR)) {
+		if (len == sp->fts_pathlen || nitems == 0)
+			--cp;
+		*cp = '\0';
+	}
+
+	/*
+	 * If descended after called from fts_children or after called from
+	 * fts_read and nothing found, get back.  At the root level we use
+	 * the saved fd; if one of fts_open()'s arguments is a relative path
+	 * to an empty directory, we wind up here with no other way back.  If
+	 * can't get back, we're done.
+	 */
+	if (descend && (type == BCHILD || !nitems) &&
+	    (cur->fts_level == FTS_ROOTLEVEL ?
+	     FCHDIR(sp, sp->fts_rfd) :
+	     fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+		cur->fts_info = FTS_ERR;
+		SET(FTS_STOP);
+		fts_lfree(head);
+		return (NULL);
+	}
+
+	/* If didn't find anything, return NULL. */
+	if (!nitems) {
+		if (type == BREAD)
+			cur->fts_info = FTS_DP;
+		fts_lfree(head);
+		return (NULL);
+	}
+
+	/* Sort the entries. */
+	if (sp->fts_compar && nitems > 1)
+		head = fts_sort(sp, head, nitems);
+	return (head);
+}
+
+static u_short
+internal_function
+fts_stat(FTS *sp, register FTSENT *p, int follow)
+{
+	register FTSENT *t;
+	register dev_t dev;
+	register ino_t ino;
+	struct stat *sbp, sb;
+	int saved_errno;
+
+	/* If user needs stat info, stat buffer already allocated. */
+	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+#if defined FTS_WHITEOUT && 0
+	/* check for whiteout */
+	if (p->fts_flags & FTS_ISW) {
+		if (sbp != &sb) {
+			memset(sbp, '\0', sizeof (*sbp));
+			sbp->st_mode = S_IFWHT;
+		}
+		return (FTS_W);
+       }
+#endif
+
+	/*
+	 * If doing a logical walk, or application requested FTS_FOLLOW, do
+	 * a stat(2).  If that fails, check for a non-existent symlink.  If
+	 * fail, set the errno from the stat call.
+	 */
+	if (ISSET(FTS_LOGICAL) || follow) {
+		if (stat(p->fts_accpath, sbp)) {
+			saved_errno = errno;
+			if (!lstat(p->fts_accpath, sbp)) {
+				__set_errno (0);
+				return (FTS_SLNONE);
+			}
+			p->fts_errno = saved_errno;
+			goto err;
+		}
+	} else if (lstat(p->fts_accpath, sbp)) {
+		p->fts_errno = errno;
+err:		memset(sbp, 0, sizeof(struct stat));
+		return (FTS_NS);
+	}
+
+	if (S_ISDIR(sbp->st_mode)) {
+		/*
+		 * Set the device/inode.  Used to find cycles and check for
+		 * crossing mount points.  Also remember the link count, used
+		 * in fts_build to limit the number of stat calls.  It is
+		 * understood that these fields are only referenced if fts_info
+		 * is set to FTS_D.
+		 */
+		dev = p->fts_dev = sbp->st_dev;
+		ino = p->fts_ino = sbp->st_ino;
+		p->fts_nlink = sbp->st_nlink;
+
+		if (ISDOT(p->fts_name))
+			return (FTS_DOT);
+
+		/*
+		 * Cycle detection is done by brute force when the directory
+		 * is first encountered.  If the tree gets deep enough or the
+		 * number of symbolic links to directories is high enough,
+		 * something faster might be worthwhile.
+		 */
+		for (t = p->fts_parent;
+		    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+			if (ino == t->fts_ino && dev == t->fts_dev) {
+				p->fts_cycle = t;
+				return (FTS_DC);
+			}
+		return (FTS_D);
+	}
+	if (S_ISLNK(sbp->st_mode))
+		return (FTS_SL);
+	if (S_ISREG(sbp->st_mode))
+		return (FTS_F);
+	return (FTS_DEFAULT);
+}
+
+static FTSENT *
+internal_function
+fts_sort(FTS *sp, FTSENT *head, register int nitems)
+{
+	register FTSENT **ap, *p;
+
+	/*
+	 * Construct an array of pointers to the structures and call qsort(3).
+	 * Reassemble the array in the order returned by qsort.  If unable to
+	 * sort for memory reasons, return the directory entries in their
+	 * current order.  Allocate enough space for the current needs plus
+	 * 40 so don't realloc one entry at a time.
+	 */
+	if (nitems > sp->fts_nitems) {
+		struct _ftsent **a;
+
+		sp->fts_nitems = nitems + 40;
+		if ((a = realloc(sp->fts_array,
+ 		    (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
+			free(sp->fts_array);
+			sp->fts_array = NULL;
+			sp->fts_nitems = 0;
+			return (head);
+		}
+		sp->fts_array = a;
+	}
+	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+		*ap++ = p;
+	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
+	for (head = *(ap = sp->fts_array); --nitems; ++ap)
+		ap[0]->fts_link = ap[1];
+	ap[0]->fts_link = NULL;
+	return (head);
+}
+
+static FTSENT *
+internal_function
+fts_alloc(FTS *sp, const char *name, size_t namelen)
+{
+	register FTSENT *p;
+	size_t len;
+
+	/*
+	 * The file name is a variable length array and no stat structure is
+	 * necessary if the user has set the nostat bit.  Allocate the FTSENT
+	 * structure, the file name and the stat structure in one chunk, but
+	 * be careful that the stat structure is reasonably aligned.  Since the
+	 * fts_name field is declared to be of size 1, the fts_name pointer is
+	 * namelen + 2 before the first possible address of the stat structure.
+	 */
+	len = sizeof(FTSENT) + namelen;
+	if (!ISSET(FTS_NOSTAT))
+		len += sizeof(struct stat) + ALIGNBYTES;
+	if ((p = malloc(len)) == NULL)
+		return (NULL);
+
+	/* Copy the name and guarantee NUL termination. */
+	memmove(p->fts_name, name, namelen);
+	p->fts_name[namelen] = '\0';
+
+	if (!ISSET(FTS_NOSTAT))
+		p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
+	p->fts_namelen = namelen;
+	p->fts_path = sp->fts_path;
+	p->fts_errno = 0;
+	p->fts_flags = 0;
+	p->fts_instr = FTS_NOINSTR;
+	p->fts_number = 0;
+	p->fts_pointer = NULL;
+	return (p);
+}
+
+static void
+internal_function
+fts_lfree(register FTSENT *head)
+{
+	register FTSENT *p;
+
+	/* Free a linked list of structures. */
+	while ((p = head)) {
+		head = head->fts_link;
+		free(p);
+	}
+}
+
+/*
+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * though the kernel won't resolve them.  Add the size (not just what's needed)
+ * plus 256 bytes so don't realloc the path 2 bytes at a time.
+ */
+static int
+internal_function
+fts_palloc(FTS *sp, size_t more)
+{
+	char *p;
+
+	sp->fts_pathlen += more + 256;
+	/*
+	 * Check for possible wraparound.  In an FTS, fts_pathlen is
+	 * a signed int but in an FTSENT it is an unsigned short.
+	 * We limit fts_pathlen to USHRT_MAX to be safe in both cases.
+	 */
+	if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) {
+		free(sp->fts_path);
+		sp->fts_path = NULL;
+		__set_errno (ENAMETOOLONG);
+		return (1);
+	}
+	p = realloc(sp->fts_path, sp->fts_pathlen);
+	if (p == NULL) {
+		free(sp->fts_path);
+		sp->fts_path = NULL;
+		return 1;
+	}
+	sp->fts_path = p;
+	return 0;
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+internal_function
+fts_padjust(FTS *sp, FTSENT *head)
+{
+	FTSENT *p;
+	char *addr = sp->fts_path;
+
+#define	ADJUST(p) do {							\
+	if ((p)->fts_accpath != (p)->fts_name) {			\
+		(p)->fts_accpath =					\
+		    (char *)addr + ((p)->fts_accpath - (p)->fts_path);	\
+	}								\
+	(p)->fts_path = addr;						\
+} while (0)
+	/* Adjust the current set of children. */
+	for (p = sp->fts_child; p; p = p->fts_link)
+		ADJUST(p);
+
+	/* Adjust the rest of the tree, including the current level. */
+	for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+		ADJUST(p);
+		p = p->fts_link ? p->fts_link : p->fts_parent;
+	}
+}
+
+static size_t
+internal_function
+fts_maxarglen(char * const *argv)
+{
+	size_t len, max;
+
+	for (max = 0; *argv; ++argv)
+		if ((len = strlen(*argv)) > max)
+			max = len;
+	return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+internal_function
+fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const char *path)
+{
+	int ret, oerrno, newfd;
+	struct stat64 sb;
+
+	newfd = fd;
+	if (ISSET(FTS_NOCHDIR))
+		return (0);
+	if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0)
+		return (-1);
+	if (fstat64(newfd, &sb)) {
+		ret = -1;
+		goto bail;
+	}
+	if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
+		__set_errno (ENOENT);		/* disinformation */
+		ret = -1;
+		goto bail;
+	}
+	ret = fchdir(newfd);
+bail:
+	oerrno = errno;
+	if (fd < 0)
+		(void)close(newfd);
+	__set_errno (oerrno);
+	return (ret);
+}
diff --git a/ap/build/uClibc/libc/misc/ftw/Makefile b/ap/build/uClibc/libc/misc/ftw/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ftw/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/ftw/Makefile.in b/ap/build/uClibc/libc/misc/ftw/Makefile.in
new file mode 100644
index 0000000..2edd819
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ftw/Makefile.in
@@ -0,0 +1,26 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/ftw
+
+CSRC := ftw.c
+ifeq ($(UCLIBC_HAS_LFS),y)
+CSRC += ftw64.c
+endif
+
+MISC_FTW_DIR := $(top_srcdir)libc/misc/ftw
+MISC_FTW_OUT := $(top_builddir)libc/misc/ftw
+
+MISC_FTW_SRC := $(patsubst %.c,$(MISC_FTW_DIR)/%.c,$(CSRC))
+MISC_FTW_OBJ := $(patsubst %.c,$(MISC_FTW_OUT)/%.o,$(CSRC))
+
+libc-$(findstring y,$(UCLIBC_HAS_FTW)$(UCLIBC_HAS_NFTW)) += $(MISC_FTW_OBJ)
+
+objclean-y += CLEAN_libc/misc/ftw
+
+CLEAN_libc/misc/ftw:
+	$(do_rm) $(addprefix $(MISC_FTW_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/ftw/ftw.c b/ap/build/uClibc/libc/misc/ftw/ftw.c
new file mode 100644
index 0000000..9031e35
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ftw/ftw.c
@@ -0,0 +1,807 @@
+/* File tree walker functions.
+   Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <features.h>
+#ifdef __UCLIBC__
+#undef _LIBC
+#define HAVE_DIRENT_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_DECL_STPCPY 1
+#define HAVE_MEMPCPY 1
+#endif
+
+#if __GNUC__
+# define alloca __builtin_alloca
+#else
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #  pragma alloca
+#  else
+char *alloca ();
+#  endif
+# endif
+#endif
+
+#if defined _LIBC
+# include <dirent.h>
+# define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent)
+#else
+# if HAVE_DIRENT_H
+#  include <dirent.h>
+#  define NAMLEN(dirent) strlen ((dirent)->d_name)
+# else
+#  define dirent direct
+#  define NAMLEN(dirent) (dirent)->d_namlen
+#  if HAVE_SYS_NDIR_H
+#   include <sys/ndir.h>
+#  endif
+#  if HAVE_SYS_DIR_H
+#   include <sys/dir.h>
+#  endif
+#  if HAVE_NDIR_H
+#   include <ndir.h>
+#  endif
+# endif
+#endif
+
+#include <errno.h>
+#include <ftw.h>
+#include <limits.h>
+#include <search.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+#ifdef _LIBC
+# include <include/sys/stat.h>
+#else
+# include <sys/stat.h>
+#endif
+
+#if !defined _LIBC && !HAVE_DECL_STPCPY && !defined stpcpy
+char *stpcpy ();
+#endif
+
+#if !defined _LIBC && ! defined HAVE_MEMPCPY && ! defined mempcpy
+/* Be CAREFUL that there are no side effects in N.  */
+# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
+#endif
+
+/* #define NDEBUG 1 */
+#include <assert.h>
+
+#if !defined _LIBC
+# undef __chdir
+# define __chdir chdir
+# undef __closedir
+# define __closedir closedir
+# undef __fchdir
+# define __fchdir fchdir
+# undef __getcwd
+# ifndef __UCLIBC__
+# define __getcwd(P, N) xgetcwd ()
+extern char *xgetcwd (void);
+# else
+# define __getcwd getcwd
+# endif
+# undef __mempcpy
+# define __mempcpy mempcpy
+# undef __opendir
+# define __opendir opendir
+# undef __readdir64
+# ifndef __UCLIBC_HAS_LFS__
+# define __readdir64 readdir
+# else
+# define __readdir64 readdir64
+# endif
+# undef __stpcpy
+# define __stpcpy stpcpy
+# undef __tdestroy
+# define __tdestroy tdestroy
+# undef __tfind
+# define __tfind tfind
+# undef __tsearch
+# define __tsearch tsearch
+# undef internal_function
+# define internal_function /* empty */
+# ifndef __UCLIBC_HAS_LFS__
+# undef dirent64
+# define dirent64 dirent
+# endif
+# undef MAX
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+/* Arrange to make lstat calls go through the wrapper function
+   on systems with an lstat function that does not dereference symlinks
+   that are specified with a trailing slash.  */
+#if !defined _LIBC && !defined LSTAT_FOLLOWS_SLASHED_SYMLINK && !defined __UCLIBC__
+int rpl_lstat (const char *, struct stat *);
+# undef lstat
+# define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf)
+#endif
+
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+/* Support for the LFS API version.  */
+#ifndef FTW_NAME
+# define FTW_NAME ftw
+# define NFTW_NAME nftw
+# define NFTW_OLD_NAME __old_nftw
+# define NFTW_NEW_NAME __new_nftw
+# define INO_T ino_t
+# define STAT stat
+# ifdef _LIBC
+#  define LXSTAT __lxstat
+#  define XSTAT __xstat
+# else
+#  define LXSTAT(V,f,sb) lstat (f,sb)
+#  define XSTAT(V,f,sb) stat (f,sb)
+# endif
+# define FTW_FUNC_T __ftw_func_t
+# define NFTW_FUNC_T __nftw_func_t
+#endif
+
+/* We define PATH_MAX if the system does not provide a definition.
+   This does not artificially limit any operation.  PATH_MAX is simply
+   used as a guesstimate for the expected maximal path length.
+   Buffers will be enlarged if necessary.  */
+#ifndef PATH_MAX
+# define PATH_MAX 1024
+#endif
+
+struct dir_data
+{
+  DIR *stream;
+  char *content;
+};
+
+struct known_object
+{
+  dev_t dev;
+  INO_T ino;
+};
+
+struct ftw_data
+{
+  /* Array with pointers to open directory streams.  */
+  struct dir_data **dirstreams;
+  size_t actdir;
+  size_t maxdir;
+
+  /* Buffer containing name of currently processed object.  */
+  char *dirbuf;
+  size_t dirbufsize;
+
+  /* Passed as fourth argument to `nftw' callback.  The `base' member
+     tracks the content of the `dirbuf'.  */
+  struct FTW ftw;
+
+  /* Flags passed to `nftw' function.  0 for `ftw'.  */
+  int flags;
+
+  /* Conversion array for flag values.  It is the identity mapping for
+     `nftw' calls, otherwise it maps the values to those known by
+     `ftw'.  */
+  const int *cvt_arr;
+
+  /* Callback function.  We always use the `nftw' form.  */
+  NFTW_FUNC_T func;
+
+  /* Device of starting point.  Needed for FTW_MOUNT.  */
+  dev_t dev;
+
+  /* Data structure for keeping fingerprints of already processed
+     object.  This is needed when not using FTW_PHYS.  */
+  void *known_objects;
+};
+
+
+/* Internally we use the FTW_* constants used for `nftw'.  When invoked
+   as `ftw', map each flag to the subset of values used by `ftw'.  */
+static const int nftw_arr[] =
+{
+  FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN
+};
+
+static const int ftw_arr[] =
+{
+  FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS
+};
+
+
+/* Forward declarations of local functions.  */
+static int ftw_dir (struct ftw_data *data, struct STAT *st,
+		    struct dir_data *old_dir) internal_function;
+
+
+static int
+object_compare (const void *p1, const void *p2)
+{
+  /* We don't need a sophisticated and useful comparison.  We are only
+     interested in equality.  However, we must be careful not to
+     accidentally compare `holes' in the structure.  */
+  const struct known_object *kp1 = p1, *kp2 = p2;
+  int cmp1;
+  cmp1 = (kp1->ino > kp2->ino) - (kp1->ino < kp2->ino);
+  if (cmp1 != 0)
+    return cmp1;
+  return (kp1->dev > kp2->dev) - (kp1->dev < kp2->dev);
+}
+
+
+static __inline__ int
+add_object (struct ftw_data *data, struct STAT *st)
+{
+  struct known_object *newp = malloc (sizeof (struct known_object));
+  if (newp == NULL)
+    return -1;
+  newp->dev = st->st_dev;
+  newp->ino = st->st_ino;
+  return __tsearch (newp, &data->known_objects, object_compare) ? 0 : -1;
+}
+
+
+static __inline__ int
+find_object (struct ftw_data *data, struct STAT *st)
+{
+  struct known_object obj;
+  obj.dev = st->st_dev;
+  obj.ino = st->st_ino;
+  return __tfind (&obj, &data->known_objects, object_compare) != NULL;
+}
+
+
+static __inline__ int
+__attribute ((always_inline))
+open_dir_stream (struct ftw_data *data, struct dir_data *dirp)
+{
+  int result = 0;
+
+  if (data->dirstreams[data->actdir] != NULL)
+    {
+      /* Oh, oh.  We must close this stream.  Get all remaining
+	 entries and store them as a list in the `content' member of
+	 the `struct dir_data' variable.  */
+      size_t bufsize = 1024;
+      char *buf = malloc (bufsize);
+
+      if (buf == NULL)
+	result = -1;
+      else
+	{
+	  DIR *st = data->dirstreams[data->actdir]->stream;
+	  struct dirent64 *d;
+	  size_t actsize = 0;
+
+	  while ((d = __readdir64 (st)) != NULL)
+	    {
+	      size_t this_len = NAMLEN (d);
+	      if (actsize + this_len + 2 >= bufsize)
+		{
+		  char *newp;
+		  bufsize += MAX (1024, 2 * this_len);
+		  newp = (char *) realloc (buf, bufsize);
+		  if (newp == NULL)
+		    {
+		      /* No more memory.  */
+		      int save_err = errno;
+		      free (buf);
+		      __set_errno (save_err);
+		      result = -1;
+		      break;
+		    }
+		  buf = newp;
+		}
+
+	      *((char *) __mempcpy (buf + actsize, d->d_name, this_len))
+		= '\0';
+	      actsize += this_len + 1;
+	    }
+
+	  /* Terminate the list with an additional NUL byte.  */
+	  buf[actsize++] = '\0';
+
+	  /* Shrink the buffer to what we actually need.  */
+	  data->dirstreams[data->actdir]->content = realloc (buf, actsize);
+	  if (data->dirstreams[data->actdir]->content == NULL)
+	    {
+	      int save_err = errno;
+	      free (buf);
+	      __set_errno (save_err);
+	      result = -1;
+	    }
+	  else
+	    {
+	      __closedir (st);
+	      data->dirstreams[data->actdir]->stream = NULL;
+	      data->dirstreams[data->actdir] = NULL;
+	    }
+	}
+    }
+
+  /* Open the new stream.  */
+  if (result == 0)
+    {
+      const char *name = ((data->flags & FTW_CHDIR)
+			  ? data->dirbuf + data->ftw.base: data->dirbuf);
+      assert (data->dirstreams[data->actdir] == NULL);
+
+      dirp->stream = __opendir (name);
+      if (dirp->stream == NULL)
+	result = -1;
+      else
+	{
+	  dirp->content = NULL;
+	  data->dirstreams[data->actdir] = dirp;
+
+	  if (++data->actdir == data->maxdir)
+	    data->actdir = 0;
+	}
+    }
+
+  return result;
+}
+
+
+static int
+internal_function
+process_entry (struct ftw_data *data, struct dir_data *dir, const char *name,
+	       size_t namlen)
+{
+  struct STAT st;
+  int result = 0;
+  int flag = 0;
+  size_t new_buflen;
+
+  if (name[0] == '.' && (name[1] == '\0'
+			 || (name[1] == '.' && name[2] == '\0')))
+    /* Don't process the "." and ".." entries.  */
+    return 0;
+
+  new_buflen = data->ftw.base + namlen + 2;
+  if (data->dirbufsize < new_buflen)
+    {
+      /* Enlarge the buffer.  */
+      char *newp;
+
+      data->dirbufsize = 2 * new_buflen;
+      newp = (char *) realloc (data->dirbuf, data->dirbufsize);
+      if (newp == NULL)
+	return -1;
+      data->dirbuf = newp;
+    }
+
+  *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0';
+
+  if ((data->flags & FTW_CHDIR) == 0)
+    name = data->dirbuf;
+
+  if (((data->flags & FTW_PHYS)
+       ? LXSTAT (_STAT_VER, name, &st)
+       : XSTAT (_STAT_VER, name, &st)) < 0)
+    {
+      if (errno != EACCES && errno != ENOENT)
+	result = -1;
+      else if (!(data->flags & FTW_PHYS)
+	       && LXSTAT (_STAT_VER, name, &st) == 0
+	       && S_ISLNK (st.st_mode))
+	flag = FTW_SLN;
+      else
+	flag = FTW_NS;
+    }
+  else
+    {
+      if (S_ISDIR (st.st_mode))
+	flag = FTW_D;
+      else if (S_ISLNK (st.st_mode))
+	flag = FTW_SL;
+      else
+	flag = FTW_F;
+    }
+
+  if (result == 0
+      && (flag == FTW_NS
+	  || !(data->flags & FTW_MOUNT) || st.st_dev == data->dev))
+    {
+      if (flag == FTW_D)
+	{
+	  if ((data->flags & FTW_PHYS)
+	      || (!find_object (data, &st)
+		  /* Remember the object.  */
+		  && (result = add_object (data, &st)) == 0))
+	    result = ftw_dir (data, &st, dir);
+	}
+      else
+	result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag],
+				&data->ftw);
+    }
+
+  if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SUBTREE)
+    result = 0;
+
+  return result;
+}
+
+
+static int
+__attribute ((noinline))
+internal_function
+ftw_dir (struct ftw_data *data, struct STAT *st, struct dir_data *old_dir)
+{
+  struct dir_data dir;
+  struct dirent64 *d;
+  int previous_base = data->ftw.base;
+  int result;
+  char *startp;
+
+  /* Open the stream for this directory.  This might require that
+     another stream has to be closed.  */
+  result = open_dir_stream (data, &dir);
+  if (result != 0)
+    {
+      if (errno == EACCES)
+	/* We cannot read the directory.  Signal this with a special flag.  */
+	result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw);
+
+      return result;
+    }
+
+  /* First, report the directory (if not depth-first).  */
+  if (!(data->flags & FTW_DEPTH))
+    {
+      result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw);
+      if (result != 0)
+	{
+	  int save_err;
+fail:
+	  save_err = errno;
+	  __closedir (dir.stream);
+	  __set_errno (save_err);
+
+	  if (data->actdir-- == 0)
+	    data->actdir = data->maxdir - 1;
+	  data->dirstreams[data->actdir] = NULL;
+	  return result;
+	}
+    }
+
+  /* If necessary, change to this directory.  */
+  if (data->flags & FTW_CHDIR)
+    {
+      if (__fchdir (dirfd (dir.stream)) < 0)
+	{
+	  result = -1;
+	  goto fail;
+	}
+    }
+
+  /* Next, update the `struct FTW' information.  */
+  ++data->ftw.level;
+  startp = strchr (data->dirbuf, '\0');
+  /* There always must be a directory name.  */
+  assert (startp != data->dirbuf);
+  if (startp[-1] != '/')
+    *startp++ = '/';
+  data->ftw.base = startp - data->dirbuf;
+
+  while (dir.stream != NULL && (d = __readdir64 (dir.stream)) != NULL)
+    {
+      result = process_entry (data, &dir, d->d_name, NAMLEN (d));
+      if (result != 0)
+	break;
+    }
+
+  if (dir.stream != NULL)
+    {
+      /* The stream is still open.  I.e., we did not need more
+	 descriptors.  Simply close the stream now.  */
+      int save_err = errno;
+
+      assert (dir.content == NULL);
+
+      __closedir (dir.stream);
+      __set_errno (save_err);
+
+      if (data->actdir-- == 0)
+	data->actdir = data->maxdir - 1;
+      data->dirstreams[data->actdir] = NULL;
+    }
+  else
+    {
+      int save_err;
+      char *runp = dir.content;
+
+      while (result == 0 && *runp != '\0')
+	{
+	  char *endp = strchr (runp, '\0');
+
+	  result = process_entry (data, &dir, runp, endp - runp);
+
+	  runp = endp + 1;
+	}
+
+      save_err = errno;
+      free (dir.content);
+      __set_errno (save_err);
+    }
+
+  if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SIBLINGS)
+    result = 0;
+
+  /* Prepare the return, revert the `struct FTW' information.  */
+  data->dirbuf[data->ftw.base - 1] = '\0';
+  --data->ftw.level;
+  data->ftw.base = previous_base;
+
+  /* Finally, if we process depth-first report the directory.  */
+  if (result == 0 && (data->flags & FTW_DEPTH))
+    result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw);
+
+  if (old_dir
+      && (data->flags & FTW_CHDIR)
+      && (result == 0
+	  || ((data->flags & FTW_ACTIONRETVAL)
+	      && (result != -1 && result != FTW_STOP))))
+    {
+      /* Change back to the parent directory.  */
+      int done = 0;
+      if (old_dir->stream != NULL)
+	if (__fchdir (dirfd (old_dir->stream)) == 0)
+	  done = 1;
+
+      if (!done)
+	{
+	  if (data->ftw.base == 1)
+	    {
+	      if (__chdir ("/") < 0)
+		result = -1;
+	    }
+	  else
+	    if (__chdir ("..") < 0)
+	      result = -1;
+	}
+    }
+
+  return result;
+}
+
+
+static int
+__attribute ((noinline))
+internal_function
+ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
+	     int flags)
+{
+  struct ftw_data data;
+  struct STAT st;
+  int result = 0;
+  int save_err;
+  char *cwd = NULL;
+  char *cp;
+
+  /* First make sure the parameters are reasonable.  */
+  if (dir[0] == '\0')
+    {
+      __set_errno (ENOENT);
+      return -1;
+    }
+
+  data.maxdir = descriptors < 1 ? 1 : descriptors;
+  data.actdir = 0;
+  data.dirstreams = (struct dir_data **) alloca (data.maxdir
+						 * sizeof (struct dir_data *));
+  memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *));
+
+  /* PATH_MAX is always defined when we get here.  */
+  data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
+  data.dirbuf = (char *) malloc (data.dirbufsize);
+  if (data.dirbuf == NULL)
+    return -1;
+  cp = __stpcpy (data.dirbuf, dir);
+  /* Strip trailing slashes.  */
+  while (cp > data.dirbuf + 1 && cp[-1] == '/')
+    --cp;
+  *cp = '\0';
+
+  data.ftw.level = 0;
+
+  /* Find basename.  */
+  while (cp > data.dirbuf && cp[-1] != '/')
+    --cp;
+  data.ftw.base = cp - data.dirbuf;
+
+  data.flags = flags;
+
+  /* This assignment might seem to be strange but it is what we want.
+     The trick is that the first three arguments to the `ftw' and
+     `nftw' callback functions are equal.  Therefore we can call in
+     every case the callback using the format of the `nftw' version
+     and get the correct result since the stack layout for a function
+     call in C allows this.  */
+  data.func = (NFTW_FUNC_T) func;
+
+  /* Since we internally use the complete set of FTW_* values we need
+     to reduce the value range before calling a `ftw' callback.  */
+  data.cvt_arr = is_nftw ? nftw_arr : ftw_arr;
+
+  /* No object known so far.  */
+  data.known_objects = NULL;
+
+  /* Now go to the directory containing the initial file/directory.  */
+  if (flags & FTW_CHDIR)
+    {
+      /* GNU extension ahead.  */
+      cwd =  __getcwd (NULL, 0);
+      if (cwd == NULL)
+	result = -1;
+      else if (data.ftw.base > 0)
+	{
+	  /* Change to the directory the file is in.  In data.dirbuf
+	     we have a writable copy of the file name.  Just NUL
+	     terminate it for now and change the directory.  */
+	  if (data.ftw.base == 1)
+	    /* I.e., the file is in the root directory.  */
+	    result = __chdir ("/");
+	  else
+	    {
+	      char ch = data.dirbuf[data.ftw.base - 1];
+	      data.dirbuf[data.ftw.base - 1] = '\0';
+	      result = __chdir (data.dirbuf);
+	      data.dirbuf[data.ftw.base - 1] = ch;
+	    }
+	}
+    }
+
+  /* Get stat info for start directory.  */
+  if (result == 0)
+    {
+      const char *name = ((data.flags & FTW_CHDIR)
+			  ? data.dirbuf + data.ftw.base
+			  : data.dirbuf);
+
+      if (((flags & FTW_PHYS)
+	   ? LXSTAT (_STAT_VER, name, &st)
+	   : XSTAT (_STAT_VER, name, &st)) < 0)
+	{
+	  if (!(flags & FTW_PHYS)
+	      && errno == ENOENT
+	      && LXSTAT (_STAT_VER, name, &st) == 0
+	      && S_ISLNK (st.st_mode))
+	    result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN],
+				   &data.ftw);
+	  else
+	    /* No need to call the callback since we cannot say anything
+	       about the object.  */
+	    result = -1;
+	}
+      else
+	{
+	  if (S_ISDIR (st.st_mode))
+	    {
+	      /* Remember the device of the initial directory in case
+		 FTW_MOUNT is given.  */
+	      data.dev = st.st_dev;
+
+	      /* We know this directory now.  */
+	      if (!(flags & FTW_PHYS))
+		result = add_object (&data, &st);
+
+	      if (result == 0)
+		result = ftw_dir (&data, &st, NULL);
+	    }
+	  else
+	    {
+	      int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F;
+
+	      result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag],
+				     &data.ftw);
+	    }
+	}
+
+      if ((flags & FTW_ACTIONRETVAL)
+	  && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS))
+	result = 0;
+    }
+
+  /* Return to the start directory (if necessary).  */
+  if (cwd != NULL)
+    {
+      save_err = errno;
+      __chdir (cwd);
+      free (cwd);
+      __set_errno (save_err);
+    }
+
+  /* Free all memory.  */
+  save_err = errno;
+  __tdestroy (data.known_objects, free);
+  free (data.dirbuf);
+  __set_errno (save_err);
+
+  return result;
+}
+
+
+
+/* Entry points.  */
+#ifdef __UCLIBC_HAS_FTW__
+int
+FTW_NAME (const char *path, FTW_FUNC_T func, int descriptors)
+{
+  return ftw_startup (path, 0, func, descriptors, 0);
+}
+#endif
+
+#ifdef __UCLIBC_HAS_NFTW__
+#ifndef _LIBC
+int
+NFTW_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags)
+{
+  return ftw_startup (path, 1, func, descriptors, flags);
+}
+#else
+
+#include <shlib-compat.h>
+
+int NFTW_NEW_NAME (const char *, NFTW_FUNC_T, int, int);
+
+int
+NFTW_NEW_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags)
+{
+  if (flags
+      & ~(FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH | FTW_ACTIONRETVAL))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+  return ftw_startup (path, 1, func, descriptors, flags);
+}
+
+versioned_symbol (libc, NFTW_NEW_NAME, NFTW_NAME, GLIBC_2_3_3);
+
+#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_3_3)
+
+/* Older nftw* version just ignored all unknown flags.  */
+
+int NFTW_OLD_NAME (const char *, NFTW_FUNC_T, int, int);
+
+int
+attribute_compat_text_section
+NFTW_OLD_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags)
+{
+  flags &= (FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH);
+  return ftw_startup (path, 1, func, descriptors, flags);
+}
+
+compat_symbol (libc, NFTW_OLD_NAME, NFTW_NAME, GLIBC_2_1);
+#endif
+#endif
+#endif
diff --git a/ap/build/uClibc/libc/misc/ftw/ftw64.c b/ap/build/uClibc/libc/misc/ftw/ftw64.c
new file mode 100644
index 0000000..de2fe22
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ftw/ftw64.c
@@ -0,0 +1,32 @@
+/* File tree walker functions.  LFS version.
+   Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define FTW_NAME ftw64
+#define NFTW_NAME nftw64
+#define NFTW_OLD_NAME __old_nftw64
+#define NFTW_NEW_NAME __new_nftw64
+#define INO_T ino64_t
+#define STAT stat64
+#define LXSTAT(V,f,sb) lstat64(f,sb)
+#define XSTAT(V,f,sb) stat64(f,sb)
+#define FTW_FUNC_T __ftw64_func_t
+#define NFTW_FUNC_T __nftw64_func_t
+
+#include "ftw.c"
diff --git a/ap/build/uClibc/libc/misc/glob/.indent.pro b/ap/build/uClibc/libc/misc/glob/.indent.pro
new file mode 100644
index 0000000..492ecf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/glob/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/ap/build/uClibc/libc/misc/glob/Makefile b/ap/build/uClibc/libc/misc/glob/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/glob/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/glob/Makefile.in b/ap/build/uClibc/libc/misc/glob/Makefile.in
new file mode 100644
index 0000000..03bfcca
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/glob/Makefile.in
@@ -0,0 +1,33 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/glob
+
+ifeq ($(UCLIBC_HAS_GNU_GLOB),y)
+CSRC := glob.c
+ifeq ($(UCLIBC_HAS_LFS),y)
+CSRC += glob64.c
+endif
+else
+CSRC := glob-susv3.c
+ifeq ($(UCLIBC_HAS_LFS),y)
+CSRC += glob64-susv3.c
+endif
+endif
+
+MISC_GLOB_DIR := $(top_srcdir)libc/misc/glob
+MISC_GLOB_OUT := $(top_builddir)libc/misc/glob
+
+MISC_GLOB_SRC := $(patsubst %.c,$(MISC_GLOB_DIR)/%.c,$(CSRC))
+MISC_GLOB_OBJ := $(patsubst %.c,$(MISC_GLOB_OUT)/%.o,$(CSRC))
+
+libc-$(UCLIBC_HAS_GLOB) += $(MISC_GLOB_OBJ)
+
+objclean-y += CLEAN_libc/misc/glob
+
+CLEAN_libc/misc/glob:
+	$(do_rm) $(addprefix $(MISC_GLOB_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/glob/glob-susv3.c b/ap/build/uClibc/libc/misc/glob/glob-susv3.c
new file mode 100644
index 0000000..59b4d8e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/glob/glob-susv3.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2006 Rich Felker <dalias@aerifal.cx>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <features.h>
+
+#ifdef __UCLIBC_HAS_LFS__
+# define BUILD_GLOB64
+#endif
+
+#include <glob.h>
+#include <fnmatch.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+
+#include <unistd.h>
+#include <stdio.h>
+
+
+struct match
+{
+	struct match *next;
+	char name[1];
+};
+
+#ifdef BUILD_GLOB64
+extern int __glob_is_literal(const char *p, int useesc) attribute_hidden;
+extern int __glob_append(struct match **tail, const char *name, size_t len, int mark) attribute_hidden;
+extern int __glob_ignore_err(const char *path, int err) attribute_hidden;
+extern void __glob_freelist(struct match *head) attribute_hidden;
+extern int __glob_sort(const void *a, const void *b) attribute_hidden;
+extern int __glob_match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail) attribute_hidden;
+#endif
+
+#ifdef __UCLIBC_HAS_LFS__
+# define stat stat64
+# define readdir_r readdir64_r
+# define dirent dirent64
+# define struct_stat struct stat64
+#else
+# define struct_stat struct stat
+#endif
+
+/* keep only one copy of these */
+#ifndef __GLOB64
+
+# ifndef BUILD_GLOB64
+static
+# endif
+int __glob_is_literal(const char *p, int useesc)
+{
+	int bracket = 0;
+	for (; *p; p++) {
+		switch (*p) {
+		case '\\':
+			if (!useesc) break;
+		case '?':
+		case '*':
+			return 0;
+		case '[':
+			bracket = 1;
+			break;
+		case ']':
+			if (bracket) return 0;
+			break;
+		}
+	}
+	return 1;
+}
+
+# ifndef BUILD_GLOB64
+static
+# endif
+int __glob_append(struct match **tail, const char *name, size_t len, int mark)
+{
+	struct match *new = malloc(sizeof(struct match) + len + 1);
+	if (!new) return -1;
+	(*tail)->next = new;
+	new->next = NULL;
+	strcpy(new->name, name);
+	if (mark) strcat(new->name, "/");
+	*tail = new;
+	return 0;
+}
+
+# ifndef BUILD_GLOB64
+static
+# endif
+int __glob_match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail)
+{
+	DIR *dir;
+	long long de_buf[(sizeof(struct dirent) + NAME_MAX + sizeof(long long))/sizeof(long long)];
+	struct dirent *de;
+	char pat[strlen(p)+1];
+	char *p2;
+	size_t l = strlen(d);
+	int literal;
+	int fnm_flags= ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) | FNM_PERIOD;
+	int error;
+
+	if ((p2 = strchr(p, '/'))) {
+		strcpy(pat, p);
+		pat[p2-p] = 0;
+		for (; *p2 == '/'; p2++);
+		p = pat;
+	}
+	literal = __glob_is_literal(p, !(flags & GLOB_NOESCAPE));
+	if (*d == '/' && !*(d+1)) l = 0;
+
+	/* rely on opendir failing for nondirectory objects */
+	dir = opendir(*d ? d : ".");
+	error = errno;
+	if (!dir) {
+		/* this is not an error -- we let opendir call stat for us */
+		if (error == ENOTDIR) return 0;
+		if (error == EACCES && !*p) {
+			struct_stat st;
+			if (!stat(d, &st) && S_ISDIR(st.st_mode)) {
+				if (__glob_append(tail, d, l, l))
+					return GLOB_NOSPACE;
+				return 0;
+			}
+		}
+		if (errfunc(d, error) || (flags & GLOB_ERR))
+			return GLOB_ABORTED;
+		return 0;
+	}
+	if (!*p) {
+		error = __glob_append(tail, d, l, l) ? GLOB_NOSPACE : 0;
+		closedir(dir);
+		return error;
+	}
+	while (!(error = readdir_r(dir, (void *)de_buf, &de)) && de) {
+		char namebuf[l+de->d_reclen+2], *name = namebuf;
+		if (!literal && fnmatch(p, de->d_name, fnm_flags))
+			continue;
+		if (literal && strcmp(p, de->d_name))
+			continue;
+		if (p2 && de->d_type && !S_ISDIR(de->d_type<<12) && !S_ISLNK(de->d_type<<12))
+			continue;
+		if (*d) {
+			memcpy(name, d, l);
+			name[l] = '/';
+			strcpy(name+l+1, de->d_name);
+		} else {
+			name = de->d_name;
+		}
+		if (p2) {
+			if ((error = __glob_match_in_dir(name, p2, flags, errfunc, tail))) {
+				closedir(dir);
+				return error;
+			}
+		} else {
+			int mark = 0;
+			if (flags & GLOB_MARK) {
+				if (de->d_type)
+					mark = S_ISDIR(de->d_type<<12);
+				else {
+					struct_stat st;
+					stat(name, &st);
+					mark = S_ISDIR(st.st_mode);
+				}
+			}
+			if (__glob_append(tail, name, l+de->d_reclen+1, mark)) {
+				closedir(dir);
+				return GLOB_NOSPACE;
+			}
+		}
+	}
+	closedir(dir);
+	if (error && (errfunc(d, error) || (flags & GLOB_ERR)))
+		return GLOB_ABORTED;
+	return 0;
+}
+
+# ifndef BUILD_GLOB64
+static
+# endif
+int __glob_ignore_err(const char * path attribute_unused,
+			int err attribute_unused)
+{
+	return 0;
+}
+
+# ifndef BUILD_GLOB64
+static
+# endif
+void __glob_freelist(struct match *head)
+{
+	struct match *match, *next;
+	for (match=head->next; match; match=next) {
+		next = match->next;
+		free(match);
+	}
+}
+
+# ifndef BUILD_GLOB64
+static
+# endif
+int __glob_sort(const void *a, const void *b)
+{
+	return strcmp(*(const char **)a, *(const char **)b);
+}
+#endif /* !__GLOB64 */
+
+int glob(const char *pat, int flags, int (*errfunc)(const char *path, int err), glob_t *g)
+{
+	const char *p=pat, *d;
+	struct match head = { .next = NULL }, *tail = &head;
+	size_t cnt, i;
+	size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
+	int error = 0;
+
+	if (*p == '/') {
+		for (; *p == '/'; p++);
+		d = "/";
+	} else {
+		d = "";
+	}
+
+	if (!errfunc) errfunc = __glob_ignore_err;
+
+	if (!(flags & GLOB_APPEND)) {
+		g->gl_offs = offs;
+		g->gl_pathc = 0;
+		g->gl_pathv = NULL;
+	}
+
+	if (*p) error = __glob_match_in_dir(d, p, flags, errfunc, &tail);
+	if (error == GLOB_NOSPACE) {
+		__glob_freelist(&head);
+		return error;
+	}
+
+	for (cnt=0, tail=head.next; tail; tail=tail->next, cnt++);
+	if (!cnt) {
+		if (flags & GLOB_NOCHECK) {
+			tail = &head;
+			if (__glob_append(&tail, pat, strlen(pat), 0))
+				return GLOB_NOSPACE;
+			cnt++;
+		} else
+			return GLOB_NOMATCH;
+	}
+
+	if (flags & GLOB_APPEND) {
+		char **pathv = realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *));
+		if (!pathv) {
+			__glob_freelist(&head);
+			return GLOB_NOSPACE;
+		}
+		g->gl_pathv = pathv;
+		offs += g->gl_pathc;
+	} else {
+		g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *));
+		if (!g->gl_pathv) {
+			__glob_freelist(&head);
+			return GLOB_NOSPACE;
+		}
+		for (i=0; i<offs; i++)
+			g->gl_pathv[i] = NULL;
+	}
+	for (i=0, tail=head.next; i<cnt; tail=tail->next, i++)
+		g->gl_pathv[offs + i] = tail->name;
+	g->gl_pathv[offs + i] = NULL;
+	g->gl_pathc += cnt;
+
+	if (!(flags & GLOB_NOSORT))
+		qsort(g->gl_pathv+offs, cnt, sizeof(char *), __glob_sort);
+
+	return error;
+}
+#ifdef __GLOB64
+libc_hidden_def(glob64)
+#else
+libc_hidden_def(glob)
+#endif
+
+void globfree(glob_t *g)
+{
+	size_t i;
+	for (i=0; i<g->gl_pathc; i++)
+		free(g->gl_pathv[g->gl_offs + i] - offsetof(struct match, name));
+	free(g->gl_pathv);
+	g->gl_pathc = 0;
+	g->gl_pathv = NULL;
+}
+#ifdef __GLOB64
+libc_hidden_def(globfree64)
+#else
+libc_hidden_def(globfree)
+#endif
diff --git a/ap/build/uClibc/libc/misc/glob/glob.c b/ap/build/uClibc/libc/misc/glob/glob.c
new file mode 100644
index 0000000..488f229
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/glob/glob.c
@@ -0,0 +1,1067 @@
+/* Copyright (C) 1991-2002,2003,2004,2005,2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#undef ENABLE_GLOB_BRACE_EXPANSION
+#undef ENABLE_GLOB_TILDE_EXPANSION
+
+#include <features.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <malloc.h>
+#include <fnmatch.h>
+#include <glob.h>
+
+
+
+#ifdef ENABLE_GLOB_TILDE_EXPANSION
+#include <pwd.h>
+#endif
+
+#ifdef COMPILE_GLOB64
+#undef stat
+#define stat stat64
+#define struct_stat64          struct stat64
+#define __stat64(fname, buf)   stat64 (fname, buf)
+#define dirent dirent64
+#define __readdir readdir64
+#define __readdir64 readdir64
+#define glob_t glob64_t
+#define glob(pattern, flags, errfunc, pglob) glob64 (pattern, flags, errfunc, pglob)
+#define globfree(pglob) globfree64 (pglob)
+#else
+#define __readdir readdir
+#ifdef __UCLIBC_HAS_LFS__
+#define __readdir64 readdir64
+#else
+#define __readdir64 readdir
+#endif
+#define struct_stat64          struct stat
+#define __stat64(fname, buf)   stat (fname, buf)
+#endif
+
+
+/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
+   if the `d_type' member for `struct dirent' is available.
+   HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB.  */
+#if defined _DIRENT_HAVE_D_TYPE
+/* True if the directory entry D must be of type T.  */
+# define DIRENT_MUST_BE(d, t)	((d)->d_type == (t))
+
+/* True if the directory entry D might be a symbolic link.  */
+# define DIRENT_MIGHT_BE_SYMLINK(d) \
+    ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
+
+/* True if the directory entry D might be a directory.  */
+# define DIRENT_MIGHT_BE_DIR(d)	 \
+    ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
+
+#else /* !HAVE_D_TYPE */
+# define DIRENT_MUST_BE(d, t)		false
+# define DIRENT_MIGHT_BE_SYMLINK(d)	true
+# define DIRENT_MIGHT_BE_DIR(d)		true
+#endif /* HAVE_D_TYPE */
+
+
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#ifdef _D_NAMLEN
+# undef NAMLEN
+# define NAMLEN(d) _D_NAMLEN(d)
+#endif
+
+# if defined _DIRENT_HAVE_D_NAMLEN
+#  define CONVERT_D_NAMLEN(d64, d32)    (d64)->d_namlen = (d32)->d_namlen;
+# else
+#  define CONVERT_D_NAMLEN(d64, d32)
+# endif
+
+#  define CONVERT_D_INO(d64, d32)	(d64)->d_ino = (d32)->d_ino;
+
+# ifdef _DIRENT_HAVE_D_TYPE
+#  define CONVERT_D_TYPE(d64, d32)	(d64)->d_type = (d32)->d_type;
+# else
+#  define CONVERT_D_TYPE(d64, d32)
+# endif
+
+# define CONVERT_DIRENT_DIRENT64(d64, d32) \
+  memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1);		      \
+  CONVERT_D_NAMLEN (d64, d32)						      \
+  CONVERT_D_INO (d64, d32)						      \
+  CONVERT_D_TYPE (d64, d32)
+
+extern int __collated_compare (const void *a, const void *b) attribute_hidden;
+extern int __prefix_array (const char *dirname, char **array, size_t n) attribute_hidden;
+#if defined ENABLE_GLOB_BRACE_EXPANSION
+extern const char *__next_brace_sub (const char *cp, int flags) attribute_hidden;
+#endif
+
+#ifndef COMPILE_GLOB64
+/* Return nonzero if PATTERN contains any metacharacters.
+   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
+int glob_pattern_p(const char *pattern, int quote)
+{
+  register const char *p;
+  int open = 0;
+
+  for (p = pattern; *p != '\0'; ++p)
+    switch (*p)
+      {
+      case '?':
+      case '*':
+	return 1;
+
+      case '\\':
+	if (quote && p[1] != '\0')
+	  ++p;
+	break;
+
+      case '[':
+	open = 1;
+	break;
+
+      case ']':
+	if (open)
+	  return 1;
+	break;
+      }
+
+  return 0;
+}
+libc_hidden_def(glob_pattern_p)
+
+
+/* Do a collated comparison of A and B.  */
+int __collated_compare (const void *a, const void *b)
+{
+  const char *const s1 = *(const char *const * const) a;
+  const char *const s2 = *(const char *const * const) b;
+
+  if (s1 == s2)
+    return 0;
+  if (s1 == NULL)
+    return 1;
+  if (s2 == NULL)
+    return -1;
+  return strcoll (s1, s2);
+}
+
+
+/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
+   elements in place.  Return nonzero if out of memory, zero if successful.
+   A slash is inserted between DIRNAME and each elt of ARRAY,
+   unless DIRNAME is just "/".  Each old element of ARRAY is freed.
+   If ADD_SLASH is non-zero, allocate one character more than
+   necessary, so that a slash can be appended later.  */
+int __prefix_array (const char *dirname, char **array, size_t n)
+{
+  register size_t i;
+  size_t dirlen = strlen (dirname);
+# define DIRSEP_CHAR '/'
+
+  if (dirlen == 1 && dirname[0] == '/')
+    /* DIRNAME is just "/", so normal prepending would get us "//foo".
+       We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
+    dirlen = 0;
+
+  for (i = 0; i < n; ++i)
+    {
+      size_t eltlen = strlen (array[i]) + 1;
+      char *new = (char *) malloc (dirlen + 1 + eltlen);
+      if (new == NULL)
+	{
+	  while (i > 0)
+	    free (array[--i]);
+	  return 1;
+	}
+
+      {
+	char *endp = mempcpy (new, dirname, dirlen);
+	*endp++ = DIRSEP_CHAR;
+	mempcpy (endp, array[i], eltlen);
+      }
+      free (array[i]);
+      array[i] = new;
+    }
+
+  return 0;
+}
+
+#if defined ENABLE_GLOB_BRACE_EXPANSION
+/* Find the end of the sub-pattern in a brace expression.  */
+const char *
+__next_brace_sub (const char *cp, int flags)
+{
+  unsigned int depth = 0;
+  while (*cp != '\0')
+    if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
+      {
+	if (*++cp == '\0')
+	  break;
+	++cp;
+      }
+    else
+      {
+	if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
+	  break;
+
+	if (*cp++ == '{')
+	  depth++;
+      }
+
+  return *cp != '\0' ? cp : NULL;
+}
+#endif
+#endif
+
+
+static int
+link_exists_p (const char *dir, size_t dirlen, const char *fname,
+	       glob_t *pglob, int flags)
+{
+  size_t fnamelen = strlen (fname);
+  char *fullname = (char *) alloca (dirlen + 1 + fnamelen + 1);
+  struct stat st;
+  struct_stat64 st64;
+
+  mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
+	   fname, fnamelen + 1);
+
+  return (((flags & GLOB_ALTDIRFUNC)
+	   ? (*pglob->gl_stat) (fullname, &st)
+	   : __stat64 (fullname, &st64)) == 0);
+}
+
+/* Like `glob', but PATTERN is a final pathname component,
+   and matches are searched for in DIRECTORY.
+   The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
+   The GLOB_APPEND flag is assumed to be set (always appends).  */
+static int glob_in_dir (const char *pattern, const char *directory, int flags,
+	     int (*errfunc) (const char *, int),
+	     glob_t *pglob)
+{
+  size_t dirlen = strlen (directory);
+  void *stream = NULL;
+  struct globlink
+    {
+      struct globlink *next;
+      char *name;
+    };
+  struct globlink *names = NULL;
+  size_t nfound;
+  int meta;
+  int save;
+
+  meta = glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
+  if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+    {
+      /* We need not do any tests.  The PATTERN contains no meta
+	 characters and we must not return an error therefore the
+	 result will always contain exactly one name.  */
+      flags |= GLOB_NOCHECK;
+      nfound = 0;
+    }
+  else if (meta == 0 &&
+	   ((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL))
+    {
+      /* Since we use the normal file functions we can also use stat()
+	 to verify the file is there.  */
+      struct stat st;
+      struct_stat64 st64;
+      size_t patlen = strlen (pattern);
+      char *fullname = (char *) alloca (dirlen + 1 + patlen + 1);
+
+      mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
+			"/", 1),
+	       pattern, patlen + 1);
+      if (((flags & GLOB_ALTDIRFUNC)
+	   ? (*pglob->gl_stat) (fullname, &st)
+	   : __stat64 (fullname, &st64)) == 0)
+	/* We found this file to be existing.  Now tell the rest
+	   of the function to copy this name into the result.  */
+	flags |= GLOB_NOCHECK;
+
+      nfound = 0;
+    }
+  else
+    {
+      if (pattern[0] == '\0')
+	{
+	  /* This is a special case for matching directories like in
+	     "*a/".  */
+	  names = (struct globlink *) alloca (sizeof (struct globlink));
+	  names->name = (char *) malloc (1);
+	  if (names->name == NULL)
+	    goto memory_error;
+	  names->name[0] = '\0';
+	  names->next = NULL;
+	  nfound = 1;
+	  meta = 0;
+	}
+      else
+	{
+	  stream = ((flags & GLOB_ALTDIRFUNC)
+		    ? (*pglob->gl_opendir) (directory)
+		    : opendir (directory));
+	  if (stream == NULL)
+	    {
+	      if (errno != ENOTDIR
+		  && ((errfunc != NULL && (*errfunc) (directory, errno))
+		      || (flags & GLOB_ERR)))
+		return GLOB_ABORTED;
+	      nfound = 0;
+	      meta = 0;
+	    }
+	  else
+	    {
+	      int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+			       | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
+			       );
+	      nfound = 0;
+	      flags |= GLOB_MAGCHAR;
+
+	      while (1)
+		{
+		  const char *name;
+		  size_t len;
+#if defined __UCLIBC_HAS_LFS__ && !defined COMPILE_GLOB64
+		  struct dirent64 *d;
+		  union
+		    {
+		      struct dirent64 d64;
+		      char room [offsetof (struct dirent64, d_name[0])
+				 + NAME_MAX + 1];
+		    }
+		  d64buf;
+
+		  if (flags & GLOB_ALTDIRFUNC)
+		    {
+		      struct dirent *d32 = (*pglob->gl_readdir) (stream);
+		      if (d32 != NULL)
+			{
+			  CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
+			  d = &d64buf.d64;
+			}
+		      else
+			d = NULL;
+		    }
+		  else
+		    d = __readdir64 (stream);
+#else
+		  struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
+				      ? ((struct dirent *)
+					 (*pglob->gl_readdir) (stream))
+				      : __readdir (stream));
+#endif
+		  if (d == NULL)
+		    break;
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+		  if (! REAL_DIR_ENTRY (d))
+		    continue;
+
+		  /* If we shall match only directories use the information
+		     provided by the dirent call if possible.  */
+		  if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d))
+		    continue;
+
+		  name = d->d_name;
+
+		  if (fnmatch (pattern, name, fnm_flags) == 0)
+		    {
+		      /* If the file we found is a symlink we have to
+			 make sure the target file exists.  */
+		      if (!DIRENT_MIGHT_BE_SYMLINK (d)
+			  || link_exists_p (directory, dirlen, name, pglob,
+					    flags))
+			{
+			  struct globlink *new = (struct globlink *)
+			    alloca (sizeof (struct globlink));
+			  len = NAMLEN (d);
+			  new->name = (char *) malloc (len + 1);
+			  if (new->name == NULL)
+			    goto memory_error;
+			  *((char *) mempcpy (new->name, name, len)) = '\0';
+			  new->next = names;
+			  names = new;
+			  ++nfound;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  if (nfound == 0 && (flags & GLOB_NOCHECK))
+    {
+      size_t len = strlen (pattern);
+      nfound = 1;
+      names = (struct globlink *) alloca (sizeof (struct globlink));
+      names->next = NULL;
+      names->name = (char *) malloc (len + 1);
+      if (names->name == NULL)
+	goto memory_error;
+      *((char *) mempcpy (names->name, pattern, len)) = '\0';
+    }
+
+  if (nfound != 0)
+    {
+      char **new_gl_pathv;
+
+      new_gl_pathv
+	= (char **) realloc (pglob->gl_pathv,
+			     (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
+			     * sizeof (char *));
+      if (new_gl_pathv == NULL)
+	goto memory_error;
+      pglob->gl_pathv = new_gl_pathv;
+
+      for (; names != NULL; names = names->next)
+	pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name;
+      pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+      pglob->gl_flags = flags;
+    }
+
+  save = errno;
+  if (stream != NULL)
+    {
+      if (flags & GLOB_ALTDIRFUNC)
+	(*pglob->gl_closedir) (stream);
+      else
+	closedir (stream);
+    }
+  __set_errno (save);
+
+  return nfound == 0 ? GLOB_NOMATCH : 0;
+
+ memory_error:
+  {
+    int save2 = errno;
+    if (flags & GLOB_ALTDIRFUNC)
+      (*pglob->gl_closedir) (stream);
+    else
+      closedir (stream);
+    __set_errno (save2);
+  }
+  while (names != NULL)
+    {
+      free (names->name);
+      names = names->next;
+    }
+  return GLOB_NOSPACE;
+}
+
+/* Do glob searching for PATTERN, placing results in PGLOB.
+   The bits defined above may be set in FLAGS.
+   If a directory cannot be opened or read and ERRFUNC is not nil,
+   it is called with the pathname that caused the error, and the
+   `errno' value from the failing call; if it returns non-zero
+   `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
+   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+   Otherwise, `glob' returns zero.  */
+int
+glob (
+     const char *pattern,
+     int flags,
+     int (*errfunc) (const char *, int),
+     glob_t *pglob)
+{
+  const char *filename;
+  const char *dirname;
+  size_t dirlen;
+  int status;
+  size_t oldcount;
+
+  if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+
+  if (!(flags & GLOB_DOOFFS))
+    /* Have to do this so `globfree' knows where to start freeing.  It
+       also makes all the code that uses gl_offs simpler. */
+    pglob->gl_offs = 0;
+
+#if defined ENABLE_GLOB_BRACE_EXPANSION
+  if (flags & GLOB_BRACE)
+    {
+      const char *begin;
+
+      if (flags & GLOB_NOESCAPE)
+	begin = strchr (pattern, '{');
+      else
+	{
+	  begin = pattern;
+	  while (1)
+	    {
+	      if (*begin == '\0')
+		{
+		  begin = NULL;
+		  break;
+		}
+
+	      if (*begin == '\\' && begin[1] != '\0')
+		++begin;
+	      else if (*begin == '{')
+		break;
+
+	      ++begin;
+	    }
+	}
+
+      if (begin != NULL)
+	{
+	  /* Allocate working buffer large enough for our work.  Note that
+	    we have at least an opening and closing brace.  */
+	  size_t firstc;
+	  char *alt_start;
+	  const char *p;
+	  const char *next;
+	  const char *rest;
+	  size_t rest_len;
+	  char onealt[strlen (pattern) - 1];
+
+	  /* We know the prefix for all sub-patterns.  */
+	  alt_start = mempcpy (onealt, pattern, begin - pattern);
+
+	  /* Find the first sub-pattern and at the same time find the
+	     rest after the closing brace.  */
+	  next = __next_brace_sub (begin + 1, flags);
+	  if (next == NULL)
+	    {
+	      /* It is an illegal expression.  */
+	      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+	    }
+
+	  /* Now find the end of the whole brace expression.  */
+	  rest = next;
+	  while (*rest != '}')
+	    {
+	      rest = __next_brace_sub (rest + 1, flags);
+	      if (rest == NULL)
+		{
+		  /* It is an illegal expression.  */
+		  return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+		}
+	    }
+	  /* Please note that we now can be sure the brace expression
+	     is well-formed.  */
+	  rest_len = strlen (++rest) + 1;
+
+	  /* We have a brace expression.  BEGIN points to the opening {,
+	     NEXT points past the terminator of the first element, and END
+	     points past the final }.  We will accumulate result names from
+	     recursive runs for each brace alternative in the buffer using
+	     GLOB_APPEND.  */
+
+	  if (!(flags & GLOB_APPEND))
+	    {
+	      /* This call is to set a new vector, so clear out the
+		 vector so we can append to it.  */
+	      pglob->gl_pathc = 0;
+	      pglob->gl_pathv = NULL;
+	    }
+	  firstc = pglob->gl_pathc;
+
+	  p = begin + 1;
+	  while (1)
+	    {
+	      int result;
+
+	      /* Construct the new glob expression.  */
+	      mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
+
+	      result = glob (onealt,
+			     ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
+			      | GLOB_APPEND), errfunc, pglob);
+
+	      /* If we got an error, return it.  */
+	      if (result && result != GLOB_NOMATCH)
+		{
+		  if (!(flags & GLOB_APPEND))
+		    {
+		      globfree (pglob);
+		      pglob->gl_pathc = 0;
+		    }
+		  return result;
+		}
+
+	      if (*next == '}')
+		/* We saw the last entry.  */
+		break;
+
+	      p = next + 1;
+	      next = __next_brace_sub (p, flags);
+	      /* assert (next != NULL); */
+	    }
+
+
+	  if (pglob->gl_pathc != firstc)
+	    /* We found some entries.  */
+	    return 0;
+	  else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+	    return GLOB_NOMATCH;
+	}
+    }
+#endif
+
+  /* Find the filename.  */
+  filename = strrchr (pattern, '/');
+  if (filename == NULL)
+    {
+      /* This can mean two things: a simple name or "~name".  The latter
+	 case is nothing but a notation for a directory.  */
+      if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
+	{
+	  dirname = pattern;
+	  dirlen = strlen (pattern);
+
+	  /* Set FILENAME to NULL as a special flag.  This is ugly but
+	     other solutions would require much more code.  We test for
+	     this special case below.  */
+	  filename = NULL;
+	}
+      else
+	{
+	  filename = pattern;
+	  dirname = ".";
+	  dirlen = 0;
+	}
+    }
+  else if (filename == pattern)
+    {
+      /* "/pattern".  */
+      dirname = "/";
+      dirlen = 1;
+      ++filename;
+    }
+  else
+    {
+      char *newp;
+      dirlen = filename - pattern;
+      newp = (char *) alloca (dirlen + 1);
+      *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
+      dirname = newp;
+      ++filename;
+
+      if (filename[0] == '\0'
+	  && dirlen > 1)
+	/* "pattern/".  Expand "pattern", appending slashes.  */
+	{
+	  int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+	  if (val == 0)
+	    pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
+			       | (flags & GLOB_MARK));
+	  return val;
+	}
+    }
+
+  if (!(flags & GLOB_APPEND))
+    {
+      pglob->gl_pathc = 0;
+      if (!(flags & GLOB_DOOFFS))
+        pglob->gl_pathv = NULL;
+      else
+	{
+	  size_t i;
+	  pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
+					      * sizeof (char *));
+	  if (pglob->gl_pathv == NULL)
+	    return GLOB_NOSPACE;
+
+	  for (i = 0; i <= pglob->gl_offs; ++i)
+	    pglob->gl_pathv[i] = NULL;
+	}
+    }
+
+  oldcount = pglob->gl_pathc + pglob->gl_offs;
+
+#if defined ENABLE_GLOB_TILDE_EXPANSION
+  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
+    {
+      if (dirname[1] == '\0' || dirname[1] == '/')
+	{
+	  /* Look up home directory.  */
+	  const char *home_dir = getenv ("HOME");
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    {
+	      int success;
+	      char *name;
+# define GET_LOGIN_NAME_MAX()	sysconf (_SC_LOGIN_NAME_MAX)
+	      size_t buflen = GET_LOGIN_NAME_MAX () + 1;
+
+	      if (buflen == 0)
+		/* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
+		   a moderate value.  */
+		buflen = 20;
+	      name = (char *) alloca (buflen);
+
+	      success = getlogin_r (name, buflen) == 0;
+	      if (success)
+		{
+		  struct passwd *p;
+# define GETPW_R_SIZE_MAX()	sysconf (_SC_GETPW_R_SIZE_MAX)
+		  long int pwbuflen = GETPW_R_SIZE_MAX ();
+		  char *pwtmpbuf;
+		  struct passwd pwbuf;
+		  int save = errno;
+
+		  pwtmpbuf = (char *) alloca (pwbuflen);
+
+		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+			 != 0)
+		    {
+		      if (errno != ERANGE)
+			{
+			  p = NULL;
+			  break;
+			}
+		      pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen,
+						2 * pwbuflen);
+		      __set_errno (save);
+		    }
+		  if (p != NULL)
+		    home_dir = p->pw_dir;
+		}
+	    }
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    {
+	      if (flags & GLOB_TILDE_CHECK)
+		return GLOB_NOMATCH;
+	      else
+		home_dir = "~"; /* No luck.  */
+	    }
+	  /* Now construct the full directory.  */
+	  if (dirname[1] == '\0')
+	    dirname = home_dir;
+	  else
+	    {
+	      char *newp;
+	      size_t home_len = strlen (home_dir);
+	      newp = (char *) alloca (home_len + dirlen);
+	      mempcpy (mempcpy (newp, home_dir, home_len),
+		       &dirname[1], dirlen);
+	      dirname = newp;
+	    }
+	}
+      else
+	{
+	  char *end_name = strchr (dirname, '/');
+	  const char *user_name;
+	  const char *home_dir;
+
+	  if (end_name == NULL)
+	    user_name = dirname + 1;
+	  else
+	    {
+	      char *newp;
+	      newp = (char *) alloca (end_name - dirname);
+	      *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
+		= '\0';
+	      user_name = newp;
+	    }
+
+	  /* Look up specific user's home directory.  */
+	  {
+	    struct passwd *p;
+	    long int buflen = GETPW_R_SIZE_MAX ();
+	    char *pwtmpbuf;
+	    struct passwd pwbuf;
+	    int save = errno;
+
+	    pwtmpbuf = (char *) alloca (buflen);
+
+	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+	      {
+		if (errno != ERANGE)
+		  {
+		    p = NULL;
+		    break;
+		  }
+		pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen);
+		__set_errno (save);
+	      }
+	    if (p != NULL)
+	      home_dir = p->pw_dir;
+	    else
+	      home_dir = NULL;
+	  }
+	  /* If we found a home directory use this.  */
+	  if (home_dir != NULL)
+	    {
+	      char *newp;
+	      size_t home_len = strlen (home_dir);
+	      size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+	      newp = (char *) alloca (home_len + rest_len + 1);
+	      *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
+				  end_name, rest_len)) = '\0';
+	      dirname = newp;
+	    }
+	  else
+	    if (flags & GLOB_TILDE_CHECK)
+	      /* We have to regard it as an error if we cannot find the
+		 home directory.  */
+	      return GLOB_NOMATCH;
+	}
+    }
+
+  /* Now test whether we looked for "~" or "~NAME".  In this case we
+     can give the answer now.  */
+  if (filename == NULL)
+    {
+      struct stat st;
+      struct_stat64 st64;
+
+      /* Return the directory if we don't check for error or if it exists.  */
+      if ((flags & GLOB_NOCHECK)
+	  || (((flags & GLOB_ALTDIRFUNC)
+	       ? ((*pglob->gl_stat) (dirname, &st) == 0
+		  && S_ISDIR (st.st_mode))
+	       : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
+	{
+	  int newcount = pglob->gl_pathc + pglob->gl_offs;
+	  char **new_gl_pathv;
+
+	  new_gl_pathv
+	    = (char **) realloc (pglob->gl_pathv,
+				 (newcount + 1 + 1) * sizeof (char *));
+	  if (new_gl_pathv == NULL)
+	    {
+	    nospace:
+	      free (pglob->gl_pathv);
+	      pglob->gl_pathv = NULL;
+	      pglob->gl_pathc = 0;
+	      return GLOB_NOSPACE;
+	    }
+	  pglob->gl_pathv = new_gl_pathv;
+
+	   pglob->gl_pathv[newcount] = strdup (dirname);
+	  if (pglob->gl_pathv[newcount] == NULL)
+	    goto nospace;
+	  pglob->gl_pathv[++newcount] = NULL;
+	  ++pglob->gl_pathc;
+	  pglob->gl_flags = flags;
+
+	  return 0;
+	}
+
+      /* Not found.  */
+      return GLOB_NOMATCH;
+    }
+#endif
+
+  if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
+    {
+      /* The directory name contains metacharacters, so we
+	 have to glob for the directory, and then glob for
+	 the pattern in each directory found.  */
+      glob_t dirs;
+      size_t i;
+
+      if ((flags & GLOB_ALTDIRFUNC) != 0)
+	{
+	  /* Use the alternative access functions also in the recursive
+	     call.  */
+	  dirs.gl_opendir = pglob->gl_opendir;
+	  dirs.gl_readdir = pglob->gl_readdir;
+	  dirs.gl_closedir = pglob->gl_closedir;
+	  dirs.gl_stat = pglob->gl_stat;
+	  dirs.gl_lstat = pglob->gl_lstat;
+	}
+
+      status = glob (dirname,
+		     ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE
+				| GLOB_ALTDIRFUNC))
+		      | GLOB_NOSORT | GLOB_ONLYDIR),
+		     errfunc, &dirs);
+      if (status != 0)
+	return status;
+
+      /* We have successfully globbed the preceding directory name.
+	 For each name we found, call glob_in_dir on it and FILENAME,
+	 appending the results to PGLOB.  */
+      for (i = 0; i < dirs.gl_pathc; ++i)
+	{
+	  int old_pathc;
+
+	  old_pathc = pglob->gl_pathc;
+	  status = glob_in_dir (filename, dirs.gl_pathv[i],
+				((flags | GLOB_APPEND)
+				 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
+				errfunc, pglob);
+	  if (status == GLOB_NOMATCH)
+	    /* No matches in this directory.  Try the next.  */
+	    continue;
+
+	  if (status != 0)
+	    {
+	      globfree (&dirs);
+	      globfree (pglob);
+	      pglob->gl_pathc = 0;
+	      return status;
+	    }
+
+	  /* Stick the directory on the front of each name.  */
+	  if (__prefix_array (dirs.gl_pathv[i],
+			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
+			    pglob->gl_pathc - old_pathc))
+	    {
+	      globfree (&dirs);
+	      globfree (pglob);
+	      pglob->gl_pathc = 0;
+	      return GLOB_NOSPACE;
+	    }
+	}
+
+      flags |= GLOB_MAGCHAR;
+
+      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
+	 But if we have not found any matching entry and the GLOB_NOCHECK
+	 flag was set we must return the input pattern itself.  */
+      if (pglob->gl_pathc + pglob->gl_offs == oldcount)
+	{
+	  /* No matches.  */
+	  if (flags & GLOB_NOCHECK)
+	    {
+	      int newcount = pglob->gl_pathc + pglob->gl_offs;
+	      char **new_gl_pathv;
+
+	      new_gl_pathv = (char **) realloc (pglob->gl_pathv,
+						(newcount + 2)
+						* sizeof (char *));
+	      if (new_gl_pathv == NULL)
+		{
+		  globfree (&dirs);
+		  return GLOB_NOSPACE;
+		}
+	      pglob->gl_pathv = new_gl_pathv;
+
+	      pglob->gl_pathv[newcount] = strdup (pattern);
+	      if (pglob->gl_pathv[newcount] == NULL)
+		{
+		  globfree (&dirs);
+		  globfree (pglob);
+		  pglob->gl_pathc = 0;
+		  return GLOB_NOSPACE;
+		}
+
+	      ++pglob->gl_pathc;
+	      ++newcount;
+
+	      pglob->gl_pathv[newcount] = NULL;
+	      pglob->gl_flags = flags;
+	    }
+	  else
+	    {
+	      globfree (&dirs);
+	      return GLOB_NOMATCH;
+	    }
+	}
+
+      globfree (&dirs);
+    }
+  else
+    {
+      int old_pathc = pglob->gl_pathc;
+
+      status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
+      if (status != 0)
+	return status;
+
+      if (dirlen > 0)
+	{
+	  /* Stick the directory on the front of each name.  */
+	  if (__prefix_array (dirname,
+			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
+			    pglob->gl_pathc - old_pathc))
+	    {
+	      globfree (pglob);
+	      pglob->gl_pathc = 0;
+	      return GLOB_NOSPACE;
+	    }
+	}
+    }
+
+  if (flags & GLOB_MARK)
+    {
+      /* Append slashes to directory names.  */
+      size_t i;
+      struct stat st;
+      struct_stat64 st64;
+
+      for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
+	if (((flags & GLOB_ALTDIRFUNC)
+	     ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
+		&& S_ISDIR (st.st_mode))
+	     : (__stat64 (pglob->gl_pathv[i], &st64) == 0
+		&& S_ISDIR (st64.st_mode))))
+	  {
+	    size_t len = strlen (pglob->gl_pathv[i]) + 2;
+	    char *new = realloc (pglob->gl_pathv[i], len);
+	    if (new == NULL)
+	      {
+		globfree (pglob);
+		pglob->gl_pathc = 0;
+		return GLOB_NOSPACE;
+	      }
+	    strcpy (&new[len - 2], "/");
+	    pglob->gl_pathv[i] = new;
+	  }
+    }
+
+  if (!(flags & GLOB_NOSORT))
+    {
+      /* Sort the vector.  */
+      qsort (&pglob->gl_pathv[oldcount],
+	     pglob->gl_pathc + pglob->gl_offs - oldcount,
+	     sizeof (char *), __collated_compare);
+    }
+
+  return 0;
+}
+#ifdef COMPILE_GLOB64
+libc_hidden_def(glob64)
+#else
+libc_hidden_def(glob)
+#endif
+
+
+/* Free storage allocated in PGLOB by a previous `glob' call.  */
+void
+globfree (register glob_t *pglob)
+{
+  if (pglob->gl_pathv != NULL)
+    {
+      size_t i;
+      for (i = 0; i < pglob->gl_pathc; ++i)
+	if (pglob->gl_pathv[pglob->gl_offs + i] != NULL)
+	  free (pglob->gl_pathv[pglob->gl_offs + i]);
+      free (pglob->gl_pathv);
+      pglob->gl_pathv = NULL;
+    }
+}
+#ifdef COMPILE_GLOB64
+libc_hidden_def(globfree64)
+#else
+libc_hidden_def(globfree)
+#endif
diff --git a/ap/build/uClibc/libc/misc/glob/glob64-susv3.c b/ap/build/uClibc/libc/misc/glob/glob64-susv3.c
new file mode 100644
index 0000000..f73e2c3
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/glob/glob64-susv3.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2006 Rich Felker <dalias@aerifal.cx>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <_lfs_64.h>
+
+#include <dirent.h>
+#include <glob.h>
+#include <sys/stat.h>
+
+#define glob_t glob64_t
+#define glob(pattern, flags, errfunc, pglob) \
+  glob64 (pattern, flags, errfunc, pglob)
+#define globfree(pglob) globfree64 (pglob)
+
+#define __GLOB64    1
+
+#include "glob-susv3.c"
diff --git a/ap/build/uClibc/libc/misc/glob/glob64.c b/ap/build/uClibc/libc/misc/glob/glob64.c
new file mode 100644
index 0000000..b84af92
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/glob/glob64.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <_lfs_64.h>
+
+#include <dirent.h>
+#include <glob.h>
+#include <sys/stat.h>
+
+#define COMPILE_GLOB64    1
+
+#include "glob.c"
diff --git a/ap/build/uClibc/libc/misc/gnu/Makefile b/ap/build/uClibc/libc/misc/gnu/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/gnu/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/gnu/Makefile.in b/ap/build/uClibc/libc/misc/gnu/Makefile.in
new file mode 100644
index 0000000..3990e4e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/gnu/Makefile.in
@@ -0,0 +1,23 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/gnu
+
+CSRC := obstack.c
+
+MISC_GNU_DIR := $(top_srcdir)libc/misc/gnu
+MISC_GNU_OUT := $(top_builddir)libc/misc/gnu
+
+MISC_GNU_SRC := $(MISC_GNU_DIR)/obstack.c
+MISC_GNU_OBJ := $(MISC_GNU_OUT)/obstack.o
+
+libc-y += $(MISC_GNU_OBJ)
+
+objclean-y += CLEAN_libc/misc/gnu
+
+CLEAN_libc/misc/gnu:
+	$(do_rm) $(addprefix $(MISC_GNU_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/gnu/obstack.c b/ap/build/uClibc/libc/misc/gnu/obstack.c
new file mode 100644
index 0000000..2391463
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/gnu/obstack.c
@@ -0,0 +1,456 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+   Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# include <obstack.h>
+#ifndef __UCLIBC__
+# include <shlib-compat.h>
+#else
+# define HAVE_INTTYPES_H 1
+# define HAVE_STDINT_H 1
+# define SHLIB_COMPAT(x,y,z) 0
+# undef libc_hidden_def
+# define libc_hidden_def(x)
+# undef strong_alias
+# define strong_alias(x,y)
+#endif
+#else
+# include "obstack.h"
+#endif
+
+/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
+   incremented whenever callers compiled using an old obstack.h can no
+   longer properly call the functions in this obstack.c.  */
+#define OBSTACK_INTERFACE_VERSION 1
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself, and the installed library
+   supports the same library interface we do.  This code is part of the GNU
+   C Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object
+   files, it is simpler to just do this in the source for each such file.  */
+
+#include <stdio.h>		/* Random thing to get __GNU_LIBRARY__.  */
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#include <stddef.h>
+
+#ifndef ELIDE_CODE
+
+
+# if HAVE_INTTYPES_H
+#  include <inttypes.h>
+# endif
+# if HAVE_STDINT_H || defined _LIBC
+#  include <stdint.h>
+# endif
+
+/* Determine default alignment.  */
+union fooround
+{
+  uintmax_t i;
+  long double d;
+  void *p;
+};
+struct fooalign
+{
+  char c;
+  union fooround u;
+};
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+   But in fact it might be less smart and round addresses to as much as
+   DEFAULT_ROUNDING.  So we prepare for it to do that.  */
+enum
+  {
+    DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
+    DEFAULT_ROUNDING = sizeof (union fooround)
+  };
+
+/* When we copy a long block of data, this is the unit to do it with.
+   On some machines, copying successive ints does not work;
+   in such a case, redefine COPYING_UNIT to `long' (if that works)
+   or `char' as a last resort.  */
+# ifndef COPYING_UNIT
+#  define COPYING_UNIT int
+# endif
+
+
+/* The functions allocating more room by calling `obstack_chunk_alloc'
+   jump to the handler pointed to by `obstack_alloc_failed_handler'.
+   This can be set to a user defined function which should either
+   abort gracefully or use longjump - but shouldn't return.  This
+   variable by default points to the internal function
+   `print_and_abort'.  */
+static void print_and_abort (void);
+static void (*__obstack_alloc_failed_handler) (void) = print_and_abort;
+weak_alias(__obstack_alloc_failed_handler,obstack_alloc_failed_handler)
+
+/* Exit value used when `print_and_abort' is used.  */
+# include <stdlib.h>
+# ifdef _LIBC
+static int __obstack_exit_failure = EXIT_FAILURE;
+weak_alias(__obstack_exit_failure,obstack_exit_failure)
+# else
+#  include "exitfail.h"
+#  define __obstack_exit_failure exit_failure
+# endif
+
+# ifdef _LIBC
+#  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+/* A looong time ago (before 1994, anyway; we're not sure) this global variable
+   was used by non-GNU-C macros to avoid multiple evaluation.  The GNU C
+   library still exports it because somebody might use it.  */
+struct obstack *_obstack_compat;
+compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
+#  endif
+# endif
+
+/* Define a macro that either calls functions with the traditional malloc/free
+   calling interface, or calls functions with the mmalloc/mfree interface
+   (that adds an extra first argument), based on the state of use_extra_arg.
+   For free, do not use ?:, since some compilers, like the MIPS compilers,
+   do not allow (expr) ? void : void.  */
+
+# define CALL_CHUNKFUN(h, size) \
+  (((h) -> use_extra_arg) \
+   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+   : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
+
+# define CALL_FREEFUN(h, old_chunk) \
+  do { \
+    if ((h) -> use_extra_arg) \
+      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+    else \
+      (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
+  } while (0)
+
+
+/* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
+   Objects start on multiples of ALIGNMENT (0 means use default).
+   CHUNKFUN is the function to use to allocate chunks,
+   and FREEFUN the function to free them.
+
+   Return nonzero if successful, calls obstack_alloc_failed_handler if
+   allocation fails.  */
+
+int
+_obstack_begin (struct obstack *h,
+		int size, int alignment,
+		void *(*chunkfun) (long),
+		void (*freefun) (void *))
+{
+  register struct _obstack_chunk *chunk; /* points to new chunk */
+
+  if (alignment == 0)
+    alignment = DEFAULT_ALIGNMENT;
+  if (size == 0)
+    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
+    {
+      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+	 Use the values for range checking, because if range checking is off,
+	 the extra bytes won't be missed terribly, but if range checking is on
+	 and we used a larger request, a whole extra 4096 bytes would be
+	 allocated.
+
+	 These number are irrelevant to the new GNU malloc.  I suspect it is
+	 less sensitive to the size of the request.  */
+      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+		    + 4 + DEFAULT_ROUNDING - 1)
+		   & ~(DEFAULT_ROUNDING - 1));
+      size = 4096 - extra;
+    }
+
+  h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
+  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+  h->chunk_size = size;
+  h->alignment_mask = alignment - 1;
+  h->use_extra_arg = 0;
+
+  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+  if (!chunk)
+    (*__obstack_alloc_failed_handler) ();
+  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+					       alignment - 1);
+  h->chunk_limit = chunk->limit
+    = (char *) chunk + h->chunk_size;
+  chunk->prev = 0;
+  /* The initial chunk now contains no empty object.  */
+  h->maybe_empty_object = 0;
+  h->alloc_failed = 0;
+  return 1;
+}
+
+int
+_obstack_begin_1 (struct obstack *h, int size, int alignment,
+		  void *(*chunkfun) (void *, long),
+		  void (*freefun) (void *, void *),
+		  void *arg)
+{
+  register struct _obstack_chunk *chunk; /* points to new chunk */
+
+  if (alignment == 0)
+    alignment = DEFAULT_ALIGNMENT;
+  if (size == 0)
+    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
+    {
+      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+	 Use the values for range checking, because if range checking is off,
+	 the extra bytes won't be missed terribly, but if range checking is on
+	 and we used a larger request, a whole extra 4096 bytes would be
+	 allocated.
+
+	 These number are irrelevant to the new GNU malloc.  I suspect it is
+	 less sensitive to the size of the request.  */
+      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+		    + 4 + DEFAULT_ROUNDING - 1)
+		   & ~(DEFAULT_ROUNDING - 1));
+      size = 4096 - extra;
+    }
+
+  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+  h->chunk_size = size;
+  h->alignment_mask = alignment - 1;
+  h->extra_arg = arg;
+  h->use_extra_arg = 1;
+
+  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+  if (!chunk)
+    (*__obstack_alloc_failed_handler) ();
+  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+					       alignment - 1);
+  h->chunk_limit = chunk->limit
+    = (char *) chunk + h->chunk_size;
+  chunk->prev = 0;
+  /* The initial chunk now contains no empty object.  */
+  h->maybe_empty_object = 0;
+  h->alloc_failed = 0;
+  return 1;
+}
+
+/* Allocate a new current chunk for the obstack *H
+   on the assumption that LENGTH bytes need to be added
+   to the current object, or a new object of length LENGTH allocated.
+   Copies any partial object from the end of the old chunk
+   to the beginning of the new one.  */
+
+void
+_obstack_newchunk (struct obstack *h, int length)
+{
+  register struct _obstack_chunk *old_chunk = h->chunk;
+  register struct _obstack_chunk *new_chunk;
+  register long	new_size;
+  register long obj_size = h->next_free - h->object_base;
+  register long i;
+  long already;
+  char *object_base;
+
+  /* Compute size for new chunk.  */
+  new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
+  if (new_size < h->chunk_size)
+    new_size = h->chunk_size;
+
+  /* Allocate and initialize the new chunk.  */
+  new_chunk = CALL_CHUNKFUN (h, new_size);
+  if (!new_chunk)
+    (*__obstack_alloc_failed_handler) ();
+  h->chunk = new_chunk;
+  new_chunk->prev = old_chunk;
+  new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+  /* Compute an aligned object_base in the new chunk */
+  object_base =
+    __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
+
+  /* Move the existing object to the new chunk.
+     Word at a time is fast and is safe if the object
+     is sufficiently aligned.  */
+  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+    {
+      for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+	   i >= 0; i--)
+	((COPYING_UNIT *)object_base)[i]
+	  = ((COPYING_UNIT *)h->object_base)[i];
+      /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+	 but that can cross a page boundary on a machine
+	 which does not do strict alignment for COPYING_UNITS.  */
+      already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+    }
+  else
+    already = 0;
+  /* Copy remaining bytes one by one.  */
+  for (i = already; i < obj_size; i++)
+    object_base[i] = h->object_base[i];
+
+  /* If the object just copied was the only data in OLD_CHUNK,
+     free that chunk and remove it from the chain.
+     But not if that chunk might contain an empty object.  */
+  if (! h->maybe_empty_object
+      && (h->object_base
+	  == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
+			  h->alignment_mask)))
+    {
+      new_chunk->prev = old_chunk->prev;
+      CALL_FREEFUN (h, old_chunk);
+    }
+
+  h->object_base = object_base;
+  h->next_free = h->object_base + obj_size;
+  /* The new chunk certainly contains no empty object yet.  */
+  h->maybe_empty_object = 0;
+}
+# ifdef _LIBC
+libc_hidden_def (_obstack_newchunk)
+# endif
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+   This is here for debugging.
+   If you use it in a program, you are probably losing.  */
+
+/* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
+   obstack.h because it is just for debugging.  */
+int _obstack_allocated_p (struct obstack *h, void *obj);
+
+int
+_obstack_allocated_p (struct obstack *h, void *obj)
+{
+  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
+
+  lp = (h)->chunk;
+  /* We use >= rather than > since the object cannot be exactly at
+     the beginning of the chunk but might be an empty object exactly
+     at the end of an adjacent chunk.  */
+  while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
+    {
+      plp = lp->prev;
+      lp = plp;
+    }
+  return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+   more recently than OBJ.  If OBJ is zero, free everything in H.  */
+
+# undef obstack_free
+
+void
+obstack_free (struct obstack *h, void *obj)
+{
+  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
+
+  lp = h->chunk;
+  /* We use >= because there cannot be an object at the beginning of a chunk.
+     But there can be an empty object at that address
+     at the end of another chunk.  */
+  while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
+    {
+      plp = lp->prev;
+      CALL_FREEFUN (h, lp);
+      lp = plp;
+      /* If we switch chunks, we can't tell whether the new current
+	 chunk contains an empty object, so assume that it may.  */
+      h->maybe_empty_object = 1;
+    }
+  if (lp)
+    {
+      h->object_base = h->next_free = (char *) (obj);
+      h->chunk_limit = lp->limit;
+      h->chunk = lp;
+    }
+  else if (obj != 0)
+    /* obj is not in any of the chunks! */
+    abort ();
+}
+
+# ifdef _LIBC
+/* Older versions of libc used a function _obstack_free intended to be
+   called by non-GCC compilers.  */
+strong_alias (obstack_free, _obstack_free)
+# endif
+
+int
+_obstack_memory_used (struct obstack *h)
+{
+  register struct _obstack_chunk* lp;
+  register int nbytes = 0;
+
+  for (lp = h->chunk; lp != 0; lp = lp->prev)
+    {
+      nbytes += lp->limit - (char *) lp;
+    }
+  return nbytes;
+}
+
+/* Define the error handler.  */
+# ifdef _LIBC
+#  include <libintl.h>
+# else
+#  include "gettext.h"
+# endif
+/* NLS: Disable gettext in obstack for now: */
+# undef _
+# define _(Str) (Str)
+# ifndef _
+#  define _(msgid) gettext (msgid)
+# endif
+
+# if defined _LIBC && !defined __UCLIBC__
+#  include <libio/iolibio.h>
+# endif
+
+# ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#   define __attribute__(Spec) /* empty */
+#  endif
+# endif
+
+static void
+attribute_noreturn
+print_and_abort (void)
+{
+  /* Don't change any of these strings.  Yes, it would be possible to add
+     the newline to the string and use fputs or so.  But this must not
+     happen because the "memory exhausted" message appears in other places
+     like this and the translation should be reused instead of creating
+     a very similar string which requires a separate translation.  */
+# if defined _LIBC && !defined __UCLIBC__
+  (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
+# else
+  fprintf (stderr, "%s\n", _("memory exhausted"));
+# endif
+  exit (__obstack_exit_failure);
+}
+
+#endif	/* !ELIDE_CODE */
diff --git a/ap/build/uClibc/libc/misc/internals/Makefile b/ap/build/uClibc/libc/misc/internals/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/internals/Makefile.in b/ap/build/uClibc/libc/misc/internals/Makefile.in
new file mode 100644
index 0000000..354dfc9
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/Makefile.in
@@ -0,0 +1,43 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/internals
+
+CSRC := tempname.c errno.c __errno_location.c __h_errno_location.c \
+	parse_config.c
+
+MISC_INTERNALS_DIR := $(top_srcdir)libc/misc/internals
+MISC_INTERNALS_OUT := $(top_builddir)libc/misc/internals
+
+MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC))
+MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC))
+
+CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS)
+
+
+libc-y += $(MISC_INTERNALS_OBJ)
+ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y)
+libc-shared-y += $(MISC_INTERNALS_OUT)/__uClibc_main.oS
+else
+libc-shared-y += $(MISC_INTERNALS_OUT)/__uClibc_main.os
+endif
+libc-static-y += $(MISC_INTERNALS_OUT)/__uClibc_main.o
+libc-static-$(UCLIBC_FORMAT_FLAT_SEP_DATA) += \
+  $(MISC_INTERNALS_OUT)/shared_flat_initfini.o \
+  $(MISC_INTERNALS_OUT)/shared_flat_add_library.o
+libc-static-$(UCLIBC_FORMAT_SHARED_FLAT) += \
+  $(MISC_INTERNALS_OUT)/shared_flat_initfini.o \
+  $(MISC_INTERNALS_OUT)/shared_flat_add_library.o
+libc-shared-$(UCLIBC_FORMAT_SHARED_FLAT) += \
+  $(MISC_INTERNALS_OUT)/shared_flat_initfini.os \
+  $(MISC_INTERNALS_OUT)/shared_flat_add_library.os
+libc-nomulti-y += $(MISC_INTERNALS_OUT)/__uClibc_main.o
+
+objclean-y += CLEAN_libc/misc/internals
+
+CLEAN_libc/misc/internals:
+	$(do_rm) $(addprefix $(MISC_INTERNALS_OUT)/*., o os oS)
diff --git a/ap/build/uClibc/libc/misc/internals/__errno_location.c b/ap/build/uClibc/libc/misc/internals/__errno_location.c
new file mode 100644
index 0000000..aec7641
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/__errno_location.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include "internal_errno.h"
+
+/* psm: moved to bits/errno.h: */
+int *
+#ifndef __UCLIBC_HAS_THREADS__
+weak_const_function
+#endif
+__errno_location (void)
+{
+    return &errno;
+}
+#ifdef IS_IN_libc /* not really need, only to keep in sync w/ libc_hidden_proto */
+libc_hidden_weak(__errno_location)
+#endif
diff --git a/ap/build/uClibc/libc/misc/internals/__h_errno_location.c b/ap/build/uClibc/libc/misc/internals/__h_errno_location.c
new file mode 100644
index 0000000..213d398
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/__h_errno_location.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include "internal_errno.h"
+
+int * weak_const_function __h_errno_location (void)
+{
+    return &h_errno;
+}
+libc_hidden_weak(__h_errno_location)
diff --git a/ap/build/uClibc/libc/misc/internals/__uClibc_main.c b/ap/build/uClibc/libc/misc/internals/__uClibc_main.c
new file mode 100644
index 0000000..71fdbd8
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/__uClibc_main.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2006 by Steven J. Hill <sjhill@realitydiluted.com>
+ * Copyright (C) 2001 by Manuel Novoa III <mjn3@uclibc.org>
+ * Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ * __uClibc_main is the routine to be called by all the arch-specific
+ * versions of crt1.S in uClibc.
+ *
+ * It is meant to handle any special initialization needed by the library
+ * such as setting the global variable(s) __environ (environ) and
+ * initializing the stdio package.  Using weak symbols, the latter is
+ * avoided in the static library case.
+ */
+
+#include <features.h>
+#ifndef __UCLIBC_HAS_THREADS_NATIVE__
+#define	_ERRNO_H
+#endif
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <elf.h>
+#include <link.h>
+#include <bits/uClibc_page.h>
+#include <paths.h>
+#include <unistd.h>
+#include <asm/errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <errno.h>
+#include <pthread-functions.h>
+#include <not-cancel.h>
+#include <atomic.h>
+#endif
+#ifdef __UCLIBC_HAS_THREADS__
+#include <pthread.h>
+#endif 
+
+#ifndef SHARED
+void *__libc_stack_end = NULL;
+
+# ifdef __UCLIBC_HAS_SSP__
+#  include <dl-osinfo.h>
+static uintptr_t stack_chk_guard;
+#  ifndef THREAD_SET_STACK_GUARD
+/* Only exported for architectures that don't store the stack guard canary
+ * in thread local area. */
+/* for gcc-4.1 non-TLS */
+uintptr_t __stack_chk_guard attribute_relro;
+#  endif
+/* for gcc-3.x + Etoh ssp */
+#  ifdef __UCLIBC_HAS_SSP_COMPAT__
+uintptr_t __guard attribute_relro;
+#  endif
+# endif
+
+/*
+ * Needed to initialize _dl_phdr when statically linked
+ */
+
+void internal_function _dl_aux_init (ElfW(auxv_t) *av);
+
+#ifdef __UCLIBC_HAS_THREADS__
+/*
+ * uClibc internal locking requires that we have weak aliases
+ * for dummy functions in case libpthread.a is not linked in.
+ * This needs to be in compilation unit that is pulled always
+ * in or linker will disregard these weaks.
+ */
+
+static int __pthread_return_0 (pthread_mutex_t *unused) { return 0; }
+weak_alias (__pthread_return_0, __pthread_mutex_lock)
+weak_alias (__pthread_return_0, __pthread_mutex_trylock)
+weak_alias (__pthread_return_0, __pthread_mutex_unlock)
+
+int weak_function
+__pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
+{
+        return 0;
+}
+
+void weak_function
+_pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *__buffer,
+                            void (*__routine) (void *), void *__arg)
+{
+        __buffer->__routine = __routine;
+        __buffer->__arg = __arg;
+}
+
+void weak_function
+_pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *__buffer,
+                             int __execute)
+{
+        if (__execute)
+                __buffer->__routine(__buffer->__arg);
+}
+#endif /* __UCLIBC_HAS_THREADS__ */
+
+#endif /* !SHARED */
+
+/* Defeat compiler optimization which assumes function addresses are never NULL */
+static __always_inline int not_null_ptr(const void *p)
+{
+	const void *q;
+	__asm__ (""
+		: "=r" (q) /* output */
+		: "0" (p) /* input */
+	);
+	return q != 0;
+}
+
+/*
+ * Prototypes.
+ */
+extern int *weak_const_function __errno_location(void);
+extern int *weak_const_function __h_errno_location(void);
+extern void weak_function _stdio_init(void) attribute_hidden;
+#ifdef __UCLIBC_HAS_LOCALE__
+extern void weak_function _locale_init(void) attribute_hidden;
+#endif
+#ifdef __UCLIBC_HAS_THREADS__
+#if !defined (__UCLIBC_HAS_THREADS_NATIVE__) || defined (SHARED)
+extern void weak_function __pthread_initialize_minimal(void);
+#else
+extern void __pthread_initialize_minimal(void);
+#endif
+#endif
+
+/* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation and finalisation
+ * is handled by the routines passed to __uClibc_main().  */
+#if defined (__UCLIBC_CTOR_DTOR__) && !defined (__UCLIBC_FORMAT_SHARED_FLAT__)
+extern void _dl_app_init_array(void);
+extern void _dl_app_fini_array(void);
+# ifndef SHARED
+/* These magic symbols are provided by the linker.  */
+extern void (*__preinit_array_start []) (void) attribute_hidden;
+extern void (*__preinit_array_end []) (void) attribute_hidden;
+extern void (*__init_array_start []) (void) attribute_hidden;
+extern void (*__init_array_end []) (void) attribute_hidden;
+extern void (*__fini_array_start []) (void) attribute_hidden;
+extern void (*__fini_array_end []) (void) attribute_hidden;
+# endif
+#endif
+
+#if defined (__LDSO_STANDALONE_SUPPORT__) && defined (SHARED) && defined __sh__
+extern unsigned long _dl_skip_args;
+#endif
+
+attribute_hidden const char *__uclibc_progname = "";
+#ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__
+const char *program_invocation_short_name = "";
+const char *program_invocation_name = "";
+#endif
+#ifdef __UCLIBC_HAS___PROGNAME__
+weak_alias (program_invocation_short_name, __progname)
+weak_alias (program_invocation_name, __progname_full)
+#endif
+
+/*
+ * Declare the __environ global variable and create a weak alias environ.
+ * This must be initialized; we cannot have a weak alias into bss.
+ */
+char **__environ = 0;
+weak_alias(__environ, environ)
+
+/* TODO: don't export __pagesize; we cant now because libpthread uses it */
+size_t __pagesize = 0;
+
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW	0
+#endif
+
+#ifndef __ARCH_HAS_NO_LDSO__
+static void __check_one_fd(int fd, int mode)
+{
+    /* Check if the specified fd is already open */
+    if (fcntl(fd, F_GETFD) == -1)
+    {
+	/* The descriptor is probably not open, so try to use /dev/null */
+	int nullfd = open(_PATH_DEVNULL, mode);
+	/* /dev/null is major=1 minor=3.  Make absolutely certain
+	 * that is in fact the device that we have opened and not
+	 * some other wierd file... [removed in uclibc] */
+	if (nullfd!=fd)
+	{
+		abort();
+	}
+    }
+}
+
+static int __check_suid(void)
+{
+    uid_t uid, euid;
+    gid_t gid, egid;
+
+    uid  = getuid();
+    euid = geteuid();
+    if (uid != euid)
+	return 1;
+    gid  = getgid();
+    egid = getegid();
+    if (gid != egid)
+	return 1;
+    return 0; /* we are not suid */
+}
+#endif
+
+/* __uClibc_init completely initialize uClibc so it is ready to use.
+ *
+ * On ELF systems (with a dynamic loader) this function must be called
+ * from the dynamic loader (see TIS and ELF Specification), so that
+ * constructors of shared libraries (which depend on libc) can use all
+ * the libc code without restriction.  For this we link the shared
+ * version of the uClibc with -init __uClibc_init so DT_INIT for
+ * uClibc is the address of __uClibc_init
+ *
+ * In all other cases we call it from the main stub
+ * __uClibc_main.
+ */
+
+extern void __uClibc_init(void);
+libc_hidden_proto(__uClibc_init)
+void __uClibc_init(void)
+{
+    /* Don't recurse */
+    if (__pagesize)
+	return;
+
+    /* Setup an initial value.  This may not be perfect, but is
+     * better than  malloc using __pagesize=0 for atexit, ctors, etc.  */
+    __pagesize = PAGE_SIZE;
+
+#ifdef __UCLIBC_HAS_THREADS__
+    /* Before we start initializing uClibc we have to call
+     * __pthread_initialize_minimal so we can use pthread_locks
+     * whenever they are needed.
+     */
+#if !defined (__UCLIBC_HAS_THREADS_NATIVE__) || defined (SHARED)
+    if (likely(__pthread_initialize_minimal!=NULL))
+#endif
+	__pthread_initialize_minimal();
+#endif
+
+#ifndef SHARED
+# ifdef __UCLIBC_HAS_SSP__
+    /* Set up the stack checker's canary.  */
+    stack_chk_guard = _dl_setup_stack_chk_guard();
+#  ifdef THREAD_SET_STACK_GUARD
+    THREAD_SET_STACK_GUARD (stack_chk_guard);
+#  else
+    __stack_chk_guard = stack_chk_guard;
+#  endif
+#  ifdef __UCLIBC_HAS_SSP_COMPAT__
+    __guard = stack_chk_guard;
+#  endif
+# endif
+#endif
+
+#ifdef __UCLIBC_HAS_LOCALE__
+    /* Initialize the global locale structure. */
+    if (likely(not_null_ptr(_locale_init)))
+	_locale_init();
+#endif
+
+    /*
+     * Initialize stdio here.  In the static library case, this will
+     * be bypassed if not needed because of the weak alias above.
+     * Thus we get a nice size savings because the stdio functions
+     * won't be pulled into the final static binary unless used.
+     */
+    if (likely(not_null_ptr(_stdio_init)))
+	_stdio_init();
+
+}
+libc_hidden_def(__uClibc_init)
+
+#ifdef __UCLIBC_CTOR_DTOR__
+void attribute_hidden (*__app_fini)(void) = NULL;
+#endif
+
+void attribute_hidden (*__rtld_fini)(void) = NULL;
+
+extern void __uClibc_fini(void);
+libc_hidden_proto(__uClibc_fini)
+void __uClibc_fini(void)
+{
+#ifdef __UCLIBC_CTOR_DTOR__
+    /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array finalisation is handled
+     * by __app_fini.  */
+# ifdef SHARED
+    _dl_app_fini_array();
+# elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__)
+    size_t i = __fini_array_end - __fini_array_start;
+    while (i-- > 0)
+	(*__fini_array_start [i]) ();
+# endif
+    if (__app_fini != NULL)
+	(__app_fini)();
+#endif
+    if (__rtld_fini != NULL)
+	(__rtld_fini)();
+}
+libc_hidden_def(__uClibc_fini)
+
+#ifndef SHARED
+extern void __nptl_deallocate_tsd (void) __attribute ((weak));
+extern unsigned int __nptl_nthreads __attribute ((weak));
+#endif
+
+/* __uClibc_main is the new main stub for uClibc. This function is
+ * called from crt1 (version 0.9.28 or newer), after ALL shared libraries
+ * are initialized, just before we call the application's main function.
+ */
+void __uClibc_main(int (*main)(int, char **, char **), int argc,
+		    char **argv, void (*app_init)(void), void (*app_fini)(void),
+		    void (*rtld_fini)(void),
+		    void *stack_end attribute_unused) attribute_noreturn;
+void __uClibc_main(int (*main)(int, char **, char **), int argc,
+		    char **argv, void (*app_init)(void), void (*app_fini)(void),
+		    void (*rtld_fini)(void), void *stack_end attribute_unused)
+{
+#ifndef __ARCH_HAS_NO_LDSO__
+    unsigned long *aux_dat;
+    ElfW(auxv_t) auxvt[AT_EGID + 1];
+#endif
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+	/* Result of the 'main' function.  */
+	int result;
+#endif
+
+#ifndef SHARED
+    __libc_stack_end = stack_end;
+#endif
+
+    __rtld_fini = rtld_fini;
+
+#if defined __LDSO_STANDALONE_SUPPORT__ && defined SHARED && defined __sh__
+	/*
+	 * Skip ld.so and its arguments
+	 * Other archs except for SH do this in _dl_start before passing
+	 * control to the application.
+	 * FIXME: align SH _dl_start to other archs and remove this from here,
+	 *        so that we can keep the visibility hidden.
+	 */
+	argc -= _dl_skip_args;
+	argv += _dl_skip_args;
+#endif
+
+    /* The environment begins right after argv.  */
+    __environ = &argv[argc + 1];
+
+    /* If the first thing after argv is the arguments
+     * then the environment is empty. */
+    if ((char *) __environ == *argv) {
+	/* Make __environ point to the NULL at argv[argc] */
+	__environ = &argv[argc];
+    }
+
+#ifndef __ARCH_HAS_NO_LDSO__
+    /* Pull stuff from the ELF header when possible */
+    memset(auxvt, 0x00, sizeof(auxvt));
+    aux_dat = (unsigned long*)__environ;
+    while (*aux_dat) {
+	aux_dat++;
+    }
+    aux_dat++;
+    while (*aux_dat) {
+	ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat;
+	if (auxv_entry->a_type <= AT_EGID) {
+	    memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t)));
+	}
+	aux_dat += 2;
+    }
+#ifndef SHARED
+    /* Get the program headers (_dl_phdr) from the aux vector
+       It will be used into __libc_setup_tls. */
+
+    _dl_aux_init (auxvt);
+#endif
+#endif
+
+    /* We need to initialize uClibc.  If we are dynamically linked this
+     * may have already been completed by the shared lib loader.  We call
+     * __uClibc_init() regardless, to be sure the right thing happens. */
+    __uClibc_init();
+
+#ifndef __ARCH_HAS_NO_LDSO__
+    /* Make certain getpagesize() gives the correct answer */
+    __pagesize = (auxvt[AT_PAGESZ].a_un.a_val)? auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
+
+    /* Prevent starting SUID binaries where the stdin. stdout, and
+     * stderr file descriptors are not already opened. */
+    if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) ||
+	    (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
+	    (auxvt[AT_UID].a_un.a_val != auxvt[AT_EUID].a_un.a_val ||
+	     auxvt[AT_GID].a_un.a_val != auxvt[AT_EGID].a_un.a_val)))
+    {
+	__check_one_fd (STDIN_FILENO, O_RDONLY | O_NOFOLLOW);
+	__check_one_fd (STDOUT_FILENO, O_RDWR | O_NOFOLLOW);
+	__check_one_fd (STDERR_FILENO, O_RDWR | O_NOFOLLOW);
+    }
+#endif
+
+    __uclibc_progname = *argv;
+#ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__
+    if (*argv != NULL) {
+	program_invocation_name = *argv;
+	program_invocation_short_name = strrchr(*argv, '/');
+	if (program_invocation_short_name != NULL)
+	    ++program_invocation_short_name;
+	else
+	    program_invocation_short_name = program_invocation_name;
+    }
+#endif
+
+#ifdef __UCLIBC_CTOR_DTOR__
+    /* Arrange for the application's dtors to run before we exit.  */
+    __app_fini = app_fini;
+
+    /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation is handled
+     * by __app_init.  */
+# if !defined (SHARED) && !defined (__UCLIBC_FORMAT_SHARED_FLAT__)
+    /* For dynamically linked executables the preinit array is executed by
+       the dynamic linker (before initializing any shared object).
+       For static executables, preinit happens rights before init.  */
+    {
+	const size_t size = __preinit_array_end - __preinit_array_start;
+	size_t i;
+	for (i = 0; i < size; i++)
+	    (*__preinit_array_start [i]) ();
+    }
+# endif
+    /* Run all the application's ctors now.  */
+    if (app_init!=NULL) {
+	app_init();
+    }
+    /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation is handled
+     * by __app_init.  */
+# ifdef SHARED
+    _dl_app_init_array();
+# elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__)
+    {
+	const size_t size = __init_array_end - __init_array_start;
+	size_t i;
+	for (i = 0; i < size; i++)
+	    (*__init_array_start [i]) ();
+    }
+# endif
+#endif
+
+    /* Note: It is possible that any initialization done above could
+     * have resulted in errno being set nonzero, so set it to 0 before
+     * we call main.
+     */
+    if (likely(not_null_ptr(__errno_location)))
+	*(__errno_location()) = 0;
+
+    /* Set h_errno to 0 as well */
+    if (likely(not_null_ptr(__h_errno_location)))
+	*(__h_errno_location()) = 0;
+
+#if defined HAVE_CLEANUP_JMP_BUF && defined __UCLIBC_HAS_THREADS_NATIVE__
+	/* Memory for the cancellation buffer.  */
+	struct pthread_unwind_buf unwind_buf;
+
+	int not_first_call;
+	not_first_call =
+		setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
+	if (__builtin_expect (! not_first_call, 1))
+	{
+		struct pthread *self = THREAD_SELF;
+
+		/* Store old info.  */
+		unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
+		unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
+
+		/* Store the new cleanup handler info.  */
+		THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
+
+		/* Run the program.  */
+		result = main (argc, argv, __environ);
+	}
+	else
+	{
+		/* Remove the thread-local data.  */
+# ifdef SHARED
+		__libc_pthread_functions.ptr__nptl_deallocate_tsd ();
+# else
+		__nptl_deallocate_tsd ();
+# endif
+
+		/* One less thread.  Decrement the counter.  If it is zero we
+		   terminate the entire process.  */
+		result = 0;
+# ifdef SHARED
+		unsigned int *const ptr = __libc_pthread_functions.ptr_nthreads;
+# else
+		unsigned int *const ptr = &__nptl_nthreads;
+# endif
+
+		if (! atomic_decrement_and_test (ptr))
+			/* Not much left to do but to exit the thread, not the process.  */
+			__exit_thread_inline (0);
+	}
+
+	exit (result);
+#else
+	/*
+	 * Finally, invoke application's main and then exit.
+	 */
+	exit (main (argc, argv, __environ));
+#endif
+}
diff --git a/ap/build/uClibc/libc/misc/internals/errno.c b/ap/build/uClibc/libc/misc/internals/errno.c
new file mode 100644
index 0000000..11d19ee
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/errno.c
@@ -0,0 +1,21 @@
+#include <features.h>
+
+#ifdef __UCLIBC_HAS_TLS__
+__thread int errno;
+__thread int h_errno;
+
+extern __thread int __libc_errno __attribute__ ((alias ("errno"))) attribute_hidden;
+extern __thread int __libc_h_errno __attribute__ ((alias ("h_errno"))) attribute_hidden;
+#define h_errno __libc_h_errno
+
+#else
+#include "internal_errno.h"
+int errno = 0;
+int h_errno = 0;
+#ifdef __UCLIBC_HAS_THREADS__
+libc_hidden_def(errno)
+weak_alias(errno, _errno)
+libc_hidden_def(h_errno)
+weak_alias(h_errno, _h_errno)
+#endif
+#endif
diff --git a/ap/build/uClibc/libc/misc/internals/internal_errno.h b/ap/build/uClibc/libc/misc/internals/internal_errno.h
new file mode 100644
index 0000000..b491985
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/internal_errno.h
@@ -0,0 +1,21 @@
+/*
+ *
+ */
+
+#include <features.h>
+#include <errno.h>
+#include <netdb.h>
+
+#ifndef __UCLIBC_HAS_TLS__
+
+#undef errno
+#undef h_errno
+
+extern int h_errno;
+extern int errno;
+
+#ifdef __UCLIBC_HAS_THREADS__
+libc_hidden_proto(h_errno)
+libc_hidden_proto(errno)
+#endif
+#endif
diff --git a/ap/build/uClibc/libc/misc/internals/parse_config.c b/ap/build/uClibc/libc/misc/internals/parse_config.c
new file mode 100644
index 0000000..4d21b5e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/parse_config.c
@@ -0,0 +1,278 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * config file parser helper
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Also for use in uClibc (http://uclibc.org/) licensed under LGPLv2.1 or later.
+ */
+
+#if !defined _LIBC
+#include "libbb.h"
+
+#if defined ENABLE_PARSE && ENABLE_PARSE
+int parse_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int parse_main(int argc UNUSED_PARAM, char **argv)
+{
+	const char *delims = "# \t";
+	unsigned flags = PARSE_NORMAL;
+	int mintokens = 0, ntokens = 128;
+
+	opt_complementary = "-1:n+:m+:f+";
+	getopt32(argv, "n:m:d:f:", &ntokens, &mintokens, &delims, &flags);
+	//argc -= optind;
+	argv += optind;
+	while (*argv) {
+		parser_t *p = config_open(*argv);
+		if (p) {
+			int n;
+			char **t = xmalloc(sizeof(char *) * ntokens);
+			while ((n = config_read(p, t, ntokens, mintokens, delims, flags)) != 0) {
+				for (int i = 0; i < n; ++i)
+					printf("[%s]", t[i]);
+				puts("");
+			}
+			config_close(p);
+		}
+		argv++;
+	}
+	return EXIT_SUCCESS;
+}
+#endif
+#else
+# include <unistd.h>
+# include <string.h>
+# include <malloc.h>
+# include <bits/uClibc_page.h>
+# include "internal/parse_config.h"
+# ifndef FAST_FUNC
+#  define FAST_FUNC
+# endif
+# define fopen_or_warn_stdin fopen
+# define bb_error_msg(...)
+# define xstrdup strdup
+# define xfunc_die() return 0
+/* Read up to EOF or EOL, treat line-continuations as extending the line.
+   Return number of bytes read into .line, -1 otherwise  */
+static off_t bb_get_chunk_with_continuation(parser_t* parsr)
+{
+	off_t pos = 0;
+	char *chp;
+
+	while (1) {
+		if (fgets(parsr->line + pos, parsr->line_len - pos, parsr->fp) == NULL) {
+			memset(parsr->line, 0, parsr->line_len);
+			pos = -1;
+			break;
+		}
+		pos += strlen(parsr->line + pos);
+		chp = strchr(parsr->line, '\n');
+		if (chp) {
+			--pos;
+			if (--*chp == '\\')
+				--pos;
+			else
+				break;
+		} else if (parsr->allocated) {
+			parsr->line_len += PAGE_SIZE;
+			parsr->data = realloc(parsr->data,
+								   parsr->data_len + parsr->line_len);
+			parsr->line = parsr->data + parsr->data_len;
+		} else {
+			/* discard rest of line if not enough space in buffer */
+			int c;
+			do {
+				c = fgetc(parsr->fp);
+			} while (c != EOF && c != '\n');
+			break;
+		}
+	}
+	return pos;
+}
+#endif
+
+/*
+
+Typical usage:
+
+----- CUT -----
+	char *t[3];	// tokens placeholder
+	parser_t *p = config_open(filename);
+	if (p) {
+		// parse line-by-line
+		while (config_read(p, t, 3, 0, delimiters, flags)) { // 1..3 tokens
+			// use tokens
+			bb_error_msg("TOKENS: [%s][%s][%s]", t[0], t[1], t[2]);
+		}
+		...
+		// free parser
+		config_close(p);
+	}
+----- CUT -----
+
+*/
+
+static __always_inline parser_t * FAST_FUNC config_open2(const char *filename,
+	FILE* FAST_FUNC (*fopen_func)(const char *path, const char *mode))
+{
+	parser_t *parser;
+	FILE* fp;
+
+	fp = fopen_func(filename, "r");
+	if (!fp)
+		return NULL;
+	parser = calloc(1, sizeof(*parser));
+	if (parser) {
+		parser->fp = fp;
+	}
+	return parser;
+}
+
+parser_t attribute_hidden * FAST_FUNC config_open(const char *filename)
+{
+	return config_open2(filename, fopen_or_warn_stdin);
+}
+
+#ifdef UNUSED
+static void config_free_data(parser_t *parser)
+{
+	free(parser->data);
+	parser->data = parser->line = NULL;
+}
+#endif
+
+void attribute_hidden FAST_FUNC config_close(parser_t *parser)
+{
+	if (parser) {
+		fclose(parser->fp);
+		if (parser->allocated)
+			free(parser->data);
+		free(parser);
+	}
+}
+
+/*
+0. If parser is NULL return 0.
+1. Read a line from config file. If nothing to read then return 0.
+   Handle continuation character. Advance lineno for each physical line.
+   Discard everything past comment character.
+2. if PARSE_TRIM is set (default), remove leading and trailing delimiters.
+3. If resulting line is empty goto 1.
+4. Look for first delimiter. If !PARSE_COLLAPSE or !PARSE_TRIM is set then
+   remember the token as empty.
+5. Else (default) if number of seen tokens is equal to max number of tokens
+   (token is the last one) and PARSE_GREEDY is set then the remainder
+   of the line is the last token.
+   Else (token is not last or PARSE_GREEDY is not set) just replace
+   first delimiter with '\0' thus delimiting the token.
+6. Advance line pointer past the end of token. If number of seen tokens
+   is less than required number of tokens then goto 4.
+7. Check the number of seen tokens is not less the min number of tokens.
+   Complain or die otherwise depending on PARSE_MIN_DIE.
+8. Return the number of seen tokens.
+
+mintokens > 0 make config_read() print error message if less than mintokens
+(but more than 0) are found. Empty lines are always skipped (not warned about).
+*/
+#undef config_read
+int attribute_hidden FAST_FUNC config_read(parser_t *parser, char ***tokens,
+											unsigned flags, const char *delims)
+{
+	char *line;
+	int ntokens, mintokens;
+	off_t len;
+	int t;
+
+	if (parser == NULL)
+		return 0;
+	ntokens = flags & 0xFF;
+	mintokens = (flags & 0xFF00) >> 8;
+again:
+	if (parser->data == NULL) {
+		if (parser->line_len == 0)
+			parser->line_len = 81;
+		if (parser->data_len == 0)
+			parser->data_len += 1 + ntokens * sizeof(char *);
+		parser->data = malloc(parser->data_len + parser->line_len);
+		if (parser->data == NULL)
+			return 0;
+		parser->allocated |= 1;
+	} /* else { assert(parser->data_len > 0); } */
+	parser->line = parser->data + parser->data_len;
+	/*config_free_data(parser);*/
+
+	/* Read one line (handling continuations with backslash) */
+	len = bb_get_chunk_with_continuation(parser);
+	if (len == -1)
+		return 0;
+	line = parser->line;
+
+	/* Skip multiple token-delimiters in the start of line? */
+	if (flags & PARSE_TRIM)
+		line += strspn(line, delims + 1);
+
+	if (line[0] == '\0' || line[0] == delims[0])
+		goto again;
+
+	*tokens = (char **) parser->data;
+	memset(*tokens, 0, sizeof(*tokens[0]) * ntokens);
+
+	/* Tokenize the line */
+	for (t = 0; *line && *line != delims[0] && t < ntokens; t++) {
+		/* Pin token */
+		*(*tokens + t) = line;
+
+		/* Combine remaining arguments? */
+		if ((t != ntokens-1) || !(flags & PARSE_GREEDY)) {
+			/* Vanilla token, find next delimiter */
+			line += strcspn(line, delims[0] ? delims : delims + 1);
+		} else {
+			/* Combining, find comment char if any */
+			line = strchrnul(line, delims[0]);
+
+			/* Trim any extra delimiters from the end */
+			if (flags & PARSE_TRIM) {
+				while (strchr(delims + 1, line[-1]) != NULL)
+					line--;
+			}
+		}
+
+		/* Token not terminated? */
+		if (line[0] == delims[0])
+			*line = '\0';
+		else if (line[0] != '\0')
+			*(line++) = '\0';
+
+#if 0 /* unused so far */
+		if (flags & PARSE_ESCAPE) {
+			const char *from;
+			char *to;
+
+			from = to = tokens[t];
+			while (*from) {
+				if (*from == '\\') {
+					from++;
+					*to++ = bb_process_escape_sequence(&from);
+				} else {
+					*to++ = *from++;
+				}
+			}
+			*to = '\0';
+		}
+#endif
+
+		/* Skip possible delimiters */
+		if (flags & PARSE_COLLAPSE)
+			line += strspn(line, delims + 1);
+	}
+
+	if (t < mintokens) {
+		bb_error_msg(/*"bad line %u: "*/"%d tokens found, %d needed",
+				/*parser->lineno, */t, mintokens);
+		if (flags & PARSE_MIN_DIE)
+			xfunc_die();
+		goto again;
+	}
+	return t;
+}
diff --git a/ap/build/uClibc/libc/misc/internals/shared_flat_add_library.c b/ap/build/uClibc/libc/misc/internals/shared_flat_add_library.c
new file mode 100644
index 0000000..f03480f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/shared_flat_add_library.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006 CodeSourcery Inc
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ * This file defines __shared_flat_add_library.  If a library has
+ * initialistion and finalisation code, it should use this routine
+ * to register itself.
+ */
+#include "shared_flat_lib.h"
+
+/* The initialisation and finalisation symbols for this library.  */
+extern void _init(void) attribute_hidden weak_function;
+extern void _fini(void) attribute_hidden weak_function;
+extern void (*__preinit_array_start[])(void) attribute_hidden;
+extern void (*__preinit_array_end[])(void) attribute_hidden;
+extern void (*__init_array_start[])(void) attribute_hidden;
+extern void (*__init_array_end[])(void) attribute_hidden;
+extern void (*__fini_array_start[])(void) attribute_hidden;
+extern void (*__fini_array_end[])(void) attribute_hidden;
+
+/* The shared_flat_lib structure that describes this library.  */
+static struct shared_flat_lib this_lib = {
+	0,
+	0,
+	__preinit_array_start,
+	__preinit_array_end,
+	__init_array_start,
+	__init_array_end,
+	__fini_array_start,
+	__fini_array_end,
+	_init,
+	_fini
+};
+
+/* Add this_lib to the end of the global list. */
+void __shared_flat_add_library(void) attribute_hidden;
+void __shared_flat_add_library(void)
+{
+	this_lib.prev = __last_shared_lib;
+	if (this_lib.prev)
+		this_lib.prev->next = &this_lib;
+	else
+		__first_shared_lib = &this_lib;
+	__last_shared_lib = &this_lib;
+}
diff --git a/ap/build/uClibc/libc/misc/internals/shared_flat_initfini.c b/ap/build/uClibc/libc/misc/internals/shared_flat_initfini.c
new file mode 100644
index 0000000..81e5383
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/shared_flat_initfini.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2006 CodeSourcery Inc
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ * This file defines the main initialisation and finalisation code for
+ * shared flat libraries.  It in turn calls the initialisation and
+ * finalisation code for each registered library.
+ */
+#include "shared_flat_lib.h"
+
+/* A doubly-linked list of shared libraries.  Those nearer the head
+ * of the list should be initialised first and finalised last.  */
+struct shared_flat_lib *__first_shared_lib;
+struct shared_flat_lib *__last_shared_lib;
+
+void __shared_flat_init(void)
+{
+	struct shared_flat_lib *lib;
+	void (**start)(void);
+	void (**end)(void);
+
+	for (lib = __first_shared_lib; lib; lib = lib->next) {
+		end = lib->preinit_array_end;
+		for (start = lib->preinit_array_start; start < end; start++)
+			(*start)();
+	}
+
+	for (lib = __first_shared_lib; lib; lib = lib->next) {
+		if (lib->init)
+			lib->init();
+
+		end = lib->init_array_end;
+		for (start = lib->init_array_start; start < end; start++)
+			(*start)();
+	}
+}
+
+void __shared_flat_fini(void)
+{
+	struct shared_flat_lib *lib;
+	void (**start)(void);
+	void (**end)(void);
+
+	for (lib = __last_shared_lib; lib; lib = lib->prev) {
+		start = lib->fini_array_start;
+		for (end = lib->fini_array_end; end > start;)
+			(*--end)();
+
+		if (lib->fini)
+			lib->fini();
+	}
+}
diff --git a/ap/build/uClibc/libc/misc/internals/shared_flat_lib.h b/ap/build/uClibc/libc/misc/internals/shared_flat_lib.h
new file mode 100644
index 0000000..e012135
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/shared_flat_lib.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2006 CodeSourcery Inc
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ * This file defines the shared_flat_lib structure and the global library
+ * list.   The structure is used to provide something close to ELF-like
+ * initialisation and finalisation when using shared flat libraries.
+ */
+#ifndef __SHARED_FLAT_LIB__
+#define __SHARED_FLAT_LIB__
+
+struct shared_flat_lib {
+	struct shared_flat_lib *prev;
+	struct shared_flat_lib *next;
+	/* .preinit_array is usually only supported for executables.
+	 * However, the distinction between the executable and its
+	 * shared libraries isn't as pronounced for flat files; a shared
+	 * library is really just a part of an executable that can be
+	 * shared with other executables.  We therefore allow
+	 * .preinit_array to be used in libraries too.  */
+	void (**preinit_array_start)(void);
+	void (**preinit_array_end)(void);
+	void (**init_array_start)(void);
+	void (**init_array_end)(void);
+	void (**fini_array_start)(void);
+	void (**fini_array_end)(void);
+	void (*init)(void);
+	void (*fini)(void);
+};
+
+extern struct shared_flat_lib *__first_shared_lib;
+extern struct shared_flat_lib *__last_shared_lib;
+
+#endif
diff --git a/ap/build/uClibc/libc/misc/internals/tempname.c b/ap/build/uClibc/libc/misc/internals/tempname.c
new file mode 100644
index 0000000..28c0098
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/tempname.c
@@ -0,0 +1,252 @@
+/* Copyright (C) 1991,92,93,94,95,96,97,98,99 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* March 11, 2002       Manuel Novoa III
+ *
+ * Modify code to remove dependency on libgcc long long arith support funcs.
+ */
+
+/* June 6, 2004       Erik Andersen
+ *
+ * Don't use brain damaged getpid() based randomness.
+ */
+
+/* April 15, 2005     Mike Frysinger
+ *
+ * Use brain damaged getpid() if real random fails.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "tempname.h"
+
+/* Return nonzero if DIR is an existent directory.  */
+static int direxists (const char *dir)
+{
+    struct stat buf;
+    return stat(dir, &buf) == 0 && S_ISDIR (buf.st_mode);
+}
+
+/* Path search algorithm, for tmpnam, tmpfile, etc.  If DIR is
+   non-null and exists, uses it; otherwise uses the first of $TMPDIR,
+   P_tmpdir, /tmp that exists.  Copies into TMPL a template suitable
+   for use with mk[s]temp.  Will fail (-1) if DIR is non-null and
+   doesn't exist, none of the searched dirs exists, or there's not
+   enough space in TMPL. */
+int attribute_hidden ___path_search (char *tmpl, size_t tmpl_len, const char *dir,
+	const char *pfx /*, int try_tmpdir*/)
+{
+    /*const char *d; */
+    /* dir and pfx lengths should always fit into an int,
+       so don't bother using size_t here.  Especially since
+       the printf func requires an int for precision (%*s).  */
+    int dlen, plen;
+
+    if (!pfx || !pfx[0])
+    {
+	pfx = "file";
+	plen = 4;
+    }
+    else
+    {
+	plen = strlen (pfx);
+	if (plen > 5)
+	    plen = 5;
+    }
+
+    /* Disable support for $TMPDIR */
+#if 0
+    if (try_tmpdir)
+    {
+	d = __secure_getenv ("TMPDIR");
+	if (d != NULL && direxists (d))
+	    dir = d;
+	else if (dir != NULL && direxists (dir))
+	    /* nothing */ ;
+	else
+	    dir = NULL;
+    }
+#endif
+    if (dir == NULL)
+    {
+	if (direxists (P_tmpdir))
+	    dir = P_tmpdir;
+	else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
+	    dir = "/tmp";
+	else
+	{
+	    __set_errno (ENOENT);
+	    return -1;
+	}
+    }
+
+    dlen = strlen (dir);
+    while (dlen > 1 && dir[dlen - 1] == '/')
+	dlen--;			/* remove trailing slashes */
+
+    /* check we have room for "${dir}/${pfx}XXXXXX\0" */
+    if (tmpl_len < (size_t)dlen + 1 + plen + 6 + 1)
+    {
+	__set_errno (EINVAL);
+	return -1;
+    }
+
+    sprintf (tmpl, "%.*s/%.*sXXXXXX", dlen, dir, plen, pfx);
+    return 0;
+}
+
+/* These are the characters used in temporary filenames.  */
+static const char letters[] =
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+#define NUM_LETTERS (62)
+
+static unsigned int fillrand(unsigned char *buf, unsigned int len)
+{
+    int fd;
+    unsigned int result = -1;
+    fd = open("/dev/urandom", O_RDONLY);
+    if (fd < 0) {
+	fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
+    }
+    if (fd >= 0) {
+	result = read(fd, buf, len);
+	close(fd);
+    }
+    return result;
+}
+
+static void brain_damaged_fillrand(unsigned char *buf, unsigned int len)
+{
+	unsigned int i, k;
+	struct timeval tv;
+	uint32_t high, low, rh;
+	static uint64_t value;
+	gettimeofday(&tv, NULL);
+	value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
+	low = value & UINT32_MAX;
+	high = value >> 32;
+	for (i = 0; i < len; ++i) {
+		rh = high % NUM_LETTERS;
+		high /= NUM_LETTERS;
+#define L ((UINT32_MAX % NUM_LETTERS + 1) % NUM_LETTERS)
+		k = (low % NUM_LETTERS) + (L * rh);
+#undef L
+#define H ((UINT32_MAX / NUM_LETTERS) + ((UINT32_MAX % NUM_LETTERS + 1) / NUM_LETTERS))
+		low = (low / NUM_LETTERS) + (H * rh) + (k / NUM_LETTERS);
+#undef H
+		k %= NUM_LETTERS;
+		buf[i] = letters[k];
+	}
+}
+
+/* Generate a temporary file name based on TMPL.  TMPL must match the
+   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
+   does not exist at the time of the call to __gen_tempname.  TMPL is
+   overwritten with the result.
+
+   KIND may be one of:
+   __GT_NOCREATE:       simply verify that the name does not exist
+                        at the time of the call. mode argument is ignored.
+   __GT_FILE:           create the file using open(O_CREAT|O_EXCL)
+                        and return a read-write fd with given mode.
+   __GT_BIGFILE:        same as __GT_FILE but use open64().
+   __GT_DIR:            create a directory with given mode.
+
+*/
+int attribute_hidden __gen_tempname (char *tmpl, int kind, mode_t mode)
+{
+    char *XXXXXX;
+    unsigned int i;
+    int fd, save_errno = errno;
+    unsigned char randomness[6];
+    size_t len;
+
+    len = strlen (tmpl);
+    /* This is where the Xs start.  */
+    XXXXXX = tmpl + len - 6;
+    if (len < 6 || strcmp (XXXXXX, "XXXXXX"))
+    {
+	__set_errno (EINVAL);
+	return -1;
+    }
+
+    for (i = 0; i < TMP_MAX; ++i) {
+	unsigned char j;
+	/* Get some random data.  */
+	if (fillrand(randomness, sizeof(randomness)) != sizeof(randomness)) {
+	    /* if random device nodes failed us, lets use the braindamaged ver */
+	    brain_damaged_fillrand(randomness, sizeof(randomness));
+	}
+	for (j = 0; j < sizeof(randomness); ++j)
+	    XXXXXX[j] = letters[randomness[j] % NUM_LETTERS];
+
+	switch (kind) {
+	    case __GT_NOCREATE:
+		{
+		    struct stat st;
+		    if (stat (tmpl, &st) < 0) {
+			if (errno == ENOENT) {
+			    fd = 0;
+			    goto restore_and_ret;
+			} else
+			    /* Give up now. */
+			    return -1;
+		    } else
+			fd = 0;
+		}
+	    case __GT_FILE:
+		fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, mode);
+		break;
+#if defined __UCLIBC_HAS_LFS__
+	    case __GT_BIGFILE:
+		fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, mode);
+		break;
+#endif
+	    case __GT_DIR:
+		fd = mkdir (tmpl, mode);
+		break;
+	    default:
+		fd = -1;
+		assert (! "invalid KIND in __gen_tempname");
+	}
+
+	if (fd >= 0) {
+restore_and_ret:
+	    __set_errno (save_errno);
+	    return fd;
+	}
+	else if (errno != EEXIST)
+	    /* Any other error will apply also to other names we might
+	       try, and there are 2^32 or so of them, so give up now. */
+	    return -1;
+    }
+
+    /* We got out of the loop because we ran out of combinations to try.  */
+    __set_errno (EEXIST);
+    return -1;
+}
diff --git a/ap/build/uClibc/libc/misc/internals/tempname.h b/ap/build/uClibc/libc/misc/internals/tempname.h
new file mode 100644
index 0000000..e75b632
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/internals/tempname.h
@@ -0,0 +1,21 @@
+#ifndef __TEMPNAME_H__
+#define __TEMPNAME_H__
+
+#define	__need_size_t
+#include <stddef.h>
+#include <sys/types.h>
+
+/* Disable support for $TMPDIR */
+extern int ___path_search (char *tmpl, size_t tmpl_len, const char *dir,
+	        const char *pfx /*, int try_tmpdir */) attribute_hidden;
+#define __path_search(tmpl, tmpl_len, dir, pfx, try_tmpdir) ___path_search(tmpl, tmpl_len, dir, pfx)
+
+extern int __gen_tempname (char *__tmpl, int __kind, mode_t mode) attribute_hidden;
+
+/* The __kind argument to __gen_tempname may be one of: */
+#define __GT_FILE     0       /* create a file */
+#define __GT_BIGFILE  1       /* create a file, using open64 */
+#define __GT_DIR      2       /* create a directory */
+#define __GT_NOCREATE 3       /* just find a name not currently in use */
+
+#endif
diff --git a/ap/build/uClibc/libc/misc/locale/Makefile b/ap/build/uClibc/libc/misc/locale/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/locale/Makefile.in b/ap/build/uClibc/libc/misc/locale/Makefile.in
new file mode 100644
index 0000000..c12befd
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/Makefile.in
@@ -0,0 +1,30 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/locale
+
+# multi source locale.c
+CSRC := setlocale.c localeconv.c _locale_init.c nl_langinfo.c
+ifeq ($(UCLIBC_HAS_LOCALE),y)
+CSRC += newlocale.c __locale_mbrtowc_l.c
+endif
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+CSRC += nl_langinfo_l.c duplocale.c freelocale.c uselocale.c __curlocale.c
+endif
+
+MISC_LOCALE_DIR := $(top_srcdir)libc/misc/locale
+MISC_LOCALE_OUT := $(top_builddir)libc/misc/locale
+
+MISC_LOCALE_SRC := $(patsubst %.c,$(MISC_LOCALE_DIR)/%.c,$(CSRC))
+MISC_LOCALE_OBJ := $(patsubst %.c,$(MISC_LOCALE_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_LOCALE_OBJ)
+
+objclean-y += CLEAN_libc/misc/locale
+
+CLEAN_libc/misc/locale:
+	$(do_rm) $(addprefix $(MISC_LOCALE_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/locale/__curlocale.c b/ap/build/uClibc/libc/misc/locale/__curlocale.c
new file mode 100644
index 0000000..aa38f43
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/__curlocale.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___curlocale
+#define __UCLIBC_DO_XLOCALE
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/__locale_mbrtowc_l.c b/ap/build/uClibc/libc/misc/locale/__locale_mbrtowc_l.c
new file mode 100644
index 0000000..ea7fbce
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/__locale_mbrtowc_l.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___locale_mbrtowc_l
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/_locale_init.c b/ap/build/uClibc/libc/misc/locale/_locale_init.c
new file mode 100644
index 0000000..9ced732
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/_locale_init.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L__locale_init
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/duplocale.c b/ap/build/uClibc/libc/misc/locale/duplocale.c
new file mode 100644
index 0000000..db9c7a3
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/duplocale.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_duplocale
+#define __UCLIBC_DO_XLOCALE
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/freelocale.c b/ap/build/uClibc/libc/misc/locale/freelocale.c
new file mode 100644
index 0000000..c1ef8e1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/freelocale.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_freelocale
+#define __UCLIBC_DO_XLOCALE
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/locale.c b/ap/build/uClibc/libc/misc/locale/locale.c
new file mode 100644
index 0000000..e8fddf6
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/locale.c
@@ -0,0 +1,1476 @@
+/*  Copyright (C) 2002     Manuel Novoa III
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Nov. 1, 2002
+ * Reworked setlocale() return values and locale arg processing to
+ *   be more like glibc.  Applications expecting to be able to
+ *   query locale settings should now work... at the cost of almost
+ *   doubling the size of the setlocale object code.
+ * Fixed a bug in the internal fixed-size-string locale specifier code.
+ *
+ * Dec 20, 2002
+ * Added in collation support and updated stub nl_langinfo.
+ *
+ * Aug 1, 2003
+ * Added glibc-like extended locale stuff (newlocale, duplocale, etc).
+ *
+ * Aug 18, 2003
+ * Bug in duplocale... collation data wasn't copied.
+ * Bug in newlocale... translate 1<<LC_ALL to LC_ALL_MASK.
+ * Bug in _wchar_utf8sntowcs... fix cut-n-paste error.
+ *
+ * Aug 31, 2003
+ * Hack around bg_BG bug; grouping specified but no thousands separator.
+ * Also, disable the locale link_warnings for now, as they generate a
+ * lot of noise when using libstd++.
+ */
+
+
+/*  TODO:
+ *  Implement the shared mmap code so non-mmu platforms can use this.
+ *  Add some basic collate functionality similar to what the previous
+ *    locale support had (8-bit codesets only).
+ */
+
+#define __CTYPE_HAS_8_BIT_LOCALES 1
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <stdint.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_setlocale
+#warning TODO: Make the link_warning()s a config option?
+#endif
+#endif
+#undef link_warning
+#define link_warning(A,B)
+
+#undef __LOCALE_C_ONLY
+#ifndef __UCLIBC_HAS_LOCALE__
+#define __LOCALE_C_ONLY
+#endif /* __UCLIBC_HAS_LOCALE__ */
+
+
+#ifdef __LOCALE_C_ONLY
+
+#include <locale.h>
+
+#else  /* __LOCALE_C_ONLY */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_setlocale
+#warning TODO: Fix the __CTYPE_HAS_8_BIT_LOCALES define at the top of the file.
+#warning TODO: Fix __WCHAR_ENABLED.
+#endif
+#endif
+
+/* Need to include this before locale.h and xlocale.h! */
+#include <bits/uClibc_locale.h>
+
+#undef CODESET_LIST
+#define CODESET_LIST			(__locale_mmap->codeset_list)
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+#include <xlocale.h>
+#include <locale.h>
+#else /* __UCLIBC_HAS_XLOCALE__ */
+/* We need this internally... */
+#define __UCLIBC_HAS_XLOCALE__ 1
+#include <xlocale.h>
+#include <locale.h>
+#undef __UCLIBC_HAS_XLOCALE__
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
+#include <wchar.h>
+
+#define LOCALE_NAMES			(__locale_mmap->locale_names5)
+#define LOCALES					(__locale_mmap->locales)
+#define LOCALE_AT_MODIFIERS		(__locale_mmap->locale_at_modifiers)
+#define CATEGORY_NAMES			(__locale_mmap->lc_names)
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: redo the MAX_LOCALE_STR stuff...
+#endif
+#define MAX_LOCALE_STR			256 /* TODO: Only sufficient for current case. */
+#define MAX_LOCALE_CATEGORY_STR	32 /* TODO: Only sufficient for current case. */
+/* Note: Best if MAX_LOCALE_CATEGORY_STR is a power of 2. */
+
+extern int _locale_set_l(const unsigned char *p, __locale_t base) attribute_hidden;
+extern void _locale_init_l(__locale_t base) attribute_hidden;
+
+#endif /* __LOCALE_C_ONLY */
+
+#undef LOCALE_STRING_SIZE
+#define LOCALE_SELECTOR_SIZE (2 * __LC_ALL + 2)
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_setlocale
+#warning TODO: Create a C locale selector string.
+#endif
+#endif
+#define C_LOCALE_SELECTOR "\x23\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80"
+
+
+#include <langinfo.h>
+#include <nl_types.h>
+
+/**********************************************************************/
+#ifdef L_setlocale
+
+#ifdef __LOCALE_C_ONLY
+
+link_warning(setlocale,"REMINDER: The 'setlocale' function supports only C|POSIX locales.")
+
+static const char C_string[] = "C";
+
+char *setlocale(int category, register const char *locale)
+{
+	return ( (((unsigned int)(category)) <= LC_ALL)
+			 && ( (!locale)		/* Request for locale category string. */
+				  || (!*locale)	/* Implementation-defined default is C. */
+				  || ((*locale == 'C') && !locale[1])
+				  || (!strcmp(locale, "POSIX"))) )
+		? (char *) C_string		/* Always in C/POSIX locale. */
+		: NULL;
+}
+
+#else /* ---------------------------------------------- __LOCALE_C_ONLY */
+
+#ifdef __UCLIBC_HAS_THREADS__
+link_warning(setlocale,"REMINDER: The 'setlocale' function is _not_ threadsafe except for simple queries.")
+#endif
+
+#if !defined(__LOCALE_DATA_NUM_LOCALES) || (__LOCALE_DATA_NUM_LOCALES <= 1)
+#error locales enabled, but not data other than for C locale!
+#endif
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Move posix and utf8 strings.
+#endif
+static const char posix[] = "POSIX";
+static const char utf8[] = "UTF-8";
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Fix dimensions of hr_locale.
+#endif
+/* Individual category strings start at hr_locale + category * MAX_LOCALE_CATEGORY.
+ * This holds for LC_ALL as well.
+ */
+static char hr_locale[(MAX_LOCALE_CATEGORY_STR * LC_ALL) + MAX_LOCALE_STR];
+
+
+static void update_hr_locale(const unsigned char *spec)
+{
+	const unsigned char *loc;
+	const unsigned char *s;
+	char *n;
+	int i, category, done;
+
+	done = category = 0;
+	do {
+		s = spec + 1;
+		n = hr_locale + category * MAX_LOCALE_CATEGORY_STR;
+
+		if (category == LC_ALL) {
+			done = 1;
+			for (i = 0 ; i < LC_ALL-1 ; i += 2) {
+				if ((s[i] != s[i+2]) || (s[i+1] != s[i+3])) {
+					goto SKIP;
+				}
+			}
+			/* All categories the same, so simplify string by using a single
+			 * category. */
+			category = LC_CTYPE;
+		}
+
+	SKIP:
+		i = (category == LC_ALL) ? 0 : category;
+		s += 2*i;
+
+		do {
+			if ((*s != 0xff) || (s[1] != 0xff)) {
+				loc = LOCALES
+					+ __LOCALE_DATA_WIDTH_LOCALES * ((((int)(*s & 0x7f)) << 7)
+													 + (s[1] & 0x7f));
+				if (category == LC_ALL) {
+					/* CATEGORY_NAMES is unsigned char* */
+					n = stpcpy(n, (char*) CATEGORY_NAMES + (int) CATEGORY_NAMES[i]);
+					*n++ = '=';
+				}
+				if (*loc == 0) {
+					*n++ = 'C';
+					*n = 0;
+				} else {
+					char at = 0;
+					memcpy(n, LOCALE_NAMES + 5*((*loc)-1), 5);
+					if (n[2] != '_') {
+						at = n[2];
+						n[2] = '_';
+					}
+					n += 5;
+					*n++ = '.';
+					if (loc[2] == 2) {
+						n = stpcpy(n, utf8);
+					} else if (loc[2] >= 3) {
+						n = stpcpy(n, (char*) CODESET_LIST + (int)(CODESET_LIST[loc[2] - 3]));
+					}
+					if (at) {
+						const char *q;
+						*n++ = '@';
+						q = (char*) LOCALE_AT_MODIFIERS;
+						do {
+							if (q[1] == at) {
+								n = stpcpy(n, q+2);
+								break;
+							}
+							q += 2 + *q;
+						} while (*q);
+					}
+				}
+				*n++ = ';';
+			}
+			s += 2;
+		} while (++i < category);
+		*--n = 0;		/* Remove trailing ';' and nul-terminate. */
+
+		++category;
+	} while (!done);
+}
+
+char *setlocale(int category, const char *locale)
+{
+	if (((unsigned int)(category)) > LC_ALL) {
+#if 0
+		__set_errno(EINVAL);	/* glibc sets errno -- SUSv3 doesn't say. */
+#endif
+		return NULL;			/* Illegal/unsupported category. */
+	}
+
+	if (locale != NULL) {		/* Not just a query... */
+		if (!newlocale((1 << category), locale, __global_locale)) {
+			return NULL;		/* Failed! */
+		}
+		update_hr_locale(__global_locale->cur_locale);
+	}
+
+	/* Either a query or a successful set, so return current locale string. */
+	return hr_locale + (category * MAX_LOCALE_CATEGORY_STR);
+}
+
+#endif /* __LOCALE_C_ONLY */
+
+#endif
+/**********************************************************************/
+#ifdef L_localeconv
+
+/* Note: We assume here that the compiler does the sane thing regarding
+ * placement of the fields in the struct.  If necessary, we could ensure
+ * this usings an array of offsets but at some size cost. */
+
+
+#ifdef __LOCALE_C_ONLY
+
+link_warning(localeconv,"REMINDER: The 'localeconv' function is hardwired for C/POSIX locale only.")
+
+static struct lconv the_lconv;
+
+static const char decpt[] = ".";
+
+struct lconv *localeconv(void)
+{
+	register char *p = (char *)(&the_lconv);
+
+	*((char **)p) = (char *) decpt;
+	do {
+		p += sizeof(char **);
+		*((char **)p) = (char *) (decpt+1);
+	} while (p < (char *) &the_lconv.negative_sign);
+
+	p = (&the_lconv.int_frac_digits);
+	do {
+		*p = CHAR_MAX;
+		++p;
+	} while (p <= &the_lconv.int_n_sign_posn);
+
+	return &the_lconv;
+}
+
+#else /* __LOCALE_C_ONLY */
+
+static struct lconv the_lconv;
+
+struct lconv *localeconv(void)
+{
+	register char *p = (char *) &the_lconv;
+	register char **q = (char **) &(__UCLIBC_CURLOCALE->decimal_point);
+
+	do {
+		*((char **)p) = *q;
+		p += sizeof(char **);
+		++q;
+	} while (p < &the_lconv.int_frac_digits);
+
+	do {
+		*p = **q;
+		++p;
+		++q;
+	} while (p <= &the_lconv.int_n_sign_posn);
+
+	return &the_lconv;
+}
+
+#endif /* __LOCALE_C_ONLY */
+
+libc_hidden_def(localeconv)
+
+#endif
+/**********************************************************************/
+#if defined(L__locale_init) && !defined(__LOCALE_C_ONLY)
+
+struct __uclibc_locale_struct __global_locale_data;
+
+__locale_t __global_locale = &__global_locale_data;
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+__locale_t __curlocale_var = &__global_locale_data;
+#endif
+
+/*----------------------------------------------------------------------*/
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Move utf8 and ascii strings.
+#endif
+static const char utf8[] = "UTF-8";
+static const char ascii[] = "ASCII";
+
+typedef struct {
+	uint16_t num_base;
+	uint16_t num_der;
+	uint16_t MAX_WEIGHTS;
+	uint16_t num_index2weight;
+#define num_index2ruleidx num_index2weight
+	uint16_t num_weightstr;
+	uint16_t num_multistart;
+	uint16_t num_override;
+	uint16_t num_ruletable;
+} coldata_header_t;
+
+typedef struct {
+	uint16_t num_weights;
+	uint16_t num_starters;
+	uint16_t ii_shift;
+	uint16_t ti_shift;
+	uint16_t ii_len;
+	uint16_t ti_len;
+	uint16_t max_weight;
+	uint16_t num_col_base;
+	uint16_t max_col_index;
+	uint16_t undefined_idx;
+	uint16_t range_low;
+	uint16_t range_count;
+	uint16_t range_base_weight;
+	uint16_t range_rule_offset;
+
+	uint16_t index2weight_offset;
+	uint16_t index2ruleidx_offset;
+	uint16_t multistart_offset;
+	uint16_t wcs2colidt_offset_low;
+	uint16_t wcs2colidt_offset_hi;
+} coldata_base_t;
+
+typedef struct {
+	uint16_t base_idx;
+	uint16_t undefined_idx;
+	uint16_t overrides_offset;
+	uint16_t multistart_offset;
+} coldata_der_t;
+
+static int init_cur_collate(int der_num, __collate_t *cur_collate)
+{
+	const uint16_t *__locale_collate_tbl = __locale_mmap->collate_data;
+	coldata_header_t *cdh;
+	coldata_base_t *cdb;
+	coldata_der_t *cdd;
+	const uint16_t *p;
+	size_t n;
+	uint16_t i, w;
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning kill of x86-specific asserts
+#endif
+#if 0
+	assert(sizeof(coldata_base_t) == 19*2);
+	assert(sizeof(coldata_der_t) == 4*2);
+	assert(sizeof(coldata_header_t) == 8*2);
+#endif
+
+	if (!der_num) { 			/* C locale... special */
+		cur_collate->num_weights = 0;
+		return 1;
+	}
+
+	--der_num;
+
+	cdh = (coldata_header_t *) __locale_collate_tbl;
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Should we assert here?
+#endif
+#if 0
+	if (der_num >= cdh->num_der) {
+		return 0;
+	}
+#else
+	assert((der_num < cdh->num_der));
+#endif
+
+	cdd = (coldata_der_t *)(__locale_collate_tbl
+							+ (sizeof(coldata_header_t)
+							   + cdh->num_base * sizeof(coldata_base_t)
+							   + der_num * sizeof(coldata_der_t)
+							   )/2 );
+
+	cdb = (coldata_base_t *)(__locale_collate_tbl
+							 + (sizeof(coldata_header_t)
+								+ cdd->base_idx * sizeof(coldata_base_t)
+								)/2 );
+
+	memcpy(cur_collate, cdb, offsetof(coldata_base_t,index2weight_offset));
+	cur_collate->undefined_idx = cdd->undefined_idx;
+
+	cur_collate->ti_mask = (1 << cur_collate->ti_shift)-1;
+	cur_collate->ii_mask = (1 << cur_collate->ii_shift)-1;
+
+/* 	fflush(stdout); */
+/* 	fprintf(stderr,"base=%d  num_col_base: %d  %d\n", cdd->base_idx ,cur_collate->num_col_base, cdb->num_col_base); */
+
+	n = (sizeof(coldata_header_t) + cdh->num_base * sizeof(coldata_base_t)
+		 + cdh->num_der * sizeof(coldata_der_t))/2;
+
+/* 	fprintf(stderr,"n   = %d\n", n); */
+	cur_collate->index2weight_tbl = __locale_collate_tbl + n + cdb->index2weight_offset;
+/* 	fprintf(stderr,"i2w = %d\n", n + cdb->index2weight_offset); */
+	n += cdh->num_index2weight;
+	cur_collate->index2ruleidx_tbl = __locale_collate_tbl + n + cdb->index2ruleidx_offset;
+/* 	fprintf(stderr,"i2r = %d\n", n + cdb->index2ruleidx_offset); */
+	n += cdh->num_index2ruleidx;
+	cur_collate->multistart_tbl = __locale_collate_tbl + n + cdd->multistart_offset;
+/* 	fprintf(stderr,"mts = %d\n", n + cdb->multistart_offset); */
+	n += cdh->num_multistart;
+	cur_collate->overrides_tbl = __locale_collate_tbl + n + cdd->overrides_offset;
+/* 	fprintf(stderr,"ovr = %d\n", n + cdd->overrides_offset); */
+	n += cdh->num_override;
+	cur_collate->ruletable = __locale_collate_tbl + n;
+/* 	fprintf(stderr, "rtb = %d\n", n); */
+	n += cdh->num_ruletable;
+	cur_collate->weightstr = __locale_collate_tbl + n;
+/* 	fprintf(stderr,"wts = %d\n", n); */
+	n += cdh->num_weightstr;
+	cur_collate->wcs2colidt_tbl = __locale_collate_tbl + n
+		+ (((unsigned long)(cdb->wcs2colidt_offset_hi)) << 16)
+		+ cdb->wcs2colidt_offset_low;
+/* 	fprintf(stderr,"wcs = %lu\n", n	+ (((unsigned long)(cdb->wcs2colidt_offset_hi)) << 16) */
+/* 			+ cdb->wcs2colidt_offset_low); */
+
+	cur_collate->MAX_WEIGHTS = cdh->MAX_WEIGHTS;
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Fix the +1 by increasing max_col_index?
+#warning CONSIDER: Since this collate info is dependent only on LC_COLLATE ll_cc and not on codeset, we could just globally allocate this for each in a table
+#endif
+
+	cur_collate->index2weight = calloc(2*cur_collate->max_col_index+2,
+									   sizeof(uint16_t));
+	if (!cur_collate->index2weight) {
+		return 0;
+	}
+	cur_collate->index2ruleidx = cur_collate->index2weight
+		+ cur_collate->max_col_index + 1;
+
+	memcpy(cur_collate->index2weight, cur_collate->index2weight_tbl,
+		   cur_collate->num_col_base * sizeof(uint16_t));
+	memcpy(cur_collate->index2ruleidx, cur_collate->index2ruleidx_tbl,
+		   cur_collate->num_col_base * sizeof(uint16_t));
+
+	/* now do the overrides */
+	p = cur_collate->overrides_tbl;
+	while (*p > 1) {
+/* 		fprintf(stderr, "processing override -- count = %d\n", *p); */
+		n = *p++;
+		w = *p++;
+		do {
+			i = *p++;
+/* 			fprintf(stderr, "	i=%d (%#x) w=%d *p=%d\n", i, i, w, *p); */
+			cur_collate->index2weight[i-1] = w++;
+			cur_collate->index2ruleidx[i-1] = *p++;
+		} while (--n);
+	}
+	assert(*p == 1);
+	while (*++p) {
+		i = *p;
+/* 		fprintf(stderr, "	i=%d (%#x) w=%d *p=%d\n", i, i, p[1], p[2]); */
+		cur_collate->index2weight[i-1] = *++p;
+		cur_collate->index2ruleidx[i-1] = *++p;
+	}
+
+
+	for (i=0 ; i < cur_collate->multistart_tbl[0] ; i++) {
+		p = cur_collate->multistart_tbl;
+/* 		fprintf(stderr, "%2d of %2d: %d ", i,  cur_collate->multistart_tbl[0], p[i]); */
+		p += p[i];
+
+		do {
+			n = *p++;
+			do {
+				if (!*p) {		/* found it */
+/* 					fprintf(stderr, "found: n=%d (%#lx) |%.*ls|\n", n, (int) *cs->s, n, cs->s); */
+/* 					fprintf(stderr, ": %d - single\n", n); */
+					goto FOUND;
+ 				}
+				/* the lookup check here is safe since we're assured that *p is a valid colidex */
+/* 				fprintf(stderr, "lookup(%lc)==%d  *p==%d\n", cs->s[n], lookup(cs->s[n]), (int) *p); */
+/* 				fprintf(stderr, ": %d - ", n); */
+				do {
+/* 					fprintf(stderr, "%d|",  *p); */
+				} while (*p++);
+				break;
+			} while (1);
+		} while (1);
+	FOUND:
+		continue;
+	}
+
+	return 1;
+}
+
+int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base)
+{
+	const char **x;
+	unsigned char *s = base->cur_locale + 1;
+	const size_t *stp;
+	const unsigned char *r;
+	const uint16_t *io;
+	const uint16_t *ii;
+	const unsigned char *d;
+	int row;					/* locale row */
+	int crow;					/* category row */
+	int len;
+	int c;
+	int i = 0;
+	__collate_t newcol;
+
+	++p;
+
+	newcol.index2weight = NULL;
+	if ((p[2*LC_COLLATE] != s[2*LC_COLLATE])
+		|| (p[2*LC_COLLATE + 1] != s[2*LC_COLLATE + 1])
+		) {
+		row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f);
+		assert(row < __LOCALE_DATA_NUM_LOCALES);
+		if (!init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES
+													  * row + 3 + LC_COLLATE ],
+							  &newcol)
+			) {
+			return 0;			/* calloc failed. */
+		}
+		free(base->collate.index2weight);
+		memcpy(&base->collate, &newcol, sizeof(__collate_t));
+	}
+
+	do {
+		if ((*p != *s) || (p[1] != s[1])) {
+			row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f);
+			assert(row < __LOCALE_DATA_NUM_LOCALES);
+
+			*s = *p;
+			s[1] = p[1];
+
+			if ((i != LC_COLLATE)
+				&& ((len = __locale_mmap->lc_common_item_offsets_LEN[i]) != 0)
+				) {
+				crow = __locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES * row
+											   + 3 + i ]
+					* len;
+
+				x = (const char **)(((char *) base)
+                                    + base->category_offsets[i]);
+
+				stp = __locale_mmap->lc_common_tbl_offsets + 4*i;
+				r = (const unsigned char *)( ((char *)__locale_mmap) + *stp );
+				io = (const uint16_t *)( ((char *)__locale_mmap) + *++stp );
+				ii = (const uint16_t *)( ((char *)__locale_mmap) + *++stp );
+				d = (const unsigned char *)( ((char *)__locale_mmap) + *++stp );
+				for (c = 0; c < len; c++) {
+					x[c] = (char*)(d + ii[r[crow + c] + io[c]]);
+				}
+			}
+			if (i == LC_CTYPE) {
+				c = __locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES * row
+											+ 2 ]; /* codeset */
+				if (c <= 2) {
+					if (c == 2) {
+						base->codeset = utf8;
+						base->encoding = __ctype_encoding_utf8;
+						/* TODO - fix for bcc */
+						base->mb_cur_max = 6;
+					} else {
+						assert(c == 1);
+						base->codeset = ascii;
+						base->encoding = __ctype_encoding_7_bit;
+						base->mb_cur_max = 1;
+					}
+				} else {
+					const __codeset_8_bit_t *c8b;
+					r = CODESET_LIST;
+					c -= 3;
+					base->codeset = (char *) (r + r[c]);
+					base->encoding = __ctype_encoding_8_bit;
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: update 8 bit mb_cur_max when translit implemented!
+#endif
+					/* TODO - update when translit implemented! */
+					base->mb_cur_max = 1;
+					c8b = __locale_mmap->codeset_8_bit + c;
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+					base->idx8ctype = c8b->idx8ctype;
+					base->idx8uplow = c8b->idx8uplow;
+#ifdef __UCLIBC_HAS_WCHAR__
+					base->idx8c2wc = c8b->idx8c2wc;
+					base->idx8wc2c = c8b->idx8wc2c;
+					/* translit  */
+#endif /* __UCLIBC_HAS_WCHAR__ */
+
+					/* What follows is fairly bloated, but it is just a hack
+					 * to get the 8-bit codeset ctype stuff functioning.
+					 * All of this will be replaced in the next generation
+					 * of locale support anyway... */
+
+					memcpy(base->__ctype_b_data,
+						   __C_ctype_b - __UCLIBC_CTYPE_B_TBL_OFFSET,
+						   (256 + __UCLIBC_CTYPE_B_TBL_OFFSET)
+						   * sizeof(__ctype_mask_t));
+					memcpy(base->__ctype_tolower_data,
+						   __C_ctype_tolower - __UCLIBC_CTYPE_TO_TBL_OFFSET,
+						   (256 + __UCLIBC_CTYPE_TO_TBL_OFFSET)
+						   * sizeof(__ctype_touplow_t));
+					memcpy(base->__ctype_toupper_data,
+						   __C_ctype_toupper - __UCLIBC_CTYPE_TO_TBL_OFFSET,
+						   (256 + __UCLIBC_CTYPE_TO_TBL_OFFSET)
+						   * sizeof(__ctype_touplow_t));
+
+#define Cctype_TBL_MASK		((1 << __LOCALE_DATA_Cctype_IDX_SHIFT) - 1)
+#define Cctype_IDX_OFFSET	(128 >> __LOCALE_DATA_Cctype_IDX_SHIFT)
+
+					{
+						int u;
+						__ctype_mask_t m;
+
+						for (u=0 ; u < 128 ; u++) {
+#ifdef __LOCALE_DATA_Cctype_PACKED
+							c = base->tbl8ctype
+								[ ((int)(c8b->idx8ctype
+										 [(u >> __LOCALE_DATA_Cctype_IDX_SHIFT) ])
+								   << (__LOCALE_DATA_Cctype_IDX_SHIFT - 1))
+								  + ((u & Cctype_TBL_MASK) >> 1)];
+							c = (u & 1) ? (c >> 4) : (c & 0xf);
+#else
+							c = base->tbl8ctype
+								[ ((int)(c8b->idx8ctype
+										 [(u >> __LOCALE_DATA_Cctype_IDX_SHIFT) ])
+								   << __LOCALE_DATA_Cctype_IDX_SHIFT)
+								  + (u & Cctype_TBL_MASK) ];
+#endif
+
+							m = base->code2flag[c];
+
+							base->__ctype_b_data
+								[128 + __UCLIBC_CTYPE_B_TBL_OFFSET + u]
+								= m;
+
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+							if (((signed char)(128 + u)) != -1) {
+								base->__ctype_b_data[__UCLIBC_CTYPE_B_TBL_OFFSET
+													 + ((signed char)(128 + u))]
+									= m;
+							}
+#endif
+
+							base->__ctype_tolower_data
+								[128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u]
+								= 128 + u;
+							base->__ctype_toupper_data
+								[128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u]
+								= 128 + u;
+
+							if (m & (_ISlower|_ISupper)) {
+								c = base->tbl8uplow
+									[ ((int)(c8b->idx8uplow
+											 [u >> __LOCALE_DATA_Cuplow_IDX_SHIFT])
+									   << __LOCALE_DATA_Cuplow_IDX_SHIFT)
+									  + ((128 + u)
+										 & ((1 << __LOCALE_DATA_Cuplow_IDX_SHIFT)
+											- 1)) ];
+								if (m & _ISlower) {
+									base->__ctype_toupper_data
+										[128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u]
+										= (unsigned char)(128 + u + c);
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+									if (((signed char)(128 + u)) != -1) {
+										base->__ctype_toupper_data
+											[__UCLIBC_CTYPE_TO_TBL_OFFSET
+											 + ((signed char)(128 + u))]
+											= (unsigned char)(128 + u + c);
+									}
+#endif
+								} else {
+									base->__ctype_tolower_data
+										[128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u]
+										= (unsigned char)(128 + u - c);
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+									if (((signed char)(128 + u)) != -1) {
+										base->__ctype_tolower_data
+											[__UCLIBC_CTYPE_TO_TBL_OFFSET
+											 + ((signed char)(128 + u))]
+											= (unsigned char)(128 + u - c);
+									}
+#endif
+								}
+							}
+						}
+					}
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+					base->__ctype_b = base->__ctype_b_data
+						+ __UCLIBC_CTYPE_B_TBL_OFFSET;
+					base->__ctype_tolower = base->__ctype_tolower_data
+						+ __UCLIBC_CTYPE_TO_TBL_OFFSET;
+					base->__ctype_toupper = base->__ctype_toupper_data
+						+ __UCLIBC_CTYPE_TO_TBL_OFFSET;
+#else /* __UCLIBC_HAS_XLOCALE__ */
+					__ctype_b = base->__ctype_b_data
+						+ __UCLIBC_CTYPE_B_TBL_OFFSET;
+					__ctype_tolower = base->__ctype_tolower_data
+						+ __UCLIBC_CTYPE_TO_TBL_OFFSET;
+					__ctype_toupper = base->__ctype_toupper_data
+						+ __UCLIBC_CTYPE_TO_TBL_OFFSET;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+				}
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Put the outdigit string length in the locale_mmap object.
+#endif
+				d = base->outdigit_length;
+				x = &base->outdigit0_mb;
+				for (c = 0 ; c < 10 ; c++) {
+					((unsigned char *)d)[c] = strlen(x[c]);
+					assert(d[c] > 0);
+				}
+			} else if (i == LC_NUMERIC) {
+				assert(LC_NUMERIC > LC_CTYPE); /* Need ctype initialized. */
+
+				base->decimal_point_len
+					= __locale_mbrtowc_l(&base->decimal_point_wc,
+											base->decimal_point, base);
+				assert(base->decimal_point_len > 0);
+				assert(base->decimal_point[base->decimal_point_len] == 0);
+
+				if (*base->grouping) {
+					base->thousands_sep_len
+						= __locale_mbrtowc_l(&base->thousands_sep_wc,
+											 base->thousands_sep, base);
+#if 1
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Remove hack involving grouping without a thousep char (bg_BG).
+#endif
+					assert(base->thousands_sep_len >= 0);
+					if (base->thousands_sep_len == 0) {
+						base->grouping = base->thousands_sep; /* empty string */
+					}
+					assert(base->thousands_sep[base->thousands_sep_len] == 0);
+#else
+					assert(base->thousands_sep_len > 0);
+					assert(base->thousands_sep[base->thousands_sep_len] == 0);
+#endif
+				}
+
+/* 			} else if (i == LC_COLLATE) { */
+/* 				init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES */
+/* 														 * row + 3 + i ], */
+/* 								 &base->collate); */
+			}
+		}
+		++i;
+		p += 2;
+		s += 2;
+	} while (i < LC_ALL);
+
+	return 1;
+}
+
+static const uint16_t __code2flag[16] = {
+	0,							/* unclassified = 0 */
+	_ISprint|_ISgraph|_ISalnum|_ISalpha, /* alpha_nonupper_nonlower */
+	_ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, /* alpha_lower */
+	_ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower|_ISupper, /* alpha_upper_lower */
+	_ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, /* alpha_upper */
+	_ISprint|_ISgraph|_ISalnum|_ISdigit, /* digit */
+	_ISprint|_ISgraph|_ISpunct,	/* punct */
+	_ISprint|_ISgraph,			/* graph */
+	_ISprint|_ISspace,			/* print_space_nonblank */
+	_ISprint|_ISspace|_ISblank,	/* print_space_blank */
+	         _ISspace,			/* space_nonblank_noncntrl */
+	         _ISspace|_ISblank,	/* space_blank_noncntrl */
+	_IScntrl|_ISspace,			/* cntrl_space_nonblank */
+	_IScntrl|_ISspace|_ISblank,	/* cntrl_space_blank */
+	_IScntrl					/* cntrl_nonspace */
+};
+
+void attribute_hidden _locale_init_l(__locale_t base)
+{
+	memset(base->cur_locale, 0, LOCALE_SELECTOR_SIZE);
+	base->cur_locale[0] = '#';
+
+	memcpy(base->category_item_count,
+		   __locale_mmap->lc_common_item_offsets_LEN,
+		   LC_ALL);
+
+	++base->category_item_count[0]; /* Increment for codeset entry. */
+	base->category_offsets[0] = offsetof(struct __uclibc_locale_struct, outdigit0_mb);
+	base->category_offsets[1] = offsetof(struct __uclibc_locale_struct, decimal_point);
+	base->category_offsets[2] = offsetof(struct __uclibc_locale_struct, int_curr_symbol);
+	base->category_offsets[3] = offsetof(struct __uclibc_locale_struct, abday_1);
+/*  	base->category_offsets[4] = offsetof(struct __uclibc_locale_struct, collate???); */
+	base->category_offsets[5] = offsetof(struct __uclibc_locale_struct, yesexpr);
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+	base->tbl8ctype
+		= (const unsigned char *) &__locale_mmap->tbl8ctype;
+	base->tbl8uplow
+		= (const unsigned char *) &__locale_mmap->tbl8uplow;
+#ifdef __UCLIBC_HAS_WCHAR__
+	base->tbl8c2wc
+		= (const uint16_t *) &__locale_mmap->tbl8c2wc;
+	base->tbl8wc2c
+		= (const unsigned char *) &__locale_mmap->tbl8wc2c;
+	/* translit  */
+#endif /* __UCLIBC_HAS_WCHAR__ */
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+#ifdef __UCLIBC_HAS_WCHAR__
+	base->tblwctype
+		= (const unsigned char *) &__locale_mmap->tblwctype;
+	base->tblwuplow
+		= (const unsigned char *) &__locale_mmap->tblwuplow;
+	base->tblwuplow_diff
+		= (const int16_t *) &__locale_mmap->tblwuplow_diff;
+/* 	base->tblwcomb */
+/* 		= (const unsigned char *) &__locale_mmap->tblwcomb; */
+	/* width?? */
+#endif /* __UCLIBC_HAS_WCHAR__ */
+
+	/* Initially, set things up to use the global C ctype tables.
+	 * This is correct for C (ASCII) and UTF-8 based locales (except tr_TR). */
+#ifdef __UCLIBC_HAS_XLOCALE__
+	base->__ctype_b = __C_ctype_b;
+	base->__ctype_tolower = __C_ctype_tolower;
+	base->__ctype_toupper = __C_ctype_toupper;
+#else /* __UCLIBC_HAS_XLOCALE__ */
+	__ctype_b = __C_ctype_b;
+	__ctype_tolower = __C_ctype_tolower;
+	__ctype_toupper = __C_ctype_toupper;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Initialize code2flag correctly based on locale_mmap.
+#endif
+	base->code2flag = __code2flag;
+
+	_locale_set_l((unsigned char*) C_LOCALE_SELECTOR, base);
+}
+
+void _locale_init(void) attribute_hidden;
+void _locale_init(void)
+{
+	/* TODO: mmap the locale file  */
+
+	/* TODO - ??? */
+	_locale_init_l(__global_locale);
+}
+
+#endif
+/**********************************************************************/
+#if defined(L_nl_langinfo) || defined(L_nl_langinfo_l)
+
+#ifdef __LOCALE_C_ONLY
+
+/* We need to index 320 bytes of data, so you might initially think we
+ * need to store the offsets in shorts.  But since the offset of the
+ * 64th item is 182, we'll store "offset - 2*64" for all items >= 64
+ * and always calculate the data offset as "offset[i] + 2*(i & 64)".
+ * This allows us to pack the data offsets in an unsigned char while
+ * also avoiding an "if".
+ *
+ * Note: Category order is assumed to be:
+ *   ctype, numeric, monetary, time, collate, messages, all
+ */
+
+#define C_LC_ALL 6
+
+/* Combine the data to avoid size penalty for seperate char arrays when
+ * compiler aligns objects.  The original code is left in as documentation. */
+#define cat_start nl_data
+#define C_locale_data (nl_data + C_LC_ALL + 1 + 90)
+
+static const unsigned char nl_data[C_LC_ALL + 1 + 90 + 320] = {
+/* static const char cat_start[LC_ALL + 1] = { */
+	'\x00', '\x0b', '\x0e', '\x24', '\x56', '\x56', '\x5a',
+/* }; */
+/* static const char item_offset[90] = { */
+	'\x00', '\x02', '\x04', '\x06', '\x08', '\x0a', '\x0c', '\x0e',
+	'\x10', '\x12', '\x14', '\x1a', '\x1b', '\x1b', '\x1b', '\x1b',
+	'\x1b', '\x1b', '\x1b', '\x1b', '\x1b', '\x1c', '\x1c', '\x1c',
+	'\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c',
+	'\x1c', '\x1c', '\x1c', '\x1e', '\x20', '\x24', '\x28', '\x2c',
+	'\x30', '\x34', '\x38', '\x3c', '\x43', '\x4a', '\x52', '\x5c',
+	'\x65', '\x6c', '\x75', '\x79', '\x7d', '\x81', '\x85', '\x89',
+	'\x8d', '\x91', '\x95', '\x99', '\x9d', '\xa1', '\xa5', '\xad',
+	'\x36', '\x3c', '\x42', '\x46', '\x4b', '\x50', '\x57', '\x61',
+	'\x69', '\x72', '\x7b', '\x7e', '\x81', '\x96', '\x9f', '\xa8',
+	'\xb3', '\xb3', '\xb3', '\xb3', '\xb3', '\xb3', '\xb4', '\xba',
+	'\xbf', '\xbf',
+/* }; */
+/* static const char C_locale_data[320] = { */
+	   '0', '\x00',    '1', '\x00',    '2', '\x00',    '3', '\x00',
+	   '4', '\x00',    '5', '\x00',    '6', '\x00',    '7', '\x00',
+	   '8', '\x00',    '9', '\x00',    'A',    'S',    'C',    'I',
+	   'I', '\x00',    '.', '\x00', '\x7f', '\x00',    '-', '\x00',
+	   'S',    'u',    'n', '\x00',    'M',    'o',    'n', '\x00',
+	   'T',    'u',    'e', '\x00',    'W',    'e',    'd', '\x00',
+	   'T',    'h',    'u', '\x00',    'F',    'r',    'i', '\x00',
+	   'S',    'a',    't', '\x00',    'S',    'u',    'n',    'd',
+	   'a',    'y', '\x00',    'M',    'o',    'n',    'd',    'a',
+	   'y', '\x00',    'T',    'u',    'e',    's',    'd',    'a',
+	   'y', '\x00',    'W',    'e',    'd',    'n',    'e',    's',
+	   'd',    'a',    'y', '\x00',    'T',    'h',    'u',    'r',
+	   's',    'd',    'a',    'y', '\x00',    'F',    'r',    'i',
+	   'd',    'a',    'y', '\x00',    'S',    'a',    't',    'u',
+	   'r',    'd',    'a',    'y', '\x00',    'J',    'a',    'n',
+	'\x00',    'F',    'e',    'b', '\x00',    'M',    'a',    'r',
+	'\x00',    'A',    'p',    'r', '\x00',    'M',    'a',    'y',
+	'\x00',    'J',    'u',    'n', '\x00',    'J',    'u',    'l',
+	'\x00',    'A',    'u',    'g', '\x00',    'S',    'e',    'p',
+	'\x00',    'O',    'c',    't', '\x00',    'N',    'o',    'v',
+	'\x00',    'D',    'e',    'c', '\x00',    'J',    'a',    'n',
+	   'u',    'a',    'r',    'y', '\x00',    'F',    'e',    'b',
+	   'r',    'u',    'a',    'r',    'y', '\x00',    'M',    'a',
+	   'r',    'c',    'h', '\x00',    'A',    'p',    'r',    'i',
+	   'l', '\x00',    'M',    'a',    'y', '\x00',    'J',    'u',
+	   'n',    'e', '\x00',    'J',    'u',    'l',    'y', '\x00',
+	   'A',    'u',    'g',    'u',    's',    't', '\x00',    'S',
+	   'e',    'p',    't',    'e',    'm',    'b',    'e',    'r',
+	'\x00',    'O',    'c',    't',    'o',    'b',    'e',    'r',
+	'\x00',    'N',    'o',    'v',    'e',    'm',    'b',    'e',
+	   'r', '\x00',    'D',    'e',    'c',    'e',    'm',    'b',
+	   'e',    'r', '\x00',    'A',    'M', '\x00',    'P',    'M',
+	'\x00',    '%',    'a',    ' ',    '%',    'b',    ' ',    '%',
+	   'e',    ' ',    '%',    'H',    ':',    '%',    'M',    ':',
+	   '%',    'S',    ' ',    '%',    'Y', '\x00',    '%',    'm',
+	   '/',    '%',    'd',    '/',    '%',    'y', '\x00',    '%',
+	   'H',    ':',    '%',    'M',    ':',    '%',    'S', '\x00',
+	   '%',    'I',    ':',    '%',    'M',    ':',    '%',    'S',
+	   ' ',    '%',    'p', '\x00',    '^',    '[',    'y',    'Y',
+	   ']', '\x00',    '^',    '[',    'n',    'N',    ']', '\x00',
+};
+
+char *nl_langinfo(nl_item item)
+{
+	unsigned int c;
+	unsigned int i;
+
+	if ((c = _NL_ITEM_CATEGORY(item)) < C_LC_ALL) {
+		if ((i = cat_start[c] + _NL_ITEM_INDEX(item)) < cat_start[c+1]) {
+/*  			return (char *) C_locale_data + item_offset[i] + (i & 64); */
+			return (char *) C_locale_data + nl_data[C_LC_ALL+1+i] + 2*(i & 64);
+		}
+	}
+	return (char *) cat_start;	/* Conveniently, this is the empty string. */
+}
+libc_hidden_def(nl_langinfo)
+
+#else /* __LOCALE_C_ONLY */
+
+#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
+
+
+
+char *nl_langinfo(nl_item item)
+{
+	return nl_langinfo_l(item, __UCLIBC_CURLOCALE);
+}
+libc_hidden_def(nl_langinfo)
+
+#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+libc_hidden_proto(__XL_NPP(nl_langinfo))
+
+static const char empty[] = "";
+
+char *__XL_NPP(nl_langinfo)(nl_item item __LOCALE_PARAM )
+{
+	unsigned int c = _NL_ITEM_CATEGORY(item);
+	unsigned int i = _NL_ITEM_INDEX(item);
+
+	if ((c < LC_ALL) && (i < __LOCALE_PTR->category_item_count[c])) {
+		return ((char **)(((char *) __LOCALE_PTR)
+						  + __LOCALE_PTR->category_offsets[c]))[i];
+	}
+
+	return (char *) empty;
+}
+libc_hidden_def(__XL_NPP(nl_langinfo))
+
+#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+#endif /* __LOCALE_C_ONLY */
+
+#endif
+/**********************************************************************/
+#ifdef L_newlocale
+
+#warning mask defines for extra locale categories
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Move posix and utf8 strings.
+#endif
+static const char posix[] = "POSIX";
+static const char utf8[] = "UTF-8";
+
+static int find_locale(int category_mask, const char *p,
+					   unsigned char *new_locale)
+{
+	int i;
+	const unsigned char *s;
+	uint16_t n;
+	unsigned char lang_cult, codeset;
+
+#if defined(__LOCALE_DATA_AT_MODIFIERS_LENGTH) && 1
+	/* Support standard locale handling for @-modifiers. */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: Fix buf size in find_locale.
+#endif
+	char buf[18];	/* TODO: 7+{max codeset name length} */
+	const char *q;
+
+	if ((q = strchr(p,'@')) != NULL) {
+		if ((((size_t)((q-p)-5)) > (sizeof(buf) - 5)) || (p[2] != '_')) {
+			return 0;
+		}
+		/* locale name at least 5 chars long and 3rd char is '_' */
+		s = LOCALE_AT_MODIFIERS;
+		do {
+			if (!strcmp((char*) (s + 2), q + 1)) {
+				break;
+			}
+			s += 2 + *s;		/* TODO - fix this throughout */
+		} while (*s);
+		if (!*s) {
+			return 0;
+		}
+		assert(q - p < sizeof(buf));
+		memcpy(buf, p, q-p);
+		buf[q-p] = 0;
+		buf[2] = s[1];
+		p = buf;
+	}
+#endif
+
+	lang_cult = codeset = 0;	/* Assume C and default codeset.  */
+	if (((*p == 'C') && !p[1]) || !strcmp(p, posix)) {
+		goto FIND_LOCALE;
+	}
+
+	if ((strlen(p) > 5) && (p[5] == '.')) {	/* Codeset in locale name? */
+		/* TODO: maybe CODESET_LIST + *s ??? */
+		/* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */
+		codeset = 2;
+		if (strcasecmp(utf8, p + 6) != 0) {/* TODO - fix! */
+			s = CODESET_LIST;
+			do {
+				++codeset;		/* Increment codeset first. */
+				if (!strcmp((char*) CODESET_LIST + *s, p + 6)) {
+					goto FIND_LANG_CULT;
+				}
+			} while (*++s);
+			return 0;			/* No matching codeset! */
+		}
+	}
+
+ FIND_LANG_CULT:				/* Find language_culture number. */
+	s = LOCALE_NAMES;
+	do {						/* TODO -- do a binary search? */
+		/* TODO -- fix gen_mmap!*/
+		++lang_cult;			/* Increment first since C/POSIX is 0. */
+		if (!strncmp((char*) s, p, 5)) { /* Found a matching locale name; */
+			goto FIND_LOCALE;
+		}
+		s += 5;
+	} while (lang_cult < __LOCALE_DATA_NUM_LOCALE_NAMES);
+	return 0;					/* No matching language_culture! */
+
+ FIND_LOCALE:					/* Find locale row matching name and codeset */
+	s = LOCALES;
+	n = 0;
+	do {						/* TODO -- do a binary search? */
+		if ((lang_cult == *s) && ((codeset == s[1]) || (codeset == s[2]))) {
+			i = 1;
+			s = new_locale + 1;
+			do {
+				if (category_mask & i) {
+					/* Encode current locale row number. */
+					((unsigned char *) s)[0] = (n >> 7) | 0x80;
+					((unsigned char *) s)[1] = (n & 0x7f) | 0x80;
+				}
+				s += 2;
+				i += i;
+			} while (i < (1 << LC_ALL));
+
+			return i;			/* Return non-zero */
+		}
+		s += __LOCALE_DATA_WIDTH_LOCALES;
+		++n;
+	} while (n <= __LOCALE_DATA_NUM_LOCALES); /* We started at 1!!! */
+
+	return 0;					/* Unsupported locale. */
+}
+
+static unsigned char *composite_locale(int category_mask, const char *locale,
+									   unsigned char *new_locale)
+{
+	char buf[MAX_LOCALE_STR];
+	char *t;
+	char *e;
+	int c;
+	int component_mask;
+
+	if (!strchr(locale,'=')) {
+		if (!find_locale(category_mask, locale, new_locale)) {
+			return NULL;
+		}
+		return new_locale;
+	}
+
+	if (strlen(locale) >= sizeof(buf)) {
+		return NULL;
+	}
+	stpcpy(buf, locale);
+
+	component_mask = 0;
+	t = strtok_r(buf, "=", &e);	/* This can't fail because of strchr test above. */
+	do {
+		c = 0;
+		/* CATEGORY_NAMES is unsigned char* */
+		while (strcmp((char*) CATEGORY_NAMES + (int) CATEGORY_NAMES[c], t)) {
+			if (++c == LC_ALL) { /* Unknown category name! */
+				return NULL;
+			}
+		}
+		t = strtok_r(NULL, ";", &e);
+		c = (1 << c);
+		if (component_mask & c) { /* Multiple components for one category. */
+			return NULL;
+		}
+		component_mask |= c;
+		if ((category_mask & c) && (!t || !find_locale(c, t, new_locale))) {
+			return NULL;
+		}
+	} while ((t = strtok_r(NULL, "=", &e)) != NULL);
+
+	if (category_mask & ~component_mask) { /* Category component(s) missing. */
+		return NULL;
+	}
+
+	return new_locale;
+}
+
+__locale_t newlocale(int category_mask, const char *locale, __locale_t base)
+{
+	const char *p;
+	int i, j, k;
+	unsigned char new_selector[LOCALE_SELECTOR_SIZE];
+
+	if (category_mask == (1 << LC_ALL)) {
+		category_mask = LC_ALL_MASK;
+	}
+
+	if (!locale || ((unsigned)(category_mask) > LC_ALL_MASK)) {
+ INVALID:
+		__set_errno(EINVAL);
+		return NULL; /* No locale or illegal/unsupported category. */
+	}
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Rename cur_locale to locale_selector.
+#endif
+	strcpy((char *) new_selector,
+		   (base ? (char *) base->cur_locale : C_LOCALE_SELECTOR));
+
+	if (!locale[0]) {	/* locale == "", so check environment. */
+		const char *envstr[4];
+
+		envstr[0] = "LC_ALL";
+		envstr[1] = NULL;
+		envstr[2] = "LANG";
+		envstr[3] = posix;
+
+		i = 1;
+		k = 0;
+		do {
+			if (category_mask & i) {
+				/* Note: SUSv3 doesn't define a fallback mechanism here.
+				 * So, if LC_ALL is invalid, we do _not_ continue trying
+				 * the other environment vars. */
+				envstr[1] = (char*) CATEGORY_NAMES + CATEGORY_NAMES[k];
+				j = 0;
+				while (1) {
+					p = envstr[j];
+					if (++j >= 4)
+						break; /* now p == "POSIX" */
+					p = getenv(p);
+					if (p && p[0])
+						break;
+				};
+
+				/* The user set something... is it valid? */
+				/* Note: Since we don't support user-supplied locales and
+				 * alternate paths, we don't need to worry about special
+				 * handling for suid/sgid apps. */
+				if (!find_locale(i, p, new_selector)) {
+					goto INVALID;
+				}
+			}
+			i += i;
+		} while (++k < LC_ALL);
+	} else if (!composite_locale(category_mask, locale, new_selector)) {
+		goto INVALID;
+	}
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Do a compatible codeset check!
+#endif
+
+	/* If we get here, the new selector corresponds to a valid locale. */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Probably want a _locale_new func to allow for caching of locales.
+#endif
+#if 0
+	if (base) {
+		_locale_set_l(new_selector, base);
+	} else {
+		base = _locale_new(new_selector);
+	}
+#else
+	if (!base) {
+		base = calloc(1, sizeof(struct __uclibc_locale_struct));
+		if (base == NULL)
+			return base;
+		_locale_init_l(base);
+	}
+
+	_locale_set_l(new_selector, base);
+#endif
+
+	return base;
+}
+#ifdef __UCLIBC_HAS_XLOCALE__
+libc_hidden_def(newlocale)
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L_duplocale
+
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: When we allocate ctype tables, remember to dup them.
+#endif
+
+__locale_t duplocale(__locale_t dataset)
+{
+	__locale_t r;
+	uint16_t * i2w;
+	size_t n;
+
+	assert(dataset != LC_GLOBAL_LOCALE);
+
+	r = malloc(sizeof(struct __uclibc_locale_struct));
+	if (r != NULL) {
+		n = 2 * dataset->collate.max_col_index + 2;
+		i2w = calloc(n, sizeof(uint16_t));
+		if (i2w != NULL) {
+			memcpy(r, dataset, sizeof(struct __uclibc_locale_struct));
+			r->collate.index2weight = i2w;
+			memcpy(i2w, dataset->collate.index2weight, n * sizeof(uint16_t));
+		} else {
+			free(r);
+			r = NULL;
+		}
+	}
+	return r;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_freelocale
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: When we allocate ctype tables, remember to free them.
+#endif
+
+void freelocale(__locale_t dataset)
+{
+	assert(dataset != __global_locale);
+	assert(dataset != LC_GLOBAL_LOCALE);
+
+	free(dataset->collate.index2weight); /* Free collation data. */
+	free(dataset);				/* Free locale */
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_uselocale
+
+__locale_t uselocale(__locale_t dataset)
+{
+	__locale_t old;
+
+	if (!dataset) {
+		old = __UCLIBC_CURLOCALE;
+	} else {
+		if (dataset == LC_GLOBAL_LOCALE) {
+			dataset = __global_locale;
+		}
+#ifdef __UCLIBC_HAS_THREADS__
+		old = __curlocale_set(dataset);
+#else
+		old = __curlocale_var;
+		__curlocale_var = dataset;
+#endif
+	}
+
+	if (old == __global_locale) {
+		return LC_GLOBAL_LOCALE;
+	}
+	return old;
+}
+libc_hidden_def(uselocale)
+
+#endif
+/**********************************************************************/
+#ifdef L___curlocale
+
+#ifdef __UCLIBC_HAS_THREADS__
+
+__locale_t weak_const_function __curlocale(void)
+{
+	return __curlocale_var; /* This is overriden by the thread version. */
+}
+
+__locale_t weak_function __curlocale_set(__locale_t newloc)
+{
+	__locale_t oldloc = __curlocale_var;
+	assert(newloc != LC_GLOBAL_LOCALE);
+	__curlocale_var = newloc;
+	return oldloc;
+}
+
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L___locale_mbrtowc_l
+
+/* NOTE: This returns an int... not size_t.  Also, it is not a general
+ * routine.  It is actually a very stripped-down version of mbrtowc
+ * that takes a __locale_t arg.  This is used by strcoll and strxfrm.
+ * It is also used above to generate wchar_t versions of the decimal point
+ * and thousands seperator. */
+
+
+#ifndef __CTYPE_HAS_UTF_8_LOCALES
+#warning __CTYPE_HAS_UTF_8_LOCALES not set!
+#endif
+#ifndef __CTYPE_HAS_8_BIT_LOCALES
+#warning __CTYPE_HAS_8_BIT_LOCALES not set!
+#endif
+
+#define Cc2wc_IDX_SHIFT		__LOCALE_DATA_Cc2wc_IDX_SHIFT
+#define Cc2wc_ROW_LEN		__LOCALE_DATA_Cc2wc_ROW_LEN
+
+extern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
+						 const char **__restrict src, size_t n,
+						 mbstate_t *ps, int allow_continuation) attribute_hidden;
+
+int attribute_hidden __locale_mbrtowc_l(wchar_t *__restrict dst,
+					   const char *__restrict src,
+					   __locale_t loc )
+{
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+	if (loc->encoding == __ctype_encoding_utf8) {
+		mbstate_t ps;
+		const char *p = src;
+		size_t r;
+		ps.__mask = 0;
+		r = _wchar_utf8sntowcs(dst, 1, &p, SIZE_MAX, &ps, 1);
+		return (r == 1) ? (p-src) : r; /* Need to return 0 if nul char. */
+	}
+#endif
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+	assert((loc->encoding == __ctype_encoding_7_bit) || (loc->encoding == __ctype_encoding_8_bit));
+#else
+	assert(loc->encoding == __ctype_encoding_7_bit);
+#endif
+
+	if ((*dst = ((unsigned char)(*src))) < 0x80) {	/* ASCII... */
+		return (*src != 0);
+	}
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+	if (loc->encoding == __ctype_encoding_8_bit) {
+		wchar_t wc = *dst - 0x80;
+		*dst = loc->tbl8c2wc[
+						(loc->idx8c2wc[wc >> Cc2wc_IDX_SHIFT]
+						 << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))];
+		if (*dst) {
+			return 1;
+		}
+	}
+#endif
+
+	return -1;
+}
+
+#endif
+/**********************************************************************/
diff --git a/ap/build/uClibc/libc/misc/locale/localeconv.c b/ap/build/uClibc/libc/misc/locale/localeconv.c
new file mode 100644
index 0000000..7e67fb2
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/localeconv.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_localeconv
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/newlocale.c b/ap/build/uClibc/libc/misc/locale/newlocale.c
new file mode 100644
index 0000000..a986884
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/newlocale.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_newlocale
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/nl_langinfo.c b/ap/build/uClibc/libc/misc/locale/nl_langinfo.c
new file mode 100644
index 0000000..0bc0a00
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/nl_langinfo.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_nl_langinfo
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/nl_langinfo_l.c b/ap/build/uClibc/libc/misc/locale/nl_langinfo_l.c
new file mode 100644
index 0000000..7205cca
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/nl_langinfo_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_nl_langinfo_l
+#define __UCLIBC_DO_XLOCALE
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/setlocale.c b/ap/build/uClibc/libc/misc/locale/setlocale.c
new file mode 100644
index 0000000..1eae88a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/setlocale.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_setlocale
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/locale/uselocale.c b/ap/build/uClibc/libc/misc/locale/uselocale.c
new file mode 100644
index 0000000..2aecc54
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/locale/uselocale.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_uselocale
+#define __UCLIBC_DO_XLOCALE
+#include "locale.c"
diff --git a/ap/build/uClibc/libc/misc/mntent/.indent.pro b/ap/build/uClibc/libc/misc/mntent/.indent.pro
new file mode 100644
index 0000000..492ecf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/mntent/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/ap/build/uClibc/libc/misc/mntent/Makefile b/ap/build/uClibc/libc/misc/mntent/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/mntent/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/mntent/Makefile.in b/ap/build/uClibc/libc/misc/mntent/Makefile.in
new file mode 100644
index 0000000..daa888d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/mntent/Makefile.in
@@ -0,0 +1,23 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/mntent
+
+CSRC := mntent.c
+
+MISC_MNTENT_DIR := $(top_srcdir)libc/misc/mntent
+MISC_MNTENT_OUT := $(top_builddir)libc/misc/mntent
+
+MISC_MNTENT_SRC := $(MISC_MNTENT_DIR)/mntent.c
+MISC_MNTENT_OBJ := $(MISC_MNTENT_OUT)/mntent.o
+
+libc-y += $(MISC_MNTENT_OBJ)
+
+objclean-y += CLEAN_libc/misc/mntent
+
+CLEAN_libc/misc/mntent:
+	$(do_rm) $(addprefix $(MISC_MNTENT_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/mntent/mntent.c b/ap/build/uClibc/libc/misc/mntent/mntent.c
new file mode 100644
index 0000000..608f84c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/mntent/mntent.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mntent.h>
+#include <bits/uClibc_mutex.h>
+
+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+
+
+/* Reentrant version of getmntent.  */
+struct mntent *getmntent_r (FILE *filep,
+	struct mntent *mnt, char *buff, int bufsize)
+{
+	static const char sep[] = " \t\n";
+
+	char *cp, *ptrptr;
+
+	if (!filep || !mnt || !buff)
+	    return NULL;
+
+	/* Loop on the file, skipping comment lines. - FvK 03/07/93 */
+	while ((cp = fgets(buff, bufsize, filep)) != NULL) {
+		if (buff[0] == '#' || buff[0] == '\n')
+			continue;
+		break;
+	}
+
+	/* At the EOF, the buffer should be unchanged. We should
+	 * check the return value from fgets ().
+	 */
+	if (cp == NULL)
+		return NULL;
+
+	ptrptr = 0;
+	mnt->mnt_fsname = strtok_r(buff, sep, &ptrptr);
+	if (mnt->mnt_fsname == NULL)
+		return NULL;
+
+	mnt->mnt_dir = strtok_r(NULL, sep, &ptrptr);
+	if (mnt->mnt_dir == NULL)
+		return NULL;
+
+	mnt->mnt_type = strtok_r(NULL, sep, &ptrptr);
+	if (mnt->mnt_type == NULL)
+		return NULL;
+
+	mnt->mnt_opts = strtok_r(NULL, sep, &ptrptr);
+	if (mnt->mnt_opts == NULL)
+		mnt->mnt_opts = "";
+
+	cp = strtok_r(NULL, sep, &ptrptr);
+	mnt->mnt_freq = (cp != NULL) ? atoi(cp) : 0;
+
+	cp = strtok_r(NULL, sep, &ptrptr);
+	mnt->mnt_passno = (cp != NULL) ? atoi(cp) : 0;
+
+	return mnt;
+}
+libc_hidden_def(getmntent_r)
+
+struct mntent *getmntent(FILE * filep)
+{
+    struct mntent *tmp;
+    static char *buff = NULL;
+    static struct mntent mnt;
+    __UCLIBC_MUTEX_LOCK(mylock);
+
+    if (!buff) {
+            buff = malloc(BUFSIZ);
+		if (!buff)
+		    abort();
+    }
+
+    tmp = getmntent_r(filep, &mnt, buff, BUFSIZ);
+    __UCLIBC_MUTEX_UNLOCK(mylock);
+    return(tmp);
+}
+
+int addmntent(FILE * filep, const struct mntent *mnt)
+{
+	if (fseek(filep, 0, SEEK_END) < 0)
+		return 1;
+
+	return (fprintf (filep, "%s %s %s %s %d %d\n", mnt->mnt_fsname, mnt->mnt_dir,
+		 mnt->mnt_type, mnt->mnt_opts, mnt->mnt_freq, mnt->mnt_passno) < 0 ? 1 : 0);
+}
+
+char *hasmntopt(const struct mntent *mnt, const char *opt)
+{
+	return strstr(mnt->mnt_opts, opt);
+}
+
+FILE *setmntent(const char *name, const char *mode)
+{
+	return fopen(name, mode);
+}
+libc_hidden_def(setmntent)
+
+int endmntent(FILE * filep)
+{
+	if (filep != NULL)
+		fclose(filep);
+	return 1;
+}
+libc_hidden_def(endmntent)
diff --git a/ap/build/uClibc/libc/misc/pthread/Makefile b/ap/build/uClibc/libc/misc/pthread/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/pthread/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/pthread/Makefile.in b/ap/build/uClibc/libc/misc/pthread/Makefile.in
new file mode 100644
index 0000000..2f436ac
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/pthread/Makefile.in
@@ -0,0 +1,18 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/pthread
+
+MISC_PTHREAD_DIR := $(top_srcdir)libc/misc/pthread
+MISC_PTHREAD_OUT := $(top_builddir)libc/misc/pthread
+
+libc-shared-$(UCLIBC_HAS_TLS) += $(MISC_PTHREAD_OUT)/tsd.os
+
+objclean-y += CLEAN_libc/misc/pthread
+
+CLEAN_libc/misc/pthread:
+	$(do_rm) $(addprefix $(MISC_PTHREAD_OUT)/*., o os oS)
diff --git a/ap/build/uClibc/libc/misc/pthread/tsd.c b/ap/build/uClibc/libc/misc/pthread/tsd.c
new file mode 100644
index 0000000..0c222e8
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/pthread/tsd.c
@@ -0,0 +1,11 @@
+/* libpthread sets _dl_error_catch_tsd to point to this function.
+   We define it here instead of in libpthread so t here instead of in libpthread so that it doesn't
+   need to have a TLS segment of its own just for this one pointer.  */
+
+void **__libc_dl_error_tsd(void) __attribute__ ((const));
+void ** __attribute__ ((const))
+__libc_dl_error_tsd (void)
+{
+  static __thread void *data __attribute__ ((tls_model ("initial-exec")));
+  return &data;
+}
diff --git a/ap/build/uClibc/libc/misc/regex/.indent.pro b/ap/build/uClibc/libc/misc/regex/.indent.pro
new file mode 100644
index 0000000..492ecf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/ap/build/uClibc/libc/misc/regex/Makefile b/ap/build/uClibc/libc/misc/regex/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/regex/Makefile.in b/ap/build/uClibc/libc/misc/regex/Makefile.in
new file mode 100644
index 0000000..9471023
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/Makefile.in
@@ -0,0 +1,27 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/regex
+
+ifeq ($(UCLIBC_HAS_REGEX_OLD),y)
+CSRC := regex_old.c
+else
+CSRC := regex.c
+endif
+
+MISC_REGEX_DIR := $(top_srcdir)libc/misc/regex
+MISC_REGEX_OUT := $(top_builddir)libc/misc/regex
+
+MISC_REGEX_SRC := $(patsubst %.c,$(MISC_REGEX_DIR)/%.c,$(CSRC))
+MISC_REGEX_OBJ := $(patsubst %.c,$(MISC_REGEX_OUT)/%.o,$(CSRC))
+
+libc-$(UCLIBC_HAS_REGEX) += $(MISC_REGEX_OBJ)
+
+objclean-y += CLEAN_libc/misc/regex
+
+CLEAN_libc/misc/regex:
+	$(do_rm) $(addprefix $(MISC_REGEX_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/regex/regcomp.c b/ap/build/uClibc/libc/misc/regex/regcomp.c
new file mode 100644
index 0000000..b25850c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/regcomp.c
@@ -0,0 +1,3779 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
+					  size_t length, reg_syntax_t syntax);
+static void re_compile_fastmap_iter (regex_t *bufp,
+				     const re_dfastate_t *init_state,
+				     char *fastmap);
+static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);
+#ifdef RE_ENABLE_I18N
+static void free_charset (re_charset_t *cset);
+#endif
+static void free_workarea_compile (regex_t *preg);
+static reg_errcode_t create_initial_state (re_dfa_t *dfa);
+#ifdef RE_ENABLE_I18N
+static void optimize_utf8 (re_dfa_t *dfa);
+#endif
+static reg_errcode_t analyze (regex_t *preg);
+static reg_errcode_t preorder (bin_tree_t *root,
+			       reg_errcode_t (fn (void *, bin_tree_t *)),
+			       void *extra);
+static reg_errcode_t postorder (bin_tree_t *root,
+				reg_errcode_t (fn (void *, bin_tree_t *)),
+				void *extra);
+static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
+static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
+static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
+				 bin_tree_t *node);
+static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
+static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
+static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
+static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint);
+static int search_duplicated_node (const re_dfa_t *dfa, int org_node,
+				   unsigned int constraint);
+static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
+static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
+					 int node, int root);
+static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
+static int fetch_number (re_string_t *input, re_token_t *token,
+			 reg_syntax_t syntax);
+static int peek_token (re_token_t *token, re_string_t *input,
+			reg_syntax_t syntax) internal_function;
+static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
+			  reg_syntax_t syntax, reg_errcode_t *err);
+static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
+				  re_token_t *token, reg_syntax_t syntax,
+				  int nest, reg_errcode_t *err);
+static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
+				 re_token_t *token, reg_syntax_t syntax,
+				 int nest, reg_errcode_t *err);
+static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
+				     re_token_t *token, reg_syntax_t syntax,
+				     int nest, reg_errcode_t *err);
+static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
+				  re_token_t *token, reg_syntax_t syntax,
+				  int nest, reg_errcode_t *err);
+static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
+				 re_dfa_t *dfa, re_token_t *token,
+				 reg_syntax_t syntax, reg_errcode_t *err);
+static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
+				      re_token_t *token, reg_syntax_t syntax,
+				      reg_errcode_t *err);
+static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
+					    re_string_t *regexp,
+					    re_token_t *token, int token_len,
+					    re_dfa_t *dfa,
+					    reg_syntax_t syntax,
+					    int accept_hyphen);
+static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
+					  re_string_t *regexp,
+					  re_token_t *token);
+#ifdef RE_ENABLE_I18N
+static reg_errcode_t build_equiv_class (bitset_t sbcset,
+					re_charset_t *mbcset,
+					int *equiv_class_alloc,
+					const unsigned char *name);
+static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
+				      bitset_t sbcset,
+				      re_charset_t *mbcset,
+				      int *char_class_alloc,
+				      const unsigned char *class_name,
+				      reg_syntax_t syntax);
+#else  /* not RE_ENABLE_I18N */
+static reg_errcode_t build_equiv_class (bitset_t sbcset,
+					const unsigned char *name);
+static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
+				      bitset_t sbcset,
+				      const unsigned char *class_name,
+				      reg_syntax_t syntax);
+#endif /* not RE_ENABLE_I18N */
+static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
+				       RE_TRANSLATE_TYPE trans,
+				       const unsigned char *class_name,
+				       const unsigned char *extra,
+				       int non_match, reg_errcode_t *err);
+static bin_tree_t *create_tree (re_dfa_t *dfa,
+				bin_tree_t *left, bin_tree_t *right,
+				re_token_type_t type);
+static bin_tree_t *create_token_tree (re_dfa_t *dfa,
+				      bin_tree_t *left, bin_tree_t *right,
+				      const re_token_t *token);
+static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
+static void free_token (re_token_t *node);
+static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
+static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
+
+/* This table gives an error message for each of the error codes listed
+   in regex.h.  Obviously the order here has to be same as there.
+   POSIX doesn't require that we do anything for REG_NOERROR,
+   but why not be nice?  */
+
+static const char __re_error_msgid[] =
+  {
+#define REG_NOERROR_IDX	0
+    gettext_noop ("Success")	/* REG_NOERROR */
+    "\0"
+#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
+    gettext_noop ("No match")	/* REG_NOMATCH */
+    "\0"
+#define REG_BADPAT_IDX	(REG_NOMATCH_IDX + sizeof "No match")
+    gettext_noop ("Invalid regular expression") /* REG_BADPAT */
+    "\0"
+#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
+    gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
+    "\0"
+#define REG_ECTYPE_IDX	(REG_ECOLLATE_IDX + sizeof "Invalid collation character")
+    gettext_noop ("Invalid character class name") /* REG_ECTYPE */
+    "\0"
+#define REG_EESCAPE_IDX	(REG_ECTYPE_IDX + sizeof "Invalid character class name")
+    gettext_noop ("Trailing backslash") /* REG_EESCAPE */
+    "\0"
+#define REG_ESUBREG_IDX	(REG_EESCAPE_IDX + sizeof "Trailing backslash")
+    gettext_noop ("Invalid back reference") /* REG_ESUBREG */
+    "\0"
+#define REG_EBRACK_IDX	(REG_ESUBREG_IDX + sizeof "Invalid back reference")
+    gettext_noop ("Unmatched [ or [^")	/* REG_EBRACK */
+    "\0"
+#define REG_EPAREN_IDX	(REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
+    gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
+    "\0"
+#define REG_EBRACE_IDX	(REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
+    gettext_noop ("Unmatched \\{") /* REG_EBRACE */
+    "\0"
+#define REG_BADBR_IDX	(REG_EBRACE_IDX + sizeof "Unmatched \\{")
+    gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
+    "\0"
+#define REG_ERANGE_IDX	(REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
+    gettext_noop ("Invalid range end")	/* REG_ERANGE */
+    "\0"
+#define REG_ESPACE_IDX	(REG_ERANGE_IDX + sizeof "Invalid range end")
+    gettext_noop ("Memory exhausted") /* REG_ESPACE */
+    "\0"
+#define REG_BADRPT_IDX	(REG_ESPACE_IDX + sizeof "Memory exhausted")
+    gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
+    "\0"
+#define REG_EEND_IDX	(REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
+    gettext_noop ("Premature end of regular expression") /* REG_EEND */
+    "\0"
+#define REG_ESIZE_IDX	(REG_EEND_IDX + sizeof "Premature end of regular expression")
+    gettext_noop ("Regular expression too big") /* REG_ESIZE */
+    "\0"
+#define REG_ERPAREN_IDX	(REG_ESIZE_IDX + sizeof "Regular expression too big")
+    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
+  };
+
+static const uint16_t __re_error_msgid_idx[] =
+  {
+    REG_NOERROR_IDX,
+    REG_NOMATCH_IDX,
+    REG_BADPAT_IDX,
+    REG_ECOLLATE_IDX,
+    REG_ECTYPE_IDX,
+    REG_EESCAPE_IDX,
+    REG_ESUBREG_IDX,
+    REG_EBRACK_IDX,
+    REG_EPAREN_IDX,
+    REG_EBRACE_IDX,
+    REG_BADBR_IDX,
+    REG_ERANGE_IDX,
+    REG_ESPACE_IDX,
+    REG_BADRPT_IDX,
+    REG_EEND_IDX,
+    REG_ESIZE_IDX,
+    REG_ERPAREN_IDX
+  };
+
+/* Entry points for GNU code.  */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+   compiles PATTERN (of length LENGTH) and puts the result in BUFP.
+   Returns 0 if the pattern was valid, otherwise an error string.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+   are set in BUFP on entry.  */
+
+const char *
+re_compile_pattern (const char *pattern,
+		size_t length,
+		struct re_pattern_buffer *bufp)
+{
+  reg_errcode_t ret;
+
+  /* And GNU code determines whether or not to get register information
+     by passing null for the REGS argument to re_match, etc., not by
+     setting no_sub, unless RE_NO_SUB is set.  */
+  bufp->no_sub = !!(re_syntax_options & RE_NO_SUB);
+
+  /* Match anchors at newline.  */
+  bufp->newline_anchor = 1;
+
+  ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
+
+  if (!ret)
+    return NULL;
+  return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
+}
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
+   also be assigned to arbitrarily: each pattern buffer stores its own
+   syntax, so it can be changed between regex compilations.  */
+/* This has no initializer because initialized variables in Emacs
+   become read-only after dumping.  */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation.  This provides
+   for compatibility for various utilities which historically have
+   different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit mask comprised of the various bits
+   defined in regex.h.  We return the old syntax.  */
+
+reg_syntax_t
+re_set_syntax (reg_syntax_t syntax)
+{
+  reg_syntax_t ret = re_syntax_options;
+
+  re_syntax_options = syntax;
+  return ret;
+}
+
+int
+re_compile_fastmap (struct re_pattern_buffer *bufp)
+{
+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+  char *fastmap = bufp->fastmap;
+
+  memset (fastmap, '\0', sizeof (char) * SBC_MAX);
+  re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
+  if (dfa->init_state != dfa->init_state_word)
+    re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
+  if (dfa->init_state != dfa->init_state_nl)
+    re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
+  if (dfa->init_state != dfa->init_state_begbuf)
+    re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
+  bufp->fastmap_accurate = 1;
+  return 0;
+}
+libc_hidden_def(re_compile_fastmap)
+
+static __inline__ void
+__attribute ((always_inline))
+re_set_fastmap (char *fastmap, int icase, int ch)
+{
+  fastmap[ch] = 1;
+  if (icase)
+    fastmap[tolower (ch)] = 1;
+}
+
+/* Helper function for re_compile_fastmap.
+   Compile fastmap for the initial_state INIT_STATE.  */
+
+static void
+re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
+			 char *fastmap)
+{
+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+  int node_cnt;
+  int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
+  for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
+    {
+      int node = init_state->nodes.elems[node_cnt];
+      re_token_type_t type = dfa->nodes[node].type;
+
+      if (type == CHARACTER)
+	{
+	  re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
+#ifdef RE_ENABLE_I18N
+	  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+	    {
+	      unsigned char *buf = alloca (dfa->mb_cur_max), *p;
+	      wchar_t wc;
+	      mbstate_t state;
+
+	      p = buf;
+	      *p++ = dfa->nodes[node].opr.c;
+	      while (++node < dfa->nodes_len
+		     &&	dfa->nodes[node].type == CHARACTER
+		     && dfa->nodes[node].mb_partial)
+		*p++ = dfa->nodes[node].opr.c;
+	      memset (&state, '\0', sizeof (state));
+	      if (mbrtowc (&wc, (const char *) buf, p - buf,
+			   &state) == p - buf
+		  && (__wcrtomb ((char *) buf, towlower (wc), &state)
+		      != (size_t) -1))
+		re_set_fastmap (fastmap, 0, buf[0]);
+	    }
+#endif
+	}
+      else if (type == SIMPLE_BRACKET)
+	{
+	  int i, ch;
+	  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+	    {
+	      int j;
+	      bitset_word_t w = dfa->nodes[node].opr.sbcset[i];
+	      for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+		if (w & ((bitset_word_t) 1 << j))
+		  re_set_fastmap (fastmap, icase, ch);
+	    }
+	}
+#ifdef RE_ENABLE_I18N
+      else if (type == COMPLEX_BRACKET)
+	{
+	  int i;
+	  re_charset_t *cset = dfa->nodes[node].opr.mbcset;
+	  if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes
+	      || cset->nranges || cset->nchar_classes)
+	    {
+# if 0
+	      if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)
+		{
+		  /* In this case we want to catch the bytes which are
+		     the first byte of any collation elements.
+		     e.g. In da_DK, we want to catch 'a' since "aa"
+			  is a valid collation element, and don't catch
+			  'b' since 'b' is the only collation element
+			  which starts from 'b'.  */
+		  const int32_t *table = (const int32_t *)
+		    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+		  for (i = 0; i < SBC_MAX; ++i)
+		    if (table[i] < 0)
+		      re_set_fastmap (fastmap, icase, i);
+		}
+# else
+	      if (dfa->mb_cur_max > 1)
+		for (i = 0; i < SBC_MAX; ++i)
+		  if (__btowc (i) == WEOF)
+		    re_set_fastmap (fastmap, icase, i);
+# endif
+	    }
+	  for (i = 0; i < cset->nmbchars; ++i)
+	    {
+	      char buf[256];
+	      mbstate_t state;
+	      memset (&state, '\0', sizeof (state));
+	      if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
+		re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
+	      if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+		{
+		  if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
+		      != (size_t) -1)
+		    re_set_fastmap (fastmap, 0, *(unsigned char *) buf);
+		}
+	    }
+	}
+#endif /* RE_ENABLE_I18N */
+      else if (type == OP_PERIOD
+#ifdef RE_ENABLE_I18N
+	       || type == OP_UTF8_PERIOD
+#endif
+	       || type == END_OF_RE)
+	{
+	  memset (fastmap, '\1', sizeof (char) * SBC_MAX);
+	  if (type == END_OF_RE)
+	    bufp->can_be_null = 1;
+	  return;
+	}
+    }
+}
+
+/* Entry point for POSIX code.  */
+/* regcomp takes a regular expression as a string and compiles it.
+
+   PREG is a regex_t *.  We do not expect any fields to be initialized,
+   since POSIX says we shouldn't.  Thus, we set
+
+     `buffer' to the compiled pattern;
+     `used' to the length of the compiled pattern;
+     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+       REG_EXTENDED bit in CFLAGS is set; otherwise, to
+       RE_SYNTAX_POSIX_BASIC;
+     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+     `fastmap' to an allocated space for the fastmap;
+     `fastmap_accurate' to zero;
+     `re_nsub' to the number of subexpressions in PATTERN.
+
+   PATTERN is the address of the pattern string.
+
+   CFLAGS is a series of bits which affect compilation.
+
+     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+     use POSIX basic syntax.
+
+     If REG_NEWLINE is set, then . and [^...] don't match newline.
+     Also, regexec will try a match beginning after every newline.
+
+     If REG_ICASE is set, then we considers upper- and lowercase
+     versions of letters to be equivalent when matching.
+
+     If REG_NOSUB is set, then when PREG is passed to regexec, that
+     routine will report only success or failure, and nothing about the
+     registers.
+
+   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
+   the return codes and their meanings.)  */
+
+int
+regcomp (regex_t *__restrict preg,
+		const char *__restrict pattern,
+		int cflags)
+{
+  reg_errcode_t ret;
+  reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
+			 : RE_SYNTAX_POSIX_BASIC);
+
+  preg->buffer = NULL;
+  preg->allocated = 0;
+  preg->used = 0;
+
+  /* Try to allocate space for the fastmap.  */
+  preg->fastmap = re_malloc (char, SBC_MAX);
+  if (BE (preg->fastmap == NULL, 0))
+    return REG_ESPACE;
+
+  syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (cflags & REG_NEWLINE)
+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~RE_DOT_NEWLINE;
+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+      /* It also changes the matching behavior.  */
+      preg->newline_anchor = 1;
+    }
+  else
+    preg->newline_anchor = 0;
+  preg->no_sub = !!(cflags & REG_NOSUB);
+  preg->translate = NULL;
+
+  ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
+
+  /* POSIX doesn't distinguish between an unmatched open-group and an
+     unmatched close-group: both are REG_EPAREN.  */
+  if (ret == REG_ERPAREN)
+    ret = REG_EPAREN;
+
+  /* We have already checked preg->fastmap != NULL.  */
+  if (BE (ret == REG_NOERROR, 1))
+    /* Compute the fastmap now, since regexec cannot modify the pattern
+       buffer.  This function never fails in this implementation.  */
+    (void) re_compile_fastmap (preg);
+  else
+    {
+      /* Some error occurred while compiling the expression.  */
+      re_free (preg->fastmap);
+      preg->fastmap = NULL;
+    }
+
+  return (int) ret;
+}
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   We don't use PREG here.  */
+
+size_t
+regerror (int errcode,
+		const regex_t *__restrict preg,
+		char *__restrict errbuf,
+		size_t errbuf_size)
+{
+  const char *msg;
+  size_t msg_size;
+
+  if (BE (errcode < 0
+	  || errcode >= (int) (sizeof (__re_error_msgid_idx)
+			       / sizeof (__re_error_msgid_idx[0])), 0))
+    /* Only error codes returned by the rest of the code should be passed
+       to this routine.  If we are given anything else, or if other regex
+       code generates an invalid error code, then the program has a bug.
+       Dump core so we can fix it.  */
+    abort ();
+
+  msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
+
+  msg_size = strlen (msg) + 1; /* Includes the null.  */
+
+  if (BE (errbuf_size != 0, 1))
+    {
+      if (BE (msg_size > errbuf_size, 0))
+	{
+	  memcpy (errbuf, msg, errbuf_size - 1);
+	  errbuf[errbuf_size - 1] = 0;
+	}
+      else
+	memcpy (errbuf, msg, msg_size);
+    }
+
+  return msg_size;
+}
+
+
+#ifdef RE_ENABLE_I18N
+/* This static array is used for the map to single-byte characters when
+   UTF-8 is used.  Otherwise we would allocate memory just to initialize
+   it the same all the time.  UTF-8 is the preferred encoding so this is
+   a worthwhile optimization.  */
+static const bitset_t utf8_sb_map =
+{
+  /* Set the first 128 bits.  */
+  [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
+};
+#endif
+
+
+static void
+free_dfa_content (re_dfa_t *dfa)
+{
+  int i, j;
+
+  if (dfa->nodes)
+    for (i = 0; i < dfa->nodes_len; ++i)
+      free_token (dfa->nodes + i);
+  re_free (dfa->nexts);
+  for (i = 0; i < dfa->nodes_len; ++i)
+    {
+      if (dfa->eclosures != NULL)
+	re_node_set_free (dfa->eclosures + i);
+      if (dfa->inveclosures != NULL)
+	re_node_set_free (dfa->inveclosures + i);
+      if (dfa->edests != NULL)
+	re_node_set_free (dfa->edests + i);
+    }
+  re_free (dfa->edests);
+  re_free (dfa->eclosures);
+  re_free (dfa->inveclosures);
+  re_free (dfa->nodes);
+
+  if (dfa->state_table)
+    for (i = 0; i <= dfa->state_hash_mask; ++i)
+      {
+	struct re_state_table_entry *entry = dfa->state_table + i;
+	for (j = 0; j < entry->num; ++j)
+	  {
+	    re_dfastate_t *state = entry->array[j];
+	    free_state (state);
+	  }
+        re_free (entry->array);
+      }
+  re_free (dfa->state_table);
+#ifdef RE_ENABLE_I18N
+  if (dfa->sb_char != utf8_sb_map)
+    re_free (dfa->sb_char);
+#endif
+  re_free (dfa->subexp_map);
+#ifdef DEBUG
+  re_free (dfa->re_str);
+#endif
+
+  re_free (dfa);
+}
+
+
+/* Free dynamically allocated space used by PREG.  */
+
+void
+regfree (regex_t *preg)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  if (BE (dfa != NULL, 1))
+    free_dfa_content (dfa);
+  preg->buffer = NULL;
+  preg->allocated = 0;
+
+  re_free (preg->fastmap);
+  preg->fastmap = NULL;
+
+  re_free (preg->translate);
+  preg->translate = NULL;
+}
+libc_hidden_def(regfree)
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#if defined _REGEX_RE_COMP || defined __UCLIBC__
+
+/* BSD has one and only one pattern buffer.  */
+static struct re_pattern_buffer *re_comp_buf;
+
+char *
+/* Make BCD definitions weak in libc, so POSIX programs can redefine
+   these names if they don't use our functions, and still use
+   regcomp/regexec above without link errors.  */
+weak_function
+re_comp (const char *s)
+{
+  reg_errcode_t ret;
+
+  /* "If re_comp() is passed NULL or a null string, it returns
+   * without changing the currently compiled regular expression." */
+  if (!s || !s[0])
+    {
+      if (!re_comp_buf)
+	return gettext ("No previous regular expression");
+      return NULL;
+    }
+
+  if (!re_comp_buf)
+    {
+      re_comp_buf = calloc (1, sizeof(*re_comp_buf));
+      if (!re_comp_buf)
+	{
+	  ret = REG_ESPACE;
+	  goto err;
+	}
+    }
+
+  if (re_comp_buf->buffer)
+    {
+      regfree (re_comp_buf);
+      memset (re_comp_buf, '\0', sizeof(*re_comp_buf));
+    }
+
+  if (re_comp_buf->fastmap == NULL)
+    {
+      re_comp_buf->fastmap = malloc (SBC_MAX);
+      if (re_comp_buf->fastmap == NULL)
+	{
+	  ret = REG_ESPACE;
+	  goto err;
+	}
+    }
+
+  /* Since `re_exec' always passes NULL for the `regs' argument, we
+     don't need to initialize the pattern buffer fields which affect it.  */
+
+  /* Match anchors at newlines.  */
+  re_comp_buf->newline_anchor = 1;
+
+  ret = re_compile_internal (re_comp_buf, s, strlen (s), re_syntax_options);
+
+  if (!ret)
+    return NULL;
+  free (re_comp_buf);
+  re_comp_buf = NULL;
+
+ err:
+  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
+  return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
+}
+
+#if 0
+libc_freeres_fn (free_mem)
+{
+  regfree (re_comp_buf);
+  free (re_comp_buf);
+  re_comp_buf = NULL;
+}
+#endif
+
+#endif /* _REGEX_RE_COMP */
+
+/* Internal entry point.
+   Compile the regular expression PATTERN, whose length is LENGTH.
+   SYNTAX indicate regular expression's syntax.  */
+
+static reg_errcode_t
+re_compile_internal (regex_t *preg, const char * pattern, size_t length,
+		     reg_syntax_t syntax)
+{
+  reg_errcode_t err = REG_NOERROR;
+  re_dfa_t *dfa;
+  re_string_t regexp;
+
+  /* Initialize the pattern buffer.  */
+  preg->fastmap_accurate = 0;
+  preg->syntax = syntax;
+  preg->not_bol = preg->not_eol = 0;
+  preg->used = 0;
+  preg->re_nsub = 0;
+  preg->can_be_null = 0;
+  preg->regs_allocated = REGS_UNALLOCATED;
+
+  /* Initialize the dfa.  */
+  dfa = (re_dfa_t *) preg->buffer;
+  if (BE (preg->allocated < sizeof (re_dfa_t), 0))
+    {
+      /* If zero allocated, but buffer is non-null, try to realloc
+	 enough space.  This loses if buffer's address is bogus, but
+	 that is the user's responsibility.  If ->buffer is NULL this
+	 is a simple allocation.  */
+      dfa = re_realloc (preg->buffer, re_dfa_t, 1);
+      if (dfa == NULL)
+	return REG_ESPACE;
+      preg->allocated = sizeof (re_dfa_t);
+      preg->buffer = (unsigned char *) dfa;
+    }
+  preg->used = sizeof (re_dfa_t);
+
+  err = init_dfa (dfa, length);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_dfa_content (dfa);
+      preg->buffer = NULL;
+      preg->allocated = 0;
+      return err;
+    }
+#ifdef DEBUG
+  /* Note: length+1 will not overflow since it is checked in init_dfa.  */
+  dfa->re_str = re_malloc (char, length + 1);
+  strncpy (dfa->re_str, pattern, length + 1);
+#endif
+
+  __libc_lock_init (dfa->lock);
+
+  err = re_string_construct (&regexp, pattern, length, preg->translate,
+			     syntax & RE_ICASE, dfa);
+  if (BE (err != REG_NOERROR, 0))
+    {
+    re_compile_internal_free_return:
+      free_workarea_compile (preg);
+      re_string_destruct (&regexp);
+      free_dfa_content (dfa);
+      preg->buffer = NULL;
+      preg->allocated = 0;
+      return err;
+    }
+
+  /* Parse the regular expression, and build a structure tree.  */
+  preg->re_nsub = 0;
+  dfa->str_tree = parse (&regexp, preg, syntax, &err);
+  if (BE (dfa->str_tree == NULL, 0))
+    goto re_compile_internal_free_return;
+
+  /* Analyze the tree and create the nfa.  */
+  err = analyze (preg);
+  if (BE (err != REG_NOERROR, 0))
+    goto re_compile_internal_free_return;
+
+#ifdef RE_ENABLE_I18N
+  /* If possible, do searching in single byte encoding to speed things up.  */
+  if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
+    optimize_utf8 (dfa);
+#endif
+
+  /* Then create the initial state of the dfa.  */
+  err = create_initial_state (dfa);
+
+  /* Release work areas.  */
+  free_workarea_compile (preg);
+  re_string_destruct (&regexp);
+
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_dfa_content (dfa);
+      preg->buffer = NULL;
+      preg->allocated = 0;
+    }
+
+  return err;
+}
+
+/* Initialize DFA.  We use the length of the regular expression PAT_LEN
+   as the initial length of some arrays.  */
+
+static reg_errcode_t
+init_dfa (re_dfa_t *dfa, size_t pat_len)
+{
+  unsigned int table_size;
+#if 1
+  char *codeset_name;
+#endif
+
+  memset (dfa, '\0', sizeof (re_dfa_t));
+
+  /* Force allocation of str_tree_storage the first time.  */
+  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
+
+  /* Avoid overflows.  */
+  if (pat_len == SIZE_MAX)
+    return REG_ESPACE;
+
+  dfa->nodes_alloc = pat_len + 1;
+  dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
+
+  /*  table_size = 2 ^ ceil(log pat_len) */
+  for (table_size = 1; ; table_size <<= 1)
+    if (table_size > pat_len)
+      break;
+
+  dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
+  dfa->state_hash_mask = table_size - 1;
+
+  dfa->mb_cur_max = MB_CUR_MAX;
+#if 0
+  if (dfa->mb_cur_max == 6
+      && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
+    dfa->is_utf8 = 1;
+  dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
+		       != 0);
+#else
+# ifdef HAVE_LANGINFO_CODESET
+  codeset_name = nl_langinfo (CODESET);
+# else
+  codeset_name = getenv ("LC_ALL");
+  if (codeset_name == NULL || codeset_name[0] == '\0')
+    codeset_name = getenv ("LC_CTYPE");
+  if (codeset_name == NULL || codeset_name[0] == '\0')
+    codeset_name = getenv ("LANG");
+  if (codeset_name == NULL)
+    codeset_name = "";
+  else if (strchr (codeset_name, '.') !=  NULL)
+    codeset_name = strchr (codeset_name, '.') + 1;
+# endif
+
+  if (strcasecmp (codeset_name, "UTF-8") == 0
+      || strcasecmp (codeset_name, "UTF8") == 0)
+    dfa->is_utf8 = 1;
+
+  /* We check exhaustively in the loop below if this charset is a
+     superset of ASCII.  */
+  dfa->map_notascii = 0;
+#endif
+
+#ifdef RE_ENABLE_I18N
+  if (dfa->mb_cur_max > 1)
+    {
+      if (dfa->is_utf8)
+	dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
+      else
+	{
+	  int i, j, ch;
+
+	  dfa->sb_char = calloc (sizeof (bitset_t), 1);
+	  if (BE (dfa->sb_char == NULL, 0))
+	    return REG_ESPACE;
+
+	  /* Set the bits corresponding to single byte chars.  */
+	  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+	    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+	      {
+		wint_t wch = __btowc (ch);
+		if (wch != WEOF)
+		  dfa->sb_char[i] |= (bitset_word_t) 1 << j;
+# if 1
+		if (isascii (ch) && wch != ch)
+		  dfa->map_notascii = 1;
+# endif
+	      }
+	}
+    }
+#endif
+
+  if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0))
+    return REG_ESPACE;
+  return REG_NOERROR;
+}
+
+/* Initialize WORD_CHAR table, which indicate which character is
+   "word".  In this case "word" means that it is the word construction
+   character used by some operators like "\<", "\>", etc.  */
+
+static void
+internal_function
+init_word_char (re_dfa_t *dfa)
+{
+  int i, j, ch;
+  dfa->word_ops_used = 1;
+  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+      if (isalnum (ch) || ch == '_')
+	dfa->word_char[i] |= (bitset_word_t) 1 << j;
+}
+
+/* Free the work area which are only used while compiling.  */
+
+static void
+free_workarea_compile (regex_t *preg)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_storage_t *storage, *next;
+  for (storage = dfa->str_tree_storage; storage; storage = next)
+    {
+      next = storage->next;
+      re_free (storage);
+    }
+  dfa->str_tree_storage = NULL;
+  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
+  dfa->str_tree = NULL;
+  re_free (dfa->org_indices);
+  dfa->org_indices = NULL;
+}
+
+/* Create initial states for all contexts.  */
+
+static reg_errcode_t
+create_initial_state (re_dfa_t *dfa)
+{
+  int first, i;
+  reg_errcode_t err;
+  re_node_set init_nodes;
+
+  /* Initial states have the epsilon closure of the node which is
+     the first node of the regular expression.  */
+  first = dfa->str_tree->first->node_idx;
+  dfa->init_node = first;
+  err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+
+  /* The back-references which are in initial states can epsilon transit,
+     since in this case all of the subexpressions can be null.
+     Then we add epsilon closures of the nodes which are the next nodes of
+     the back-references.  */
+  if (dfa->nbackref > 0)
+    for (i = 0; i < init_nodes.nelem; ++i)
+      {
+	int node_idx = init_nodes.elems[i];
+	re_token_type_t type = dfa->nodes[node_idx].type;
+
+	int clexp_idx;
+	if (type != OP_BACK_REF)
+	  continue;
+	for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
+	  {
+	    re_token_t *clexp_node;
+	    clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
+	    if (clexp_node->type == OP_CLOSE_SUBEXP
+		&& clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)
+	      break;
+	  }
+	if (clexp_idx == init_nodes.nelem)
+	  continue;
+
+	if (type == OP_BACK_REF)
+	  {
+	    int dest_idx = dfa->edests[node_idx].elems[0];
+	    if (!re_node_set_contains (&init_nodes, dest_idx))
+	      {
+		re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
+		i = 0;
+	      }
+	  }
+      }
+
+  /* It must be the first time to invoke acquire_state.  */
+  dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
+  /* We don't check ERR here, since the initial state must not be NULL.  */
+  if (BE (dfa->init_state == NULL, 0))
+    return err;
+  if (dfa->init_state->has_constraint)
+    {
+      dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
+						       CONTEXT_WORD);
+      dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
+						     CONTEXT_NEWLINE);
+      dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
+							 &init_nodes,
+							 CONTEXT_NEWLINE
+							 | CONTEXT_BEGBUF);
+      if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL
+	      || dfa->init_state_begbuf == NULL, 0))
+	return err;
+    }
+  else
+    dfa->init_state_word = dfa->init_state_nl
+      = dfa->init_state_begbuf = dfa->init_state;
+
+  re_node_set_free (&init_nodes);
+  return REG_NOERROR;
+}
+
+#ifdef RE_ENABLE_I18N
+/* If it is possible to do searching in single byte encoding instead of UTF-8
+   to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
+   DFA nodes where needed.  */
+
+static void
+optimize_utf8 (re_dfa_t *dfa)
+{
+  int node, i, mb_chars = 0, has_period = 0;
+
+  for (node = 0; node < dfa->nodes_len; ++node)
+    switch (dfa->nodes[node].type)
+      {
+      case CHARACTER:
+	if (dfa->nodes[node].opr.c >= 0x80)
+	  mb_chars = 1;
+	break;
+      case ANCHOR:
+	switch (dfa->nodes[node].opr.idx)
+	  {
+	  case LINE_FIRST:
+	  case LINE_LAST:
+	  case BUF_FIRST:
+	  case BUF_LAST:
+	    break;
+	  default:
+	    /* Word anchors etc. cannot be handled.  */
+	    return;
+	  }
+	break;
+      case OP_PERIOD:
+        has_period = 1;
+        break;
+      case OP_BACK_REF:
+      case OP_ALT:
+      case END_OF_RE:
+      case OP_DUP_ASTERISK:
+      case OP_OPEN_SUBEXP:
+      case OP_CLOSE_SUBEXP:
+	break;
+      case COMPLEX_BRACKET:
+	return;
+      case SIMPLE_BRACKET:
+	/* Just double check.  The non-ASCII range starts at 0x80.  */
+	assert (0x80 % BITSET_WORD_BITS == 0);
+        for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
+	  if (dfa->nodes[node].opr.sbcset[i])
+	    return;
+	break;
+      default:
+	abort ();
+      }
+
+  if (mb_chars || has_period)
+    for (node = 0; node < dfa->nodes_len; ++node)
+      {
+	if (dfa->nodes[node].type == CHARACTER
+	    && dfa->nodes[node].opr.c >= 0x80)
+	  dfa->nodes[node].mb_partial = 0;
+	else if (dfa->nodes[node].type == OP_PERIOD)
+	  dfa->nodes[node].type = OP_UTF8_PERIOD;
+      }
+
+  /* The search can be in single byte locale.  */
+  dfa->mb_cur_max = 1;
+  dfa->is_utf8 = 0;
+  dfa->has_mb_node = dfa->nbackref > 0 || has_period;
+}
+#endif
+
+/* Analyze the structure tree, and calculate "first", "next", "edest",
+   "eclosure", and "inveclosure".  */
+
+static reg_errcode_t
+analyze (regex_t *preg)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  reg_errcode_t ret;
+
+  /* Allocate arrays.  */
+  dfa->nexts = re_malloc (int, dfa->nodes_alloc);
+  dfa->org_indices = re_malloc (int, dfa->nodes_alloc);
+  dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
+  dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
+  if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
+	  || dfa->eclosures == NULL, 0))
+    return REG_ESPACE;
+
+  dfa->subexp_map = re_malloc (int, preg->re_nsub);
+  if (dfa->subexp_map != NULL)
+    {
+      int i;
+      for (i = 0; i < preg->re_nsub; i++)
+	dfa->subexp_map[i] = i;
+      preorder (dfa->str_tree, optimize_subexps, dfa);
+      for (i = 0; i < preg->re_nsub; i++)
+	if (dfa->subexp_map[i] != i)
+	  break;
+      if (i == preg->re_nsub)
+	{
+	  free (dfa->subexp_map);
+	  dfa->subexp_map = NULL;
+	}
+    }
+
+  ret = postorder (dfa->str_tree, lower_subexps, preg);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  ret = postorder (dfa->str_tree, calc_first, dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  preorder (dfa->str_tree, calc_next, dfa);
+  ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  ret = calc_eclosure (dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+
+  /* We only need this during the prune_impossible_nodes pass in regexec.c;
+     skip it if p_i_n will not run, as calc_inveclosure can be quadratic.  */
+  if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
+      || dfa->nbackref)
+    {
+      dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
+      if (BE (dfa->inveclosures == NULL, 0))
+        return REG_ESPACE;
+      ret = calc_inveclosure (dfa);
+    }
+
+  return ret;
+}
+
+/* Our parse trees are very unbalanced, so we cannot use a stack to
+   implement parse tree visits.  Instead, we use parent pointers and
+   some hairy code in these two functions.  */
+static reg_errcode_t
+postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
+	   void *extra)
+{
+  bin_tree_t *node, *prev;
+
+  for (node = root; ; )
+    {
+      /* Descend down the tree, preferably to the left (or to the right
+	 if that's the only child).  */
+      while (node->left || node->right)
+	if (node->left)
+          node = node->left;
+        else
+          node = node->right;
+
+      do
+	{
+	  reg_errcode_t err = fn (extra, node);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+          if (node->parent == NULL)
+	    return REG_NOERROR;
+	  prev = node;
+	  node = node->parent;
+	}
+      /* Go up while we have a node that is reached from the right.  */
+      while (node->right == prev || node->right == NULL);
+      node = node->right;
+    }
+}
+
+static reg_errcode_t
+preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
+	  void *extra)
+{
+  bin_tree_t *node;
+
+  for (node = root; ; )
+    {
+      reg_errcode_t err = fn (extra, node);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+
+      /* Go to the left node, or up and to the right.  */
+      if (node->left)
+	node = node->left;
+      else
+	{
+	  bin_tree_t *prev = NULL;
+	  while (node->right == prev || node->right == NULL)
+	    {
+	      prev = node;
+	      node = node->parent;
+	      if (!node)
+	        return REG_NOERROR;
+	    }
+	  node = node->right;
+	}
+    }
+}
+
+/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
+   re_search_internal to map the inner one's opr.idx to this one's.  Adjust
+   backreferences as well.  Requires a preorder visit.  */
+static reg_errcode_t
+optimize_subexps (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+
+  if (node->token.type == OP_BACK_REF && dfa->subexp_map)
+    {
+      int idx = node->token.opr.idx;
+      node->token.opr.idx = dfa->subexp_map[idx];
+      dfa->used_bkref_map |= 1 << node->token.opr.idx;
+    }
+
+  else if (node->token.type == SUBEXP
+           && node->left && node->left->token.type == SUBEXP)
+    {
+      int other_idx = node->left->token.opr.idx;
+
+      node->left = node->left->left;
+      if (node->left)
+        node->left->parent = node;
+
+      dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
+      if (other_idx < BITSET_WORD_BITS)
+	  dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
+    }
+
+  return REG_NOERROR;
+}
+
+/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
+   of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP.  */
+static reg_errcode_t
+lower_subexps (void *extra, bin_tree_t *node)
+{
+  regex_t *preg = (regex_t *) extra;
+  reg_errcode_t err = REG_NOERROR;
+
+  if (node->left && node->left->token.type == SUBEXP)
+    {
+      node->left = lower_subexp (&err, preg, node->left);
+      if (node->left)
+	node->left->parent = node;
+    }
+  if (node->right && node->right->token.type == SUBEXP)
+    {
+      node->right = lower_subexp (&err, preg, node->right);
+      if (node->right)
+	node->right->parent = node;
+    }
+
+  return err;
+}
+
+static bin_tree_t *
+lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *body = node->left;
+  bin_tree_t *op, *cls, *tree1, *tree;
+
+  if (preg->no_sub
+      /* We do not optimize empty subexpressions, because otherwise we may
+	 have bad CONCAT nodes with NULL children.  This is obviously not
+	 very common, so we do not lose much.  An example that triggers
+	 this case is the sed "script" /\(\)/x.  */
+      && node->left != NULL
+      && (node->token.opr.idx >= BITSET_WORD_BITS
+	  || !(dfa->used_bkref_map
+	       & ((bitset_word_t) 1 << node->token.opr.idx))))
+    return node->left;
+
+  /* Convert the SUBEXP node to the concatenation of an
+     OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP.  */
+  op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
+  cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
+  tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
+  tree = create_tree (dfa, op, tree1, CONCAT);
+  if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
+  op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
+  return tree;
+}
+
+/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
+   nodes.  Requires a postorder visit.  */
+static reg_errcode_t
+calc_first (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+  if (node->token.type == CONCAT)
+    {
+      node->first = node->left->first;
+      node->node_idx = node->left->node_idx;
+    }
+  else
+    {
+      node->first = node;
+      node->node_idx = re_dfa_add_node (dfa, node->token);
+      if (BE (node->node_idx == -1, 0))
+        return REG_ESPACE;
+    }
+  return REG_NOERROR;
+}
+
+/* Pass 2: compute NEXT on the tree.  Preorder visit.  */
+static reg_errcode_t
+calc_next (void *extra, bin_tree_t *node)
+{
+  switch (node->token.type)
+    {
+    case OP_DUP_ASTERISK:
+      node->left->next = node;
+      break;
+    case CONCAT:
+      node->left->next = node->right->first;
+      node->right->next = node->next;
+      break;
+    default:
+      if (node->left)
+	node->left->next = node->next;
+      if (node->right)
+        node->right->next = node->next;
+      break;
+    }
+  return REG_NOERROR;
+}
+
+/* Pass 3: link all DFA nodes to their NEXT node (any order will do).  */
+static reg_errcode_t
+link_nfa_nodes (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+  int idx = node->node_idx;
+  reg_errcode_t err = REG_NOERROR;
+
+  switch (node->token.type)
+    {
+    case CONCAT:
+      break;
+
+    case END_OF_RE:
+      assert (node->next == NULL);
+      break;
+
+    case OP_DUP_ASTERISK:
+    case OP_ALT:
+      {
+	int left, right;
+	dfa->has_plural_match = 1;
+	if (node->left != NULL)
+	  left = node->left->first->node_idx;
+	else
+	  left = node->next->node_idx;
+	if (node->right != NULL)
+	  right = node->right->first->node_idx;
+	else
+	  right = node->next->node_idx;
+	assert (left > -1);
+	assert (right > -1);
+	err = re_node_set_init_2 (dfa->edests + idx, left, right);
+      }
+      break;
+
+    case ANCHOR:
+    case OP_OPEN_SUBEXP:
+    case OP_CLOSE_SUBEXP:
+      err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
+      break;
+
+    case OP_BACK_REF:
+      dfa->nexts[idx] = node->next->node_idx;
+      if (node->token.type == OP_BACK_REF)
+	re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
+      break;
+
+    default:
+      assert (!IS_EPSILON_NODE (node->token.type));
+      dfa->nexts[idx] = node->next->node_idx;
+      break;
+    }
+
+  return err;
+}
+
+/* Duplicate the epsilon closure of the node ROOT_NODE.
+   Note that duplicated nodes have constraint INIT_CONSTRAINT in addition
+   to their own constraint.  */
+
+static reg_errcode_t
+internal_function
+duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
+			int root_node, unsigned int init_constraint)
+{
+  int org_node, clone_node, ret;
+  unsigned int constraint = init_constraint;
+  for (org_node = top_org_node, clone_node = top_clone_node;;)
+    {
+      int org_dest, clone_dest;
+      if (dfa->nodes[org_node].type == OP_BACK_REF)
+	{
+	  /* If the back reference epsilon-transit, its destination must
+	     also have the constraint.  Then duplicate the epsilon closure
+	     of the destination of the back reference, and store it in
+	     edests of the back reference.  */
+	  org_dest = dfa->nexts[org_node];
+	  re_node_set_empty (dfa->edests + clone_node);
+	  clone_dest = duplicate_node (dfa, org_dest, constraint);
+	  if (BE (clone_dest == -1, 0))
+	    return REG_ESPACE;
+	  dfa->nexts[clone_node] = dfa->nexts[org_node];
+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	  if (BE (ret < 0, 0))
+	    return REG_ESPACE;
+	}
+      else if (dfa->edests[org_node].nelem == 0)
+	{
+	  /* In case of the node can't epsilon-transit, don't duplicate the
+	     destination and store the original destination as the
+	     destination of the node.  */
+	  dfa->nexts[clone_node] = dfa->nexts[org_node];
+	  break;
+	}
+      else if (dfa->edests[org_node].nelem == 1)
+	{
+	  /* In case of the node can epsilon-transit, and it has only one
+	     destination.  */
+	  org_dest = dfa->edests[org_node].elems[0];
+	  re_node_set_empty (dfa->edests + clone_node);
+	  if (dfa->nodes[org_node].type == ANCHOR)
+	    {
+	      /* In case of the node has another constraint, append it.  */
+	      if (org_node == root_node && clone_node != org_node)
+		{
+		  /* ...but if the node is root_node itself, it means the
+		     epsilon closure have a loop, then tie it to the
+		     destination of the root_node.  */
+		  ret = re_node_set_insert (dfa->edests + clone_node,
+					    org_dest);
+		  if (BE (ret < 0, 0))
+		    return REG_ESPACE;
+		  break;
+		}
+	      constraint |= dfa->nodes[org_node].opr.ctx_type;
+	    }
+	  clone_dest = duplicate_node (dfa, org_dest, constraint);
+	  if (BE (clone_dest == -1, 0))
+	    return REG_ESPACE;
+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	  if (BE (ret < 0, 0))
+	    return REG_ESPACE;
+	}
+      else /* dfa->edests[org_node].nelem == 2 */
+	{
+	  /* In case of the node can epsilon-transit, and it has two
+	     destinations. In the bin_tree_t and DFA, that's '|' and '*'.   */
+	  org_dest = dfa->edests[org_node].elems[0];
+	  re_node_set_empty (dfa->edests + clone_node);
+	  /* Search for a duplicated node which satisfies the constraint.  */
+	  clone_dest = search_duplicated_node (dfa, org_dest, constraint);
+	  if (clone_dest == -1)
+	    {
+	      /* There are no such a duplicated node, create a new one.  */
+	      reg_errcode_t err;
+	      clone_dest = duplicate_node (dfa, org_dest, constraint);
+	      if (BE (clone_dest == -1, 0))
+		return REG_ESPACE;
+	      ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	      if (BE (ret < 0, 0))
+		return REG_ESPACE;
+	      err = duplicate_node_closure (dfa, org_dest, clone_dest,
+					    root_node, constraint);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	    }
+	  else
+	    {
+	      /* There are a duplicated node which satisfy the constraint,
+		 use it to avoid infinite loop.  */
+	      ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	      if (BE (ret < 0, 0))
+		return REG_ESPACE;
+	    }
+
+	  org_dest = dfa->edests[org_node].elems[1];
+	  clone_dest = duplicate_node (dfa, org_dest, constraint);
+	  if (BE (clone_dest == -1, 0))
+	    return REG_ESPACE;
+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	  if (BE (ret < 0, 0))
+	    return REG_ESPACE;
+	}
+      org_node = org_dest;
+      clone_node = clone_dest;
+    }
+  return REG_NOERROR;
+}
+
+/* Search for a node which is duplicated from the node ORG_NODE, and
+   satisfies the constraint CONSTRAINT.  */
+
+static int
+search_duplicated_node (const re_dfa_t *dfa, int org_node,
+			unsigned int constraint)
+{
+  int idx;
+  for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
+    {
+      if (org_node == dfa->org_indices[idx]
+	  && constraint == dfa->nodes[idx].constraint)
+	return idx; /* Found.  */
+    }
+  return -1; /* Not found.  */
+}
+
+/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
+   Return the index of the new node, or -1 if insufficient storage is
+   available.  */
+
+static int
+duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint)
+{
+  int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
+  if (BE (dup_idx != -1, 1))
+    {
+      dfa->nodes[dup_idx].constraint = constraint;
+      if (dfa->nodes[org_idx].type == ANCHOR)
+	dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type;
+      dfa->nodes[dup_idx].duplicated = 1;
+
+      /* Store the index of the original node.  */
+      dfa->org_indices[dup_idx] = org_idx;
+    }
+  return dup_idx;
+}
+
+static reg_errcode_t
+calc_inveclosure (re_dfa_t *dfa)
+{
+  int src, idx, ret;
+  for (idx = 0; idx < dfa->nodes_len; ++idx)
+    re_node_set_init_empty (dfa->inveclosures + idx);
+
+  for (src = 0; src < dfa->nodes_len; ++src)
+    {
+      int *elems = dfa->eclosures[src].elems;
+      for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
+	{
+	  ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
+	  if (BE (ret == -1, 0))
+	    return REG_ESPACE;
+	}
+    }
+
+  return REG_NOERROR;
+}
+
+/* Calculate "eclosure" for all the node in DFA.  */
+
+static reg_errcode_t
+calc_eclosure (re_dfa_t *dfa)
+{
+  int node_idx, incomplete;
+#ifdef DEBUG
+  assert (dfa->nodes_len > 0);
+#endif
+  incomplete = 0;
+  /* For each nodes, calculate epsilon closure.  */
+  for (node_idx = 0; ; ++node_idx)
+    {
+      reg_errcode_t err;
+      re_node_set eclosure_elem;
+      if (node_idx == dfa->nodes_len)
+	{
+	  if (!incomplete)
+	    break;
+	  incomplete = 0;
+	  node_idx = 0;
+	}
+
+#ifdef DEBUG
+      assert (dfa->eclosures[node_idx].nelem != -1);
+#endif
+
+      /* If we have already calculated, skip it.  */
+      if (dfa->eclosures[node_idx].nelem != 0)
+	continue;
+      /* Calculate epsilon closure of `node_idx'.  */
+      err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+
+      if (dfa->eclosures[node_idx].nelem == 0)
+	{
+	  incomplete = 1;
+	  re_node_set_free (&eclosure_elem);
+	}
+    }
+  return REG_NOERROR;
+}
+
+/* Calculate epsilon closure of NODE.  */
+
+static reg_errcode_t
+calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
+{
+  reg_errcode_t err;
+  unsigned int constraint;
+  int i, incomplete;
+  re_node_set eclosure;
+  incomplete = 0;
+  err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+
+  /* This indicates that we are calculating this node now.
+     We reference this value to avoid infinite loop.  */
+  dfa->eclosures[node].nelem = -1;
+
+  constraint = ((dfa->nodes[node].type == ANCHOR)
+		? dfa->nodes[node].opr.ctx_type : 0);
+  /* If the current node has constraints, duplicate all nodes.
+     Since they must inherit the constraints.  */
+  if (constraint
+      && dfa->edests[node].nelem
+      && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
+    {
+      err = duplicate_node_closure (dfa, node, node, node, constraint);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+    }
+
+  /* Expand each epsilon destination nodes.  */
+  if (IS_EPSILON_NODE(dfa->nodes[node].type))
+    for (i = 0; i < dfa->edests[node].nelem; ++i)
+      {
+	re_node_set eclosure_elem;
+	int edest = dfa->edests[node].elems[i];
+	/* If calculating the epsilon closure of `edest' is in progress,
+	   return intermediate result.  */
+	if (dfa->eclosures[edest].nelem == -1)
+	  {
+	    incomplete = 1;
+	    continue;
+	  }
+	/* If we haven't calculated the epsilon closure of `edest' yet,
+	   calculate now. Otherwise use calculated epsilon closure.  */
+	if (dfa->eclosures[edest].nelem == 0)
+	  {
+	    err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0);
+	    if (BE (err != REG_NOERROR, 0))
+	      return err;
+	  }
+	else
+	  eclosure_elem = dfa->eclosures[edest];
+	/* Merge the epsilon closure of `edest'.  */
+	re_node_set_merge (&eclosure, &eclosure_elem);
+	/* If the epsilon closure of `edest' is incomplete,
+	   the epsilon closure of this node is also incomplete.  */
+	if (dfa->eclosures[edest].nelem == 0)
+	  {
+	    incomplete = 1;
+	    re_node_set_free (&eclosure_elem);
+	  }
+      }
+
+  /* Epsilon closures include itself.  */
+  re_node_set_insert (&eclosure, node);
+  if (incomplete && !root)
+    dfa->eclosures[node].nelem = 0;
+  else
+    dfa->eclosures[node] = eclosure;
+  *new_set = eclosure;
+  return REG_NOERROR;
+}
+
+/* Functions for token which are used in the parser.  */
+
+/* Fetch a token from INPUT.
+   We must not use this function inside bracket expressions.  */
+
+static void
+internal_function
+fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
+{
+  re_string_skip_bytes (input, peek_token (result, input, syntax));
+}
+
+/* Peek a token from INPUT, and return the length of the token.
+   We must not use this function inside bracket expressions.  */
+
+static int
+internal_function
+peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
+{
+  unsigned char c;
+
+  if (re_string_eoi (input))
+    {
+      token->type = END_OF_RE;
+      return 0;
+    }
+
+  c = re_string_peek_byte (input, 0);
+  token->opr.c = c;
+
+  token->word_char = 0;
+#ifdef RE_ENABLE_I18N
+  token->mb_partial = 0;
+  if (input->mb_cur_max > 1 &&
+      !re_string_first_byte (input, re_string_cur_idx (input)))
+    {
+      token->type = CHARACTER;
+      token->mb_partial = 1;
+      return 1;
+    }
+#endif
+  if (c == '\\')
+    {
+      unsigned char c2;
+      if (re_string_cur_idx (input) + 1 >= re_string_length (input))
+	{
+	  token->type = BACK_SLASH;
+	  return 1;
+	}
+
+      c2 = re_string_peek_byte_case (input, 1);
+      token->opr.c = c2;
+      token->type = CHARACTER;
+#ifdef RE_ENABLE_I18N
+      if (input->mb_cur_max > 1)
+	{
+	  wint_t wc = re_string_wchar_at (input,
+					  re_string_cur_idx (input) + 1);
+	  token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+	}
+      else
+#endif
+	token->word_char = IS_WORD_CHAR (c2) != 0;
+
+      switch (c2)
+	{
+	case '|':
+	  if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
+	    token->type = OP_ALT;
+	  break;
+	case '1': case '2': case '3': case '4': case '5':
+	case '6': case '7': case '8': case '9':
+	  if (!(syntax & RE_NO_BK_REFS))
+	    {
+	      token->type = OP_BACK_REF;
+	      token->opr.idx = c2 - '1';
+	    }
+	  break;
+	case '<':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = WORD_FIRST;
+	    }
+	  break;
+	case '>':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = WORD_LAST;
+	    }
+	  break;
+	case 'b':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = WORD_DELIM;
+	    }
+	  break;
+	case 'B':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = NOT_WORD_DELIM;
+	    }
+	  break;
+	case 'w':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    token->type = OP_WORD;
+	  break;
+	case 'W':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    token->type = OP_NOTWORD;
+	  break;
+	case 's':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    token->type = OP_SPACE;
+	  break;
+	case 'S':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    token->type = OP_NOTSPACE;
+	  break;
+	case '`':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = BUF_FIRST;
+	    }
+	  break;
+	case '\'':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = BUF_LAST;
+	    }
+	  break;
+	case '(':
+	  if (!(syntax & RE_NO_BK_PARENS))
+	    token->type = OP_OPEN_SUBEXP;
+	  break;
+	case ')':
+	  if (!(syntax & RE_NO_BK_PARENS))
+	    token->type = OP_CLOSE_SUBEXP;
+	  break;
+	case '+':
+	  if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
+	    token->type = OP_DUP_PLUS;
+	  break;
+	case '?':
+	  if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
+	    token->type = OP_DUP_QUESTION;
+	  break;
+	case '{':
+	  if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
+	    token->type = OP_OPEN_DUP_NUM;
+	  break;
+	case '}':
+	  if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
+	    token->type = OP_CLOSE_DUP_NUM;
+	  break;
+	default:
+	  break;
+	}
+      return 2;
+    }
+
+  token->type = CHARACTER;
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1)
+    {
+      wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
+      token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+    }
+  else
+#endif
+    token->word_char = IS_WORD_CHAR (token->opr.c);
+
+  switch (c)
+    {
+    case '\n':
+      if (syntax & RE_NEWLINE_ALT)
+	token->type = OP_ALT;
+      break;
+    case '|':
+      if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
+	token->type = OP_ALT;
+      break;
+    case '*':
+      token->type = OP_DUP_ASTERISK;
+      break;
+    case '+':
+      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
+	token->type = OP_DUP_PLUS;
+      break;
+    case '?':
+      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
+	token->type = OP_DUP_QUESTION;
+      break;
+    case '{':
+      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+	token->type = OP_OPEN_DUP_NUM;
+      break;
+    case '}':
+      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+	token->type = OP_CLOSE_DUP_NUM;
+      break;
+    case '(':
+      if (syntax & RE_NO_BK_PARENS)
+	token->type = OP_OPEN_SUBEXP;
+      break;
+    case ')':
+      if (syntax & RE_NO_BK_PARENS)
+	token->type = OP_CLOSE_SUBEXP;
+      break;
+    case '[':
+      token->type = OP_OPEN_BRACKET;
+      break;
+    case '.':
+      token->type = OP_PERIOD;
+      break;
+    case '^':
+      if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) &&
+	  re_string_cur_idx (input) != 0)
+	{
+	  char prev = re_string_peek_byte (input, -1);
+	  if (!(syntax & RE_NEWLINE_ALT) || prev != '\n')
+	    break;
+	}
+      token->type = ANCHOR;
+      token->opr.ctx_type = LINE_FIRST;
+      break;
+    case '$':
+      if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
+	  re_string_cur_idx (input) + 1 != re_string_length (input))
+	{
+	  re_token_t next;
+	  re_string_skip_bytes (input, 1);
+	  peek_token (&next, input, syntax);
+	  re_string_skip_bytes (input, -1);
+	  if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
+	    break;
+	}
+      token->type = ANCHOR;
+      token->opr.ctx_type = LINE_LAST;
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/* Peek a token from INPUT, and return the length of the token.
+   We must not use this function out of bracket expressions.  */
+
+static int
+internal_function
+peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
+{
+  unsigned char c;
+  if (re_string_eoi (input))
+    {
+      token->type = END_OF_RE;
+      return 0;
+    }
+  c = re_string_peek_byte (input, 0);
+  token->opr.c = c;
+
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1 &&
+      !re_string_first_byte (input, re_string_cur_idx (input)))
+    {
+      token->type = CHARACTER;
+      return 1;
+    }
+#endif
+
+  if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)
+      && re_string_cur_idx (input) + 1 < re_string_length (input))
+    {
+      /* In this case, '\' escape a character.  */
+      unsigned char c2;
+      re_string_skip_bytes (input, 1);
+      c2 = re_string_peek_byte (input, 0);
+      token->opr.c = c2;
+      token->type = CHARACTER;
+      return 1;
+    }
+  if (c == '[') /* '[' is a special char in a bracket exps.  */
+    {
+      unsigned char c2;
+      int token_len;
+      if (re_string_cur_idx (input) + 1 < re_string_length (input))
+	c2 = re_string_peek_byte (input, 1);
+      else
+	c2 = 0;
+      token->opr.c = c2;
+      token_len = 2;
+      switch (c2)
+	{
+	case '.':
+	  token->type = OP_OPEN_COLL_ELEM;
+	  break;
+	case '=':
+	  token->type = OP_OPEN_EQUIV_CLASS;
+	  break;
+	case ':':
+	  if (syntax & RE_CHAR_CLASSES)
+	    {
+	      token->type = OP_OPEN_CHAR_CLASS;
+	      break;
+	    }
+	  /* else fall through.  */
+	default:
+	  token->type = CHARACTER;
+	  token->opr.c = c;
+	  token_len = 1;
+	  break;
+	}
+      return token_len;
+    }
+  switch (c)
+    {
+    case '-':
+      token->type = OP_CHARSET_RANGE;
+      break;
+    case ']':
+      token->type = OP_CLOSE_BRACKET;
+      break;
+    case '^':
+      token->type = OP_NON_MATCH_LIST;
+      break;
+    default:
+      token->type = CHARACTER;
+    }
+  return 1;
+}
+
+/* Functions for parser.  */
+
+/* Entry point of the parser.
+   Parse the regular expression REGEXP and return the structure tree.
+   If an error is occured, ERR is set by error code, and return NULL.
+   This function build the following tree, from regular expression <reg_exp>:
+	   CAT
+	   / \
+	  /   \
+   <reg_exp>  EOR
+
+   CAT means concatenation.
+   EOR means end of regular expression.  */
+
+static bin_tree_t *
+parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
+       reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *tree, *eor, *root;
+  re_token_t current_token;
+  dfa->syntax = syntax;
+  fetch_token (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+  tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+  eor = create_tree (dfa, NULL, NULL, END_OF_RE);
+  if (tree != NULL)
+    root = create_tree (dfa, tree, eor, CONCAT);
+  else
+    root = eor;
+  if (BE (eor == NULL || root == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+  return root;
+}
+
+/* This function build the following tree, from regular expression
+   <branch1>|<branch2>:
+	   ALT
+	   / \
+	  /   \
+   <branch1> <branch2>
+
+   ALT means alternative, which represents the operator `|'.  */
+
+static bin_tree_t *
+parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
+	       reg_syntax_t syntax, int nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *tree, *branch = NULL;
+  tree = parse_branch (regexp, preg, token, syntax, nest, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+
+  while (token->type == OP_ALT)
+    {
+      fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+      if (token->type != OP_ALT && token->type != END_OF_RE
+	  && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
+	{
+	  branch = parse_branch (regexp, preg, token, syntax, nest, err);
+	  if (BE (*err != REG_NOERROR && branch == NULL, 0))
+	    return NULL;
+	}
+      else
+	branch = NULL;
+      tree = create_tree (dfa, tree, branch, OP_ALT);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+    }
+  return tree;
+}
+
+/* This function build the following tree, from regular expression
+   <exp1><exp2>:
+	CAT
+	/ \
+       /   \
+   <exp1> <exp2>
+
+   CAT means concatenation.  */
+
+static bin_tree_t *
+parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
+	      reg_syntax_t syntax, int nest, reg_errcode_t *err)
+{
+  bin_tree_t *tree, *exp;
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  tree = parse_expression (regexp, preg, token, syntax, nest, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+
+  while (token->type != OP_ALT && token->type != END_OF_RE
+	 && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
+    {
+      exp = parse_expression (regexp, preg, token, syntax, nest, err);
+      if (BE (*err != REG_NOERROR && exp == NULL, 0))
+	{
+	  return NULL;
+	}
+      if (tree != NULL && exp != NULL)
+	{
+	  tree = create_tree (dfa, tree, exp, CONCAT);
+	  if (tree == NULL)
+	    {
+	      *err = REG_ESPACE;
+	      return NULL;
+	    }
+	}
+      else if (tree == NULL)
+	tree = exp;
+      /* Otherwise exp == NULL, we don't need to create new tree.  */
+    }
+  return tree;
+}
+
+/* This function build the following tree, from regular expression a*:
+	 *
+	 |
+	 a
+*/
+
+static bin_tree_t *
+parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
+		  reg_syntax_t syntax, int nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *tree;
+  switch (token->type)
+    {
+    case CHARACTER:
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+	{
+	  while (!re_string_eoi (regexp)
+		 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
+	    {
+	      bin_tree_t *mbc_remain;
+	      fetch_token (token, regexp, syntax);
+	      mbc_remain = create_token_tree (dfa, NULL, NULL, token);
+	      tree = create_tree (dfa, tree, mbc_remain, CONCAT);
+	      if (BE (mbc_remain == NULL || tree == NULL, 0))
+		{
+		  *err = REG_ESPACE;
+		  return NULL;
+		}
+	    }
+	}
+#endif
+      break;
+    case OP_OPEN_SUBEXP:
+      tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      break;
+    case OP_OPEN_BRACKET:
+      tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      break;
+    case OP_BACK_REF:
+      if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1))
+	{
+	  *err = REG_ESUBREG;
+	  return NULL;
+	}
+      dfa->used_bkref_map |= 1 << token->opr.idx;
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+      ++dfa->nbackref;
+      dfa->has_mb_node = 1;
+      break;
+    case OP_OPEN_DUP_NUM:
+      if (syntax & RE_CONTEXT_INVALID_DUP)
+	{
+	  *err = REG_BADRPT;
+	  return NULL;
+	}
+      /* FALLTHROUGH */
+    case OP_DUP_ASTERISK:
+    case OP_DUP_PLUS:
+    case OP_DUP_QUESTION:
+      if (syntax & RE_CONTEXT_INVALID_OPS)
+	{
+	  *err = REG_BADRPT;
+	  return NULL;
+	}
+      else if (syntax & RE_CONTEXT_INDEP_OPS)
+	{
+	  fetch_token (token, regexp, syntax);
+	  return parse_expression (regexp, preg, token, syntax, nest, err);
+	}
+      /* else fall through  */
+    case OP_CLOSE_SUBEXP:
+      if ((token->type == OP_CLOSE_SUBEXP) &&
+	  !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
+	{
+	  *err = REG_ERPAREN;
+	  return NULL;
+	}
+      /* else fall through  */
+    case OP_CLOSE_DUP_NUM:
+      /* We treat it as a normal character.  */
+
+      /* Then we can these characters as normal characters.  */
+      token->type = CHARACTER;
+      /* mb_partial and word_char bits should be initialized already
+	 by peek_token.  */
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+      break;
+    case ANCHOR:
+      if ((token->opr.ctx_type
+	   & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
+	  && dfa->word_ops_used == 0)
+	init_word_char (dfa);
+      if (token->opr.ctx_type == WORD_DELIM
+          || token->opr.ctx_type == NOT_WORD_DELIM)
+	{
+	  bin_tree_t *tree_first, *tree_last;
+	  if (token->opr.ctx_type == WORD_DELIM)
+	    {
+	      token->opr.ctx_type = WORD_FIRST;
+	      tree_first = create_token_tree (dfa, NULL, NULL, token);
+	      token->opr.ctx_type = WORD_LAST;
+            }
+          else
+            {
+	      token->opr.ctx_type = INSIDE_WORD;
+	      tree_first = create_token_tree (dfa, NULL, NULL, token);
+	      token->opr.ctx_type = INSIDE_NOTWORD;
+            }
+	  tree_last = create_token_tree (dfa, NULL, NULL, token);
+	  tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
+	  if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0))
+	    {
+	      *err = REG_ESPACE;
+	      return NULL;
+	    }
+	}
+      else
+	{
+	  tree = create_token_tree (dfa, NULL, NULL, token);
+	  if (BE (tree == NULL, 0))
+	    {
+	      *err = REG_ESPACE;
+	      return NULL;
+	    }
+	}
+      /* We must return here, since ANCHORs can't be followed
+	 by repetition operators.
+	 eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
+	     it must not be "<ANCHOR(^)><REPEAT(*)>".  */
+      fetch_token (token, regexp, syntax);
+      return tree;
+    case OP_PERIOD:
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+      if (dfa->mb_cur_max > 1)
+	dfa->has_mb_node = 1;
+      break;
+    case OP_WORD:
+    case OP_NOTWORD:
+      tree = build_charclass_op (dfa, regexp->trans,
+				 (const unsigned char *) "alnum",
+				 (const unsigned char *) "_",
+				 token->type == OP_NOTWORD, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      break;
+    case OP_SPACE:
+    case OP_NOTSPACE:
+      tree = build_charclass_op (dfa, regexp->trans,
+				 (const unsigned char *) "space",
+				 (const unsigned char *) "",
+				 token->type == OP_NOTSPACE, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      break;
+    case OP_ALT:
+    case END_OF_RE:
+      return NULL;
+    case BACK_SLASH:
+      *err = REG_EESCAPE;
+      return NULL;
+    default:
+      /* Must not happen?  */
+#ifdef DEBUG
+      assert (0);
+#endif
+      return NULL;
+    }
+  fetch_token (token, regexp, syntax);
+
+  while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
+	 || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
+    {
+      tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      /* In BRE consecutive duplications are not allowed.  */
+      if ((syntax & RE_CONTEXT_INVALID_DUP)
+	  && (token->type == OP_DUP_ASTERISK
+	      || token->type == OP_OPEN_DUP_NUM))
+	{
+	  *err = REG_BADRPT;
+	  return NULL;
+	}
+    }
+
+  return tree;
+}
+
+/* This function build the following tree, from regular expression
+   (<reg_exp>):
+	 SUBEXP
+	    |
+	<reg_exp>
+*/
+
+static bin_tree_t *
+parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
+	       reg_syntax_t syntax, int nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *tree;
+  size_t cur_nsub;
+  cur_nsub = preg->re_nsub++;
+
+  fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+
+  /* The subexpression may be a null string.  */
+  if (token->type == OP_CLOSE_SUBEXP)
+    tree = NULL;
+  else
+    {
+      tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
+      if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))
+        *err = REG_EPAREN;
+      if (BE (*err != REG_NOERROR, 0))
+	return NULL;
+    }
+
+  if (cur_nsub <= '9' - '1')
+    dfa->completed_bkref_map |= 1 << cur_nsub;
+
+  tree = create_tree (dfa, tree, NULL, SUBEXP);
+  if (BE (tree == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+  tree->token.opr.idx = cur_nsub;
+  return tree;
+}
+
+/* This function parse repetition operators like "*", "+", "{1,3}" etc.  */
+
+static bin_tree_t *
+parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
+	      re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
+{
+  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;
+
+  if (token->type == OP_OPEN_DUP_NUM)
+    {
+      end = 0;
+      start = fetch_number (regexp, token, syntax);
+      if (start == -1)
+	{
+	  if (token->type == CHARACTER && token->opr.c == ',')
+	    start = 0; /* We treat "{,m}" as "{0,m}".  */
+	  else
+	    {
+	      *err = REG_BADBR; /* <re>{} is invalid.  */
+	      return NULL;
+	    }
+	}
+      if (BE (start != -2, 1))
+	{
+	  /* We treat "{n}" as "{n,n}".  */
+	  end = ((token->type == OP_CLOSE_DUP_NUM) ? start
+		 : ((token->type == CHARACTER && token->opr.c == ',')
+		    ? fetch_number (regexp, token, syntax) : -2));
+	}
+      if (BE (start == -2 || end == -2, 0))
+	{
+	  /* Invalid sequence.  */
+	  if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
+	    {
+	      if (token->type == END_OF_RE)
+		*err = REG_EBRACE;
+	      else
+		*err = REG_BADBR;
+
+	      return NULL;
+	    }
+
+	  /* If the syntax bit is set, rollback.  */
+	  re_string_set_index (regexp, start_idx);
+	  *token = start_token;
+	  token->type = CHARACTER;
+	  /* mb_partial and word_char bits should be already initialized by
+	     peek_token.  */
+	  return elem;
+	}
+
+      if (BE (end != -1 && start > end, 0))
+	{
+	  /* First number greater than second.  */
+	  *err = REG_BADBR;
+	  return NULL;
+	}
+    }
+  else
+    {
+      start = (token->type == OP_DUP_PLUS) ? 1 : 0;
+      end = (token->type == OP_DUP_QUESTION) ? 1 : -1;
+    }
+
+  fetch_token (token, regexp, syntax);
+
+  if (BE (elem == NULL, 0))
+    return NULL;
+  if (BE (start == 0 && end == 0, 0))
+    {
+      postorder (elem, free_tree, NULL);
+      return NULL;
+    }
+
+  /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}".  */
+  if (BE (start > 0, 0))
+    {
+      tree = elem;
+      for (i = 2; i <= start; ++i)
+	{
+	  elem = duplicate_tree (elem, dfa);
+	  tree = create_tree (dfa, tree, elem, CONCAT);
+	  if (BE (elem == NULL || tree == NULL, 0))
+	    goto parse_dup_op_espace;
+	}
+
+      if (start == end)
+	return tree;
+
+      /* Duplicate ELEM before it is marked optional.  */
+      elem = duplicate_tree (elem, dfa);
+      old_tree = tree;
+    }
+  else
+    old_tree = NULL;
+
+  if (elem->token.type == SUBEXP)
+    postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx);
+
+  tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
+  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);
+      if (BE (elem == NULL || tree == NULL, 0))
+        goto parse_dup_op_espace;
+
+      tree = create_tree (dfa, tree, NULL, OP_ALT);
+      if (BE (tree == NULL, 0))
+        goto parse_dup_op_espace;
+    }
+
+  if (old_tree)
+    tree = create_tree (dfa, old_tree, tree, CONCAT);
+
+  return tree;
+
+ parse_dup_op_espace:
+  *err = REG_ESPACE;
+  return NULL;
+}
+
+/* Size of the names for collating symbol/equivalence_class/character_class.
+   I'm not sure, but maybe enough.  */
+#define BRACKET_NAME_BUF_SIZE 32
+
+#if 1
+  /* Local function for parse_bracket_exp only used in case of NOT glibc.
+     Build the range expression which starts from START_ELEM, and ends
+     at END_ELEM.  The result are written to MBCSET and SBCSET.
+     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
+     mbcset->range_ends, is a pointer argument sinse we may
+     update it.  */
+
+static reg_errcode_t
+internal_function
+# ifdef RE_ENABLE_I18N
+build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,
+		 bracket_elem_t *start_elem, bracket_elem_t *end_elem)
+# else
+build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
+		 bracket_elem_t *end_elem)
+# endif
+{
+  unsigned int start_ch, end_ch;
+  /* Equivalence Classes and Character Classes can't be a range start/end.  */
+  if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
+	  || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
+	  0))
+    return REG_ERANGE;
+
+  /* We can handle no multi character collating elements without libc
+     support.  */
+  if (BE ((start_elem->type == COLL_SYM
+	   && strlen ((char *) start_elem->opr.name) > 1)
+	  || (end_elem->type == COLL_SYM
+	      && strlen ((char *) end_elem->opr.name) > 1), 0))
+    return REG_ECOLLATE;
+
+# ifdef RE_ENABLE_I18N
+  {
+    wchar_t wc;
+    wint_t start_wc;
+    wint_t end_wc;
+    wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
+
+    start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
+		: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
+		   : 0));
+    end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
+	      : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
+		 : 0));
+    start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
+		? __btowc (start_ch) : start_elem->opr.wch);
+    end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
+	      ? __btowc (end_ch) : end_elem->opr.wch);
+    if (start_wc == WEOF || end_wc == WEOF)
+      return REG_ECOLLATE;
+    cmp_buf[0] = start_wc;
+    cmp_buf[4] = end_wc;
+    if (wcscoll (cmp_buf, cmp_buf + 4) > 0)
+      return REG_ERANGE;
+
+    /* Got valid collation sequence values, add them as a new entry.
+       However, for !glibc we have no collation elements: if the
+       character set is single byte, the single byte character set
+       that we build below suffices.  parse_bracket_exp passes
+       no MBCSET if dfa->mb_cur_max == 1.  */
+    if (mbcset)
+      {
+        /* Check the space of the arrays.  */
+        if (BE (*range_alloc == mbcset->nranges, 0))
+          {
+	    /* There is not enough space, need realloc.  */
+	    wchar_t *new_array_start, *new_array_end;
+	    int new_nranges;
+
+	    /* +1 in case of mbcset->nranges is 0.  */
+	    new_nranges = 2 * mbcset->nranges + 1;
+	    /* Use realloc since mbcset->range_starts and mbcset->range_ends
+	       are NULL if *range_alloc == 0.  */
+	    new_array_start = re_realloc (mbcset->range_starts, wchar_t,
+				          new_nranges);
+	    new_array_end = re_realloc (mbcset->range_ends, wchar_t,
+				        new_nranges);
+
+	    if (BE (new_array_start == NULL || new_array_end == NULL, 0))
+	      return REG_ESPACE;
+
+	    mbcset->range_starts = new_array_start;
+	    mbcset->range_ends = new_array_end;
+	    *range_alloc = new_nranges;
+          }
+
+        mbcset->range_starts[mbcset->nranges] = start_wc;
+        mbcset->range_ends[mbcset->nranges++] = end_wc;
+      }
+
+    /* Build the table for single byte characters.  */
+    for (wc = 0; wc < SBC_MAX; ++wc)
+      {
+	cmp_buf[2] = wc;
+	if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
+	    && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
+	  bitset_set (sbcset, wc);
+      }
+  }
+# else /* not RE_ENABLE_I18N */
+  {
+    unsigned int ch;
+    start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
+		: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
+		   : 0));
+    end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
+	      : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
+		 : 0));
+    if (start_ch > end_ch)
+      return REG_ERANGE;
+    /* Build the table for single byte characters.  */
+    for (ch = 0; ch < SBC_MAX; ++ch)
+      if (start_ch <= ch  && ch <= end_ch)
+	bitset_set (sbcset, ch);
+  }
+# endif /* not RE_ENABLE_I18N */
+  return REG_NOERROR;
+}
+#endif
+
+#if 1
+/* Helper function for parse_bracket_exp only used in case of NOT glibc.
+   Build the collating element which is represented by NAME.
+   The result are written to MBCSET and SBCSET.
+   COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
+   pointer argument since we may update it.  */
+
+static reg_errcode_t
+internal_function
+# ifdef RE_ENABLE_I18N
+build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
+			int *coll_sym_alloc, const unsigned char *name)
+# else
+build_collating_symbol (bitset_t sbcset, const unsigned char *name)
+# endif
+{
+  size_t name_len = strlen ((const char *) name);
+  if (BE (name_len != 1, 0))
+    return REG_ECOLLATE;
+  bitset_set (sbcset, name[0]);
+  return REG_NOERROR;
+}
+#endif
+
+/* This function parse bracket expression like "[abc]", "[a-c]",
+   "[[.a-a.]]" etc.  */
+
+static bin_tree_t *
+parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
+		   reg_syntax_t syntax, reg_errcode_t *err)
+{
+#if 0
+  const unsigned char *collseqmb;
+  const char *collseqwc;
+  uint32_t nrules;
+  int32_t table_size;
+  const int32_t *symb_table;
+  const unsigned char *extra;
+
+  /* Local function for parse_bracket_exp used in glibc.
+     Seek the collating symbol entry correspondings to NAME.
+     Return the index of the symbol in the SYMB_TABLE.  */
+
+  auto __inline__ int32_t
+  __attribute ((always_inline))
+  seek_collating_symbol_entry (const unsigned char *name, size_t name_len)
+    {
+      int32_t hash = elem_hash ((const char *) name, name_len);
+      int32_t elem = hash % table_size;
+      if (symb_table[2 * elem] != 0)
+	{
+	  int32_t second = hash % (table_size - 2) + 1;
+
+	  do
+	    {
+	      /* First compare the hashing value.  */
+	      if (symb_table[2 * elem] == hash
+		  /* Compare the length of the name.  */
+		  && name_len == extra[symb_table[2 * elem + 1]]
+		  /* Compare the name.  */
+		  && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],
+			     name_len) == 0)
+		{
+		  /* Yep, this is the entry.  */
+		  break;
+		}
+
+	      /* Next entry.  */
+	      elem += second;
+	    }
+	  while (symb_table[2 * elem] != 0);
+	}
+      return elem;
+    }
+
+  /* Local function for parse_bracket_exp used in glibc.
+     Look up the collation sequence value of BR_ELEM.
+     Return the value if succeeded, UINT_MAX otherwise.  */
+
+  auto __inline__ unsigned int
+  __attribute ((always_inline))
+  lookup_collation_sequence_value (bracket_elem_t *br_elem)
+    {
+      if (br_elem->type == SB_CHAR)
+	{
+	  /*
+	  if (MB_CUR_MAX == 1)
+	  */
+	  if (nrules == 0)
+	    return collseqmb[br_elem->opr.ch];
+	  else
+	    {
+	      wint_t wc = __btowc (br_elem->opr.ch);
+	      return __collseq_table_lookup (collseqwc, wc);
+	    }
+	}
+      else if (br_elem->type == MB_CHAR)
+	{
+	  return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
+	}
+      else if (br_elem->type == COLL_SYM)
+	{
+	  size_t sym_name_len = strlen ((char *) br_elem->opr.name);
+	  if (nrules != 0)
+	    {
+	      int32_t elem, idx;
+	      elem = seek_collating_symbol_entry (br_elem->opr.name,
+						  sym_name_len);
+	      if (symb_table[2 * elem] != 0)
+		{
+		  /* We found the entry.  */
+		  idx = symb_table[2 * elem + 1];
+		  /* Skip the name of collating element name.  */
+		  idx += 1 + extra[idx];
+		  /* Skip the byte sequence of the collating element.  */
+		  idx += 1 + extra[idx];
+		  /* Adjust for the alignment.  */
+		  idx = (idx + 3) & ~3;
+		  /* Skip the multibyte collation sequence value.  */
+		  idx += sizeof (unsigned int);
+		  /* Skip the wide char sequence of the collating element.  */
+		  idx += sizeof (unsigned int) *
+		    (1 + *(unsigned int *) (extra + idx));
+		  /* Return the collation sequence value.  */
+		  return *(unsigned int *) (extra + idx);
+		}
+	      else if (symb_table[2 * elem] == 0 && sym_name_len == 1)
+		{
+		  /* No valid character.  Match it as a single byte
+		     character.  */
+		  return collseqmb[br_elem->opr.name[0]];
+		}
+	    }
+	  else if (sym_name_len == 1)
+	    return collseqmb[br_elem->opr.name[0]];
+	}
+      return UINT_MAX;
+    }
+
+  /* Local function for parse_bracket_exp used in glibc.
+     Build the range expression which starts from START_ELEM, and ends
+     at END_ELEM.  The result are written to MBCSET and SBCSET.
+     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
+     mbcset->range_ends, is a pointer argument sinse we may
+     update it.  */
+
+  auto __inline__ reg_errcode_t
+  __attribute ((always_inline))
+  build_range_exp (re_charset_t *mbcset,
+		int *range_alloc,
+		bitset_t sbcset,
+		bracket_elem_t *start_elem,
+		bracket_elem_t *end_elem)
+    {
+      unsigned int ch;
+      uint32_t start_collseq;
+      uint32_t end_collseq;
+
+      /* Equivalence Classes and Character Classes can't be a range
+	 start/end.  */
+      if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
+	      || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
+	      0))
+	return REG_ERANGE;
+
+      start_collseq = lookup_collation_sequence_value (start_elem);
+      end_collseq = lookup_collation_sequence_value (end_elem);
+      /* Check start/end collation sequence values.  */
+      if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))
+	return REG_ECOLLATE;
+      if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))
+	return REG_ERANGE;
+
+      /* Got valid collation sequence values, add them as a new entry.
+	 However, if we have no collation elements, and the character set
+	 is single byte, the single byte character set that we
+	 build below suffices. */
+      if (nrules > 0 || dfa->mb_cur_max > 1)
+	{
+          /* Check the space of the arrays.  */
+          if (BE (*range_alloc == mbcset->nranges, 0))
+	    {
+	      /* There is not enough space, need realloc.  */
+	      uint32_t *new_array_start;
+	      uint32_t *new_array_end;
+	      int new_nranges;
+
+	      /* +1 in case of mbcset->nranges is 0.  */
+	      new_nranges = 2 * mbcset->nranges + 1;
+	      new_array_start = re_realloc (mbcset->range_starts, uint32_t,
+					    new_nranges);
+	      new_array_end = re_realloc (mbcset->range_ends, uint32_t,
+				          new_nranges);
+
+	      if (BE (new_array_start == NULL || new_array_end == NULL, 0))
+	        return REG_ESPACE;
+
+	      mbcset->range_starts = new_array_start;
+	      mbcset->range_ends = new_array_end;
+	      *range_alloc = new_nranges;
+	    }
+
+          mbcset->range_starts[mbcset->nranges] = start_collseq;
+          mbcset->range_ends[mbcset->nranges++] = end_collseq;
+	}
+
+      /* Build the table for single byte characters.  */
+      for (ch = 0; ch < SBC_MAX; ch++)
+	{
+	  uint32_t ch_collseq;
+	  /*
+	  if (MB_CUR_MAX == 1)
+	  */
+	  if (nrules == 0)
+	    ch_collseq = collseqmb[ch];
+	  else
+	    ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
+	  if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
+	    bitset_set (sbcset, ch);
+	}
+      return REG_NOERROR;
+    }
+
+  /* Local function for parse_bracket_exp used in glibc.
+     Build the collating element which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
+     pointer argument sinse we may update it.  */
+
+  auto __inline__ reg_errcode_t
+  __attribute ((always_inline))
+  build_collating_symbol (re_charset_t *mbcset,
+		int *coll_sym_alloc,
+		bitset_t sbcset,
+		const unsigned char *name)
+    {
+      int32_t elem, idx;
+      size_t name_len = strlen ((const char *) name);
+      if (nrules != 0)
+	{
+	  elem = seek_collating_symbol_entry (name, name_len);
+	  if (symb_table[2 * elem] != 0)
+	    {
+	      /* We found the entry.  */
+	      idx = symb_table[2 * elem + 1];
+	      /* Skip the name of collating element name.  */
+	      idx += 1 + extra[idx];
+	    }
+	  else if (symb_table[2 * elem] == 0 && name_len == 1)
+	    {
+	      /* No valid character, treat it as a normal
+		 character.  */
+	      bitset_set (sbcset, name[0]);
+	      return REG_NOERROR;
+	    }
+	  else
+	    return REG_ECOLLATE;
+
+	  /* Got valid collation sequence, add it as a new entry.  */
+	  /* Check the space of the arrays.  */
+	  if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0))
+	    {
+	      /* Not enough, realloc it.  */
+	      /* +1 in case of mbcset->ncoll_syms is 0.  */
+	      int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
+	      /* Use realloc since mbcset->coll_syms is NULL
+		 if *alloc == 0.  */
+	      int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
+						   new_coll_sym_alloc);
+	      if (BE (new_coll_syms == NULL, 0))
+		return REG_ESPACE;
+	      mbcset->coll_syms = new_coll_syms;
+	      *coll_sym_alloc = new_coll_sym_alloc;
+	    }
+	  mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
+	  return REG_NOERROR;
+	}
+      else
+	{
+	  if (BE (name_len != 1, 0))
+	    return REG_ECOLLATE;
+	  else
+	    {
+	      bitset_set (sbcset, name[0]);
+	      return REG_NOERROR;
+	    }
+	}
+    }
+#endif
+
+  re_token_t br_token;
+  re_bitset_ptr_t sbcset;
+#ifdef RE_ENABLE_I18N
+  re_charset_t *mbcset;
+  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
+  int equiv_class_alloc = 0, char_class_alloc = 0;
+#endif
+  int non_match = 0;
+  bin_tree_t *work_tree;
+  int token_len;
+  int first_round = 1;
+#if 0
+  collseqmb = (const unsigned char *)
+    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules)
+    {
+      /*
+      if (MB_CUR_MAX > 1)
+      */
+      collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+      table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
+      symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+						  _NL_COLLATE_SYMB_TABLEMB);
+      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+						   _NL_COLLATE_SYMB_EXTRAMB);
+    }
+#endif
+  sbcset = calloc (sizeof (bitset_t), 1);
+#ifdef RE_ENABLE_I18N
+  mbcset = calloc (sizeof (re_charset_t), 1);
+#endif
+#ifdef RE_ENABLE_I18N
+  if (BE (sbcset == NULL || mbcset == NULL, 0))
+#else
+  if (BE (sbcset == NULL, 0))
+#endif
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  token_len = peek_token_bracket (token, regexp, syntax);
+  if (BE (token->type == END_OF_RE, 0))
+    {
+      *err = REG_BADPAT;
+      goto parse_bracket_exp_free_return;
+    }
+  if (token->type == OP_NON_MATCH_LIST)
+    {
+#ifdef RE_ENABLE_I18N
+      mbcset->non_match = 1;
+#endif
+      non_match = 1;
+      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
+	bitset_set (sbcset, '\0');
+      re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+      token_len = peek_token_bracket (token, regexp, syntax);
+      if (BE (token->type == END_OF_RE, 0))
+	{
+	  *err = REG_BADPAT;
+	  goto parse_bracket_exp_free_return;
+	}
+    }
+
+  /* We treat the first ']' as a normal character.  */
+  if (token->type == OP_CLOSE_BRACKET)
+    token->type = CHARACTER;
+
+  while (1)
+    {
+      bracket_elem_t start_elem, end_elem;
+      unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
+      unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
+      reg_errcode_t ret;
+      int token_len2 = 0, is_range_exp = 0;
+      re_token_t token2;
+
+      start_elem.opr.name = start_name_buf;
+      ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
+				   syntax, first_round);
+      if (BE (ret != REG_NOERROR, 0))
+	{
+	  *err = ret;
+	  goto parse_bracket_exp_free_return;
+	}
+      first_round = 0;
+
+      /* Get information about the next token.  We need it in any case.  */
+      token_len = peek_token_bracket (token, regexp, syntax);
+
+      /* Do not check for ranges if we know they are not allowed.  */
+      if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)
+	{
+	  if (BE (token->type == END_OF_RE, 0))
+	    {
+	      *err = REG_EBRACK;
+	      goto parse_bracket_exp_free_return;
+	    }
+	  if (token->type == OP_CHARSET_RANGE)
+	    {
+	      re_string_skip_bytes (regexp, token_len); /* Skip '-'.  */
+	      token_len2 = peek_token_bracket (&token2, regexp, syntax);
+	      if (BE (token2.type == END_OF_RE, 0))
+		{
+		  *err = REG_EBRACK;
+		  goto parse_bracket_exp_free_return;
+		}
+	      if (token2.type == OP_CLOSE_BRACKET)
+		{
+		  /* We treat the last '-' as a normal character.  */
+		  re_string_skip_bytes (regexp, -token_len);
+		  token->type = CHARACTER;
+		}
+	      else
+		is_range_exp = 1;
+	    }
+	}
+
+      if (is_range_exp == 1)
+	{
+	  end_elem.opr.name = end_name_buf;
+	  ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
+				       dfa, syntax, 1);
+	  if (BE (ret != REG_NOERROR, 0))
+	    {
+	      *err = ret;
+	      goto parse_bracket_exp_free_return;
+	    }
+
+	  token_len = peek_token_bracket (token, regexp, syntax);
+
+#if 0
+	  *err = build_range_exp (sbcset, mbcset, &range_alloc,
+				  &start_elem, &end_elem);
+#else
+# ifdef RE_ENABLE_I18N
+	  *err = build_range_exp (sbcset,
+				  dfa->mb_cur_max > 1 ? mbcset : NULL,
+				  &range_alloc, &start_elem, &end_elem);
+# else
+	  *err = build_range_exp (sbcset, &start_elem, &end_elem);
+# endif
+#endif
+	  if (BE (*err != REG_NOERROR, 0))
+	    goto parse_bracket_exp_free_return;
+	}
+      else
+	{
+	  switch (start_elem.type)
+	    {
+	    case SB_CHAR:
+	      bitset_set (sbcset, start_elem.opr.ch);
+	      break;
+#ifdef RE_ENABLE_I18N
+	    case MB_CHAR:
+	      /* Check whether the array has enough space.  */
+	      if (BE (mbchar_alloc == mbcset->nmbchars, 0))
+		{
+		  wchar_t *new_mbchars;
+		  /* Not enough, realloc it.  */
+		  /* +1 in case of mbcset->nmbchars is 0.  */
+		  mbchar_alloc = 2 * mbcset->nmbchars + 1;
+		  /* Use realloc since array is NULL if *alloc == 0.  */
+		  new_mbchars = re_realloc (mbcset->mbchars, wchar_t,
+					    mbchar_alloc);
+		  if (BE (new_mbchars == NULL, 0))
+		    goto parse_bracket_exp_espace;
+		  mbcset->mbchars = new_mbchars;
+		}
+	      mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
+	      break;
+#endif /* RE_ENABLE_I18N */
+	    case EQUIV_CLASS:
+	      *err = build_equiv_class (sbcset,
+#ifdef RE_ENABLE_I18N
+					mbcset, &equiv_class_alloc,
+#endif
+					start_elem.opr.name);
+	      if (BE (*err != REG_NOERROR, 0))
+		goto parse_bracket_exp_free_return;
+	      break;
+	    case COLL_SYM:
+	      *err = build_collating_symbol (sbcset,
+#ifdef RE_ENABLE_I18N
+					     mbcset, &coll_sym_alloc,
+#endif
+					     start_elem.opr.name);
+	      if (BE (*err != REG_NOERROR, 0))
+		goto parse_bracket_exp_free_return;
+	      break;
+	    case CHAR_CLASS:
+	      *err = build_charclass (regexp->trans, sbcset,
+#ifdef RE_ENABLE_I18N
+				      mbcset, &char_class_alloc,
+#endif
+				      start_elem.opr.name, syntax);
+	      if (BE (*err != REG_NOERROR, 0))
+	       goto parse_bracket_exp_free_return;
+	      break;
+	    default:
+	      assert (0);
+	      break;
+	    }
+	}
+      if (BE (token->type == END_OF_RE, 0))
+	{
+	  *err = REG_EBRACK;
+	  goto parse_bracket_exp_free_return;
+	}
+      if (token->type == OP_CLOSE_BRACKET)
+	break;
+    }
+
+  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+
+  /* If it is non-matching list.  */
+  if (non_match)
+    bitset_not (sbcset);
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure only single byte characters are set.  */
+  if (dfa->mb_cur_max > 1)
+    bitset_mask (sbcset, dfa->sb_char);
+
+  if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
+      || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
+						     || mbcset->non_match)))
+    {
+      bin_tree_t *mbc_tree;
+      int sbc_idx;
+      /* Build a tree for complex bracket.  */
+      dfa->has_mb_node = 1;
+      br_token.type = COMPLEX_BRACKET;
+      br_token.opr.mbcset = mbcset;
+      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (mbc_tree == NULL, 0))
+	goto parse_bracket_exp_espace;
+      for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)
+	if (sbcset[sbc_idx])
+	  break;
+      /* If there are no bits set in sbcset, there is no point
+	 of having both SIMPLE_BRACKET and COMPLEX_BRACKET.  */
+      if (sbc_idx < BITSET_WORDS)
+	{
+          /* Build a tree for simple bracket.  */
+          br_token.type = SIMPLE_BRACKET;
+          br_token.opr.sbcset = sbcset;
+          work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+          if (BE (work_tree == NULL, 0))
+            goto parse_bracket_exp_espace;
+
+          /* Then join them by ALT node.  */
+          work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
+          if (BE (work_tree == NULL, 0))
+            goto parse_bracket_exp_espace;
+	}
+      else
+	{
+	  re_free (sbcset);
+	  work_tree = mbc_tree;
+	}
+    }
+  else
+#endif /* not RE_ENABLE_I18N */
+    {
+#ifdef RE_ENABLE_I18N
+      free_charset (mbcset);
+#endif
+      /* Build a tree for simple bracket.  */
+      br_token.type = SIMPLE_BRACKET;
+      br_token.opr.sbcset = sbcset;
+      work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (work_tree == NULL, 0))
+        goto parse_bracket_exp_espace;
+    }
+  return work_tree;
+
+ parse_bracket_exp_espace:
+  *err = REG_ESPACE;
+ parse_bracket_exp_free_return:
+  re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+  free_charset (mbcset);
+#endif
+  return NULL;
+}
+
+/* Parse an element in the bracket expression.  */
+
+static reg_errcode_t
+parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
+		       re_token_t *token, int token_len, re_dfa_t *dfa,
+		       reg_syntax_t syntax, int accept_hyphen)
+{
+#ifdef RE_ENABLE_I18N
+  int cur_char_size;
+  cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
+  if (cur_char_size > 1)
+    {
+      elem->type = MB_CHAR;
+      elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
+      re_string_skip_bytes (regexp, cur_char_size);
+      return REG_NOERROR;
+    }
+#endif /* RE_ENABLE_I18N */
+  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+  if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
+      || token->type == OP_OPEN_EQUIV_CLASS)
+    return parse_bracket_symbol (elem, regexp, token);
+  if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen)
+    {
+      /* A '-' must only appear as anything but a range indicator before
+	 the closing bracket.  Everything else is an error.  */
+      re_token_t token2;
+      (void) peek_token_bracket (&token2, regexp, syntax);
+      if (token2.type != OP_CLOSE_BRACKET)
+	/* The actual error value is not standardized since this whole
+	   case is undefined.  But ERANGE makes good sense.  */
+	return REG_ERANGE;
+    }
+  elem->type = SB_CHAR;
+  elem->opr.ch = token->opr.c;
+  return REG_NOERROR;
+}
+
+/* Parse a bracket symbol in the bracket expression.  Bracket symbols are
+   such as [:<character_class>:], [.<collating_element>.], and
+   [=<equivalent_class>=].  */
+
+static reg_errcode_t
+parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
+		      re_token_t *token)
+{
+  unsigned char ch, delim = token->opr.c;
+  int i = 0;
+  if (re_string_eoi(regexp))
+    return REG_EBRACK;
+  for (;; ++i)
+    {
+      if (i >= BRACKET_NAME_BUF_SIZE)
+	return REG_EBRACK;
+      if (token->type == OP_OPEN_CHAR_CLASS)
+	ch = re_string_fetch_byte_case (regexp);
+      else
+	ch = re_string_fetch_byte (regexp);
+      if (re_string_eoi(regexp))
+	return REG_EBRACK;
+      if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
+	break;
+      elem->opr.name[i] = ch;
+    }
+  re_string_skip_bytes (regexp, 1);
+  elem->opr.name[i] = '\0';
+  switch (token->type)
+    {
+    case OP_OPEN_COLL_ELEM:
+      elem->type = COLL_SYM;
+      break;
+    case OP_OPEN_EQUIV_CLASS:
+      elem->type = EQUIV_CLASS;
+      break;
+    case OP_OPEN_CHAR_CLASS:
+      elem->type = CHAR_CLASS;
+      break;
+    default:
+      break;
+    }
+  return REG_NOERROR;
+}
+
+  /* Helper function for parse_bracket_exp.
+     Build the equivalence class which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
+     is a pointer argument sinse we may update it.  */
+
+static reg_errcode_t
+#ifdef RE_ENABLE_I18N
+build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
+		   int *equiv_class_alloc, const unsigned char *name)
+#else
+build_equiv_class (bitset_t sbcset, const unsigned char *name)
+#endif
+{
+#if 0
+  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules != 0)
+    {
+      const int32_t *table, *indirect;
+      const unsigned char *weights, *extra, *cp;
+      unsigned char char_buf[2];
+      int32_t idx1, idx2;
+      unsigned int ch;
+      size_t len;
+      /* This #include defines a local function!  */
+# include <locale/weight.h>
+      /* Calculate the index for equivalence class.  */
+      cp = name;
+      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+      weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_WEIGHTMB);
+      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+						   _NL_COLLATE_EXTRAMB);
+      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+						_NL_COLLATE_INDIRECTMB);
+      idx1 = findidx (&cp);
+      if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0))
+	/* This isn't a valid character.  */
+	return REG_ECOLLATE;
+
+      /* Build single byte matcing table for this equivalence class.  */
+      char_buf[1] = (unsigned char) '\0';
+      len = weights[idx1];
+      for (ch = 0; ch < SBC_MAX; ++ch)
+	{
+	  char_buf[0] = ch;
+	  cp = char_buf;
+	  idx2 = findidx (&cp);
+/*
+	  idx2 = table[ch];
+*/
+	  if (idx2 == 0)
+	    /* This isn't a valid character.  */
+	    continue;
+	  if (len == weights[idx2])
+	    {
+	      int cnt = 0;
+	      while (cnt <= len &&
+		     weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt])
+		++cnt;
+
+	      if (cnt > len)
+		bitset_set (sbcset, ch);
+	    }
+	}
+      /* Check whether the array has enough space.  */
+      if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))
+	{
+	  /* Not enough, realloc it.  */
+	  /* +1 in case of mbcset->nequiv_classes is 0.  */
+	  int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
+	  /* Use realloc since the array is NULL if *alloc == 0.  */
+	  int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
+						   int32_t,
+						   new_equiv_class_alloc);
+	  if (BE (new_equiv_classes == NULL, 0))
+	    return REG_ESPACE;
+	  mbcset->equiv_classes = new_equiv_classes;
+	  *equiv_class_alloc = new_equiv_class_alloc;
+	}
+      mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
+    }
+  else
+#endif
+    {
+      if (BE (strlen ((const char *) name) != 1, 0))
+	return REG_ECOLLATE;
+      bitset_set (sbcset, *name);
+    }
+  return REG_NOERROR;
+}
+
+  /* Helper function for parse_bracket_exp.
+     Build the character class which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
+     is a pointer argument sinse we may update it.  */
+
+static reg_errcode_t
+#ifdef RE_ENABLE_I18N
+build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
+		 re_charset_t *mbcset, int *char_class_alloc,
+		 const unsigned char *class_name, reg_syntax_t syntax)
+#else
+build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
+		 const unsigned char *class_name, reg_syntax_t syntax)
+#endif
+{
+  int i;
+  const char *name = (const char *) class_name;
+
+  /* In case of REG_ICASE "upper" and "lower" match the both of
+     upper and lower cases.  */
+  if ((syntax & RE_ICASE)
+      && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
+    name = "alpha";
+
+#ifdef RE_ENABLE_I18N
+  /* Check the space of the arrays.  */
+  if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
+    {
+      /* Not enough, realloc it.  */
+      /* +1 in case of mbcset->nchar_classes is 0.  */
+      int new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
+      /* Use realloc since array is NULL if *alloc == 0.  */
+      wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
+					       new_char_class_alloc);
+      if (BE (new_char_classes == NULL, 0))
+	return REG_ESPACE;
+      mbcset->char_classes = new_char_classes;
+      *char_class_alloc = new_char_class_alloc;
+    }
+  mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
+#endif /* RE_ENABLE_I18N */
+
+#define BUILD_CHARCLASS_LOOP(ctype_func)	\
+  do {						\
+    if (BE (trans != NULL, 0))			\
+      {						\
+	for (i = 0; i < SBC_MAX; ++i)		\
+  	  if (ctype_func (i))			\
+	    bitset_set (sbcset, trans[i]);	\
+      }						\
+    else					\
+      {						\
+	for (i = 0; i < SBC_MAX; ++i)		\
+  	  if (ctype_func (i))			\
+	    bitset_set (sbcset, i);		\
+      }						\
+  } while (0)
+
+  if (strcmp (name, "alnum") == 0)
+    BUILD_CHARCLASS_LOOP (isalnum);
+  else if (strcmp (name, "cntrl") == 0)
+    BUILD_CHARCLASS_LOOP (iscntrl);
+  else if (strcmp (name, "lower") == 0)
+    BUILD_CHARCLASS_LOOP (islower);
+  else if (strcmp (name, "space") == 0)
+    BUILD_CHARCLASS_LOOP (isspace);
+  else if (strcmp (name, "alpha") == 0)
+    BUILD_CHARCLASS_LOOP (isalpha);
+  else if (strcmp (name, "digit") == 0)
+    BUILD_CHARCLASS_LOOP (isdigit);
+  else if (strcmp (name, "print") == 0)
+    BUILD_CHARCLASS_LOOP (isprint);
+  else if (strcmp (name, "upper") == 0)
+    BUILD_CHARCLASS_LOOP (isupper);
+  else if (strcmp (name, "blank") == 0)
+    BUILD_CHARCLASS_LOOP (isblank);
+  else if (strcmp (name, "graph") == 0)
+    BUILD_CHARCLASS_LOOP (isgraph);
+  else if (strcmp (name, "punct") == 0)
+    BUILD_CHARCLASS_LOOP (ispunct);
+  else if (strcmp (name, "xdigit") == 0)
+    BUILD_CHARCLASS_LOOP (isxdigit);
+  else
+    return REG_ECTYPE;
+
+  return REG_NOERROR;
+}
+
+static bin_tree_t *
+build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
+		    const unsigned char *class_name,
+		    const unsigned char *extra, int non_match,
+		    reg_errcode_t *err)
+{
+  re_bitset_ptr_t sbcset;
+#ifdef RE_ENABLE_I18N
+  re_charset_t *mbcset;
+  int alloc = 0;
+#endif
+  reg_errcode_t ret;
+  re_token_t br_token;
+  bin_tree_t *tree;
+
+  sbcset = calloc (sizeof (bitset_t), 1);
+#ifdef RE_ENABLE_I18N
+  mbcset = calloc (sizeof (re_charset_t), 1);
+#endif
+
+#ifdef RE_ENABLE_I18N
+  if (BE (sbcset == NULL || mbcset == NULL, 0))
+#else
+  if (BE (sbcset == NULL, 0))
+#endif
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  if (non_match)
+    {
+#ifdef RE_ENABLE_I18N
+      /*
+      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
+	bitset_set(cset->sbcset, '\0');
+      */
+      mbcset->non_match = 1;
+#endif
+    }
+
+  /* We don't care the syntax in this case.  */
+  ret = build_charclass (trans, sbcset,
+#ifdef RE_ENABLE_I18N
+			 mbcset, &alloc,
+#endif
+			 class_name, 0);
+
+  if (BE (ret != REG_NOERROR, 0))
+    {
+      re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+      free_charset (mbcset);
+#endif
+      *err = ret;
+      return NULL;
+    }
+  /* \w match '_' also.  */
+  for (; *extra; extra++)
+    bitset_set (sbcset, *extra);
+
+  /* If it is non-matching list.  */
+  if (non_match)
+    bitset_not (sbcset);
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure only single byte characters are set.  */
+  if (dfa->mb_cur_max > 1)
+    bitset_mask (sbcset, dfa->sb_char);
+#endif
+
+  /* Build a tree for simple bracket.  */
+  br_token.type = SIMPLE_BRACKET;
+  br_token.opr.sbcset = sbcset;
+  tree = create_token_tree (dfa, NULL, NULL, &br_token);
+  if (BE (tree == NULL, 0))
+    goto build_word_op_espace;
+
+#ifdef RE_ENABLE_I18N
+  if (dfa->mb_cur_max > 1)
+    {
+      bin_tree_t *mbc_tree;
+      /* Build a tree for complex bracket.  */
+      br_token.type = COMPLEX_BRACKET;
+      br_token.opr.mbcset = mbcset;
+      dfa->has_mb_node = 1;
+      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (mbc_tree == NULL, 0))
+	goto build_word_op_espace;
+      /* Then join them by ALT node.  */
+      tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
+      if (BE (mbc_tree != NULL, 1))
+	return tree;
+    }
+  else
+    {
+      free_charset (mbcset);
+      return tree;
+    }
+#else /* not RE_ENABLE_I18N */
+  return tree;
+#endif
+
+ build_word_op_espace:
+  re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+  free_charset (mbcset);
+#endif
+  *err = REG_ESPACE;
+  return NULL;
+}
+
+/* This is intended for the expressions like "a{1,3}".
+   Fetch a number from `input', and return the number.
+   Return -1, if the number field is empty like "{,1}".
+   Return -2, If an error is occured.  */
+
+static int
+fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
+{
+  int num = -1;
+  unsigned char c;
+  while (1)
+    {
+      fetch_token (token, input, syntax);
+      c = token->opr.c;
+      if (BE (token->type == END_OF_RE, 0))
+	return -2;
+      if (token->type == OP_CLOSE_DUP_NUM || c == ',')
+	break;
+      num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
+	     ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));
+      num = (num > RE_DUP_MAX) ? -2 : num;
+    }
+  return num;
+}
+
+#ifdef RE_ENABLE_I18N
+static void
+free_charset (re_charset_t *cset)
+{
+  re_free (cset->mbchars);
+# if 0
+  re_free (cset->coll_syms);
+  re_free (cset->equiv_classes);
+  re_free (cset->range_starts);
+  re_free (cset->range_ends);
+# endif
+  re_free (cset->char_classes);
+  re_free (cset);
+}
+#endif /* RE_ENABLE_I18N */
+
+/* Functions for binary tree operation.  */
+
+/* Create a tree node.  */
+
+static bin_tree_t *
+create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
+	     re_token_type_t type)
+{
+  re_token_t t;
+  t.type = type;
+  return create_token_tree (dfa, left, right, &t);
+}
+
+static bin_tree_t *
+create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
+		   const re_token_t *token)
+{
+  bin_tree_t *tree;
+  if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0))
+    {
+      bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);
+
+      if (storage == NULL)
+	return NULL;
+      storage->next = dfa->str_tree_storage;
+      dfa->str_tree_storage = storage;
+      dfa->str_tree_storage_idx = 0;
+    }
+  tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];
+
+  tree->parent = NULL;
+  tree->left = left;
+  tree->right = right;
+  tree->token = *token;
+  tree->token.duplicated = 0;
+  tree->token.opt_subexp = 0;
+  tree->first = NULL;
+  tree->next = NULL;
+  tree->node_idx = -1;
+
+  if (left != NULL)
+    left->parent = tree;
+  if (right != NULL)
+    right->parent = tree;
+  return tree;
+}
+
+/* Mark the tree SRC as an optional subexpression.
+   To be called from preorder or postorder.  */
+
+static reg_errcode_t
+mark_opt_subexp (void *extra, bin_tree_t *node)
+{
+  int idx = (int) (long) extra;
+  if (node->token.type == SUBEXP && node->token.opr.idx == idx)
+    node->token.opt_subexp = 1;
+
+  return REG_NOERROR;
+}
+
+/* Free the allocated memory inside NODE. */
+
+static void
+free_token (re_token_t *node)
+{
+#ifdef RE_ENABLE_I18N
+  if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
+    free_charset (node->opr.mbcset);
+  else
+#endif
+    if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
+      re_free (node->opr.sbcset);
+}
+
+/* Worker function for tree walking.  Free the allocated memory inside NODE
+   and its children. */
+
+static reg_errcode_t
+free_tree (void *extra, bin_tree_t *node)
+{
+  free_token (&node->token);
+  return REG_NOERROR;
+}
+
+
+/* Duplicate the node SRC, and return new node.  This is a preorder
+   visit similar to the one implemented by the generic visitor, but
+   we need more infrastructure to maintain two parallel trees --- so,
+   it's easier to duplicate.  */
+
+static bin_tree_t *
+duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)
+{
+  const bin_tree_t *node;
+  bin_tree_t *dup_root;
+  bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
+
+  for (node = root; ; )
+    {
+      /* Create a new tree and link it back to the current parent.  */
+      *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
+      if (*p_new == NULL)
+	return NULL;
+      (*p_new)->parent = dup_node;
+      (*p_new)->token.duplicated = 1;
+      dup_node = *p_new;
+
+      /* Go to the left node, or up and to the right.  */
+      if (node->left)
+	{
+	  node = node->left;
+	  p_new = &dup_node->left;
+	}
+      else
+	{
+	  const bin_tree_t *prev = NULL;
+	  while (node->right == prev || node->right == NULL)
+	    {
+	      prev = node;
+	      node = node->parent;
+	      dup_node = dup_node->parent;
+	      if (!node)
+	        return dup_root;
+	    }
+	  node = node->right;
+	  p_new = &dup_node->right;
+	}
+    }
+}
diff --git a/ap/build/uClibc/libc/misc/regex/regex.c b/ap/build/uClibc/libc/misc/regex/regex.c
new file mode 100644
index 0000000..fa46f63
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/regex.c
@@ -0,0 +1,58 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <features.h>
+
+#ifdef __UCLIBC__
+# define _REGEX_RE_COMP
+# define HAVE_LANGINFO
+# define HAVE_LANGINFO_CODESET
+# include <stdbool.h>
+# include <stdint.h>
+# include <string.h>
+# include <stdlib.h>
+# ifdef __UCLIBC_HAS_WCHAR__
+#  define RE_ENABLE_I18N
+#  include <wchar.h>
+#  include <wctype.h>
+#  define __iswctype iswctype
+#  define __wcrtomb wcrtomb
+#  define __btowc btowc
+#  define __wctype wctype
+# endif
+# include <ctype.h>
+#endif
+
+/* Make sure noone compiles this code with a C++ compiler.  */
+#ifdef __cplusplus
+# error "This is C code, use a C compiler"
+#endif
+
+/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
+   GNU regex allows.  Include it before <regex.h>, which correctly
+   #undefs RE_DUP_MAX and sets it to the right value.  */
+#include <limits.h>
+
+#include <regex.h>
+
+#include "regex_internal.h"
+#include "regex_internal.c"
+#include "regcomp.c"
+#include "regexec.c"
diff --git a/ap/build/uClibc/libc/misc/regex/regex_internal.c b/ap/build/uClibc/libc/misc/regex/regex_internal.c
new file mode 100644
index 0000000..c6ac8dd
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/regex_internal.c
@@ -0,0 +1,1640 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+static void re_string_construct_common (const char *str, int len,
+					re_string_t *pstr,
+					RE_TRANSLATE_TYPE trans, int icase,
+					const re_dfa_t *dfa) internal_function;
+static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
+					  const re_node_set *nodes,
+					  unsigned int hash) internal_function;
+static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
+					  const re_node_set *nodes,
+					  unsigned int context,
+					  unsigned int hash) internal_function;
+
+/* Functions for string operation.  */
+
+/* This function allocate the buffers.  It is necessary to call
+   re_string_reconstruct before using the object.  */
+
+static reg_errcode_t
+internal_function
+re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
+		    RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
+{
+  reg_errcode_t ret;
+  int init_buf_len;
+
+  /* Ensure at least one character fits into the buffers.  */
+  if (init_len < dfa->mb_cur_max)
+    init_len = dfa->mb_cur_max;
+  init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
+  re_string_construct_common (str, len, pstr, trans, icase, dfa);
+
+  ret = re_string_realloc_buffers (pstr, init_buf_len);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+
+  pstr->word_char = dfa->word_char;
+  pstr->word_ops_used = dfa->word_ops_used;
+  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+  pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
+  pstr->valid_raw_len = pstr->valid_len;
+  return REG_NOERROR;
+}
+
+/* This function allocate the buffers, and initialize them.  */
+
+static reg_errcode_t
+internal_function
+re_string_construct (re_string_t *pstr, const char *str, int len,
+		     RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
+{
+  reg_errcode_t ret;
+  memset (pstr, '\0', sizeof (re_string_t));
+  re_string_construct_common (str, len, pstr, trans, icase, dfa);
+
+  if (len > 0)
+    {
+      ret = re_string_realloc_buffers (pstr, len + 1);
+      if (BE (ret != REG_NOERROR, 0))
+	return ret;
+    }
+  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+
+  if (icase)
+    {
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+	{
+	  while (1)
+	    {
+	      ret = build_wcs_upper_buffer (pstr);
+	      if (BE (ret != REG_NOERROR, 0))
+		return ret;
+	      if (pstr->valid_raw_len >= len)
+		break;
+	      if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
+		break;
+	      ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
+	      if (BE (ret != REG_NOERROR, 0))
+		return ret;
+	    }
+	}
+      else
+#endif /* RE_ENABLE_I18N  */
+	build_upper_buffer (pstr);
+    }
+  else
+    {
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+	build_wcs_buffer (pstr);
+      else
+#endif
+	{
+	  if (trans != NULL)
+	    re_string_translate_buffer (pstr);
+	  else
+	    {
+	      pstr->valid_len = pstr->bufs_len;
+	      pstr->valid_raw_len = pstr->bufs_len;
+	    }
+	}
+    }
+
+  return REG_NOERROR;
+}
+
+/* Helper functions for re_string_allocate, and re_string_construct.  */
+
+static reg_errcode_t
+internal_function
+re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
+{
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1)
+    {
+      wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
+      if (BE (new_wcs == NULL, 0))
+	return REG_ESPACE;
+      pstr->wcs = new_wcs;
+      if (pstr->offsets != NULL)
+	{
+	  int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len);
+	  if (BE (new_offsets == NULL, 0))
+	    return REG_ESPACE;
+	  pstr->offsets = new_offsets;
+	}
+    }
+#endif /* RE_ENABLE_I18N  */
+  if (pstr->mbs_allocated)
+    {
+      unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
+					   new_buf_len);
+      if (BE (new_mbs == NULL, 0))
+	return REG_ESPACE;
+      pstr->mbs = new_mbs;
+    }
+  pstr->bufs_len = new_buf_len;
+  return REG_NOERROR;
+}
+
+
+static void
+internal_function
+re_string_construct_common (const char *str, int len, re_string_t *pstr,
+			    RE_TRANSLATE_TYPE trans, int icase,
+			    const re_dfa_t *dfa)
+{
+  pstr->raw_mbs = (const unsigned char *) str;
+  pstr->len = len;
+  pstr->raw_len = len;
+  pstr->trans = trans;
+  pstr->icase = icase ? 1 : 0;
+  pstr->mbs_allocated = (trans != NULL || icase);
+  pstr->mb_cur_max = dfa->mb_cur_max;
+  pstr->is_utf8 = dfa->is_utf8;
+  pstr->map_notascii = dfa->map_notascii;
+  pstr->stop = pstr->len;
+  pstr->raw_stop = pstr->stop;
+}
+
+#ifdef RE_ENABLE_I18N
+
+/* Build wide character buffer PSTR->WCS.
+   If the byte sequence of the string are:
+     <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
+   Then wide character buffer will be:
+     <wc1>   , WEOF    , <wc2>   , WEOF    , <wc3>
+   We use WEOF for padding, they indicate that the position isn't
+   a first byte of a multibyte character.
+
+   Note that this function assumes PSTR->VALID_LEN elements are already
+   built and starts from PSTR->VALID_LEN.  */
+
+static void
+internal_function
+build_wcs_buffer (re_string_t *pstr)
+{
+#if defined __UCLIBC__
+  unsigned char buf[MB_LEN_MAX];
+  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+#else
+  unsigned char buf[64];
+#endif
+  mbstate_t prev_st;
+  int byte_idx, end_idx, remain_len;
+  size_t mbclen;
+
+  /* Build the buffers from pstr->valid_len to either pstr->len or
+     pstr->bufs_len.  */
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+  for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
+    {
+      wchar_t wc;
+      const char *p;
+
+      remain_len = end_idx - byte_idx;
+      prev_st = pstr->cur_state;
+      /* Apply the translation if we need.  */
+      if (BE (pstr->trans != NULL, 0))
+	{
+	  int i, ch;
+
+	  for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+	    {
+	      ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
+	      buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
+	    }
+	  p = (const char *) buf;
+	}
+      else
+	p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
+      mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
+      if (BE (mbclen == (size_t) -2, 0))
+	{
+	  /* The buffer doesn't have enough space, finish to build.  */
+	  pstr->cur_state = prev_st;
+	  break;
+	}
+      else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
+	{
+	  /* We treat these cases as a singlebyte character.  */
+	  mbclen = 1;
+	  wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
+	  if (BE (pstr->trans != NULL, 0))
+	    wc = pstr->trans[wc];
+	  pstr->cur_state = prev_st;
+	}
+
+      /* Write wide character and padding.  */
+      pstr->wcs[byte_idx++] = wc;
+      /* Write paddings.  */
+      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+	pstr->wcs[byte_idx++] = WEOF;
+    }
+  pstr->valid_len = byte_idx;
+  pstr->valid_raw_len = byte_idx;
+}
+
+/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
+   but for REG_ICASE.  */
+
+static reg_errcode_t
+internal_function
+build_wcs_upper_buffer (re_string_t *pstr)
+{
+  mbstate_t prev_st;
+  int src_idx, byte_idx, end_idx, remain_len;
+  size_t mbclen;
+#if defined __UCLIBC__
+  char buf[MB_LEN_MAX];
+  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+#else
+  char buf[64];
+#endif
+
+  byte_idx = pstr->valid_len;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  /* The following optimization assumes that ASCII characters can be
+     mapped to wide characters with a simple cast.  */
+  if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)
+    {
+      while (byte_idx < end_idx)
+	{
+	  wchar_t wc;
+
+	  if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
+	      && mbsinit (&pstr->cur_state))
+	    {
+	      /* In case of a singlebyte character.  */
+	      pstr->mbs[byte_idx]
+		= toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
+	      /* The next step uses the assumption that wchar_t is encoded
+		 ASCII-safe: all ASCII values can be converted like this.  */
+	      pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
+	      ++byte_idx;
+	      continue;
+	    }
+
+	  remain_len = end_idx - byte_idx;
+	  prev_st = pstr->cur_state;
+	  mbclen = mbrtowc (&wc,
+			    ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
+			     + byte_idx), remain_len, &pstr->cur_state);
+	  if (BE (mbclen + 2 > 2, 1))
+	    {
+	      wchar_t wcu = wc;
+	      if (iswlower (wc))
+		{
+		  size_t mbcdlen;
+
+		  wcu = towupper (wc);
+		  mbcdlen = wcrtomb (buf, wcu, &prev_st);
+		  if (BE (mbclen == mbcdlen, 1))
+		    memcpy (pstr->mbs + byte_idx, buf, mbclen);
+		  else
+		    {
+		      src_idx = byte_idx;
+		      goto offsets_needed;
+		    }
+		}
+	      else
+		memcpy (pstr->mbs + byte_idx,
+			pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
+	      pstr->wcs[byte_idx++] = wcu;
+	      /* Write paddings.  */
+	      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+		pstr->wcs[byte_idx++] = WEOF;
+	    }
+	  else if (mbclen == (size_t) -1 || mbclen == 0)
+	    {
+	      /* It is an invalid character or '\0'.  Just use the byte.  */
+	      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
+	      pstr->mbs[byte_idx] = ch;
+	      /* And also cast it to wide char.  */
+	      pstr->wcs[byte_idx++] = (wchar_t) ch;
+	      if (BE (mbclen == (size_t) -1, 0))
+		pstr->cur_state = prev_st;
+	    }
+	  else
+	    {
+	      /* The buffer doesn't have enough space, finish to build.  */
+	      pstr->cur_state = prev_st;
+	      break;
+	    }
+	}
+      pstr->valid_len = byte_idx;
+      pstr->valid_raw_len = byte_idx;
+      return REG_NOERROR;
+    }
+  else
+    for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)
+      {
+	wchar_t wc;
+	const char *p;
+      offsets_needed:
+	remain_len = end_idx - byte_idx;
+	prev_st = pstr->cur_state;
+	if (BE (pstr->trans != NULL, 0))
+	  {
+	    int i, ch;
+
+	    for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+	      {
+		ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
+		buf[i] = pstr->trans[ch];
+	      }
+	    p = (const char *) buf;
+	  }
+	else
+	  p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
+	mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
+	if (BE (mbclen + 2 > 2, 1))
+	  {
+	    wchar_t wcu = wc;
+	    if (iswlower (wc))
+	      {
+		size_t mbcdlen;
+
+		wcu = towupper (wc);
+		mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st);
+		if (BE (mbclen == mbcdlen, 1))
+		  memcpy (pstr->mbs + byte_idx, buf, mbclen);
+		else if (mbcdlen != (size_t) -1)
+		  {
+		    size_t i;
+
+		    if (byte_idx + mbcdlen > pstr->bufs_len)
+		      {
+			pstr->cur_state = prev_st;
+			break;
+		      }
+
+		    if (pstr->offsets == NULL)
+		      {
+			pstr->offsets = re_malloc (int, pstr->bufs_len);
+
+			if (pstr->offsets == NULL)
+			  return REG_ESPACE;
+		      }
+		    if (!pstr->offsets_needed)
+		      {
+			for (i = 0; i < (size_t) byte_idx; ++i)
+			  pstr->offsets[i] = i;
+			pstr->offsets_needed = 1;
+		      }
+
+		    memcpy (pstr->mbs + byte_idx, buf, mbcdlen);
+		    pstr->wcs[byte_idx] = wcu;
+		    pstr->offsets[byte_idx] = src_idx;
+		    for (i = 1; i < mbcdlen; ++i)
+		      {
+			pstr->offsets[byte_idx + i]
+			  = src_idx + (i < mbclen ? i : mbclen - 1);
+			pstr->wcs[byte_idx + i] = WEOF;
+		      }
+		    pstr->len += mbcdlen - mbclen;
+		    if (pstr->raw_stop > src_idx)
+		      pstr->stop += mbcdlen - mbclen;
+		    end_idx = (pstr->bufs_len > pstr->len)
+			      ? pstr->len : pstr->bufs_len;
+		    byte_idx += mbcdlen;
+		    src_idx += mbclen;
+		    continue;
+		  }
+                else
+                  memcpy (pstr->mbs + byte_idx, p, mbclen);
+	      }
+	    else
+	      memcpy (pstr->mbs + byte_idx, p, mbclen);
+
+	    if (BE (pstr->offsets_needed != 0, 0))
+	      {
+		size_t i;
+		for (i = 0; i < mbclen; ++i)
+		  pstr->offsets[byte_idx + i] = src_idx + i;
+	      }
+	    src_idx += mbclen;
+
+	    pstr->wcs[byte_idx++] = wcu;
+	    /* Write paddings.  */
+	    for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+	      pstr->wcs[byte_idx++] = WEOF;
+	  }
+	else if (mbclen == (size_t) -1 || mbclen == 0)
+	  {
+	    /* It is an invalid character or '\0'.  Just use the byte.  */
+	    int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
+
+	    if (BE (pstr->trans != NULL, 0))
+	      ch = pstr->trans [ch];
+	    pstr->mbs[byte_idx] = ch;
+
+	    if (BE (pstr->offsets_needed != 0, 0))
+	      pstr->offsets[byte_idx] = src_idx;
+	    ++src_idx;
+
+	    /* And also cast it to wide char.  */
+	    pstr->wcs[byte_idx++] = (wchar_t) ch;
+	    if (BE (mbclen == (size_t) -1, 0))
+	      pstr->cur_state = prev_st;
+	  }
+	else
+	  {
+	    /* The buffer doesn't have enough space, finish to build.  */
+	    pstr->cur_state = prev_st;
+	    break;
+	  }
+      }
+  pstr->valid_len = byte_idx;
+  pstr->valid_raw_len = src_idx;
+  return REG_NOERROR;
+}
+
+/* Skip characters until the index becomes greater than NEW_RAW_IDX.
+   Return the index.  */
+
+static int
+internal_function
+re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
+{
+  mbstate_t prev_st;
+  int rawbuf_idx;
+  size_t mbclen;
+  wchar_t wc = 0;
+
+  /* Skip the characters which are not necessary to check.  */
+  for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
+       rawbuf_idx < new_raw_idx;)
+    {
+      int remain_len;
+      remain_len = pstr->len - rawbuf_idx;
+      prev_st = pstr->cur_state;
+      mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx,
+			remain_len, &pstr->cur_state);
+      if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
+	{
+	  /* We treat these cases as a singlebyte character.  */
+	  mbclen = 1;
+	  pstr->cur_state = prev_st;
+	}
+      /* Then proceed the next character.  */
+      rawbuf_idx += mbclen;
+    }
+  *last_wc = (wint_t) wc;
+  return rawbuf_idx;
+}
+#endif /* RE_ENABLE_I18N  */
+
+/* Build the buffer PSTR->MBS, and apply the translation if we need.
+   This function is used in case of REG_ICASE.  */
+
+static void
+internal_function
+build_upper_buffer (re_string_t *pstr)
+{
+  int char_idx, end_idx;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
+    {
+      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
+      if (BE (pstr->trans != NULL, 0))
+	ch = pstr->trans[ch];
+      if (islower (ch))
+	pstr->mbs[char_idx] = toupper (ch);
+      else
+	pstr->mbs[char_idx] = ch;
+    }
+  pstr->valid_len = char_idx;
+  pstr->valid_raw_len = char_idx;
+}
+
+/* Apply TRANS to the buffer in PSTR.  */
+
+static void
+internal_function
+re_string_translate_buffer (re_string_t *pstr)
+{
+  int buf_idx, end_idx;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
+    {
+      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
+      pstr->mbs[buf_idx] = pstr->trans[ch];
+    }
+
+  pstr->valid_len = buf_idx;
+  pstr->valid_raw_len = buf_idx;
+}
+
+/* This function re-construct the buffers.
+   Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
+   convert to upper case in case of REG_ICASE, apply translation.  */
+
+static reg_errcode_t
+internal_function
+re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
+{
+  int offset = idx - pstr->raw_mbs_idx;
+  if (BE (offset < 0, 0))
+    {
+      /* Reset buffer.  */
+#ifdef RE_ENABLE_I18N
+      if (pstr->mb_cur_max > 1)
+	memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
+#endif
+      pstr->len = pstr->raw_len;
+      pstr->stop = pstr->raw_stop;
+      pstr->valid_len = 0;
+      pstr->raw_mbs_idx = 0;
+      pstr->valid_raw_len = 0;
+      pstr->offsets_needed = 0;
+      pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
+			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
+      if (!pstr->mbs_allocated)
+	pstr->mbs = (unsigned char *) pstr->raw_mbs;
+      offset = idx;
+    }
+
+  if (BE (offset != 0, 1))
+    {
+      /* Are the characters which are already checked remain?  */
+      if (BE (offset < pstr->valid_raw_len, 1)
+#ifdef RE_ENABLE_I18N
+	  /* Handling this would enlarge the code too much.
+	     Accept a slowdown in that case.  */
+	  && pstr->offsets_needed == 0
+#endif
+	 )
+	{
+	  /* Yes, move them to the front of the buffer.  */
+	  pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags);
+#ifdef RE_ENABLE_I18N
+	  if (pstr->mb_cur_max > 1)
+	    memmove (pstr->wcs, pstr->wcs + offset,
+		     (pstr->valid_len - offset) * sizeof (wint_t));
+#endif
+	  if (BE (pstr->mbs_allocated, 0))
+	    memmove (pstr->mbs, pstr->mbs + offset,
+		     pstr->valid_len - offset);
+	  pstr->valid_len -= offset;
+	  pstr->valid_raw_len -= offset;
+#ifdef DEBUG
+	  assert (pstr->valid_len > 0);
+#endif
+	}
+      else
+	{
+	  /* No, skip all characters until IDX.  */
+#ifdef RE_ENABLE_I18N
+	  if (BE (pstr->offsets_needed, 0))
+	    {
+	      pstr->len = pstr->raw_len - idx + offset;
+	      pstr->stop = pstr->raw_stop - idx + offset;
+	      pstr->offsets_needed = 0;
+	    }
+#endif
+	  pstr->valid_len = 0;
+	  pstr->valid_raw_len = 0;
+#ifdef RE_ENABLE_I18N
+	  if (pstr->mb_cur_max > 1)
+	    {
+	      int wcs_idx;
+	      wint_t wc = WEOF;
+
+	      if (pstr->is_utf8)
+		{
+		  const unsigned char *raw, *p, *end;
+
+		  /* Special case UTF-8.  Multi-byte chars start with any
+		     byte other than 0x80 - 0xbf.  */
+		  raw = pstr->raw_mbs + pstr->raw_mbs_idx;
+		  end = raw + (offset - pstr->mb_cur_max);
+		  p = raw + offset - 1;
+#if 0
+		  /* We know the wchar_t encoding is UCS4, so for the simple
+		     case, ASCII characters, skip the conversion step.  */
+		  if (isascii (*p) && BE (pstr->trans == NULL, 1))
+		    {
+		      memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
+		      pstr->valid_len = 0;
+		      wc = (wchar_t) *p;
+		    }
+		  else
+#endif
+		    for (; p >= end; --p)
+		      if ((*p & 0xc0) != 0x80)
+			{
+			  mbstate_t cur_state;
+			  wchar_t wc2;
+			  int mlen = raw + pstr->len - p;
+			  unsigned char buf[6];
+			  size_t mbclen;
+
+			  if (BE (pstr->trans != NULL, 0))
+			    {
+			      int i = mlen < 6 ? mlen : 6;
+			      while (--i >= 0)
+				buf[i] = pstr->trans[p[i]];
+			    }
+			  /* XXX Don't use mbrtowc, we know which conversion
+			     to use (UTF-8 -> UCS4).  */
+			  memset (&cur_state, 0, sizeof (cur_state));
+			  mbclen = mbrtowc (&wc2, (const char *) p, mlen,
+					    &cur_state);
+			  if (raw + offset - p <= mbclen
+			      && mbclen < (size_t) -2)
+			    {
+			      memset (&pstr->cur_state, '\0',
+				      sizeof (mbstate_t));
+			      pstr->valid_len = mbclen - (raw + offset - p);
+			      wc = wc2;
+			    }
+			  break;
+			}
+		}
+
+	      if (wc == WEOF)
+		pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
+	      if (BE (pstr->valid_len, 0))
+		{
+		  for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
+		    pstr->wcs[wcs_idx] = WEOF;
+		  if (pstr->mbs_allocated)
+		    memset (pstr->mbs, 255, pstr->valid_len);
+		}
+	      pstr->valid_raw_len = pstr->valid_len;
+	      pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
+				    && IS_WIDE_WORD_CHAR (wc))
+				   ? CONTEXT_WORD
+				   : ((IS_WIDE_NEWLINE (wc)
+				       && pstr->newline_anchor)
+				      ? CONTEXT_NEWLINE : 0));
+	    }
+	  else
+#endif /* RE_ENABLE_I18N */
+	    {
+	      int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
+	      if (pstr->trans)
+		c = pstr->trans[c];
+	      pstr->tip_context = (bitset_contain (pstr->word_char, c)
+				   ? CONTEXT_WORD
+				   : ((IS_NEWLINE (c) && pstr->newline_anchor)
+				      ? CONTEXT_NEWLINE : 0));
+	    }
+	}
+      if (!BE (pstr->mbs_allocated, 0))
+	pstr->mbs += offset;
+    }
+  pstr->raw_mbs_idx = idx;
+  pstr->len -= offset;
+  pstr->stop -= offset;
+
+  /* Then build the buffers.  */
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1)
+    {
+      if (pstr->icase)
+	{
+	  reg_errcode_t ret = build_wcs_upper_buffer (pstr);
+	  if (BE (ret != REG_NOERROR, 0))
+	    return ret;
+	}
+      else
+	build_wcs_buffer (pstr);
+    }
+  else
+#endif
+    if (BE (pstr->mbs_allocated, 0))
+      {
+	if (pstr->icase)
+	  build_upper_buffer (pstr);
+	else if (pstr->trans != NULL)
+	  re_string_translate_buffer (pstr);
+      }
+    else
+      pstr->valid_len = pstr->len;
+
+  pstr->cur_idx = 0;
+  return REG_NOERROR;
+}
+
+static unsigned char
+internal_function __attribute ((pure))
+re_string_peek_byte_case (const re_string_t *pstr, int idx)
+{
+  int ch, off;
+
+  /* Handle the common (easiest) cases first.  */
+  if (BE (!pstr->mbs_allocated, 1))
+    return re_string_peek_byte (pstr, idx);
+
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1
+      && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
+    return re_string_peek_byte (pstr, idx);
+#endif
+
+  off = pstr->cur_idx + idx;
+#ifdef RE_ENABLE_I18N
+  if (pstr->offsets_needed)
+    off = pstr->offsets[off];
+#endif
+
+  ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
+     this function returns CAPITAL LETTER I instead of first byte of
+     DOTLESS SMALL LETTER I.  The latter would confuse the parser,
+     since peek_byte_case doesn't advance cur_idx in any way.  */
+  if (pstr->offsets_needed && !isascii (ch))
+    return re_string_peek_byte (pstr, idx);
+#endif
+
+  return ch;
+}
+
+static unsigned char
+internal_function __attribute ((pure))
+re_string_fetch_byte_case (re_string_t *pstr)
+{
+  if (BE (!pstr->mbs_allocated, 1))
+    return re_string_fetch_byte (pstr);
+
+#ifdef RE_ENABLE_I18N
+  if (pstr->offsets_needed)
+    {
+      int off, ch;
+
+      /* For tr_TR.UTF-8 [[:islower:]] there is
+	 [[: CAPITAL LETTER I WITH DOT lower:]] in mbs.  Skip
+	 in that case the whole multi-byte character and return
+	 the original letter.  On the other side, with
+	 [[: DOTLESS SMALL LETTER I return [[:I, as doing
+	 anything else would complicate things too much.  */
+
+      if (!re_string_first_byte (pstr, pstr->cur_idx))
+	return re_string_fetch_byte (pstr);
+
+      off = pstr->offsets[pstr->cur_idx];
+      ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
+
+      if (! isascii (ch))
+	return re_string_fetch_byte (pstr);
+
+      re_string_skip_bytes (pstr,
+			    re_string_char_size_at (pstr, pstr->cur_idx));
+      return ch;
+    }
+#endif
+
+  return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
+}
+
+static void
+internal_function
+re_string_destruct (re_string_t *pstr)
+{
+#ifdef RE_ENABLE_I18N
+  re_free (pstr->wcs);
+  re_free (pstr->offsets);
+#endif /* RE_ENABLE_I18N  */
+  if (pstr->mbs_allocated)
+    re_free (pstr->mbs);
+}
+
+/* Return the context at IDX in INPUT.  */
+
+static unsigned int
+internal_function
+re_string_context_at (const re_string_t *input, int idx, int eflags)
+{
+  int c;
+  if (BE (idx < 0, 0))
+    /* In this case, we use the value stored in input->tip_context,
+       since we can't know the character in input->mbs[-1] here.  */
+    return input->tip_context;
+  if (BE (idx == input->len, 0))
+    return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
+	    : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1)
+    {
+      wint_t wc;
+      int wc_idx = idx;
+      while(input->wcs[wc_idx] == WEOF)
+	{
+#ifdef DEBUG
+	  /* It must not happen.  */
+	  assert (wc_idx >= 0);
+#endif
+	  --wc_idx;
+	  if (wc_idx < 0)
+	    return input->tip_context;
+	}
+      wc = input->wcs[wc_idx];
+      if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc))
+	return CONTEXT_WORD;
+      return (IS_WIDE_NEWLINE (wc) && input->newline_anchor
+	      ? CONTEXT_NEWLINE : 0);
+    }
+#endif
+  c = re_string_byte_at (input, idx);
+  if (bitset_contain (input->word_char, c))
+    return CONTEXT_WORD;
+  return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;
+}
+
+/* Functions for set operation.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_alloc (re_node_set *set, int size)
+{
+  set->alloc = size;
+  set->nelem = 0;
+  set->elems = re_malloc (int, size);	/* can be NULL if size == 0
+					   (see re_node_set_init_empty(set)) */
+  if (BE (set->elems == NULL && size != 0, 0))
+    return REG_ESPACE;
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_1 (re_node_set *set, int elem)
+{
+  set->alloc = 1;
+  set->nelem = 1;
+  set->elems = re_malloc (int, 1);
+  if (BE (set->elems == NULL, 0))
+    {
+      set->alloc = set->nelem = 0;
+      return REG_ESPACE;
+    }
+  set->elems[0] = elem;
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
+{
+  set->alloc = 2;
+  set->elems = re_malloc (int, 2);
+  if (BE (set->elems == NULL, 0))
+    return REG_ESPACE;
+  if (elem1 == elem2)
+    {
+      set->nelem = 1;
+      set->elems[0] = elem1;
+    }
+  else
+    {
+      set->nelem = 2;
+      if (elem1 < elem2)
+	{
+	  set->elems[0] = elem1;
+	  set->elems[1] = elem2;
+	}
+      else
+	{
+	  set->elems[0] = elem2;
+	  set->elems[1] = elem1;
+	}
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
+{
+  dest->nelem = src->nelem;
+  if (src->nelem > 0)
+    {
+      dest->alloc = dest->nelem;
+      dest->elems = re_malloc (int, dest->alloc);
+      if (BE (dest->elems == NULL, 0))
+	{
+	  dest->alloc = dest->nelem = 0;
+	  return REG_ESPACE;
+	}
+      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
+    }
+  else
+    re_node_set_init_empty (dest);
+  return REG_NOERROR;
+}
+
+/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.
+   Note: We assume dest->elems is NULL, when dest->alloc is 0.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
+			   const re_node_set *src2)
+{
+  int i1, i2, is, id, delta, sbase;
+  if (src1->nelem == 0 || src2->nelem == 0)
+    return REG_NOERROR;
+
+  /* We need dest->nelem + 2 * elems_in_intersection; this is a
+     conservative estimate.  */
+  if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
+    {
+      int new_alloc = src1->nelem + src2->nelem + dest->alloc;
+      int *new_elems = re_realloc (dest->elems, int, new_alloc);
+      if (BE (new_elems == NULL, 0))
+        return REG_ESPACE;
+      dest->elems = new_elems;
+      dest->alloc = new_alloc;
+    }
+
+  /* Find the items in the intersection of SRC1 and SRC2, and copy
+     into the top of DEST those that are not already in DEST itself.  */
+  sbase = dest->nelem + src1->nelem + src2->nelem;
+  i1 = src1->nelem - 1;
+  i2 = src2->nelem - 1;
+  id = dest->nelem - 1;
+  for (;;)
+    {
+      if (src1->elems[i1] == src2->elems[i2])
+	{
+	  /* Try to find the item in DEST.  Maybe we could binary search?  */
+	  while (id >= 0 && dest->elems[id] > src1->elems[i1])
+	    --id;
+
+          if (id < 0 || dest->elems[id] != src1->elems[i1])
+            dest->elems[--sbase] = src1->elems[i1];
+
+	  if (--i1 < 0 || --i2 < 0)
+	    break;
+	}
+
+      /* Lower the highest of the two items.  */
+      else if (src1->elems[i1] < src2->elems[i2])
+	{
+	  if (--i2 < 0)
+	    break;
+	}
+      else
+	{
+	  if (--i1 < 0)
+	    break;
+	}
+    }
+
+  id = dest->nelem - 1;
+  is = dest->nelem + src1->nelem + src2->nelem - 1;
+  delta = is - sbase + 1;
+
+  /* Now copy.  When DELTA becomes zero, the remaining
+     DEST elements are already in place; this is more or
+     less the same loop that is in re_node_set_merge.  */
+  dest->nelem += delta;
+  if (delta > 0 && id >= 0)
+    for (;;)
+      {
+        if (dest->elems[is] > dest->elems[id])
+          {
+            /* Copy from the top.  */
+            dest->elems[id + delta--] = dest->elems[is--];
+            if (delta == 0)
+              break;
+          }
+        else
+          {
+            /* Slide from the bottom.  */
+            dest->elems[id + delta] = dest->elems[id];
+            if (--id < 0)
+              break;
+          }
+      }
+
+  /* Copy remaining SRC elements.  */
+  memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int));
+
+  return REG_NOERROR;
+}
+
+/* Calculate the union set of the sets SRC1 and SRC2. And store it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
+			const re_node_set *src2)
+{
+  int i1, i2, id;
+  if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
+    {
+      dest->alloc = src1->nelem + src2->nelem;
+      dest->elems = re_malloc (int, dest->alloc);
+      if (BE (dest->elems == NULL, 0))
+	return REG_ESPACE;
+    }
+  else
+    {
+      if (src1 != NULL && src1->nelem > 0)
+	return re_node_set_init_copy (dest, src1);
+      if (src2 != NULL && src2->nelem > 0)
+	return re_node_set_init_copy (dest, src2);
+      re_node_set_init_empty (dest);
+      return REG_NOERROR;
+    }
+  for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
+    {
+      if (src1->elems[i1] > src2->elems[i2])
+	{
+	  dest->elems[id++] = src2->elems[i2++];
+	  continue;
+	}
+      if (src1->elems[i1] == src2->elems[i2])
+	++i2;
+      dest->elems[id++] = src1->elems[i1++];
+    }
+  if (i1 < src1->nelem)
+    {
+      memcpy (dest->elems + id, src1->elems + i1,
+	     (src1->nelem - i1) * sizeof (int));
+      id += src1->nelem - i1;
+    }
+  else if (i2 < src2->nelem)
+    {
+      memcpy (dest->elems + id, src2->elems + i2,
+	     (src2->nelem - i2) * sizeof (int));
+      id += src2->nelem - i2;
+    }
+  dest->nelem = id;
+  return REG_NOERROR;
+}
+
+/* Calculate the union set of the sets DEST and SRC. And store it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_merge (re_node_set *dest, const re_node_set *src)
+{
+  int is, id, sbase, delta;
+  if (src == NULL || src->nelem == 0)
+    return REG_NOERROR;
+  if (dest->alloc < 2 * src->nelem + dest->nelem)
+    {
+      int new_alloc = 2 * (src->nelem + dest->alloc);
+      int *new_buffer = re_realloc (dest->elems, int, new_alloc);
+      if (BE (new_buffer == NULL, 0))
+	return REG_ESPACE;
+      dest->elems = new_buffer;
+      dest->alloc = new_alloc;
+    }
+
+  if (BE (dest->nelem == 0, 0))
+    {
+      dest->nelem = src->nelem;
+      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
+      return REG_NOERROR;
+    }
+
+  /* Copy into the top of DEST the items of SRC that are not
+     found in DEST.  Maybe we could binary search in DEST?  */
+  for (sbase = dest->nelem + 2 * src->nelem,
+       is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; )
+    {
+      if (dest->elems[id] == src->elems[is])
+        is--, id--;
+      else if (dest->elems[id] < src->elems[is])
+        dest->elems[--sbase] = src->elems[is--];
+      else /* if (dest->elems[id] > src->elems[is]) */
+        --id;
+    }
+
+  if (is >= 0)
+    {
+      /* If DEST is exhausted, the remaining items of SRC must be unique.  */
+      sbase -= is + 1;
+      memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int));
+    }
+
+  id = dest->nelem - 1;
+  is = dest->nelem + 2 * src->nelem - 1;
+  delta = is - sbase + 1;
+  if (delta == 0)
+    return REG_NOERROR;
+
+  /* Now copy.  When DELTA becomes zero, the remaining
+     DEST elements are already in place.  */
+  dest->nelem += delta;
+  for (;;)
+    {
+      if (dest->elems[is] > dest->elems[id])
+        {
+	  /* Copy from the top.  */
+          dest->elems[id + delta--] = dest->elems[is--];
+	  if (delta == 0)
+	    break;
+	}
+      else
+        {
+          /* Slide from the bottom.  */
+          dest->elems[id + delta] = dest->elems[id];
+	  if (--id < 0)
+	    {
+	      /* Copy remaining SRC elements.  */
+	      memcpy (dest->elems, dest->elems + sbase,
+	              delta * sizeof (int));
+	      break;
+	    }
+	}
+    }
+
+  return REG_NOERROR;
+}
+
+/* Insert the new element ELEM to the re_node_set* SET.
+   SET should not already have ELEM.
+   return -1 if an error is occured, return 1 otherwise.  */
+
+static int
+internal_function
+re_node_set_insert (re_node_set *set, int elem)
+{
+  int idx;
+  /* In case the set is empty.  */
+  if (set->alloc == 0)
+    {
+      if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
+	return 1;
+      return -1;
+    }
+
+  if (BE (set->nelem, 0) == 0)
+    {
+      /* We already guaranteed above that set->alloc != 0.  */
+      set->elems[0] = elem;
+      ++set->nelem;
+      return 1;
+    }
+
+  /* Realloc if we need.  */
+  if (set->alloc == set->nelem)
+    {
+      int *new_elems;
+      set->alloc = set->alloc * 2;
+      new_elems = re_realloc (set->elems, int, set->alloc);
+      if (BE (new_elems == NULL, 0))
+	return -1;
+      set->elems = new_elems;
+    }
+
+  /* Move the elements which follows the new element.  Test the
+     first element separately to skip a check in the inner loop.  */
+  if (elem < set->elems[0])
+    {
+      idx = 0;
+      for (idx = set->nelem; idx > 0; idx--)
+        set->elems[idx] = set->elems[idx - 1];
+    }
+  else
+    {
+      for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
+        set->elems[idx] = set->elems[idx - 1];
+    }
+
+  /* Insert the new element.  */
+  set->elems[idx] = elem;
+  ++set->nelem;
+  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
+internal_function
+re_node_set_insert_last (re_node_set *set, int elem)
+{
+  /* Realloc if we need.  */
+  if (set->alloc == set->nelem)
+    {
+      int *new_elems;
+      set->alloc = (set->alloc + 1) * 2;
+      new_elems = re_realloc (set->elems, int, set->alloc);
+      if (BE (new_elems == NULL, 0))
+	return -1;
+      set->elems = new_elems;
+    }
+
+  /* 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.  */
+
+static int
+internal_function __attribute ((pure))
+re_node_set_compare (const re_node_set *set1, const re_node_set *set2)
+{
+  int i;
+  if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
+    return 0;
+  for (i = set1->nelem ; --i >= 0 ; )
+    if (set1->elems[i] != set2->elems[i])
+      return 0;
+  return 1;
+}
+
+/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise.  */
+
+static int
+internal_function __attribute ((pure))
+re_node_set_contains (const re_node_set *set, int elem)
+{
+  unsigned int idx, right, mid;
+  if (set->nelem <= 0)
+    return 0;
+
+  /* Binary search the element.  */
+  idx = 0;
+  right = set->nelem - 1;
+  while (idx < right)
+    {
+      mid = (idx + right) / 2;
+      if (set->elems[mid] < elem)
+	idx = mid + 1;
+      else
+	right = mid;
+    }
+  return set->elems[idx] == elem ? idx + 1 : 0;
+}
+
+static void
+internal_function
+re_node_set_remove_at (re_node_set *set, int idx)
+{
+  if (idx < 0 || idx >= set->nelem)
+    return;
+  --set->nelem;
+  for (; idx < set->nelem; idx++)
+    set->elems[idx] = set->elems[idx + 1];
+}
+
+
+/* Add the token TOKEN to dfa->nodes, and return the index of the token.
+   Or return -1, if an error will be occured.  */
+
+static int
+internal_function
+re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
+{
+#ifdef RE_ENABLE_I18N
+  int type = token.type;
+#endif
+  if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
+    {
+      size_t new_nodes_alloc = dfa->nodes_alloc * 2;
+      int *new_nexts, *new_indices;
+      re_node_set *new_edests, *new_eclosures;
+      re_token_t *new_nodes;
+
+      /* Avoid overflows.  */
+      if (BE (new_nodes_alloc < dfa->nodes_alloc, 0))
+	return -1;
+
+      new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
+      if (BE (new_nodes == NULL, 0))
+	return -1;
+      dfa->nodes = new_nodes;
+      new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);
+      new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);
+      new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
+      new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
+      if (BE (new_nexts == NULL || new_indices == NULL
+	      || new_edests == NULL || new_eclosures == NULL, 0))
+	return -1;
+      dfa->nexts = new_nexts;
+      dfa->org_indices = new_indices;
+      dfa->edests = new_edests;
+      dfa->eclosures = new_eclosures;
+      dfa->nodes_alloc = new_nodes_alloc;
+    }
+  dfa->nodes[dfa->nodes_len] = token;
+  dfa->nodes[dfa->nodes_len].constraint = 0;
+#ifdef RE_ENABLE_I18N
+  dfa->nodes[dfa->nodes_len].accept_mb =
+    (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
+#endif
+  dfa->nexts[dfa->nodes_len] = -1;
+  re_node_set_init_empty (dfa->edests + dfa->nodes_len);
+  re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
+  return dfa->nodes_len++;
+}
+
+static __inline__ unsigned int
+internal_function
+calc_state_hash (const re_node_set *nodes, unsigned int context)
+{
+  unsigned int hash = nodes->nelem + context;
+  int i;
+  for (i = 0 ; i < nodes->nelem ; i++)
+    hash += nodes->elems[i];
+  return hash;
+}
+
+/* Search for the state whose node_set is equivalent to NODES.
+   Return the pointer to the state, if we found it in the DFA.
+   Otherwise create the new one and return it.  In case of an error
+   return NULL and set the error code in ERR.
+   Note: - We assume NULL as the invalid state, then it is possible that
+	   return value is NULL and ERR is REG_NOERROR.
+	 - We never return non-NULL value in case of any errors, it is for
+	   optimization.  */
+
+static re_dfastate_t *
+internal_function
+re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
+		  const re_node_set *nodes)
+{
+  unsigned int hash;
+  re_dfastate_t *new_state;
+  struct re_state_table_entry *spot;
+  int i;
+  if (BE (nodes->nelem == 0, 0))
+    {
+      *err = REG_NOERROR;
+      return NULL;
+    }
+  hash = calc_state_hash (nodes, 0);
+  spot = dfa->state_table + (hash & dfa->state_hash_mask);
+
+  for (i = 0 ; i < spot->num ; i++)
+    {
+      re_dfastate_t *state = spot->array[i];
+      if (hash != state->hash)
+	continue;
+      if (re_node_set_compare (&state->nodes, nodes))
+	return state;
+    }
+
+  /* There are no appropriate state in the dfa, create the new one.  */
+  new_state = create_ci_newstate (dfa, nodes, hash);
+  if (BE (new_state == NULL, 0))
+    *err = REG_ESPACE;
+
+  return new_state;
+}
+
+/* Search for the state whose node_set is equivalent to NODES and
+   whose context is equivalent to CONTEXT.
+   Return the pointer to the state, if we found it in the DFA.
+   Otherwise create the new one and return it.  In case of an error
+   return NULL and set the error code in ERR.
+   Note: - We assume NULL as the invalid state, then it is possible that
+	   return value is NULL and ERR is REG_NOERROR.
+	 - We never return non-NULL value in case of any errors, it is for
+	   optimization.  */
+
+static re_dfastate_t *
+internal_function
+re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
+			  const re_node_set *nodes, unsigned int context)
+{
+  unsigned int hash;
+  re_dfastate_t *new_state;
+  struct re_state_table_entry *spot;
+  int i;
+  if (nodes->nelem == 0)
+    {
+      *err = REG_NOERROR;
+      return NULL;
+    }
+  hash = calc_state_hash (nodes, context);
+  spot = dfa->state_table + (hash & dfa->state_hash_mask);
+
+  for (i = 0 ; i < spot->num ; i++)
+    {
+      re_dfastate_t *state = spot->array[i];
+      if (state->hash == hash
+	  && state->context == context
+	  && re_node_set_compare (state->entrance_nodes, nodes))
+	return state;
+    }
+  /* There are no appropriate state in `dfa', create the new one.  */
+  new_state = create_cd_newstate (dfa, nodes, context, hash);
+  if (BE (new_state == NULL, 0))
+    *err = REG_ESPACE;
+
+  return new_state;
+}
+
+/* Finish initialization of the new state NEWSTATE, and using its hash value
+   HASH put in the appropriate bucket of DFA's state table.  Return value
+   indicates the error code if failed.  */
+
+static reg_errcode_t
+register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
+		unsigned int hash)
+{
+  struct re_state_table_entry *spot;
+  reg_errcode_t err;
+  int i;
+
+  newstate->hash = hash;
+  err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);
+  if (BE (err != REG_NOERROR, 0))
+    return REG_ESPACE;
+  for (i = 0; i < newstate->nodes.nelem; i++)
+    {
+      int elem = newstate->nodes.elems[i];
+      if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
+        re_node_set_insert_last (&newstate->non_eps_nodes, elem);
+    }
+
+  spot = dfa->state_table + (hash & dfa->state_hash_mask);
+  if (BE (spot->alloc <= spot->num, 0))
+    {
+      int new_alloc = 2 * spot->num + 2;
+      re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
+					      new_alloc);
+      if (BE (new_array == NULL, 0))
+	return REG_ESPACE;
+      spot->array = new_array;
+      spot->alloc = new_alloc;
+    }
+  spot->array[spot->num++] = newstate;
+  return REG_NOERROR;
+}
+
+static void
+free_state (re_dfastate_t *state)
+{
+  re_node_set_free (&state->non_eps_nodes);
+  re_node_set_free (&state->inveclosure);
+  if (state->entrance_nodes != &state->nodes)
+    {
+      re_node_set_free (state->entrance_nodes);
+      re_free (state->entrance_nodes);
+    }
+  re_node_set_free (&state->nodes);
+  re_free (state->word_trtable);
+  re_free (state->trtable);
+  re_free (state);
+}
+
+/* Create the new state which is independ of contexts.
+   Return the new state if succeeded, otherwise return NULL.  */
+
+static re_dfastate_t *
+internal_function
+create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
+		    unsigned int hash)
+{
+  int i;
+  reg_errcode_t err;
+  re_dfastate_t *newstate;
+
+  newstate = calloc (sizeof (re_dfastate_t), 1);
+  if (BE (newstate == NULL, 0))
+    return NULL;
+  err = re_node_set_init_copy (&newstate->nodes, nodes);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      re_free (newstate);
+      return NULL;
+    }
+
+  newstate->entrance_nodes = &newstate->nodes;
+  for (i = 0 ; i < nodes->nelem ; i++)
+    {
+      re_token_t *node = dfa->nodes + nodes->elems[i];
+      re_token_type_t type = node->type;
+
+      if (type == CHARACTER && !node->constraint)
+	continue;
+#ifdef RE_ENABLE_I18N
+      newstate->accept_mb |= node->accept_mb;
+#endif
+
+      /* If the state has the halt node, the state is a halt state.  */
+      if (type == END_OF_RE)
+	newstate->halt = 1;
+      else if (type == OP_BACK_REF)
+	newstate->has_backref = 1;
+      else if (type == ANCHOR || node->constraint)
+	newstate->has_constraint = 1;
+    }
+  err = register_state (dfa, newstate, hash);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_state (newstate);
+      newstate = NULL;
+    }
+  return newstate;
+}
+
+/* Create the new state which is depend on the context CONTEXT.
+   Return the new state if succeeded, otherwise return NULL.  */
+
+static re_dfastate_t *
+internal_function
+create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
+		    unsigned int context, unsigned int hash)
+{
+  int i, nctx_nodes = 0;
+  reg_errcode_t err;
+  re_dfastate_t *newstate;
+
+  newstate = calloc (sizeof (re_dfastate_t), 1);
+  if (BE (newstate == NULL, 0))
+    return NULL;
+  err = re_node_set_init_copy (&newstate->nodes, nodes);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      re_free (newstate);
+      return NULL;
+    }
+
+  newstate->context = context;
+  newstate->entrance_nodes = &newstate->nodes;
+
+  for (i = 0 ; i < nodes->nelem ; i++)
+    {
+      unsigned int constraint = 0;
+      re_token_t *node = dfa->nodes + nodes->elems[i];
+      re_token_type_t type = node->type;
+      if (node->constraint)
+	constraint = node->constraint;
+
+      if (type == CHARACTER && !constraint)
+	continue;
+#ifdef RE_ENABLE_I18N
+      newstate->accept_mb |= node->accept_mb;
+#endif /* RE_ENABLE_I18N */
+
+      /* If the state has the halt node, the state is a halt state.  */
+      if (type == END_OF_RE)
+	newstate->halt = 1;
+      else if (type == OP_BACK_REF)
+	newstate->has_backref = 1;
+      else if (type == ANCHOR)
+	constraint = node->opr.ctx_type;
+
+      if (constraint)
+	{
+	  if (newstate->entrance_nodes == &newstate->nodes)
+	    {
+	      newstate->entrance_nodes = re_malloc (re_node_set, 1);
+	      if (BE (newstate->entrance_nodes == NULL, 0))
+		{
+		  free_state (newstate);
+		  return NULL;
+		}
+	      re_node_set_init_copy (newstate->entrance_nodes, nodes);
+	      nctx_nodes = 0;
+	      newstate->has_constraint = 1;
+	    }
+
+	  if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
+	    {
+	      re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
+	      ++nctx_nodes;
+	    }
+	}
+    }
+  err = register_state (dfa, newstate, hash);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_state (newstate);
+      newstate = NULL;
+    }
+  return  newstate;
+}
diff --git a/ap/build/uClibc/libc/misc/regex/regex_internal.h b/ap/build/uClibc/libc/misc/regex/regex_internal.h
new file mode 100644
index 0000000..0a255e3
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/regex_internal.h
@@ -0,0 +1,708 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _REGEX_INTERNAL_H
+#define _REGEX_INTERNAL_H 1
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET
+# include <langinfo.h>
+#endif
+#if defined HAVE_LOCALE_H
+# include <locale.h>
+#endif
+#if defined HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+#if defined HAVE_WCTYPE_H
+# include <wctype.h>
+#endif
+#if defined HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+#if defined HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#ifdef __UCLIBC_HAS_THREADS__
+#include <bits/libc-lock.h>
+#else
+#define __libc_lock_define(CLASS, NAME)
+#define __libc_lock_init(NAME)   do { } while (0)
+#define __libc_lock_lock(NAME)   do { } while (0)
+#define __libc_lock_unlock(NAME) do { } while (0)
+#endif
+
+#undef gettext
+#undef gettext_noop
+#define gettext(msgid)       (msgid)
+#define gettext_noop(String) String
+
+#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL)
+# define RE_ENABLE_I18N
+#endif
+
+#if __GNUC__ >= 3
+/* uclibc: lean towards smaller size a bit:
+ * OFF: # define BE(expr, val) __builtin_expect (expr, val) */
+# define BE(expr, val) (expr)
+#else
+# define BE(expr, val) (expr)
+# define inline
+#endif
+
+/* Number of single byte character.  */
+#define SBC_MAX 256
+
+#define COLL_ELEM_LEN_MAX 8
+
+/* The character which represents newline.  */
+#define NEWLINE_CHAR '\n'
+#define WIDE_NEWLINE_CHAR L'\n'
+
+#ifdef __GNUC__
+# define __attribute(arg) __attribute__ (arg)
+#else
+# define __attribute(arg)
+#endif
+
+/* An integer used to represent a set of bits.  It must be unsigned,
+   and must be at least as wide as unsigned int.  */
+typedef unsigned long int bitset_word_t;
+/* All bits set in a bitset_word_t.  */
+#define BITSET_WORD_MAX ULONG_MAX
+/* Number of bits in a bitset_word_t.  */
+#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT)
+/* Number of bitset_word_t in a bit_set.  */
+#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS)
+typedef bitset_word_t bitset_t[BITSET_WORDS];
+typedef bitset_word_t *re_bitset_ptr_t;
+typedef const bitset_word_t *re_const_bitset_ptr_t;
+
+#define bitset_set(set,i) \
+  (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS)
+#define bitset_clear(set,i) \
+  (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS))
+#define bitset_contain(set,i) \
+  (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS))
+#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t))
+#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t))
+#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t))
+
+#define PREV_WORD_CONSTRAINT 0x0001
+#define PREV_NOTWORD_CONSTRAINT 0x0002
+#define NEXT_WORD_CONSTRAINT 0x0004
+#define NEXT_NOTWORD_CONSTRAINT 0x0008
+#define PREV_NEWLINE_CONSTRAINT 0x0010
+#define NEXT_NEWLINE_CONSTRAINT 0x0020
+#define PREV_BEGBUF_CONSTRAINT 0x0040
+#define NEXT_ENDBUF_CONSTRAINT 0x0080
+#define WORD_DELIM_CONSTRAINT 0x0100
+#define NOT_WORD_DELIM_CONSTRAINT 0x0200
+
+typedef enum
+{
+  INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
+  WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
+  WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
+  INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
+  LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
+  LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
+  BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
+  BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
+  WORD_DELIM = WORD_DELIM_CONSTRAINT,
+  NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
+} re_context_type;
+
+typedef struct
+{
+  int alloc;
+  int nelem;
+  int *elems;
+} re_node_set;
+
+typedef enum
+{
+  NON_TYPE = 0,
+
+  /* Node type, These are used by token, node, tree.  */
+  CHARACTER = 1,
+  END_OF_RE = 2,
+  SIMPLE_BRACKET = 3,
+  OP_BACK_REF = 4,
+  OP_PERIOD = 5,
+#ifdef RE_ENABLE_I18N
+  COMPLEX_BRACKET = 6,
+  OP_UTF8_PERIOD = 7,
+#endif /* RE_ENABLE_I18N */
+
+  /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used
+     when the debugger shows values of this enum type.  */
+#define EPSILON_BIT 8
+  OP_OPEN_SUBEXP = EPSILON_BIT | 0,
+  OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
+  OP_ALT = EPSILON_BIT | 2,
+  OP_DUP_ASTERISK = EPSILON_BIT | 3,
+  ANCHOR = EPSILON_BIT | 4,
+
+  /* Tree type, these are used only by tree. */
+  CONCAT = 16,
+  SUBEXP = 17,
+
+  /* Token type, these are used only by token.  */
+  OP_DUP_PLUS = 18,
+  OP_DUP_QUESTION,
+  OP_OPEN_BRACKET,
+  OP_CLOSE_BRACKET,
+  OP_CHARSET_RANGE,
+  OP_OPEN_DUP_NUM,
+  OP_CLOSE_DUP_NUM,
+  OP_NON_MATCH_LIST,
+  OP_OPEN_COLL_ELEM,
+  OP_CLOSE_COLL_ELEM,
+  OP_OPEN_EQUIV_CLASS,
+  OP_CLOSE_EQUIV_CLASS,
+  OP_OPEN_CHAR_CLASS,
+  OP_CLOSE_CHAR_CLASS,
+  OP_WORD,
+  OP_NOTWORD,
+  OP_SPACE,
+  OP_NOTSPACE,
+  BACK_SLASH
+
+} re_token_type_t;
+
+#ifdef RE_ENABLE_I18N
+typedef struct
+{
+  /* Multibyte characters.  */
+  wchar_t *mbchars;
+
+  /* Collating symbols.  */
+# if 0
+  int32_t *coll_syms;
+# endif
+
+  /* Equivalence classes. */
+# if 0
+  int32_t *equiv_classes;
+# endif
+
+  /* Range expressions. */
+# if 0
+  uint32_t *range_starts;
+  uint32_t *range_ends;
+# else
+  wchar_t *range_starts;
+  wchar_t *range_ends;
+# endif
+
+  /* Character classes. */
+  wctype_t *char_classes;
+
+  /* If this character set is the non-matching list.  */
+  unsigned int non_match : 1;
+
+  /* # of multibyte characters.  */
+  int nmbchars;
+
+  /* # of collating symbols.  */
+  int ncoll_syms;
+
+  /* # of equivalence classes. */
+  int nequiv_classes;
+
+  /* # of range expressions. */
+  int nranges;
+
+  /* # of character classes. */
+  int nchar_classes;
+} re_charset_t;
+#endif /* RE_ENABLE_I18N */
+
+typedef struct
+{
+  union
+  {
+    unsigned char c;		/* for CHARACTER */
+    re_bitset_ptr_t sbcset;	/* for SIMPLE_BRACKET */
+#ifdef RE_ENABLE_I18N
+    re_charset_t *mbcset;	/* for COMPLEX_BRACKET */
+#endif /* RE_ENABLE_I18N */
+    int idx;			/* for BACK_REF */
+    re_context_type ctx_type;	/* for ANCHOR */
+  } opr;
+#if __GNUC__ >= 2
+  re_token_type_t type : 8;
+#else
+  re_token_type_t type;
+#endif
+  unsigned int constraint : 10;	/* context constraint */
+  unsigned int duplicated : 1;
+  unsigned int opt_subexp : 1;
+#ifdef RE_ENABLE_I18N
+  unsigned int accept_mb : 1;
+  /* These 2 bits can be moved into the union if needed (e.g. if running out
+     of bits; move opr.c to opr.c.c and move the flags to opr.c.flags).  */
+  unsigned int mb_partial : 1;
+#endif
+  unsigned int word_char : 1;
+} re_token_t;
+
+#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
+
+struct re_string_t
+{
+  /* Indicate the raw buffer which is the original string passed as an
+     argument of regexec(), re_search(), etc..  */
+  const unsigned char *raw_mbs;
+  /* Store the multibyte string.  In case of "case insensitive mode" like
+     REG_ICASE, upper cases of the string are stored, otherwise MBS points
+     the same address that RAW_MBS points.  */
+  unsigned char *mbs;
+#ifdef RE_ENABLE_I18N
+  /* Store the wide character string which is corresponding to MBS.  */
+  wint_t *wcs;
+  int *offsets;
+  mbstate_t cur_state;
+#endif
+  /* Index in RAW_MBS.  Each character mbs[i] corresponds to
+     raw_mbs[raw_mbs_idx + i].  */
+  int raw_mbs_idx;
+  /* The length of the valid characters in the buffers.  */
+  int valid_len;
+  /* The corresponding number of bytes in raw_mbs array.  */
+  int valid_raw_len;
+  /* The length of the buffers MBS and WCS.  */
+  int bufs_len;
+  /* The index in MBS, which is updated by re_string_fetch_byte.  */
+  int cur_idx;
+  /* length of RAW_MBS array.  */
+  int raw_len;
+  /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN.  */
+  int len;
+  /* End of the buffer may be shorter than its length in the cases such
+     as re_match_2, re_search_2.  Then, we use STOP for end of the buffer
+     instead of LEN.  */
+  int raw_stop;
+  /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS.  */
+  int stop;
+
+  /* The context of mbs[0].  We store the context independently, since
+     the context of mbs[0] may be different from raw_mbs[0], which is
+     the beginning of the input string.  */
+  unsigned int tip_context;
+  /* The translation passed as a part of an argument of re_compile_pattern.  */
+  RE_TRANSLATE_TYPE trans;
+  /* Copy of re_dfa_t's word_char.  */
+  re_const_bitset_ptr_t word_char;
+  /* 1 if REG_ICASE.  */
+  unsigned char icase;
+  unsigned char is_utf8;
+  unsigned char map_notascii;
+  unsigned char mbs_allocated;
+  unsigned char offsets_needed;
+  unsigned char newline_anchor;
+  unsigned char word_ops_used;
+  int mb_cur_max;
+};
+typedef struct re_string_t re_string_t;
+
+struct re_dfa_t;
+typedef struct re_dfa_t re_dfa_t;
+
+static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
+						int new_buf_len)
+     internal_function;
+#ifdef RE_ENABLE_I18N
+static void build_wcs_buffer (re_string_t *pstr) internal_function;
+static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) internal_function;
+#endif /* RE_ENABLE_I18N */
+static void build_upper_buffer (re_string_t *pstr) internal_function;
+static void re_string_translate_buffer (re_string_t *pstr) internal_function;
+static unsigned int re_string_context_at (const re_string_t *input, int idx,
+					  int eflags)
+     internal_function __attribute ((pure));
+#define re_string_peek_byte(pstr, offset) \
+  ((pstr)->mbs[(pstr)->cur_idx + offset])
+#define re_string_fetch_byte(pstr) \
+  ((pstr)->mbs[(pstr)->cur_idx++])
+#define re_string_first_byte(pstr, idx) \
+  ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)
+#define re_string_is_single_byte_char(pstr, idx) \
+  ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \
+				|| (pstr)->wcs[(idx) + 1] != WEOF))
+#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
+#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
+#define re_string_get_buffer(pstr) ((pstr)->mbs)
+#define re_string_length(pstr) ((pstr)->len)
+#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
+#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
+#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
+
+#include <alloca.h>
+
+#if 1
+# ifdef HAVE_ALLOCA
+/* The OS usually guarantees only one guard page at the bottom of the stack,
+   and a page size can be as small as 4096 bytes.  So we cannot safely
+   allocate anything larger than 4096 bytes.  Also care for the possibility
+   of a few compiler-allocated temporary stack slots.  */
+#  define __libc_use_alloca(n) ((n) < 4032)
+# else
+/* alloca is implemented with malloc, so just use malloc.  */
+#  define __libc_use_alloca(n) 0
+# endif
+#endif
+
+#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
+#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
+#define re_free(p) free (p)
+
+struct bin_tree_t
+{
+  struct bin_tree_t *parent;
+  struct bin_tree_t *left;
+  struct bin_tree_t *right;
+  struct bin_tree_t *first;
+  struct bin_tree_t *next;
+
+  re_token_t token;
+
+  /* `node_idx' is the index in dfa->nodes, if `type' == 0.
+     Otherwise `type' indicate the type of this node.  */
+  int node_idx;
+};
+typedef struct bin_tree_t bin_tree_t;
+
+#define BIN_TREE_STORAGE_SIZE \
+  ((1024 - sizeof (void *)) / sizeof (bin_tree_t))
+
+struct bin_tree_storage_t
+{
+  struct bin_tree_storage_t *next;
+  bin_tree_t data[BIN_TREE_STORAGE_SIZE];
+};
+typedef struct bin_tree_storage_t bin_tree_storage_t;
+
+#define CONTEXT_WORD 1
+#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
+#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
+#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
+
+#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
+#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
+#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
+#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
+#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
+
+#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
+#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
+#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_')
+#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
+
+#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
+ ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
+  || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
+  || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
+  || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
+
+#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
+ ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
+  || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
+  || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
+  || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
+
+struct re_dfastate_t
+{
+  unsigned int hash;
+  re_node_set nodes;
+  re_node_set non_eps_nodes;
+  re_node_set inveclosure;
+  re_node_set *entrance_nodes;
+  struct re_dfastate_t **trtable, **word_trtable;
+  unsigned int context : 4;
+  unsigned int halt : 1;
+  /* If this state can accept `multi byte'.
+     Note that we refer to multibyte characters, and multi character
+     collating elements as `multi byte'.  */
+  unsigned int accept_mb : 1;
+  /* If this state has backreference node(s).  */
+  unsigned int has_backref : 1;
+  unsigned int has_constraint : 1;
+};
+typedef struct re_dfastate_t re_dfastate_t;
+
+struct re_state_table_entry
+{
+  int num;
+  int alloc;
+  re_dfastate_t **array;
+};
+
+/* Array type used in re_sub_match_last_t and re_sub_match_top_t.  */
+
+typedef struct
+{
+  int next_idx;
+  int alloc;
+  re_dfastate_t **array;
+} state_array_t;
+
+/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP.  */
+
+typedef struct
+{
+  int node;
+  int str_idx; /* The position NODE match at.  */
+  state_array_t path;
+} re_sub_match_last_t;
+
+/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
+   And information about the node, whose type is OP_CLOSE_SUBEXP,
+   corresponding to NODE is stored in LASTS.  */
+
+typedef struct
+{
+  int str_idx;
+  int node;
+  state_array_t *path;
+  int alasts; /* Allocation size of LASTS.  */
+  int nlasts; /* The number of LASTS.  */
+  re_sub_match_last_t **lasts;
+} re_sub_match_top_t;
+
+struct re_backref_cache_entry
+{
+  int node;
+  int str_idx;
+  int subexp_from;
+  int subexp_to;
+  char more;
+  char unused;
+  unsigned short int eps_reachable_subexps_map;
+};
+
+typedef struct
+{
+  /* The string object corresponding to the input string.  */
+  re_string_t input;
+  const re_dfa_t *dfa;
+  /* EFLAGS of the argument of regexec.  */
+  int eflags;
+  /* Where the matching ends.  */
+  int match_last;
+  int last_node;
+  /* The state log used by the matcher.  */
+  re_dfastate_t **state_log;
+  int state_log_top;
+  /* Back reference cache.  */
+  int nbkref_ents;
+  int abkref_ents;
+  struct re_backref_cache_entry *bkref_ents;
+  int max_mb_elem_len;
+  int nsub_tops;
+  int asub_tops;
+  re_sub_match_top_t **sub_tops;
+} re_match_context_t;
+
+typedef struct
+{
+  re_dfastate_t **sifted_states;
+  re_dfastate_t **limited_states;
+  int last_node;
+  int last_str_idx;
+  re_node_set limits;
+} re_sift_context_t;
+
+struct re_fail_stack_ent_t
+{
+  int idx;
+  int node;
+  regmatch_t *regs;
+  re_node_set eps_via_nodes;
+};
+
+struct re_fail_stack_t
+{
+  int num;
+  int alloc;
+  struct re_fail_stack_ent_t *stack;
+};
+
+struct re_dfa_t
+{
+  re_token_t *nodes;
+  size_t nodes_alloc;
+  size_t nodes_len;
+  int *nexts;
+  int *org_indices;
+  re_node_set *edests;
+  re_node_set *eclosures;
+  re_node_set *inveclosures;
+  struct re_state_table_entry *state_table;
+  re_dfastate_t *init_state;
+  re_dfastate_t *init_state_word;
+  re_dfastate_t *init_state_nl;
+  re_dfastate_t *init_state_begbuf;
+  bin_tree_t *str_tree;
+  bin_tree_storage_t *str_tree_storage;
+  re_bitset_ptr_t sb_char;
+  int str_tree_storage_idx;
+
+  /* number of subexpressions `re_nsub' is in regex_t.  */
+  unsigned int state_hash_mask;
+  int init_node;
+  int nbackref; /* The number of backreference in this dfa.  */
+
+  /* Bitmap expressing which backreference is used.  */
+  bitset_word_t used_bkref_map;
+  bitset_word_t completed_bkref_map;
+
+  unsigned int has_plural_match : 1;
+  /* If this dfa has "multibyte node", which is a backreference or
+     a node which can accept multibyte character or multi character
+     collating element.  */
+  unsigned int has_mb_node : 1;
+  unsigned int is_utf8 : 1;
+  unsigned int map_notascii : 1;
+  unsigned int word_ops_used : 1;
+  int mb_cur_max;
+  bitset_t word_char;
+  reg_syntax_t syntax;
+  int *subexp_map;
+#ifdef DEBUG
+  char* re_str;
+#endif
+  __libc_lock_define (, lock)
+};
+
+#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
+#define re_node_set_remove(set,id) \
+  (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
+#define re_node_set_empty(p) ((p)->nelem = 0)
+#define re_node_set_free(set) re_free ((set)->elems)
+
+
+typedef enum
+{
+  SB_CHAR,
+  MB_CHAR,
+  EQUIV_CLASS,
+  COLL_SYM,
+  CHAR_CLASS
+} bracket_elem_type;
+
+typedef struct
+{
+  bracket_elem_type type;
+  union
+  {
+    unsigned char ch;
+    unsigned char *name;
+#ifdef __UCLIBC_HAS_WCHAR__
+    wchar_t wch;
+#endif
+  } opr;
+} bracket_elem_t;
+
+
+/* Inline functions for bitset operation.  */
+static __inline__ void
+bitset_not (bitset_t set)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+    set[bitset_i] = ~set[bitset_i];
+}
+
+static __inline__ void
+bitset_merge (bitset_t dest, const bitset_t src)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+    dest[bitset_i] |= src[bitset_i];
+}
+
+static __inline__ void
+bitset_mask (bitset_t dest, const bitset_t src)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+    dest[bitset_i] &= src[bitset_i];
+}
+
+#ifdef RE_ENABLE_I18N
+/* Inline functions for re_string.  */
+static __inline__ int
+internal_function __attribute ((pure))
+re_string_char_size_at (const re_string_t *pstr, int idx)
+{
+  int byte_idx;
+  if (pstr->mb_cur_max == 1)
+    return 1;
+  for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
+    if (pstr->wcs[idx + byte_idx] != WEOF)
+      break;
+  return byte_idx;
+}
+
+static __inline__ wint_t
+internal_function __attribute ((pure))
+re_string_wchar_at (const re_string_t *pstr, int idx)
+{
+  if (pstr->mb_cur_max == 1)
+    return (wint_t) pstr->mbs[idx];
+  return (wint_t) pstr->wcs[idx];
+}
+
+static int
+internal_function __attribute ((pure))
+re_string_elem_size_at (const re_string_t *pstr, int idx)
+{
+# if 0
+  const unsigned char *p, *extra;
+  const int32_t *table, *indirect;
+  int32_t tmp;
+#  include <locale/weight.h>
+  uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+
+  if (nrules != 0)
+    {
+      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+      extra = (const unsigned char *)
+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+						_NL_COLLATE_INDIRECTMB);
+      p = pstr->mbs + idx;
+      tmp = findidx (&p);
+      return p - pstr->mbs - idx;
+    }
+# endif
+  return 1;
+}
+#endif /* RE_ENABLE_I18N */
+
+#endif /*  _REGEX_INTERNAL_H */
diff --git a/ap/build/uClibc/libc/misc/regex/regex_old.c b/ap/build/uClibc/libc/misc/regex/regex_old.c
new file mode 100644
index 0000000..acf81a3
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/regex_old.c
@@ -0,0 +1,8269 @@
+/* Extended regular expression matching and search library,
+   version 0.12.
+   (Implements POSIX draft P1003.2/D11.2, except for some of the
+   internationalization features.)
+   Copyright (C) 1993-1999, 2000, 2001 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* To exclude some unwanted junk.... */
+#undef emacs
+#include <features.h>
+/* unistd.h must be included with _LIBC defined: we need smallint */
+#include <unistd.h>
+#ifdef __UCLIBC__
+# undef _LIBC
+# define _REGEX_RE_COMP
+# define STDC_HEADERS
+# define RE_TRANSLATE_TYPE char *
+#endif
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+/* AIX requires this to be the first thing in the file. */
+#if defined _AIX && !defined REGEX_MALLOC
+# pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef INSIDE_RECURSION
+
+# if defined STDC_HEADERS && !defined emacs
+#  include <stddef.h>
+# else
+/* We need this for `regex.h', and perhaps for the Emacs include files.  */
+#  include <sys/types.h>
+# endif
+
+
+/* For platform which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+# if defined __UCLIBC_HAS_WCHAR__
+#  define WIDE_CHAR_SUPPORT 1
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+#  include <wchar.h>
+#  include <wctype.h>
+# endif
+
+# if defined _LIBC || defined __UCLIBC__
+/* We have to keep the namespace clean.  */
+
+# ifndef __UCLIBC__
+#  define btowc __btowc
+
+/* We are also using some library internals.  */
+#  include <locale/localeinfo.h>
+#  include <locale/elem-hash.h>
+#  include <langinfo.h>
+#  include <locale/coll-lookup.h>
+# endif
+# endif
+
+/* This is for other GNU distributions with internationalized messages.  */
+# if defined HAVE_LIBINTL_H || defined _LIBC
+#  include <libintl.h>
+#  ifdef _LIBC
+#   undef gettext
+#   define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES)
+#  endif
+# else
+#  define gettext(msgid) (msgid)
+# endif
+
+# ifndef gettext_noop
+/* This define is so xgettext can find the internationalizable
+   strings.  */
+#  define gettext_noop(String) String
+# endif
+
+/* The `emacs' switch turns on certain matching commands
+   that make sense only in Emacs. */
+# ifdef emacs
+
+#  include "lisp.h"
+#  include "buffer.h"
+#  include "syntax.h"
+
+# else  /* not emacs */
+
+/* If we are not linking with Emacs proper,
+   we can't use the relocating allocator
+   even if config.h says that we can.  */
+#  undef REL_ALLOC
+
+#  if defined STDC_HEADERS || defined _LIBC
+#   include <stdlib.h>
+#  else
+char *malloc ();
+char *realloc ();
+#  endif
+
+/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
+   If nothing else has been done, use the method below.  */
+#  ifdef INHIBIT_STRING_HEADER
+#   if !(defined HAVE_BZERO && defined HAVE_BCOPY)
+#    if !defined bzero && !defined bcopy
+#     undef INHIBIT_STRING_HEADER
+#    endif
+#   endif
+#  endif
+
+/* This is the normal way of making sure we have a bcopy and a bzero.
+   This is used in most programs--a few other programs avoid this
+   by defining INHIBIT_STRING_HEADER.  */
+#  ifndef INHIBIT_STRING_HEADER
+#   if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC
+#    include <string.h>
+#    ifndef bzero
+#     ifndef _LIBC
+#      define bzero(s, n)	(memset (s, '\0', n), (s))
+#     else
+#      define bzero(s, n)	__bzero (s, n)
+#     endif
+#    endif
+#   else
+#    include <strings.h>
+#    ifndef memcmp
+#     define memcmp(s1, s2, n)	bcmp (s1, s2, n)
+#    endif
+#    ifndef memcpy
+#     define memcpy(d, s, n)	(bcopy (s, d, n), (d))
+#    endif
+#   endif
+#  endif
+
+/* Define the syntax stuff for \<, \>, etc.  */
+
+/* This must be nonzero for the wordchar and notwordchar pattern
+   commands in re_match_2.  */
+#  ifndef Sword
+#   define Sword 1
+#  endif
+
+#  ifdef SWITCH_ENUM_BUG
+#   define SWITCH_ENUM_CAST(x) ((int)(x))
+#  else
+#   define SWITCH_ENUM_CAST(x) (x)
+#  endif
+
+# endif /* not emacs */
+
+# if defined _LIBC || defined HAVE_LIMITS_H
+#  include <limits.h>
+# endif
+
+# ifndef MB_LEN_MAX
+#  define MB_LEN_MAX 1
+# endif
+
+/* Get the interface, including the syntax bits.  */
+# include <regex.h>
+
+/* isalpha etc. are used for the character classes.  */
+# include <ctype.h>
+
+/* Jim Meyering writes:
+
+   "... Some ctype macros are valid only for character codes that
+   isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+   using /bin/cc or gcc but without giving an ansi option).  So, all
+   ctype uses should be through macros like ISPRINT...  If
+   STDC_HEADERS is defined, then autoconf has verified that the ctype
+   macros don't need to be guarded with references to isascii. ...
+   Defining isascii to 1 should let any compiler worth its salt
+   eliminate the && through constant folding."
+   Solaris defines some of these symbols so we must undefine them first.  */
+
+# undef ISASCII
+# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+#  define ISASCII(c) 1
+# else
+#  define ISASCII(c) isascii(c)
+# endif
+
+# ifdef isblank
+#  define ISBLANK(c) (ISASCII (c) && isblank (c))
+# else
+#  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# endif
+# ifdef isgraph
+#  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+# else
+#  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+# endif
+
+# undef ISPRINT
+# define ISPRINT(c) (ISASCII (c) && isprint (c))
+# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+# define ISALNUM(c) (ISASCII (c) && isalnum (c))
+# define ISALPHA(c) (ISASCII (c) && isalpha (c))
+# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+# define ISLOWER(c) (ISASCII (c) && islower (c))
+# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+# define ISSPACE(c) (ISASCII (c) && isspace (c))
+# define ISUPPER(c) (ISASCII (c) && isupper (c))
+# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+# ifdef _tolower
+#  define TOLOWER(c) _tolower(c)
+# else
+#  define TOLOWER(c) tolower(c)
+# endif
+
+# ifndef NULL
+#  define NULL (void *)0
+# endif
+
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+   since ours (we hope) works properly with all combinations of
+   machines, compilers, `char' and `unsigned char' argument types.
+   (Per Bothner suggested the basic approach.)  */
+# undef SIGN_EXTEND_CHAR
+# if __STDC__
+#  define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+# else  /* not __STDC__ */
+/* As in Harbison and Steele.  */
+#  define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+# endif
+
+# ifndef emacs
+/* How many characters in the character set.  */
+#  define CHAR_SET_SIZE 256
+
+#  ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+#  else /* not SYNTAX_TABLE */
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void init_syntax_once (void);
+
+static void
+init_syntax_once (void)
+{
+   register int c;
+   static smallint done = 0;
+
+   if (done)
+     return;
+   bzero (re_syntax_table, sizeof re_syntax_table);
+
+   for (c = 0; c < CHAR_SET_SIZE; ++c)
+     if (ISALNUM (c))
+	re_syntax_table[c] = Sword;
+
+   re_syntax_table['_'] = Sword;
+
+   done = 1;
+}
+
+#  endif /* not SYNTAX_TABLE */
+
+#  define SYNTAX(c) re_syntax_table[(unsigned char) (c)]
+
+# endif /* emacs */
+
+/* Integer type for pointers.  */
+# if !defined _LIBC && !defined __intptr_t_defined
+typedef unsigned long int uintptr_t;
+# endif
+
+/* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
+   use `alloca' instead of `malloc'.  This is because using malloc in
+   re_search* or re_match* could cause memory leaks when C-g is used in
+   Emacs; also, malloc is slower and causes storage fragmentation.  On
+   the other hand, malloc is more portable, and easier to debug.
+
+   Because we sometimes use alloca, some routines have to be macros,
+   not functions -- `alloca'-allocated space disappears at the end of the
+   function it is called in.  */
+
+# ifdef REGEX_MALLOC
+
+#  define REGEX_ALLOCATE malloc
+#  define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+#  define REGEX_FREE free
+
+# else /* not REGEX_MALLOC  */
+
+/* Emacs already defines alloca, sometimes.  */
+#  ifndef alloca
+
+/* Make alloca work the best possible way.  */
+#   ifdef __GNUC__
+#    define alloca __builtin_alloca
+#   else /* not __GNUC__ */
+#    if HAVE_ALLOCA_H
+#     include <alloca.h>
+#    endif /* HAVE_ALLOCA_H */
+#   endif /* not __GNUC__ */
+
+#  endif /* not alloca */
+
+#  define REGEX_ALLOCATE alloca
+
+/* Assumes a `char *destination' variable.  */
+#  define REGEX_REALLOCATE(source, osize, nsize)			\
+  (destination = (char *) alloca (nsize),				\
+   memcpy (destination, source, osize))
+
+/* No need to do anything to free, after alloca.  */
+#  define REGEX_FREE(arg) ((void)0) /* Do nothing!  But inhibit gcc warning.  */
+
+# endif /* not REGEX_MALLOC */
+
+/* Define how to allocate the failure stack.  */
+
+# if defined REL_ALLOC && defined REGEX_MALLOC
+
+#  define REGEX_ALLOCATE_STACK(size)				\
+  r_alloc (&failure_stack_ptr, (size))
+#  define REGEX_REALLOCATE_STACK(source, osize, nsize)		\
+  r_re_alloc (&failure_stack_ptr, (nsize))
+#  define REGEX_FREE_STACK(ptr)					\
+  r_alloc_free (&failure_stack_ptr)
+
+# else /* not using relocating allocator */
+
+#  ifdef REGEX_MALLOC
+
+#   define REGEX_ALLOCATE_STACK malloc
+#   define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
+#   define REGEX_FREE_STACK free
+
+#  else /* not REGEX_MALLOC */
+
+#   define REGEX_ALLOCATE_STACK alloca
+
+#   define REGEX_REALLOCATE_STACK(source, osize, nsize)			\
+   REGEX_REALLOCATE (source, osize, nsize)
+/* No need to explicitly free anything.  */
+#   define REGEX_FREE_STACK(arg)
+
+#  endif /* not REGEX_MALLOC */
+# endif /* not using relocating allocator */
+
+
+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
+   `string1' or just past its end.  This works if PTR is NULL, which is
+   a good thing.  */
+# define FIRST_STRING_P(ptr) 					\
+  (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
+
+/* (Re)Allocate N items of type T using malloc, or fail.  */
+# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
+# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
+# define RETALLOC_IF(addr, n, t) \
+  if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
+# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+# define BYTEWIDTH 8 /* In bits.  */
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# undef MAX
+# undef MIN
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+# define false 0
+# define true 1
+
+static reg_errcode_t byte_regex_compile (const char *pattern, size_t size,
+                                                   reg_syntax_t syntax,
+                                                   struct re_pattern_buffer *bufp);
+
+static int byte_re_match_2_internal (struct re_pattern_buffer *bufp,
+					     const char *string1, int size1,
+					     const char *string2, int size2,
+					     int pos,
+					     struct re_registers *regs,
+					     int stop);
+static int byte_re_search_2 (struct re_pattern_buffer *bufp,
+				     const char *string1, int size1,
+				     const char *string2, int size2,
+				     int startpos, int range,
+				     struct re_registers *regs, int stop);
+static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp);
+
+#ifdef MBS_SUPPORT
+static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size,
+                                                   reg_syntax_t syntax,
+                                                   struct re_pattern_buffer *bufp);
+
+
+static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp,
+					    const char *cstring1, int csize1,
+					    const char *cstring2, int csize2,
+					    int pos,
+					    struct re_registers *regs,
+					    int stop,
+					    wchar_t *string1, int size1,
+					    wchar_t *string2, int size2,
+					    int *mbs_offset1, int *mbs_offset2);
+static int wcs_re_search_2 (struct re_pattern_buffer *bufp,
+				    const char *string1, int size1,
+				    const char *string2, int size2,
+				    int startpos, int range,
+				    struct re_registers *regs, int stop);
+static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp);
+#endif
+
+/* These are the command codes that appear in compiled regular
+   expressions.  Some opcodes are followed by argument bytes.  A
+   command code can specify any interpretation whatsoever for its
+   arguments.  Zero bytes may appear in the compiled regular expression.  */
+
+typedef enum
+{
+  no_op = 0,
+
+  /* Succeed right away--no more backtracking.  */
+  succeed,
+
+        /* Followed by one byte giving n, then by n literal bytes.  */
+  exactn,
+
+# ifdef MBS_SUPPORT
+	/* Same as exactn, but contains binary data.  */
+  exactn_bin,
+# endif
+
+        /* Matches any (more or less) character.  */
+  anychar,
+
+        /* Matches any one char belonging to specified set.  First
+           following byte is number of bitmap bytes.  Then come bytes
+           for a bitmap saying which chars are in.  Bits in each byte
+           are ordered low-bit-first.  A character is in the set if its
+           bit is 1.  A character too large to have a bit in the map is
+           automatically not in the set.  */
+        /* ifdef MBS_SUPPORT, following element is length of character
+	   classes, length of collating symbols, length of equivalence
+	   classes, length of character ranges, and length of characters.
+	   Next, character class element, collating symbols elements,
+	   equivalence class elements, range elements, and character
+	   elements follow.
+	   See regex_compile function.  */
+  charset,
+
+        /* Same parameters as charset, but match any character that is
+           not one of those specified.  */
+  charset_not,
+
+        /* Start remembering the text that is matched, for storing in a
+           register.  Followed by one byte with the register number, in
+           the range 0 to one less than the pattern buffer's re_nsub
+           field.  Then followed by one byte with the number of groups
+           inner to this one.  (This last has to be part of the
+           start_memory only because we need it in the on_failure_jump
+           of re_match_2.)  */
+  start_memory,
+
+        /* Stop remembering the text that is matched and store it in a
+           memory register.  Followed by one byte with the register
+           number, in the range 0 to one less than `re_nsub' in the
+           pattern buffer, and one byte with the number of inner groups,
+           just like `start_memory'.  (We need the number of inner
+           groups here because we don't have any easy way of finding the
+           corresponding start_memory when we're at a stop_memory.)  */
+  stop_memory,
+
+        /* Match a duplicate of something remembered. Followed by one
+           byte containing the register number.  */
+  duplicate,
+
+        /* Fail unless at beginning of line.  */
+  begline,
+
+        /* Fail unless at end of line.  */
+  endline,
+
+        /* Succeeds if at beginning of buffer (if emacs) or at beginning
+           of string to be matched (if not).  */
+  begbuf,
+
+        /* Analogously, for end of buffer/string.  */
+  endbuf,
+
+        /* Followed by two byte relative address to which to jump.  */
+  jump,
+
+	/* Same as jump, but marks the end of an alternative.  */
+  jump_past_alt,
+
+        /* Followed by two-byte relative address of place to resume at
+           in case of failure.  */
+        /* ifdef MBS_SUPPORT, the size of address is 1.  */
+  on_failure_jump,
+
+        /* Like on_failure_jump, but pushes a placeholder instead of the
+           current string position when executed.  */
+  on_failure_keep_string_jump,
+
+        /* Throw away latest failure point and then jump to following
+           two-byte relative address.  */
+        /* ifdef MBS_SUPPORT, the size of address is 1.  */
+  pop_failure_jump,
+
+        /* Change to pop_failure_jump if know won't have to backtrack to
+           match; otherwise change to jump.  This is used to jump
+           back to the beginning of a repeat.  If what follows this jump
+           clearly won't match what the repeat does, such that we can be
+           sure that there is no use backtracking out of repetitions
+           already matched, then we change it to a pop_failure_jump.
+           Followed by two-byte address.  */
+        /* ifdef MBS_SUPPORT, the size of address is 1.  */
+  maybe_pop_jump,
+
+        /* Jump to following two-byte address, and push a dummy failure
+           point. This failure point will be thrown away if an attempt
+           is made to use it for a failure.  A `+' construct makes this
+           before the first repeat.  Also used as an intermediary kind
+           of jump when compiling an alternative.  */
+        /* ifdef MBS_SUPPORT, the size of address is 1.  */
+  dummy_failure_jump,
+
+	/* Push a dummy failure point and continue.  Used at the end of
+	   alternatives.  */
+  push_dummy_failure,
+
+        /* Followed by two-byte relative address and two-byte number n.
+           After matching N times, jump to the address upon failure.  */
+        /* ifdef MBS_SUPPORT, the size of address is 1.  */
+  succeed_n,
+
+        /* Followed by two-byte relative address, and two-byte number n.
+           Jump to the address N times, then fail.  */
+        /* ifdef MBS_SUPPORT, the size of address is 1.  */
+  jump_n,
+
+        /* Set the following two-byte relative address to the
+           subsequent two-byte number.  The address *includes* the two
+           bytes of number.  */
+        /* ifdef MBS_SUPPORT, the size of address is 1.  */
+  set_number_at,
+
+  wordchar,	/* Matches any word-constituent character.  */
+  notwordchar,	/* Matches any char that is not a word-constituent.  */
+
+  wordbeg,	/* Succeeds if at word beginning.  */
+  wordend,	/* Succeeds if at word end.  */
+
+  wordbound,	/* Succeeds if at a word boundary.  */
+  notwordbound	/* Succeeds if not at a word boundary.  */
+
+# ifdef emacs
+  ,before_dot,	/* Succeeds if before point.  */
+  at_dot,	/* Succeeds if at point.  */
+  after_dot,	/* Succeeds if after point.  */
+
+	/* Matches any character whose syntax is specified.  Followed by
+           a byte which contains a syntax code, e.g., Sword.  */
+  syntaxspec,
+
+	/* Matches any character whose syntax is not that specified.  */
+  notsyntaxspec
+# endif /* emacs */
+} re_opcode_t;
+#endif /* not INSIDE_RECURSION */
+
+
+#ifdef BYTE
+# define CHAR_T char
+# define UCHAR_T unsigned char
+# define COMPILED_BUFFER_VAR bufp->buffer
+# define OFFSET_ADDRESS_SIZE 2
+# define PREFIX(name) byte_##name
+# define ARG_PREFIX(name) name
+# define PUT_CHAR(c) putchar (c)
+#else
+# ifdef WCHAR
+#  define CHAR_T wchar_t
+#  define UCHAR_T wchar_t
+#  define COMPILED_BUFFER_VAR wc_buffer
+#  define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */
+#  define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1)
+#  define PREFIX(name) wcs_##name
+#  define ARG_PREFIX(name) c##name
+/* Should we use wide stream??  */
+#  define PUT_CHAR(c) printf ("%C", c);
+#  define TRUE 1
+#  define FALSE 0
+# else
+#  ifdef MBS_SUPPORT
+#   define WCHAR
+#   define INSIDE_RECURSION
+#   include "regex_old.c"
+#   undef INSIDE_RECURSION
+#  endif
+#  define BYTE
+#  define INSIDE_RECURSION
+#  include "regex_old.c"
+#  undef INSIDE_RECURSION
+# endif
+#endif
+
+#ifdef INSIDE_RECURSION
+/* Common operations on the compiled pattern.  */
+
+/* Store NUMBER in two contiguous bytes starting at DESTINATION.  */
+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element.  */
+
+# ifdef WCHAR
+#  define STORE_NUMBER(destination, number)				\
+  do {									\
+    *(destination) = (UCHAR_T)(number);				\
+  } while (0)
+# else /* BYTE */
+#  define STORE_NUMBER(destination, number)				\
+  do {									\
+    (destination)[0] = (number) & 0377;					\
+    (destination)[1] = (number) >> 8;					\
+  } while (0)
+# endif /* WCHAR */
+
+/* Same as STORE_NUMBER, except increment DESTINATION to
+   the byte after where the number is stored.  Therefore, DESTINATION
+   must be an lvalue.  */
+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element.  */
+
+# define STORE_NUMBER_AND_INCR(destination, number)			\
+  do {									\
+    STORE_NUMBER (destination, number);					\
+    (destination) += OFFSET_ADDRESS_SIZE;				\
+  } while (0)
+
+/* Put into DESTINATION a number stored in two contiguous bytes starting
+   at SOURCE.  */
+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element.  */
+
+# ifdef WCHAR
+#  define EXTRACT_NUMBER(destination, source)				\
+  do {									\
+    (destination) = *(source);						\
+  } while (0)
+# else /* BYTE */
+#  define EXTRACT_NUMBER(destination, source)				\
+  do {									\
+    (destination) = *(source) & 0377;					\
+    (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8;		\
+  } while (0)
+# endif
+
+# ifdef DEBUG
+static void PREFIX(extract_number) (int *dest, UCHAR_T *source)
+{
+#  ifdef WCHAR
+  *dest = *source;
+#  else /* BYTE */
+  int temp = SIGN_EXTEND_CHAR (*(source + 1));
+  *dest = *source & 0377;
+  *dest += temp << 8;
+#  endif
+}
+
+#  ifndef EXTRACT_MACROS /* To debug the macros.  */
+#   undef EXTRACT_NUMBER
+#   define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src)
+#  endif /* not EXTRACT_MACROS */
+
+# endif /* DEBUG */
+
+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
+   SOURCE must be an lvalue.  */
+
+# define EXTRACT_NUMBER_AND_INCR(destination, source)			\
+  do {									\
+    EXTRACT_NUMBER (destination, source);				\
+    (source) += OFFSET_ADDRESS_SIZE; 					\
+  } while (0)
+
+# ifdef DEBUG
+static void PREFIX(extract_number_and_incr) (int *destination,
+						       UCHAR_T **source)
+{
+  PREFIX(extract_number) (destination, *source);
+  *source += OFFSET_ADDRESS_SIZE;
+}
+
+#  ifndef EXTRACT_MACROS
+#   undef EXTRACT_NUMBER_AND_INCR
+#   define EXTRACT_NUMBER_AND_INCR(dest, src) \
+  PREFIX(extract_number_and_incr) (&dest, &src)
+#  endif /* not EXTRACT_MACROS */
+
+# endif /* DEBUG */
+
+
+
+/* If DEBUG is defined, Regex prints many voluminous messages about what
+   it is doing (if the variable `debug' is nonzero).  If linked with the
+   main program in `iregex.c', you can enter patterns and strings
+   interactively.  And if linked with the main program in `main.c' and
+   the other test files, you can run the already-written tests.  */
+
+# ifdef DEBUG
+
+#  ifndef DEFINED_ONCE
+
+/* We use standard I/O for debugging.  */
+#   include <stdio.h>
+
+/* It is useful to test things that ``must'' be true when debugging.  */
+#   include <assert.h>
+
+static smallint debug;
+
+#   define DEBUG_STATEMENT(e) e
+#   define DEBUG_PRINT1(x) if (debug) printf (x)
+#   define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
+#   define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
+#   define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+#  endif /* not DEFINED_ONCE */
+
+#  define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) 			\
+  if (debug) PREFIX(print_partial_compiled_pattern) (s, e)
+#  define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)		\
+  if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2)
+
+
+/* Print the fastmap in human-readable form.  */
+
+#  ifndef DEFINED_ONCE
+static void
+print_fastmap (char *fastmap)
+{
+  unsigned was_a_range = 0;
+  unsigned i = 0;
+
+  while (i < (1 << BYTEWIDTH))
+    {
+      if (fastmap[i++])
+	{
+	  was_a_range = 0;
+          putchar (i - 1);
+          while (i < (1 << BYTEWIDTH)  &&  fastmap[i])
+            {
+              was_a_range = 1;
+              i++;
+            }
+	  if (was_a_range)
+            {
+              printf ("-");
+              putchar (i - 1);
+            }
+        }
+    }
+  putchar ('\n');
+}
+#  endif /* not DEFINED_ONCE */
+
+
+/* Print a compiled pattern string in human-readable form, starting at
+   the START pointer into it and ending just before the pointer END.  */
+
+static void
+PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end)
+{
+  int mcnt, mcnt2;
+  UCHAR_T *p1;
+  UCHAR_T *p = start;
+  UCHAR_T *pend = end;
+
+  if (start == NULL)
+    {
+      printf ("(null)\n");
+      return;
+    }
+
+  /* Loop over pattern commands.  */
+  while (p < pend)
+    {
+#  ifdef _LIBC
+      printf ("%td:\t", p - start);
+#  else
+      printf ("%ld:\t", (long int) (p - start));
+#  endif
+
+      switch ((re_opcode_t) *p++)
+	{
+        case no_op:
+          printf ("/no_op");
+          break;
+
+	case exactn:
+	  mcnt = *p++;
+          printf ("/exactn/%d", mcnt);
+          do
+	    {
+              putchar ('/');
+	      PUT_CHAR (*p++);
+            }
+          while (--mcnt);
+          break;
+
+#  ifdef MBS_SUPPORT
+	case exactn_bin:
+	  mcnt = *p++;
+	  printf ("/exactn_bin/%d", mcnt);
+          do
+	    {
+	      printf("/%lx", (long int) *p++);
+            }
+          while (--mcnt);
+          break;
+#  endif /* MBS_SUPPORT */
+
+	case start_memory:
+          mcnt = *p++;
+          printf ("/start_memory/%d/%ld", mcnt, (long int) *p++);
+          break;
+
+	case stop_memory:
+          mcnt = *p++;
+	  printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++);
+          break;
+
+	case duplicate:
+	  printf ("/duplicate/%ld", (long int) *p++);
+	  break;
+
+	case anychar:
+	  printf ("/anychar");
+	  break;
+
+	case charset:
+        case charset_not:
+          {
+#  ifdef WCHAR
+	    int i, length;
+	    wchar_t *workp = p;
+	    printf ("/charset [%s",
+	            (re_opcode_t) *(workp - 1) == charset_not ? "^" : "");
+	    p += 5;
+	    length = *workp++; /* the length of char_classes */
+	    for (i=0 ; i<length ; i++)
+	      printf("[:%lx:]", (long int) *p++);
+	    length = *workp++; /* the length of collating_symbol */
+	    for (i=0 ; i<length ;)
+	      {
+		printf("[.");
+		while(*p != 0)
+		  PUT_CHAR((i++,*p++));
+		i++,p++;
+		printf(".]");
+	      }
+	    length = *workp++; /* the length of equivalence_class */
+	    for (i=0 ; i<length ;)
+	      {
+		printf("[=");
+		while(*p != 0)
+		  PUT_CHAR((i++,*p++));
+		i++,p++;
+		printf("=]");
+	      }
+	    length = *workp++; /* the length of char_range */
+	    for (i=0 ; i<length ; i++)
+	      {
+		wchar_t range_start = *p++;
+		wchar_t range_end = *p++;
+		printf("%C-%C", range_start, range_end);
+	      }
+	    length = *workp++; /* the length of char */
+	    for (i=0 ; i<length ; i++)
+	      printf("%C", *p++);
+	    putchar (']');
+#  else
+            register int c, last = -100;
+	    register int in_range = 0;
+
+	    printf ("/charset [%s",
+	            (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
+
+            assert (p + *p < pend);
+
+            for (c = 0; c < 256; c++)
+	      if (c / 8 < *p
+		  && (p[1 + (c/8)] & (1 << (c % 8))))
+		{
+		  /* Are we starting a range?  */
+		  if (last + 1 == c && ! in_range)
+		    {
+		      putchar ('-');
+		      in_range = 1;
+		    }
+		  /* Have we broken a range?  */
+		  else if (last + 1 != c && in_range)
+              {
+		      putchar (last);
+		      in_range = 0;
+		    }
+
+		  if (! in_range)
+		    putchar (c);
+
+		  last = c;
+              }
+
+	    if (in_range)
+	      putchar (last);
+
+	    putchar (']');
+
+	    p += 1 + *p;
+#  endif /* WCHAR */
+	  }
+	  break;
+
+	case begline:
+	  printf ("/begline");
+          break;
+
+	case endline:
+          printf ("/endline");
+          break;
+
+	case on_failure_jump:
+          PREFIX(extract_number_and_incr) (&mcnt, &p);
+#  ifdef _LIBC
+  	  printf ("/on_failure_jump to %td", p + mcnt - start);
+#  else
+  	  printf ("/on_failure_jump to %ld", (long int) (p + mcnt - start));
+#  endif
+          break;
+
+	case on_failure_keep_string_jump:
+          PREFIX(extract_number_and_incr) (&mcnt, &p);
+#  ifdef _LIBC
+  	  printf ("/on_failure_keep_string_jump to %td", p + mcnt - start);
+#  else
+  	  printf ("/on_failure_keep_string_jump to %ld",
+		  (long int) (p + mcnt - start));
+#  endif
+          break;
+
+	case dummy_failure_jump:
+          PREFIX(extract_number_and_incr) (&mcnt, &p);
+#  ifdef _LIBC
+  	  printf ("/dummy_failure_jump to %td", p + mcnt - start);
+#  else
+  	  printf ("/dummy_failure_jump to %ld", (long int) (p + mcnt - start));
+#  endif
+          break;
+
+	case push_dummy_failure:
+          printf ("/push_dummy_failure");
+          break;
+
+        case maybe_pop_jump:
+          PREFIX(extract_number_and_incr) (&mcnt, &p);
+#  ifdef _LIBC
+  	  printf ("/maybe_pop_jump to %td", p + mcnt - start);
+#  else
+  	  printf ("/maybe_pop_jump to %ld", (long int) (p + mcnt - start));
+#  endif
+	  break;
+
+        case pop_failure_jump:
+	  PREFIX(extract_number_and_incr) (&mcnt, &p);
+#  ifdef _LIBC
+  	  printf ("/pop_failure_jump to %td", p + mcnt - start);
+#  else
+  	  printf ("/pop_failure_jump to %ld", (long int) (p + mcnt - start));
+#  endif
+	  break;
+
+        case jump_past_alt:
+	  PREFIX(extract_number_and_incr) (&mcnt, &p);
+#  ifdef _LIBC
+  	  printf ("/jump_past_alt to %td", p + mcnt - start);
+#  else
+  	  printf ("/jump_past_alt to %ld", (long int) (p + mcnt - start));
+#  endif
+	  break;
+
+        case jump:
+	  PREFIX(extract_number_and_incr) (&mcnt, &p);
+#  ifdef _LIBC
+  	  printf ("/jump to %td", p + mcnt - start);
+#  else
+  	  printf ("/jump to %ld", (long int) (p + mcnt - start));
+#  endif
+	  break;
+
+        case succeed_n:
+          PREFIX(extract_number_and_incr) (&mcnt, &p);
+	  p1 = p + mcnt;
+          PREFIX(extract_number_and_incr) (&mcnt2, &p);
+#  ifdef _LIBC
+	  printf ("/succeed_n to %td, %d times", p1 - start, mcnt2);
+#  else
+	  printf ("/succeed_n to %ld, %d times",
+		  (long int) (p1 - start), mcnt2);
+#  endif
+          break;
+
+        case jump_n:
+          PREFIX(extract_number_and_incr) (&mcnt, &p);
+	  p1 = p + mcnt;
+          PREFIX(extract_number_and_incr) (&mcnt2, &p);
+	  printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
+          break;
+
+        case set_number_at:
+          PREFIX(extract_number_and_incr) (&mcnt, &p);
+	  p1 = p + mcnt;
+          PREFIX(extract_number_and_incr) (&mcnt2, &p);
+#  ifdef _LIBC
+	  printf ("/set_number_at location %td to %d", p1 - start, mcnt2);
+#  else
+	  printf ("/set_number_at location %ld to %d",
+		  (long int) (p1 - start), mcnt2);
+#  endif
+          break;
+
+        case wordbound:
+	  printf ("/wordbound");
+	  break;
+
+	case notwordbound:
+	  printf ("/notwordbound");
+          break;
+
+	case wordbeg:
+	  printf ("/wordbeg");
+	  break;
+
+	case wordend:
+	  printf ("/wordend");
+	  break;
+
+#  ifdef emacs
+	case before_dot:
+	  printf ("/before_dot");
+          break;
+
+	case at_dot:
+	  printf ("/at_dot");
+          break;
+
+	case after_dot:
+	  printf ("/after_dot");
+          break;
+
+	case syntaxspec:
+          printf ("/syntaxspec");
+	  mcnt = *p++;
+	  printf ("/%d", mcnt);
+          break;
+
+	case notsyntaxspec:
+          printf ("/notsyntaxspec");
+	  mcnt = *p++;
+	  printf ("/%d", mcnt);
+	  break;
+#  endif /* emacs */
+
+	case wordchar:
+	  printf ("/wordchar");
+          break;
+
+	case notwordchar:
+	  printf ("/notwordchar");
+          break;
+
+	case begbuf:
+	  printf ("/begbuf");
+          break;
+
+	case endbuf:
+	  printf ("/endbuf");
+          break;
+
+        default:
+          printf ("?%ld", (long int) *(p-1));
+	}
+
+      putchar ('\n');
+    }
+
+#  ifdef _LIBC
+  printf ("%td:\tend of pattern.\n", p - start);
+#  else
+  printf ("%ld:\tend of pattern.\n", (long int) (p - start));
+#  endif
+}
+
+
+static void
+PREFIX(print_compiled_pattern) (struct re_pattern_buffer *bufp)
+{
+  UCHAR_T *buffer = (UCHAR_T*) bufp->buffer;
+
+  PREFIX(print_partial_compiled_pattern) (buffer, buffer
+				  + bufp->used / sizeof(UCHAR_T));
+  printf ("%ld bytes used/%ld bytes allocated.\n",
+	  bufp->used, bufp->allocated);
+
+  if (bufp->fastmap_accurate && bufp->fastmap)
+    {
+      printf ("fastmap: ");
+      print_fastmap (bufp->fastmap);
+    }
+
+#  ifdef _LIBC
+  printf ("re_nsub: %Zd\t", bufp->re_nsub);
+#  else
+  printf ("re_nsub: %ld\t", (long int) bufp->re_nsub);
+#  endif
+  printf ("regs_alloc: %d\t", bufp->regs_allocated);
+  printf ("can_be_null: %d\t", bufp->can_be_null);
+  printf ("newline_anchor: %d\n", bufp->newline_anchor);
+  printf ("no_sub: %d\t", bufp->no_sub);
+  printf ("not_bol: %d\t", bufp->not_bol);
+  printf ("not_eol: %d\t", bufp->not_eol);
+  printf ("syntax: %lx\n", bufp->syntax);
+  /* Perhaps we should print the translate table?  */
+}
+
+
+static void
+PREFIX(print_double_string) (
+    const CHAR_T *where,
+    const CHAR_T *string1,
+    int size1,
+    const CHAR_T *string2,
+    int size2)
+{
+  int this_char;
+
+  if (where == NULL)
+    printf ("(null)");
+  else
+    {
+      int cnt;
+
+      if (FIRST_STRING_P (where))
+        {
+          for (this_char = where - string1; this_char < size1; this_char++)
+	    PUT_CHAR (string1[this_char]);
+
+          where = string2;
+        }
+
+      cnt = 0;
+      for (this_char = where - string2; this_char < size2; this_char++)
+	{
+	  PUT_CHAR (string2[this_char]);
+	  if (++cnt > 100)
+	    {
+	      fputs ("...", stdout);
+	      break;
+	    }
+	}
+    }
+}
+
+#  if 0 /* ndef DEFINED_ONCE */
+void
+printchar (int c)
+{
+  putc (c, stderr);
+}
+#  endif
+
+# else /* not DEBUG */
+
+#  ifndef DEFINED_ONCE
+#   undef assert
+#   define assert(e)
+
+#   define DEBUG_STATEMENT(e)
+#   define DEBUG_PRINT1(x)
+#   define DEBUG_PRINT2(x1, x2)
+#   define DEBUG_PRINT3(x1, x2, x3)
+#   define DEBUG_PRINT4(x1, x2, x3, x4)
+#  endif /* not DEFINED_ONCE */
+#  define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+#  define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+# endif /* not DEBUG */
+
+
+
+# ifdef WCHAR
+/* This  convert a multibyte string to a wide character string.
+   And write their correspondances to offset_buffer(see below)
+   and write whether each wchar_t is binary data to is_binary.
+   This assume invalid multibyte sequences as binary data.
+   We assume offset_buffer and is_binary is already allocated
+   enough space.  */
+
+static size_t
+convert_mbs_to_wcs (
+     CHAR_T *dest,
+     const unsigned char* src,
+     size_t len, /* the length of multibyte string.  */
+
+     /* It hold correspondances between src(char string) and
+	dest(wchar_t string) for optimization.
+	e.g. src  = "xxxyzz"
+             dest = {'X', 'Y', 'Z'}
+	      (each "xxx", "y" and "zz" represent one multibyte character
+	       corresponding to 'X', 'Y' and 'Z'.)
+	  offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")}
+	  	        = {0, 3, 4, 6}
+     */
+     int *offset_buffer,
+     char *is_binary)
+{
+  wchar_t *pdest = dest;
+  const unsigned char *psrc = src;
+  size_t wc_count = 0;
+
+  mbstate_t mbs;
+  int i, consumed;
+  size_t mb_remain = len;
+  size_t mb_count = 0;
+
+  /* Initialize the conversion state.  */
+  memset (&mbs, 0, sizeof (mbstate_t));
+
+  offset_buffer[0] = 0;
+  for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed,
+	 psrc += consumed)
+    {
+#ifdef _LIBC
+      consumed = __mbrtowc (pdest, psrc, mb_remain, &mbs);
+#else
+      consumed = mbrtowc (pdest, psrc, mb_remain, &mbs);
+#endif
+
+      if (consumed <= 0)
+	/* failed to convert. maybe src contains binary data.
+	   So we consume 1 byte manualy.  */
+	{
+	  *pdest = *psrc;
+	  consumed = 1;
+	  is_binary[wc_count] = TRUE;
+	}
+      else
+	is_binary[wc_count] = FALSE;
+      /* In sjis encoding, we use yen sign as escape character in
+	 place of reverse solidus. So we convert 0x5c(yen sign in
+	 sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse
+	 solidus in UCS2).  */
+      if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5)
+	*pdest = (wchar_t) *psrc;
+
+      offset_buffer[wc_count + 1] = mb_count += consumed;
+    }
+
+  /* Fill remain of the buffer with sentinel.  */
+  for (i = wc_count + 1 ; i <= len ; i++)
+    offset_buffer[i] = mb_count + 1;
+
+  return wc_count;
+}
+
+# endif /* WCHAR */
+
+#else /* not INSIDE_RECURSION */
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
+   also be assigned to arbitrarily: each pattern buffer stores its own
+   syntax, so it can be changed between regex compilations.  */
+/* This has no initializer because initialized variables in Emacs
+   become read-only after dumping.  */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation.  This provides
+   for compatibility for various utilities which historically have
+   different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit mask comprised of the various bits
+   defined in regex.h.  We return the old syntax.  */
+
+reg_syntax_t
+re_set_syntax (reg_syntax_t syntax)
+{
+  reg_syntax_t ret = re_syntax_options;
+
+  re_syntax_options = syntax;
+# ifdef DEBUG
+  if (syntax & RE_DEBUG)
+    debug = 1;
+  else if (debug) /* was on but now is not */
+    debug = 0;
+# endif /* DEBUG */
+  return ret;
+}
+
+/* This table gives an error message for each of the error codes listed
+   in regex.h.  Obviously the order here has to be same as there.
+   POSIX doesn't require that we do anything for REG_NOERROR,
+   but why not be nice?  */
+
+static const char re_error_msgid[] =
+  {
+# define REG_NOERROR_IDX	0
+    gettext_noop ("Success")	/* REG_NOERROR */
+    "\0"
+# define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
+    gettext_noop ("No match")	/* REG_NOMATCH */
+    "\0"
+# define REG_BADPAT_IDX	(REG_NOMATCH_IDX + sizeof "No match")
+    gettext_noop ("Invalid regular expression") /* REG_BADPAT */
+    "\0"
+# define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
+    gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
+    "\0"
+# define REG_ECTYPE_IDX	(REG_ECOLLATE_IDX + sizeof "Invalid collation character")
+    gettext_noop ("Invalid character class name") /* REG_ECTYPE */
+    "\0"
+# define REG_EESCAPE_IDX	(REG_ECTYPE_IDX + sizeof "Invalid character class name")
+    gettext_noop ("Trailing backslash") /* REG_EESCAPE */
+    "\0"
+# define REG_ESUBREG_IDX	(REG_EESCAPE_IDX + sizeof "Trailing backslash")
+    gettext_noop ("Invalid back reference") /* REG_ESUBREG */
+    "\0"
+# define REG_EBRACK_IDX	(REG_ESUBREG_IDX + sizeof "Invalid back reference")
+    gettext_noop ("Unmatched [ or [^")	/* REG_EBRACK */
+    "\0"
+# define REG_EPAREN_IDX	(REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
+    gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
+    "\0"
+# define REG_EBRACE_IDX	(REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
+    gettext_noop ("Unmatched \\{") /* REG_EBRACE */
+    "\0"
+# define REG_BADBR_IDX	(REG_EBRACE_IDX + sizeof "Unmatched \\{")
+    gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
+    "\0"
+# define REG_ERANGE_IDX	(REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
+    gettext_noop ("Invalid range end")	/* REG_ERANGE */
+    "\0"
+# define REG_ESPACE_IDX	(REG_ERANGE_IDX + sizeof "Invalid range end")
+    gettext_noop ("Memory exhausted") /* REG_ESPACE */
+    "\0"
+# define REG_BADRPT_IDX	(REG_ESPACE_IDX + sizeof "Memory exhausted")
+    gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
+    "\0"
+# define REG_EEND_IDX	(REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
+    gettext_noop ("Premature end of regular expression") /* REG_EEND */
+    "\0"
+# define REG_ESIZE_IDX	(REG_EEND_IDX + sizeof "Premature end of regular expression")
+    gettext_noop ("Regular expression too big") /* REG_ESIZE */
+    "\0"
+# define REG_ERPAREN_IDX	(REG_ESIZE_IDX + sizeof "Regular expression too big")
+    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
+  };
+
+static const uint16_t re_error_msgid_idx[] =
+  {
+    REG_NOERROR_IDX,
+    REG_NOMATCH_IDX,
+    REG_BADPAT_IDX,
+    REG_ECOLLATE_IDX,
+    REG_ECTYPE_IDX,
+    REG_EESCAPE_IDX,
+    REG_ESUBREG_IDX,
+    REG_EBRACK_IDX,
+    REG_EPAREN_IDX,
+    REG_EBRACE_IDX,
+    REG_BADBR_IDX,
+    REG_ERANGE_IDX,
+    REG_ESPACE_IDX,
+    REG_BADRPT_IDX,
+    REG_EEND_IDX,
+    REG_ESIZE_IDX,
+    REG_ERPAREN_IDX
+  };
+
+#endif /* INSIDE_RECURSION */
+
+#ifndef DEFINED_ONCE
+/* Avoiding alloca during matching, to placate r_alloc.  */
+
+/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
+   searching and matching functions should not call alloca.  On some
+   systems, alloca is implemented in terms of malloc, and if we're
+   using the relocating allocator routines, then malloc could cause a
+   relocation, which might (if the strings being searched are in the
+   ralloc heap) shift the data out from underneath the regexp
+   routines.
+
+   Here's another reason to avoid allocation: Emacs
+   processes input from X in a signal handler; processing X input may
+   call malloc; if input arrives while a matching routine is calling
+   malloc, then we're scrod.  But Emacs can't just block input while
+   calling matching routines; then we don't notice interrupts when
+   they come in.  So, Emacs blocks input around all regexp calls
+   except the matching calls, which it leaves unprotected, in the
+   faith that they will not malloc.  */
+
+/* Normally, this is fine.  */
+# define MATCH_MAY_ALLOCATE
+
+/* When using GNU C, we are not REALLY using the C alloca, no matter
+   what config.h may say.  So don't take precautions for it.  */
+# ifdef __GNUC__
+#  undef C_ALLOCA
+# endif
+
+/* The match routines may not allocate if (1) they would do it with malloc
+   and (2) it's not safe for them to use malloc.
+   Note that if REL_ALLOC is defined, matching would not use malloc for the
+   failure stack, but we would still use it for the register vectors;
+   so REL_ALLOC should not affect this.  */
+# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
+#  undef MATCH_MAY_ALLOCATE
+# endif
+#endif /* not DEFINED_ONCE */
+
+#ifdef INSIDE_RECURSION
+/* Failure stack declarations and macros; both re_compile_fastmap and
+   re_match_2 use a failure stack.  These have to be macros because of
+   REGEX_ALLOCATE_STACK.  */
+
+
+/* Number of failure points for which to initially allocate space
+   when matching.  If this number is exceeded, we allocate more
+   space, so it is not a hard limit.  */
+# ifndef INIT_FAILURE_ALLOC
+#  define INIT_FAILURE_ALLOC 5
+# endif
+
+/* Roughly the maximum number of failure points on the stack.  Would be
+   exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
+   This is a variable only so users of regex can assign to it; we never
+   change it ourselves.  */
+
+# ifdef INT_IS_16BIT
+
+#  ifndef DEFINED_ONCE
+#   if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+   whose default stack limit is 2mb.  */
+long int re_max_failures = 4000;
+#   else
+long int re_max_failures = 2000;
+#   endif
+#  endif
+
+union PREFIX(fail_stack_elt)
+{
+  UCHAR_T *pointer;
+  long int integer;
+};
+
+typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t);
+
+typedef struct
+{
+  PREFIX(fail_stack_elt_t) *stack;
+  unsigned long int size;
+  unsigned long int avail;		/* Offset of next open position.  */
+} PREFIX(fail_stack_type);
+
+# else /* not INT_IS_16BIT */
+
+#  ifndef DEFINED_ONCE
+#   if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+   whose default stack limit is 2mb.  */
+int re_max_failures = 4000;
+#   else
+int re_max_failures = 2000;
+#   endif
+#  endif
+
+union PREFIX(fail_stack_elt)
+{
+  UCHAR_T *pointer;
+  int integer;
+};
+
+typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t);
+
+typedef struct
+{
+  PREFIX(fail_stack_elt_t) *stack;
+  unsigned size;
+  unsigned avail;			/* Offset of next open position.  */
+} PREFIX(fail_stack_type);
+
+# endif /* INT_IS_16BIT */
+
+# ifndef DEFINED_ONCE
+#  define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
+#  define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
+#  define FAIL_STACK_FULL()      (fail_stack.avail == fail_stack.size)
+# endif
+
+
+/* Define macros to initialize and free the failure stack.
+   Do `return -2' if the alloc fails.  */
+
+# ifdef MATCH_MAY_ALLOCATE
+#  define INIT_FAIL_STACK()						\
+  do {									\
+    fail_stack.stack = (PREFIX(fail_stack_elt_t) *)		\
+      REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \
+									\
+    if (fail_stack.stack == NULL)				\
+      return -2;							\
+									\
+    fail_stack.size = INIT_FAILURE_ALLOC;			\
+    fail_stack.avail = 0;					\
+  } while (0)
+
+#  define RESET_FAIL_STACK()  REGEX_FREE_STACK (fail_stack.stack)
+# else
+#  define INIT_FAIL_STACK()						\
+  do {									\
+    fail_stack.avail = 0;					\
+  } while (0)
+
+#  define RESET_FAIL_STACK()
+# endif
+
+
+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
+
+   Return 1 if succeeds, and 0 if either ran out of memory
+   allocating space for it or it was already too large.
+
+   REGEX_REALLOCATE_STACK requires `destination' be declared.   */
+
+# define DOUBLE_FAIL_STACK(fail_stack)					\
+  ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS)	\
+   ? 0									\
+   : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *)			\
+        REGEX_REALLOCATE_STACK ((fail_stack).stack, 			\
+          (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)),	\
+          ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\
+									\
+      (fail_stack).stack == NULL					\
+      ? 0								\
+      : ((fail_stack).size <<= 1, 					\
+         1)))
+
+
+/* Push pointer POINTER on FAIL_STACK.
+   Return 1 if was able to do so and 0 if ran out of memory allocating
+   space to do so.  */
+# define PUSH_PATTERN_OP(POINTER, FAIL_STACK)				\
+  ((FAIL_STACK_FULL ()							\
+    && !DOUBLE_FAIL_STACK (FAIL_STACK))					\
+   ? 0									\
+   : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER,	\
+      1))
+
+/* Push a pointer value onto the failure stack.
+   Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
+# define PUSH_FAILURE_POINTER(item)					\
+  fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item)
+
+/* This pushes an integer-valued item onto the failure stack.
+   Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
+# define PUSH_FAILURE_INT(item)					\
+  fail_stack.stack[fail_stack.avail++].integer = (item)
+
+/* Push a fail_stack_elt_t value onto the failure stack.
+   Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
+# define PUSH_FAILURE_ELT(item)					\
+  fail_stack.stack[fail_stack.avail++] =  (item)
+
+/* These three POP... operations complement the three PUSH... operations.
+   All assume that `fail_stack' is nonempty.  */
+# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
+# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
+# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
+
+/* Used to omit pushing failure point id's when we're not debugging.  */
+# ifdef DEBUG
+#  define DEBUG_PUSH PUSH_FAILURE_INT
+#  define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
+# else
+#  define DEBUG_PUSH(item)
+#  define DEBUG_POP(item_addr)
+# endif
+
+
+/* Push the information about the state we will need
+   if we ever fail back to it.
+
+   Requires variables fail_stack, regstart, regend, reg_info, and
+   num_regs_pushed be declared.  DOUBLE_FAIL_STACK requires `destination'
+   be declared.
+
+   Does `return FAILURE_CODE' if runs out of memory.  */
+
+# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code)	\
+  do {									\
+    char *destination;							\
+    /* Must be int, so when we don't save any registers, the arithmetic	\
+       of 0 + -1 isn't done as unsigned.  */				\
+    /* Can't be int, since there is not a shred of a guarantee that int	\
+       is wide enough to hold a value of something to which pointer can	\
+       be assigned */							\
+    active_reg_t this_reg;						\
+    									\
+    DEBUG_STATEMENT (failure_id++);					\
+    DEBUG_STATEMENT (nfailure_points_pushed++);				\
+    DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);		\
+    DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
+    DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
+									\
+    DEBUG_PRINT2 ("  slots needed: %ld\n", NUM_FAILURE_ITEMS);		\
+    DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);	\
+									\
+    /* Ensure we have enough space allocated for what we will push.  */	\
+    while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)			\
+      {									\
+        if (!DOUBLE_FAIL_STACK (fail_stack))				\
+          return failure_code;						\
+									\
+        DEBUG_PRINT2 ("\n  Doubled stack; size now: %d\n",		\
+		       (fail_stack).size);				\
+        DEBUG_PRINT2 ("  slots available: %d\n", REMAINING_AVAIL_SLOTS);\
+      }									\
+									\
+    /* Push the info, starting with the registers.  */			\
+    DEBUG_PRINT1 ("\n");						\
+									\
+    if (1)								\
+      for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
+	   this_reg++)							\
+	{								\
+	  DEBUG_PRINT2 ("  Pushing reg: %lu\n", this_reg);		\
+	  DEBUG_STATEMENT (num_regs_pushed++);				\
+									\
+	  DEBUG_PRINT2 ("    start: %p\n", regstart[this_reg]);		\
+	  PUSH_FAILURE_POINTER (regstart[this_reg]);			\
+									\
+	  DEBUG_PRINT2 ("    end: %p\n", regend[this_reg]);		\
+	  PUSH_FAILURE_POINTER (regend[this_reg]);			\
+									\
+	  DEBUG_PRINT2 ("    info: %p\n      ",				\
+			reg_info[this_reg].word.pointer);		\
+	  DEBUG_PRINT2 (" match_null=%d",				\
+			REG_MATCH_NULL_STRING_P (reg_info[this_reg]));	\
+	  DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));	\
+	  DEBUG_PRINT2 (" matched_something=%d",			\
+			MATCHED_SOMETHING (reg_info[this_reg]));	\
+	  DEBUG_PRINT2 (" ever_matched=%d",				\
+			EVER_MATCHED_SOMETHING (reg_info[this_reg]));	\
+	  DEBUG_PRINT1 ("\n");						\
+	  PUSH_FAILURE_ELT (reg_info[this_reg].word);			\
+	}								\
+									\
+    DEBUG_PRINT2 ("  Pushing  low active reg: %ld\n", lowest_active_reg);\
+    PUSH_FAILURE_INT (lowest_active_reg);				\
+									\
+    DEBUG_PRINT2 ("  Pushing high active reg: %ld\n", highest_active_reg);\
+    PUSH_FAILURE_INT (highest_active_reg);				\
+									\
+    DEBUG_PRINT2 ("  Pushing pattern %p:\n", pattern_place);		\
+    DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);		\
+    PUSH_FAILURE_POINTER (pattern_place);				\
+									\
+    DEBUG_PRINT2 ("  Pushing string %p: `", string_place);		\
+    DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
+				 size2);				\
+    DEBUG_PRINT1 ("'\n");						\
+    PUSH_FAILURE_POINTER (string_place);				\
+									\
+    DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);		\
+    DEBUG_PUSH (failure_id);						\
+  } while (0)
+
+# ifndef DEFINED_ONCE
+/* This is the number of items that are pushed and popped on the stack
+   for each register.  */
+#  define NUM_REG_ITEMS  3
+
+/* Individual items aside from the registers.  */
+#  ifdef DEBUG
+#   define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
+#  else
+#   define NUM_NONREG_ITEMS 4
+#  endif
+
+/* We push at most this many items on the stack.  */
+/* We used to use (num_regs - 1), which is the number of registers
+   this regexp will save; but that was changed to 5
+   to avoid stack overflow for a regexp with lots of parens.  */
+#  define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items.  */
+#  define NUM_FAILURE_ITEMS				\
+  (((0							\
+     ? 0 : highest_active_reg - lowest_active_reg + 1)	\
+    * NUM_REG_ITEMS)					\
+   + NUM_NONREG_ITEMS)
+
+/* How many items can still be added to the stack without overflowing it.  */
+#  define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+# endif /* not DEFINED_ONCE */
+
+
+/* Pops what PUSH_FAIL_STACK pushes.
+
+   We restore into the parameters, all of which should be lvalues:
+     STR -- the saved data position.
+     PAT -- the saved pattern position.
+     LOW_REG, HIGH_REG -- the highest and lowest active registers.
+     REGSTART, REGEND -- arrays of string positions.
+     REG_INFO -- array of information about each subexpression.
+
+   Also assumes the variables `fail_stack' and (if debugging), `bufp',
+   `pend', `string1', `size1', `string2', and `size2'.  */
+# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
+{									\
+  DEBUG_STATEMENT (unsigned failure_id;)				\
+  active_reg_t this_reg;						\
+  const UCHAR_T *string_temp;						\
+									\
+  assert (!FAIL_STACK_EMPTY ());					\
+									\
+  /* Remove failure points and point to how many regs pushed.  */	\
+  DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");				\
+  DEBUG_PRINT2 ("  Before pop, next avail: %d\n", fail_stack.avail);	\
+  DEBUG_PRINT2 ("                    size: %d\n", fail_stack.size);	\
+									\
+  assert (fail_stack.avail >= NUM_NONREG_ITEMS);			\
+									\
+  DEBUG_POP (&failure_id);						\
+  DEBUG_PRINT2 ("  Popping failure id: %u\n", failure_id);		\
+									\
+  /* If the saved string location is NULL, it came from an		\
+     on_failure_keep_string_jump opcode, and we want to throw away the	\
+     saved NULL, thus retaining our current position in the string.  */	\
+  string_temp = POP_FAILURE_POINTER ();					\
+  if (string_temp != NULL)						\
+    str = (const CHAR_T *) string_temp;					\
+									\
+  DEBUG_PRINT2 ("  Popping string %p: `", str);				\
+  DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);	\
+  DEBUG_PRINT1 ("'\n");							\
+									\
+  pat = (UCHAR_T *) POP_FAILURE_POINTER ();				\
+  DEBUG_PRINT2 ("  Popping pattern %p:\n", pat);			\
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);			\
+									\
+  /* Restore register info.  */						\
+  high_reg = (active_reg_t) POP_FAILURE_INT ();				\
+  DEBUG_PRINT2 ("  Popping high active reg: %ld\n", high_reg);		\
+									\
+  low_reg = (active_reg_t) POP_FAILURE_INT ();				\
+  DEBUG_PRINT2 ("  Popping  low active reg: %ld\n", low_reg);		\
+									\
+  if (1)								\
+    for (this_reg = high_reg; this_reg >= low_reg; this_reg--)		\
+      {									\
+	DEBUG_PRINT2 ("    Popping reg: %ld\n", this_reg);		\
+									\
+	reg_info[this_reg].word = POP_FAILURE_ELT ();			\
+	DEBUG_PRINT2 ("      info: %p\n",				\
+		      reg_info[this_reg].word.pointer);			\
+									\
+	regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER ();	\
+	DEBUG_PRINT2 ("      end: %p\n", regend[this_reg]);		\
+									\
+	regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER ();	\
+	DEBUG_PRINT2 ("      start: %p\n", regstart[this_reg]);		\
+      }									\
+  else									\
+    {									\
+      for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
+	{								\
+	  reg_info[this_reg].word.integer = 0;				\
+	  regend[this_reg] = 0;						\
+	  regstart[this_reg] = 0;					\
+	}								\
+      highest_active_reg = high_reg;					\
+    }									\
+									\
+  set_regs_matched_done = 0;						\
+  DEBUG_STATEMENT (nfailure_points_popped++);				\
+} /* POP_FAILURE_POINT */
+
+/* Structure for per-register (a.k.a. per-group) information.
+   Other register information, such as the
+   starting and ending positions (which are addresses), and the list of
+   inner groups (which is a bits list) are maintained in separate
+   variables.
+
+   We are making a (strictly speaking) nonportable assumption here: that
+   the compiler will pack our bit fields into something that fits into
+   the type of `word', i.e., is something that fits into one item on the
+   failure stack.  */
+
+
+/* Declarations and macros for re_match_2.  */
+
+typedef union
+{
+  PREFIX(fail_stack_elt_t) word;
+  struct
+  {
+      /* This field is one if this group can match the empty string,
+         zero if not.  If not yet determined,  `MATCH_NULL_UNSET_VALUE'.  */
+# define MATCH_NULL_UNSET_VALUE 3
+    unsigned match_null_string_p : 2;
+    unsigned is_active : 1;
+    unsigned matched_something : 1;
+    unsigned ever_matched_something : 1;
+  } bits;
+} PREFIX(register_info_type);
+
+# ifndef DEFINED_ONCE
+#  define REG_MATCH_NULL_STRING_P(R)  ((R).bits.match_null_string_p)
+#  define IS_ACTIVE(R)  ((R).bits.is_active)
+#  define MATCHED_SOMETHING(R)  ((R).bits.matched_something)
+#  define EVER_MATCHED_SOMETHING(R)  ((R).bits.ever_matched_something)
+
+
+/* Call this when have matched a real character; it sets `matched' flags
+   for the subexpressions which we are currently inside.  Also records
+   that those subexprs have matched.  */
+#  define SET_REGS_MATCHED()						\
+  do									\
+    {									\
+      if (!set_regs_matched_done)					\
+	{								\
+	  active_reg_t r;						\
+	  set_regs_matched_done = 1;					\
+	  for (r = lowest_active_reg; r <= highest_active_reg; r++)	\
+	    {								\
+	      MATCHED_SOMETHING (reg_info[r])				\
+		= EVER_MATCHED_SOMETHING (reg_info[r])			\
+		= 1;							\
+	    }								\
+	}								\
+    }									\
+  while (0)
+# endif /* not DEFINED_ONCE */
+
+/* Registers are set to a sentinel when they haven't yet matched.  */
+static CHAR_T PREFIX(reg_unset_dummy);
+# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy))
+# define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+/* Subroutine declarations and macros for regex_compile.  */
+static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg);
+static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc,
+				 int arg1, int arg2);
+static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc,
+				  int arg, UCHAR_T *end);
+static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc,
+				  int arg1, int arg2, UCHAR_T *end);
+static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern,
+					   const CHAR_T *p,
+					   reg_syntax_t syntax);
+static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p,
+					   const CHAR_T *pend,
+					   reg_syntax_t syntax);
+# ifdef WCHAR
+static reg_errcode_t wcs_compile_range (CHAR_T range_start,
+						  const CHAR_T **p_ptr,
+						  const CHAR_T *pend,
+						  char *translate,
+						  reg_syntax_t syntax,
+						  UCHAR_T *b,
+						  CHAR_T *char_set);
+static void insert_space (int num, CHAR_T *loc, CHAR_T *end);
+# else /* BYTE */
+static reg_errcode_t byte_compile_range (unsigned int range_start,
+						   const char **p_ptr,
+						   const char *pend,
+						   char *translate,
+						   reg_syntax_t syntax,
+						   unsigned char *b);
+# endif /* WCHAR */
+
+/* Fetch the next character in the uncompiled pattern---translating it
+   if necessary.  Also cast from a signed character in the constant
+   string passed to us by the user to an unsigned char that we can use
+   as an array index (in, e.g., `translate').  */
+/* ifdef MBS_SUPPORT, we translate only if character <= 0xff,
+   because it is impossible to allocate 4GB array for some encodings
+   which have 4 byte character_set like UCS4.  */
+# ifndef PATFETCH
+#  ifdef WCHAR
+#   define PATFETCH(c)							\
+  do {if (p == pend) return REG_EEND;					\
+    c = (UCHAR_T) *p++;							\
+    if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c];		\
+  } while (0)
+#  else /* BYTE */
+#   define PATFETCH(c)							\
+  do {if (p == pend) return REG_EEND;					\
+    c = (unsigned char) *p++;						\
+    if (translate) c = (unsigned char) translate[c];			\
+  } while (0)
+#  endif /* WCHAR */
+# endif
+
+/* Fetch the next character in the uncompiled pattern, with no
+   translation.  */
+# define PATFETCH_RAW(c)						\
+  do {if (p == pend) return REG_EEND;					\
+    c = (UCHAR_T) *p++; 	       					\
+  } while (0)
+
+/* Go backwards one character in the pattern.  */
+# define PATUNFETCH p--
+
+
+/* If `translate' is non-null, return translate[D], else just D.  We
+   cast the subscript to translate because some data is declared as
+   `char *', to avoid warnings when a string constant is passed.  But
+   when we use a character as a subscript we must make it unsigned.  */
+/* ifdef MBS_SUPPORT, we translate only if character <= 0xff,
+   because it is impossible to allocate 4GB array for some encodings
+   which have 4 byte character_set like UCS4.  */
+
+# ifndef TRANSLATE
+#  ifdef WCHAR
+#   define TRANSLATE(d) \
+  ((translate && ((UCHAR_T) (d)) <= 0xff) \
+   ? (char) translate[(unsigned char) (d)] : (d))
+# else /* BYTE */
+#   define TRANSLATE(d) \
+  (translate ? (char) translate[(unsigned char) (d)] : (d))
+#  endif /* WCHAR */
+# endif
+
+
+/* Macros for outputting the compiled pattern into `buffer'.  */
+
+/* If the buffer isn't allocated when it comes in, use this.  */
+# define INIT_BUF_SIZE  (32 * sizeof(UCHAR_T))
+
+/* Make sure we have at least N more bytes of space in buffer.  */
+# ifdef WCHAR
+#  define GET_BUFFER_SPACE(n)						\
+    while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR	\
+            + (n)*sizeof(CHAR_T)) > bufp->allocated)			\
+      EXTEND_BUFFER ()
+# else /* BYTE */
+#  define GET_BUFFER_SPACE(n)						\
+    while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated)	\
+      EXTEND_BUFFER ()
+# endif /* WCHAR */
+
+/* Make sure we have one more byte of buffer space and then add C to it.  */
+# define BUF_PUSH(c)							\
+  do {									\
+    GET_BUFFER_SPACE (1);						\
+    *b++ = (UCHAR_T) (c);						\
+  } while (0)
+
+
+/* Ensure we have two more bytes of buffer space and then append C1 and C2.  */
+# define BUF_PUSH_2(c1, c2)						\
+  do {									\
+    GET_BUFFER_SPACE (2);						\
+    *b++ = (UCHAR_T) (c1);						\
+    *b++ = (UCHAR_T) (c2);						\
+  } while (0)
+
+
+/* As with BUF_PUSH_2, except for three bytes.  */
+# define BUF_PUSH_3(c1, c2, c3)						\
+  do {									\
+    GET_BUFFER_SPACE (3);						\
+    *b++ = (UCHAR_T) (c1);						\
+    *b++ = (UCHAR_T) (c2);						\
+    *b++ = (UCHAR_T) (c3);						\
+  } while (0)
+
+/* Store a jump with opcode OP at LOC to location TO.  We store a
+   relative address offset by the three bytes the jump itself occupies.  */
+# define STORE_JUMP(op, loc, to) \
+ PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)))
+
+/* Likewise, for a two-argument jump.  */
+# define STORE_JUMP2(op, loc, to, arg) \
+  PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg)
+
+/* Like `STORE_JUMP', but for inserting.  Assume `b' is the buffer end.  */
+# define INSERT_JUMP(op, loc, to) \
+  PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b)
+
+/* Like `STORE_JUMP2', but for inserting.  Assume `b' is the buffer end.  */
+# define INSERT_JUMP2(op, loc, to, arg) \
+  PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\
+	      arg, b)
+
+/* This is not an arbitrary limit: the arguments which represent offsets
+   into the pattern are two bytes long.  So if 2^16 bytes turns out to
+   be too small, many things would have to change.  */
+/* Any other compiler which, like MSC, has allocation limit below 2^16
+   bytes will have to use approach similar to what was done below for
+   MSC and drop MAX_BUF_SIZE a bit.  Otherwise you may end up
+   reallocating to 0 bytes.  Such thing is not going to work too well.
+   You have been warned!!  */
+# ifndef DEFINED_ONCE
+#  if defined _MSC_VER  && !defined WIN32
+/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
+   The REALLOC define eliminates a flurry of conversion warnings,
+   but is not required. */
+#   define MAX_BUF_SIZE  65500L
+#   define REALLOC(p,s) realloc ((p), (size_t) (s))
+#  else
+#   define MAX_BUF_SIZE (1L << 16)
+#   define REALLOC(p,s) realloc ((p), (s))
+#  endif
+# endif /* not DEFINED_ONCE */
+
+/* Extend the buffer by twice its current size via realloc and
+   reset the pointers that pointed into the old block to point to the
+   correct places in the new one.  If extending the buffer results in it
+   being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
+# ifdef WCHAR
+#  define EXTEND_BUFFER()						\
+  do {									\
+    UCHAR_T *old_buffer = COMPILED_BUFFER_VAR;				\
+    int wchar_count;							\
+    if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE)		\
+      return REG_ESIZE;							\
+    bufp->allocated <<= 1;						\
+    if (bufp->allocated > MAX_BUF_SIZE)					\
+      bufp->allocated = MAX_BUF_SIZE;					\
+    /* How many characters the new buffer can have?  */			\
+    wchar_count = bufp->allocated / sizeof(UCHAR_T);			\
+    if (wchar_count == 0) wchar_count = 1;				\
+    /* Truncate the buffer to CHAR_T align.  */			\
+    bufp->allocated = wchar_count * sizeof(UCHAR_T);			\
+    RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T);		\
+    bufp->buffer = (char*)COMPILED_BUFFER_VAR;				\
+    if (COMPILED_BUFFER_VAR == NULL)					\
+      return REG_ESPACE;						\
+    /* If the buffer moved, move all the pointers into it.  */		\
+    if (old_buffer != COMPILED_BUFFER_VAR)				\
+      {									\
+	int incr = COMPILED_BUFFER_VAR - old_buffer;			\
+	b += incr;							\
+	begalt += incr;							\
+	if (fixup_alt_jump)						\
+	  fixup_alt_jump += incr;					\
+	if (laststart)							\
+	  laststart += incr;						\
+	if (pending_exact)						\
+	  pending_exact += incr;					\
+      }									\
+  } while (0)
+# else /* BYTE */
+#  define EXTEND_BUFFER()						\
+  do {									\
+    UCHAR_T *old_buffer = COMPILED_BUFFER_VAR;				\
+    if (bufp->allocated == MAX_BUF_SIZE)				\
+      return REG_ESIZE;							\
+    bufp->allocated <<= 1;						\
+    if (bufp->allocated > MAX_BUF_SIZE)					\
+      bufp->allocated = MAX_BUF_SIZE;					\
+    bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR,		\
+						bufp->allocated);	\
+    if (COMPILED_BUFFER_VAR == NULL)					\
+      return REG_ESPACE;						\
+    /* If the buffer moved, move all the pointers into it.  */		\
+    if (old_buffer != COMPILED_BUFFER_VAR)				\
+      {									\
+	int incr = COMPILED_BUFFER_VAR - old_buffer;			\
+	b += incr;							\
+	begalt += incr;							\
+	if (fixup_alt_jump)						\
+	  fixup_alt_jump += incr;					\
+	if (laststart)							\
+	  laststart += incr;						\
+	if (pending_exact)						\
+	  pending_exact += incr;					\
+      }									\
+  } while (0)
+# endif /* WCHAR */
+
+# ifndef DEFINED_ONCE
+/* Since we have one byte reserved for the register number argument to
+   {start,stop}_memory, the maximum number of groups we can report
+   things about is what fits in that byte.  */
+#  define MAX_REGNUM 255
+
+/* But patterns can have more than `MAX_REGNUM' registers.  We just
+   ignore the excess.  */
+typedef unsigned regnum_t;
+
+
+/* Macros for the compile stack.  */
+
+/* Since offsets can go either forwards or backwards, this type needs to
+   be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.  */
+/* int may be not enough when sizeof(int) == 2.  */
+typedef long pattern_offset_t;
+
+typedef struct
+{
+  pattern_offset_t begalt_offset;
+  pattern_offset_t fixup_alt_jump;
+  pattern_offset_t inner_group_offset;
+  pattern_offset_t laststart_offset;
+  regnum_t regnum;
+} compile_stack_elt_t;
+
+
+typedef struct
+{
+  compile_stack_elt_t *stack;
+  unsigned size;
+  unsigned avail;			/* Offset of next open position.  */
+} compile_stack_type;
+
+
+#  define INIT_COMPILE_STACK_SIZE 32
+
+#  define COMPILE_STACK_EMPTY  (compile_stack.avail == 0)
+#  define COMPILE_STACK_FULL  (compile_stack.avail == compile_stack.size)
+
+/* The next available element.  */
+#  define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+# endif /* not DEFINED_ONCE */
+
+/* Set the bit for character C in a list.  */
+# ifndef DEFINED_ONCE
+#  define SET_LIST_BIT(c)                               \
+  (b[((unsigned char) (c)) / BYTEWIDTH]               \
+   |= 1 << (((unsigned char) c) % BYTEWIDTH))
+# endif /* DEFINED_ONCE */
+
+/* Get the next unsigned number in the uncompiled pattern.  */
+# define GET_UNSIGNED_NUMBER(num) \
+  {									\
+    while (p != pend)							\
+      {									\
+	PATFETCH (c);							\
+	if (c < '0' || c > '9')						\
+	  break;							\
+	if (num <= RE_DUP_MAX)						\
+	  {								\
+	    if (num < 0)						\
+	      num = 0;							\
+	    num = num * 10 + c - '0';					\
+	  }								\
+      }									\
+  }
+
+# ifndef DEFINED_ONCE
+#  if defined _LIBC || defined WIDE_CHAR_SUPPORT
+/* The GNU C library provides support for user-defined character classes
+   and the functions from ISO C amendement 1.  */
+#   ifdef CHARCLASS_NAME_MAX
+#    define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+#   else
+/* This shouldn't happen but some implementation might still have this
+   problem.  Use a reasonable default value.  */
+#    define CHAR_CLASS_MAX_LENGTH 256
+#   endif
+
+#   ifdef _LIBC
+#    define IS_CHAR_CLASS(string) __wctype (string)
+#   else
+#    define IS_CHAR_CLASS(string) wctype (string)
+#   endif
+#  else
+#   define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#   define IS_CHAR_CLASS(string)					\
+   (STREQ (string, "alpha") || STREQ (string, "upper")			\
+    || STREQ (string, "lower") || STREQ (string, "digit")		\
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")		\
+    || STREQ (string, "space") || STREQ (string, "print")		\
+    || STREQ (string, "punct") || STREQ (string, "graph")		\
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+#  endif
+# endif /* DEFINED_ONCE */
+
+# ifndef MATCH_MAY_ALLOCATE
+
+/* If we cannot allocate large objects within re_match_2_internal,
+   we make the fail stack and register vectors global.
+   The fail stack, we grow to the maximum size when a regexp
+   is compiled.
+   The register vectors, we adjust in size each time we
+   compile a regexp, according to the number of registers it needs.  */
+
+static PREFIX(fail_stack_type) fail_stack;
+
+/* Size with which the following vectors are currently allocated.
+   That is so we can make them bigger as needed,
+   but never make them smaller.  */
+#  ifdef DEFINED_ONCE
+static int regs_allocated_size;
+
+static const char **     regstart, **     regend;
+static const char ** old_regstart, ** old_regend;
+static const char **best_regstart, **best_regend;
+static const char **reg_dummy;
+#  endif /* DEFINED_ONCE */
+
+static PREFIX(register_info_type) *PREFIX(reg_info);
+static PREFIX(register_info_type) *PREFIX(reg_info_dummy);
+
+/* Make the register vectors big enough for NUM_REGS registers,
+   but don't make them smaller.  */
+
+static void
+PREFIX(regex_grow_registers) (int num_regs)
+{
+  if (num_regs > regs_allocated_size)
+    {
+      RETALLOC_IF (regstart,	 num_regs, const char *);
+      RETALLOC_IF (regend,	 num_regs, const char *);
+      RETALLOC_IF (old_regstart, num_regs, const char *);
+      RETALLOC_IF (old_regend,	 num_regs, const char *);
+      RETALLOC_IF (best_regstart, num_regs, const char *);
+      RETALLOC_IF (best_regend,	 num_regs, const char *);
+      RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type));
+      RETALLOC_IF (reg_dummy,	 num_regs, const char *);
+      RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type));
+
+      regs_allocated_size = num_regs;
+    }
+}
+
+# endif /* not MATCH_MAY_ALLOCATE */
+
+# ifndef DEFINED_ONCE
+static boolean group_in_compile_stack (compile_stack_type
+						 compile_stack,
+						 regnum_t regnum);
+# endif /* not DEFINED_ONCE */
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+   Returns one of error codes defined in `regex.h', or zero for success.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate'
+   fields are set in BUFP on entry.
+
+   If it succeeds, results are put in BUFP (if it returns an error, the
+   contents of BUFP are undefined):
+     `buffer' is the compiled pattern;
+     `syntax' is set to SYNTAX;
+     `used' is set to the length of the compiled pattern;
+     `fastmap_accurate' is zero;
+     `re_nsub' is the number of subexpressions in PATTERN;
+     `not_bol' and `not_eol' are zero;
+
+   The `fastmap' and `newline_anchor' fields are neither
+   examined nor set.  */
+
+/* Return, freeing storage we allocated.  */
+# ifdef WCHAR
+#  define FREE_STACK_RETURN(value)		\
+  return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value)
+# else
+#  define FREE_STACK_RETURN(value)		\
+  return (free (compile_stack.stack), value)
+# endif /* WCHAR */
+
+static reg_errcode_t
+PREFIX(regex_compile) (
+     const char *ARG_PREFIX(pattern),
+     size_t ARG_PREFIX(size),
+     reg_syntax_t syntax,
+     struct re_pattern_buffer *bufp)
+{
+  /* We fetch characters from PATTERN here.  Even though PATTERN is
+     `char *' (i.e., signed), we declare these variables as unsigned, so
+     they can be reliably used as array indices.  */
+  register UCHAR_T c, c1;
+
+#ifdef WCHAR
+  /* A temporary space to keep wchar_t pattern and compiled pattern.  */
+  CHAR_T *pattern, *COMPILED_BUFFER_VAR;
+  size_t size;
+  /* offset buffer for optimization. See convert_mbs_to_wc.  */
+  int *mbs_offset = NULL;
+  /* It hold whether each wchar_t is binary data or not.  */
+  char *is_binary = NULL;
+  /* A flag whether exactn is handling binary data or not.  */
+  char is_exactn_bin = FALSE;
+#endif /* WCHAR */
+
+  /* A random temporary spot in PATTERN.  */
+  const CHAR_T *p1;
+
+  /* Points to the end of the buffer, where we should append.  */
+  register UCHAR_T *b;
+
+  /* Keeps track of unclosed groups.  */
+  compile_stack_type compile_stack;
+
+  /* Points to the current (ending) position in the pattern.  */
+#ifdef WCHAR
+  const CHAR_T *p;
+  const CHAR_T *pend;
+#else /* BYTE */
+  const CHAR_T *p = pattern;
+  const CHAR_T *pend = pattern + size;
+#endif /* WCHAR */
+
+  /* How to translate the characters in the pattern.  */
+  RE_TRANSLATE_TYPE translate = bufp->translate;
+
+  /* Address of the count-byte of the most recently inserted `exactn'
+     command.  This makes it possible to tell if a new exact-match
+     character can be added to that command or if the character requires
+     a new `exactn' command.  */
+  UCHAR_T *pending_exact = 0;
+
+  /* Address of start of the most recently finished expression.
+     This tells, e.g., postfix * where to find the start of its
+     operand.  Reset at the beginning of groups and alternatives.  */
+  UCHAR_T *laststart = 0;
+
+  /* Address of beginning of regexp, or inside of last group.  */
+  UCHAR_T *begalt;
+
+  /* Address of the place where a forward jump should go to the end of
+     the containing expression.  Each alternative of an `or' -- except the
+     last -- ends with a forward jump of this sort.  */
+  UCHAR_T *fixup_alt_jump = 0;
+
+  /* Counts open-groups as they are encountered.  Remembered for the
+     matching close-group on the compile stack, so the same register
+     number is put in the stop_memory as the start_memory.  */
+  regnum_t regnum = 0;
+
+#ifdef WCHAR
+  /* Initialize the wchar_t PATTERN and offset_buffer.  */
+  p = pend = pattern = TALLOC(csize + 1, CHAR_T);
+  mbs_offset = TALLOC(csize + 1, int);
+  is_binary = TALLOC(csize + 1, char);
+  if (pattern == NULL || mbs_offset == NULL || is_binary == NULL)
+    {
+      free(pattern);
+      free(mbs_offset);
+      free(is_binary);
+      return REG_ESPACE;
+    }
+  pattern[csize] = L'\0';	/* sentinel */
+  size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary);
+  pend = p + size;
+  if (size < 0)
+    {
+      free(pattern);
+      free(mbs_offset);
+      free(is_binary);
+      return REG_BADPAT;
+    }
+#endif
+
+#ifdef DEBUG
+  DEBUG_PRINT1 ("\nCompiling pattern: ");
+  if (debug)
+    {
+      unsigned debug_count;
+
+      for (debug_count = 0; debug_count < size; debug_count++)
+        PUT_CHAR (pattern[debug_count]);
+      putchar ('\n');
+    }
+#endif /* DEBUG */
+
+  /* Initialize the compile stack.  */
+  compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
+  if (compile_stack.stack == NULL)
+    {
+#ifdef WCHAR
+      free(pattern);
+      free(mbs_offset);
+      free(is_binary);
+#endif
+      return REG_ESPACE;
+    }
+
+  compile_stack.size = INIT_COMPILE_STACK_SIZE;
+  compile_stack.avail = 0;
+
+  /* Initialize the pattern buffer.  */
+  bufp->syntax = syntax;
+  bufp->fastmap_accurate = 0;
+  bufp->not_bol = bufp->not_eol = 0;
+
+  /* Set `used' to zero, so that if we return an error, the pattern
+     printer (for debugging) will think there's no pattern.  We reset it
+     at the end.  */
+  bufp->used = 0;
+
+  /* Always count groups, whether or not bufp->no_sub is set.  */
+  bufp->re_nsub = 0;
+
+#if !defined emacs && !defined SYNTAX_TABLE
+  /* Initialize the syntax table.  */
+   init_syntax_once ();
+#endif
+
+  if (bufp->allocated == 0)
+    {
+      if (bufp->buffer)
+	{ /* If zero allocated, but buffer is non-null, try to realloc
+             enough space.  This loses if buffer's address is bogus, but
+             that is the user's responsibility.  */
+#ifdef WCHAR
+	  /* Free bufp->buffer and allocate an array for wchar_t pattern
+	     buffer.  */
+          free(bufp->buffer);
+          COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T),
+					UCHAR_T);
+#else
+          RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T);
+#endif /* WCHAR */
+        }
+      else
+        { /* Caller did not allocate a buffer.  Do it for them.  */
+          COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T),
+					UCHAR_T);
+        }
+
+      if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE);
+#ifdef WCHAR
+      bufp->buffer = (char*)COMPILED_BUFFER_VAR;
+#endif /* WCHAR */
+      bufp->allocated = INIT_BUF_SIZE;
+    }
+#ifdef WCHAR
+  else
+    COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer;
+#endif
+
+  begalt = b = COMPILED_BUFFER_VAR;
+
+  /* Loop through the uncompiled pattern until we're at the end.  */
+  while (p != pend)
+    {
+      PATFETCH (c);
+
+      switch (c)
+        {
+        case '^':
+          {
+            if (   /* If at start of pattern, it's an operator.  */
+                   p == pattern + 1
+                   /* If context independent, it's an operator.  */
+                || syntax & RE_CONTEXT_INDEP_ANCHORS
+                   /* Otherwise, depends on what's come before.  */
+                || PREFIX(at_begline_loc_p) (pattern, p, syntax))
+              BUF_PUSH (begline);
+            else
+              goto normal_char;
+          }
+          break;
+
+
+        case '$':
+          {
+            if (   /* If at end of pattern, it's an operator.  */
+                   p == pend
+                   /* If context independent, it's an operator.  */
+                || syntax & RE_CONTEXT_INDEP_ANCHORS
+                   /* Otherwise, depends on what's next.  */
+                || PREFIX(at_endline_loc_p) (p, pend, syntax))
+               BUF_PUSH (endline);
+             else
+               goto normal_char;
+           }
+           break;
+
+
+	case '+':
+        case '?':
+          if ((syntax & RE_BK_PLUS_QM)
+              || (syntax & RE_LIMITED_OPS))
+            goto normal_char;
+        handle_plus:
+        case '*':
+          /* If there is no previous pattern... */
+          if (!laststart)
+            {
+              if (syntax & RE_CONTEXT_INVALID_OPS)
+                FREE_STACK_RETURN (REG_BADRPT);
+              else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+                goto normal_char;
+            }
+
+          {
+            /* Are we optimizing this jump?  */
+            boolean keep_string_p = false;
+
+            /* 1 means zero (many) matches is allowed.  */
+            char zero_times_ok = 0, many_times_ok = 0;
+
+            /* If there is a sequence of repetition chars, collapse it
+               down to just one (the right one).  We can't combine
+               interval operators with these because of, e.g., `a{2}*',
+               which should only match an even number of `a's.  */
+
+            for (;;)
+              {
+                zero_times_ok |= c != '+';
+                many_times_ok |= c != '?';
+
+                if (p == pend)
+                  break;
+
+                PATFETCH (c);
+
+                if (c == '*'
+                    || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+                  ;
+
+                else if (syntax & RE_BK_PLUS_QM  &&  c == '\\')
+                  {
+                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+                    PATFETCH (c1);
+                    if (!(c1 == '+' || c1 == '?'))
+                      {
+                        PATUNFETCH;
+                        PATUNFETCH;
+                        break;
+                      }
+
+                    c = c1;
+                  }
+                else
+                  {
+                    PATUNFETCH;
+                    break;
+                  }
+
+                /* If we get here, we found another repeat character.  */
+               }
+
+            /* Star, etc. applied to an empty pattern is equivalent
+               to an empty pattern.  */
+            if (!laststart)
+              break;
+
+            /* Now we know whether or not zero matches is allowed
+               and also whether or not two or more matches is allowed.  */
+            if (many_times_ok)
+              { /* More than one repetition is allowed, so put in at the
+                   end a backward relative jump from `b' to before the next
+                   jump we're going to put in below (which jumps from
+                   laststart to after this jump).
+
+                   But if we are at the `*' in the exact sequence `.*\n',
+                   insert an unconditional jump backwards to the .,
+                   instead of the beginning of the loop.  This way we only
+                   push a failure point once, instead of every time
+                   through the loop.  */
+                assert (p - 1 > pattern);
+
+                /* Allocate the space for the jump.  */
+                GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+
+                /* We know we are not at the first character of the pattern,
+                   because laststart was nonzero.  And we've already
+                   incremented `p', by the way, to be the character after
+                   the `*'.  Do we have to do something analogous here
+                   for null bytes, because of RE_DOT_NOT_NULL?  */
+                if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
+		    && zero_times_ok
+                    && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
+                    && !(syntax & RE_DOT_NEWLINE))
+                  { /* We have .*\n.  */
+                    STORE_JUMP (jump, b, laststart);
+                    keep_string_p = true;
+                  }
+                else
+                  /* Anything else.  */
+                  STORE_JUMP (maybe_pop_jump, b, laststart -
+			      (1 + OFFSET_ADDRESS_SIZE));
+
+                /* We've added more stuff to the buffer.  */
+                b += 1 + OFFSET_ADDRESS_SIZE;
+              }
+
+            /* On failure, jump from laststart to b + 3, which will be the
+               end of the buffer after this jump is inserted.  */
+	    /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of
+	       'b + 3'.  */
+            GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+            INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
+                                       : on_failure_jump,
+                         laststart, b + 1 + OFFSET_ADDRESS_SIZE);
+            pending_exact = 0;
+            b += 1 + OFFSET_ADDRESS_SIZE;
+
+            if (!zero_times_ok)
+              {
+                /* At least one repetition is required, so insert a
+                   `dummy_failure_jump' before the initial
+                   `on_failure_jump' instruction of the loop. This
+                   effects a skip over that instruction the first time
+                   we hit that loop.  */
+                GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+                INSERT_JUMP (dummy_failure_jump, laststart, laststart +
+			     2 + 2 * OFFSET_ADDRESS_SIZE);
+                b += 1 + OFFSET_ADDRESS_SIZE;
+              }
+            }
+	  break;
+
+
+	case '.':
+          laststart = b;
+          BUF_PUSH (anychar);
+          break;
+
+
+        case '[':
+          {
+            boolean had_char_class = false;
+#ifdef WCHAR
+	    CHAR_T range_start = 0xffffffff;
+#else
+	    unsigned int range_start = 0xffffffff;
+#endif
+            if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+#ifdef WCHAR
+	    /* We assume a charset(_not) structure as a wchar_t array.
+	       charset[0] = (re_opcode_t) charset(_not)
+               charset[1] = l (= length of char_classes)
+               charset[2] = m (= length of collating_symbols)
+               charset[3] = n (= length of equivalence_classes)
+	       charset[4] = o (= length of char_ranges)
+	       charset[5] = p (= length of chars)
+
+               charset[6] = char_class (wctype_t)
+               charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t)
+                         ...
+               charset[l+5]  = char_class (wctype_t)
+
+               charset[l+6]  = collating_symbol (wchar_t)
+                            ...
+               charset[l+m+5]  = collating_symbol (wchar_t)
+					ifdef _LIBC we use the index if
+					_NL_COLLATE_SYMB_EXTRAMB instead of
+					wchar_t string.
+
+               charset[l+m+6]  = equivalence_classes (wchar_t)
+                              ...
+               charset[l+m+n+5]  = equivalence_classes (wchar_t)
+					ifdef _LIBC we use the index in
+					_NL_COLLATE_WEIGHT instead of
+					wchar_t string.
+
+	       charset[l+m+n+6] = range_start
+	       charset[l+m+n+7] = range_end
+	                       ...
+	       charset[l+m+n+2o+4] = range_start
+	       charset[l+m+n+2o+5] = range_end
+					ifdef _LIBC we use the value looked up
+					in _NL_COLLATE_COLLSEQ instead of
+					wchar_t character.
+
+	       charset[l+m+n+2o+6] = char
+	                          ...
+	       charset[l+m+n+2o+p+5] = char
+
+	     */
+
+	    /* We need at least 6 spaces: the opcode, the length of
+               char_classes, the length of collating_symbols, the length of
+               equivalence_classes, the length of char_ranges, the length of
+               chars.  */
+	    GET_BUFFER_SPACE (6);
+
+	    /* Save b as laststart. And We use laststart as the pointer
+	       to the first element of the charset here.
+	       In other words, laststart[i] indicates charset[i].  */
+            laststart = b;
+
+            /* We test `*p == '^' twice, instead of using an if
+               statement, so we only need one BUF_PUSH.  */
+            BUF_PUSH (*p == '^' ? charset_not : charset);
+            if (*p == '^')
+              p++;
+
+            /* Push the length of char_classes, the length of
+               collating_symbols, the length of equivalence_classes, the
+               length of char_ranges and the length of chars.  */
+            BUF_PUSH_3 (0, 0, 0);
+            BUF_PUSH_2 (0, 0);
+
+            /* Remember the first position in the bracket expression.  */
+            p1 = p;
+
+            /* charset_not matches newline according to a syntax bit.  */
+            if ((re_opcode_t) b[-6] == charset_not
+                && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+	      {
+		BUF_PUSH('\n');
+		laststart[5]++; /* Update the length of characters  */
+	      }
+
+            /* Read in characters and ranges, setting map bits.  */
+            for (;;)
+              {
+                if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                PATFETCH (c);
+
+                /* \ might escape characters inside [...] and [^...].  */
+                if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+                  {
+                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+                    PATFETCH (c1);
+		    BUF_PUSH(c1);
+		    laststart[5]++; /* Update the length of chars  */
+		    range_start = c1;
+                    continue;
+                  }
+
+                /* Could be the end of the bracket expression.  If it's
+                   not (i.e., when the bracket expression is `[]' so
+                   far), the ']' character bit gets set way below.  */
+                if (c == ']' && p != p1 + 1)
+                  break;
+
+                /* Look ahead to see if it's a range when the last thing
+                   was a character class.  */
+                if (had_char_class && c == '-' && *p != ']')
+                  FREE_STACK_RETURN (REG_ERANGE);
+
+                /* Look ahead to see if it's a range when the last thing
+                   was a character: if this is a hyphen not at the
+                   beginning or the end of a list, then it's the range
+                   operator.  */
+                if (c == '-'
+                    && !(p - 2 >= pattern && p[-2] == '[')
+                    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+                    && *p != ']')
+                  {
+                    reg_errcode_t ret;
+		    /* Allocate the space for range_start and range_end.  */
+		    GET_BUFFER_SPACE (2);
+		    /* Update the pointer to indicate end of buffer.  */
+                    b += 2;
+                    ret = wcs_compile_range (range_start, &p, pend, translate,
+                                         syntax, b, laststart);
+                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+                    range_start = 0xffffffff;
+                  }
+                else if (p[0] == '-' && p[1] != ']')
+                  { /* This handles ranges made up of characters only.  */
+                    reg_errcode_t ret;
+
+		    /* Move past the `-'.  */
+                    PATFETCH (c1);
+		    /* Allocate the space for range_start and range_end.  */
+		    GET_BUFFER_SPACE (2);
+		    /* Update the pointer to indicate end of buffer.  */
+                    b += 2;
+                    ret = wcs_compile_range (c, &p, pend, translate, syntax, b,
+                                         laststart);
+                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+		    range_start = 0xffffffff;
+                  }
+
+                /* See if we're at the beginning of a possible character
+                   class.  */
+                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+                  { /* Leave room for the null.  */
+                    char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+                    PATFETCH (c);
+                    c1 = 0;
+
+                    /* If pattern is `[[:'.  */
+                    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                    for (;;)
+                      {
+                        PATFETCH (c);
+                        if ((c == ':' && *p == ']') || p == pend)
+                          break;
+			if (c1 < CHAR_CLASS_MAX_LENGTH)
+			  str[c1++] = c;
+			else
+			  /* This is in any case an invalid class name.  */
+			  str[0] = '\0';
+                      }
+                    str[c1] = '\0';
+
+                    /* If isn't a word bracketed by `[:' and `:]':
+                       undo the ending character, the letters, and leave
+                       the leading `:' and `[' (but store them as character).  */
+                    if (c == ':' && *p == ']')
+                      {
+			wctype_t wt;
+			uintptr_t alignedp;
+
+			/* Query the character class as wctype_t.  */
+			wt = IS_CHAR_CLASS (str);
+			if (wt == 0)
+			  FREE_STACK_RETURN (REG_ECTYPE);
+
+                        /* Throw away the ] at the end of the character
+                           class.  */
+                        PATFETCH (c);
+
+                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+			/* Allocate the space for character class.  */
+                        GET_BUFFER_SPACE(CHAR_CLASS_SIZE);
+			/* Update the pointer to indicate end of buffer.  */
+                        b += CHAR_CLASS_SIZE;
+			/* Move data which follow character classes
+			    not to violate the data.  */
+                        insert_space(CHAR_CLASS_SIZE,
+				     laststart + 6 + laststart[1],
+				     b - 1);
+			alignedp = ((uintptr_t)(laststart + 6 + laststart[1])
+				    + __alignof__(wctype_t) - 1)
+			  	    & ~(uintptr_t)(__alignof__(wctype_t) - 1);
+			/* Store the character class.  */
+                        *((wctype_t*)alignedp) = wt;
+                        /* Update length of char_classes */
+                        laststart[1] += CHAR_CLASS_SIZE;
+
+                        had_char_class = true;
+                      }
+                    else
+                      {
+                        c1++;
+                        while (c1--)
+                          PATUNFETCH;
+                        BUF_PUSH ('[');
+                        BUF_PUSH (':');
+                        laststart[5] += 2; /* Update the length of characters  */
+			range_start = ':';
+                        had_char_class = false;
+                      }
+                  }
+                else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '='
+							  || *p == '.'))
+		  {
+		    CHAR_T str[128];	/* Should be large enough.  */
+		    CHAR_T delim = *p; /* '=' or '.'  */
+# ifdef _LIBC
+		    uint32_t nrules =
+		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+# endif
+		    PATFETCH (c);
+		    c1 = 0;
+
+		    /* If pattern is `[[=' or '[[.'.  */
+		    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+		    for (;;)
+		      {
+			PATFETCH (c);
+			if ((c == delim && *p == ']') || p == pend)
+			  break;
+			if (c1 < sizeof (str) - 1)
+			  str[c1++] = c;
+			else
+			  /* This is in any case an invalid class name.  */
+			  str[0] = '\0';
+                      }
+		    str[c1] = '\0';
+
+		    if (c == delim && *p == ']' && str[0] != '\0')
+		      {
+                        unsigned int i, offset;
+			/* If we have no collation data we use the default
+			   collation in which each character is in a class
+			   by itself.  It also means that ASCII is the
+			   character set and therefore we cannot have character
+			   with more than one byte in the multibyte
+			   representation.  */
+
+                        /* If not defined _LIBC, we push the name and
+			   `\0' for the sake of matching performance.  */
+			int datasize = c1 + 1;
+
+# ifdef _LIBC
+			int32_t idx = 0;
+			if (nrules == 0)
+# endif
+			  {
+			    if (c1 != 1)
+			      FREE_STACK_RETURN (REG_ECOLLATE);
+			  }
+# ifdef _LIBC
+			else
+			  {
+			    const int32_t *table;
+			    const int32_t *weights;
+			    const int32_t *extra;
+			    const int32_t *indirect;
+			    wint_t *cp;
+
+			    /* This #include defines a local function!  */
+#  include <locale/weightwc.h>
+
+			    if(delim == '=')
+			      {
+				/* We push the index for equivalence class.  */
+				cp = (wint_t*)str;
+
+				table = (const int32_t *)
+				  _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_TABLEWC);
+				weights = (const int32_t *)
+				  _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_WEIGHTWC);
+				extra = (const int32_t *)
+				  _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_EXTRAWC);
+				indirect = (const int32_t *)
+				  _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_INDIRECTWC);
+
+				idx = findidx ((const wint_t**)&cp);
+				if (idx == 0 || cp < (wint_t*) str + c1)
+				  /* This is no valid character.  */
+				  FREE_STACK_RETURN (REG_ECOLLATE);
+
+				str[0] = (wchar_t)idx;
+			      }
+			    else /* delim == '.' */
+			      {
+				/* We push collation sequence value
+				   for collating symbol.  */
+				int32_t table_size;
+				const int32_t *symb_table;
+				const unsigned char *extra;
+				int32_t idx;
+				int32_t elem;
+				int32_t second;
+				int32_t hash;
+				char char_str[c1];
+
+				/* We have to convert the name to a single-byte
+				   string.  This is possible since the names
+				   consist of ASCII characters and the internal
+				   representation is UCS4.  */
+				for (i = 0; i < c1; ++i)
+				  char_str[i] = str[i];
+
+				table_size =
+				  _NL_CURRENT_WORD (LC_COLLATE,
+						    _NL_COLLATE_SYMB_HASH_SIZEMB);
+				symb_table = (const int32_t *)
+				  _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_SYMB_TABLEMB);
+				extra = (const unsigned char *)
+				  _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_SYMB_EXTRAMB);
+
+				/* Locate the character in the hashing table.  */
+				hash = elem_hash (char_str, c1);
+
+				idx = 0;
+				elem = hash % table_size;
+				second = hash % (table_size - 2);
+				while (symb_table[2 * elem] != 0)
+				  {
+				    /* First compare the hashing value.  */
+				    if (symb_table[2 * elem] == hash
+					&& c1 == extra[symb_table[2 * elem + 1]]
+					&& memcmp (char_str,
+						   &extra[symb_table[2 * elem + 1]
+							 + 1], c1) == 0)
+				      {
+					/* Yep, this is the entry.  */
+					idx = symb_table[2 * elem + 1];
+					idx += 1 + extra[idx];
+					break;
+				      }
+
+				    /* Next entry.  */
+				    elem += second;
+				  }
+
+				if (symb_table[2 * elem] != 0)
+				  {
+				    /* Compute the index of the byte sequence
+				       in the table.  */
+				    idx += 1 + extra[idx];
+				    /* Adjust for the alignment.  */
+				    idx = (idx + 3) & ~3;
+
+				    str[0] = (wchar_t) idx + 4;
+				  }
+				else if (symb_table[2 * elem] == 0 && c1 == 1)
+				  {
+				    /* No valid character.  Match it as a
+				       single byte character.  */
+				    had_char_class = false;
+				    BUF_PUSH(str[0]);
+				    /* Update the length of characters  */
+				    laststart[5]++;
+				    range_start = str[0];
+
+				    /* Throw away the ] at the end of the
+				       collating symbol.  */
+				    PATFETCH (c);
+				    /* exit from the switch block.  */
+				    continue;
+				  }
+				else
+				  FREE_STACK_RETURN (REG_ECOLLATE);
+			      }
+			    datasize = 1;
+			  }
+# endif
+                        /* Throw away the ] at the end of the equivalence
+                           class (or collating symbol).  */
+                        PATFETCH (c);
+
+			/* Allocate the space for the equivalence class
+			   (or collating symbol) (and '\0' if needed).  */
+                        GET_BUFFER_SPACE(datasize);
+			/* Update the pointer to indicate end of buffer.  */
+                        b += datasize;
+
+			if (delim == '=')
+			  { /* equivalence class  */
+			    /* Calculate the offset of char_ranges,
+			       which is next to equivalence_classes.  */
+			    offset = laststart[1] + laststart[2]
+			      + laststart[3] +6;
+			    /* Insert space.  */
+			    insert_space(datasize, laststart + offset, b - 1);
+
+			    /* Write the equivalence_class and \0.  */
+			    for (i = 0 ; i < datasize ; i++)
+			      laststart[offset + i] = str[i];
+
+			    /* Update the length of equivalence_classes.  */
+			    laststart[3] += datasize;
+			    had_char_class = true;
+			  }
+			else /* delim == '.' */
+			  { /* collating symbol  */
+			    /* Calculate the offset of the equivalence_classes,
+			       which is next to collating_symbols.  */
+			    offset = laststart[1] + laststart[2] + 6;
+			    /* Insert space and write the collationg_symbol
+			       and \0.  */
+			    insert_space(datasize, laststart + offset, b-1);
+			    for (i = 0 ; i < datasize ; i++)
+			      laststart[offset + i] = str[i];
+
+			    /* In re_match_2_internal if range_start < -1, we
+			       assume -range_start is the offset of the
+			       collating symbol which is specified as
+			       the character of the range start.  So we assign
+			       -(laststart[1] + laststart[2] + 6) to
+			       range_start.  */
+			    range_start = -(laststart[1] + laststart[2] + 6);
+			    /* Update the length of collating_symbol.  */
+			    laststart[2] += datasize;
+			    had_char_class = false;
+			  }
+		      }
+                    else
+                      {
+                        c1++;
+                        while (c1--)
+                          PATUNFETCH;
+                        BUF_PUSH ('[');
+                        BUF_PUSH (delim);
+                        laststart[5] += 2; /* Update the length of characters  */
+			range_start = delim;
+                        had_char_class = false;
+                      }
+		  }
+                else
+                  {
+                    had_char_class = false;
+		    BUF_PUSH(c);
+		    laststart[5]++;  /* Update the length of characters  */
+		    range_start = c;
+                  }
+	      }
+
+#else /* BYTE */
+            /* Ensure that we have enough space to push a charset: the
+               opcode, the length count, and the bitset; 34 bytes in all.  */
+	    GET_BUFFER_SPACE (34);
+
+            laststart = b;
+
+            /* We test `*p == '^' twice, instead of using an if
+               statement, so we only need one BUF_PUSH.  */
+            BUF_PUSH (*p == '^' ? charset_not : charset);
+            if (*p == '^')
+              p++;
+
+            /* Remember the first position in the bracket expression.  */
+            p1 = p;
+
+            /* Push the number of bytes in the bitmap.  */
+            BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+
+            /* Clear the whole map.  */
+            bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+
+            /* charset_not matches newline according to a syntax bit.  */
+            if ((re_opcode_t) b[-2] == charset_not
+                && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+              SET_LIST_BIT ('\n');
+
+            /* Read in characters and ranges, setting map bits.  */
+            for (;;)
+              {
+                if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                PATFETCH (c);
+
+                /* \ might escape characters inside [...] and [^...].  */
+                if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+                  {
+                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+                    PATFETCH (c1);
+                    SET_LIST_BIT (c1);
+		    range_start = c1;
+                    continue;
+                  }
+
+                /* Could be the end of the bracket expression.  If it's
+                   not (i.e., when the bracket expression is `[]' so
+                   far), the ']' character bit gets set way below.  */
+                if (c == ']' && p != p1 + 1)
+                  break;
+
+                /* Look ahead to see if it's a range when the last thing
+                   was a character class.  */
+                if (had_char_class && c == '-' && *p != ']')
+                  FREE_STACK_RETURN (REG_ERANGE);
+
+                /* Look ahead to see if it's a range when the last thing
+                   was a character: if this is a hyphen not at the
+                   beginning or the end of a list, then it's the range
+                   operator.  */
+                if (c == '-'
+                    && !(p - 2 >= pattern && p[-2] == '[')
+                    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+                    && *p != ']')
+                  {
+                    reg_errcode_t ret
+                      = byte_compile_range (range_start, &p, pend, translate,
+					    syntax, b);
+                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+		    range_start = 0xffffffff;
+                  }
+
+                else if (p[0] == '-' && p[1] != ']')
+                  { /* This handles ranges made up of characters only.  */
+                    reg_errcode_t ret;
+
+		    /* Move past the `-'.  */
+                    PATFETCH (c1);
+
+                    ret = byte_compile_range (c, &p, pend, translate, syntax, b);
+                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+		    range_start = 0xffffffff;
+                  }
+
+                /* See if we're at the beginning of a possible character
+                   class.  */
+
+                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+                  { /* Leave room for the null.  */
+                    char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+                    PATFETCH (c);
+                    c1 = 0;
+
+                    /* If pattern is `[[:'.  */
+                    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                    for (;;)
+                      {
+                        PATFETCH (c);
+                        if ((c == ':' && *p == ']') || p == pend)
+                          break;
+#if CHAR_CLASS_MAX_LENGTH != 256
+			if (c1 < CHAR_CLASS_MAX_LENGTH)
+			  str[c1++] = c;
+			else
+			  /* This is in any case an invalid class name.  */
+			  str[0] = '\0';
+#else
+			  str[c1++] = c;
+#endif
+                      }
+                    str[c1] = '\0';
+
+                    /* If isn't a word bracketed by `[:' and `:]':
+                       undo the ending character, the letters, and leave
+                       the leading `:' and `[' (but set bits for them).  */
+                    if (c == ':' && *p == ']')
+                      {
+# if defined _LIBC || defined WIDE_CHAR_SUPPORT
+                        boolean is_lower = STREQ (str, "lower");
+                        boolean is_upper = STREQ (str, "upper");
+			wctype_t wt;
+                        int ch;
+
+			wt = IS_CHAR_CLASS (str);
+			if (wt == 0)
+			  FREE_STACK_RETURN (REG_ECTYPE);
+
+                        /* Throw away the ] at the end of the character
+                           class.  */
+                        PATFETCH (c);
+
+                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                        for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
+			  {
+#  ifdef _LIBC
+			    if (__iswctype (__btowc (ch), wt))
+			      SET_LIST_BIT (ch);
+#  else
+			    if (iswctype (btowc (ch), wt))
+			      SET_LIST_BIT (ch);
+#  endif
+
+			    if (translate && (is_upper || is_lower)
+				&& (ISUPPER (ch) || ISLOWER (ch)))
+			      SET_LIST_BIT (ch);
+			  }
+
+                        had_char_class = true;
+# else
+                        int ch;
+                        boolean is_alnum = STREQ (str, "alnum");
+                        boolean is_alpha = STREQ (str, "alpha");
+                        boolean is_blank = STREQ (str, "blank");
+                        boolean is_cntrl = STREQ (str, "cntrl");
+                        boolean is_digit = STREQ (str, "digit");
+                        boolean is_graph = STREQ (str, "graph");
+                        boolean is_lower = STREQ (str, "lower");
+                        boolean is_print = STREQ (str, "print");
+                        boolean is_punct = STREQ (str, "punct");
+                        boolean is_space = STREQ (str, "space");
+                        boolean is_upper = STREQ (str, "upper");
+                        boolean is_xdigit = STREQ (str, "xdigit");
+
+                        if (!IS_CHAR_CLASS (str))
+			  FREE_STACK_RETURN (REG_ECTYPE);
+
+                        /* Throw away the ] at the end of the character
+                           class.  */
+                        PATFETCH (c);
+
+                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                        for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+                          {
+			    /* This was split into 3 if's to
+			       avoid an arbitrary limit in some compiler.  */
+                            if (   (is_alnum  && ISALNUM (ch))
+                                || (is_alpha  && ISALPHA (ch))
+                                || (is_blank  && ISBLANK (ch))
+                                || (is_cntrl  && ISCNTRL (ch)))
+			      SET_LIST_BIT (ch);
+			    if (   (is_digit  && ISDIGIT (ch))
+                                || (is_graph  && ISGRAPH (ch))
+                                || (is_lower  && ISLOWER (ch))
+                                || (is_print  && ISPRINT (ch)))
+			      SET_LIST_BIT (ch);
+			    if (   (is_punct  && ISPUNCT (ch))
+                                || (is_space  && ISSPACE (ch))
+                                || (is_upper  && ISUPPER (ch))
+                                || (is_xdigit && ISXDIGIT (ch)))
+			      SET_LIST_BIT (ch);
+			    if (   translate && (is_upper || is_lower)
+				&& (ISUPPER (ch) || ISLOWER (ch)))
+			      SET_LIST_BIT (ch);
+                          }
+                        had_char_class = true;
+# endif	/* libc || wctype.h */
+                      }
+                    else
+                      {
+                        c1++;
+                        while (c1--)
+                          PATUNFETCH;
+                        SET_LIST_BIT ('[');
+                        SET_LIST_BIT (':');
+			range_start = ':';
+                        had_char_class = false;
+                      }
+                  }
+                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=')
+		  {
+		    unsigned char str[MB_LEN_MAX + 1];
+# ifdef _LIBC
+		    uint32_t nrules =
+		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+# endif
+
+		    PATFETCH (c);
+		    c1 = 0;
+
+		    /* If pattern is `[[='.  */
+		    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+		    for (;;)
+		      {
+			PATFETCH (c);
+			if ((c == '=' && *p == ']') || p == pend)
+			  break;
+			if (c1 < MB_LEN_MAX)
+			  str[c1++] = c;
+			else
+			  /* This is in any case an invalid class name.  */
+			  str[0] = '\0';
+                      }
+		    str[c1] = '\0';
+
+		    if (c == '=' && *p == ']' && str[0] != '\0')
+		      {
+			/* If we have no collation data we use the default
+			   collation in which each character is in a class
+			   by itself.  It also means that ASCII is the
+			   character set and therefore we cannot have character
+			   with more than one byte in the multibyte
+			   representation.  */
+# ifdef _LIBC
+			if (nrules == 0)
+# endif
+			  {
+			    if (c1 != 1)
+			      FREE_STACK_RETURN (REG_ECOLLATE);
+
+			    /* Throw away the ] at the end of the equivalence
+			       class.  */
+			    PATFETCH (c);
+
+			    /* Set the bit for the character.  */
+			    SET_LIST_BIT (str[0]);
+			  }
+# ifdef _LIBC
+			else
+			  {
+			    /* Try to match the byte sequence in `str' against
+			       those known to the collate implementation.
+			       First find out whether the bytes in `str' are
+			       actually from exactly one character.  */
+			    const int32_t *table;
+			    const unsigned char *weights;
+			    const unsigned char *extra;
+			    const int32_t *indirect;
+			    int32_t idx;
+			    const unsigned char *cp = str;
+			    int ch;
+
+			    /* This #include defines a local function!  */
+#  include <locale/weight.h>
+
+			    table = (const int32_t *)
+			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+			    weights = (const unsigned char *)
+			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+			    extra = (const unsigned char *)
+			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+			    indirect = (const int32_t *)
+			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+
+			    idx = findidx (&cp);
+			    if (idx == 0 || cp < str + c1)
+			      /* This is no valid character.  */
+			      FREE_STACK_RETURN (REG_ECOLLATE);
+
+			    /* Throw away the ] at the end of the equivalence
+			       class.  */
+			    PATFETCH (c);
+
+			    /* Now we have to go throught the whole table
+			       and find all characters which have the same
+			       first level weight.
+
+			       XXX Note that this is not entirely correct.
+			       we would have to match multibyte sequences
+			       but this is not possible with the current
+			       implementation.  */
+			    for (ch = 1; ch < 256; ++ch)
+			      /* XXX This test would have to be changed if we
+				 would allow matching multibyte sequences.  */
+			      if (table[ch] > 0)
+				{
+				  int32_t idx2 = table[ch];
+				  size_t len = weights[idx2];
+
+				  /* Test whether the lenghts match.  */
+				  if (weights[idx] == len)
+				    {
+				      /* They do.  New compare the bytes of
+					 the weight.  */
+				      size_t cnt = 0;
+
+				      while (cnt < len
+					     && (weights[idx + 1 + cnt]
+						 == weights[idx2 + 1 + cnt]))
+					++cnt;
+
+				      if (cnt == len)
+					/* They match.  Mark the character as
+					   acceptable.  */
+					SET_LIST_BIT (ch);
+				    }
+				}
+			  }
+# endif
+			had_char_class = true;
+		      }
+                    else
+                      {
+                        c1++;
+                        while (c1--)
+                          PATUNFETCH;
+                        SET_LIST_BIT ('[');
+                        SET_LIST_BIT ('=');
+			range_start = '=';
+                        had_char_class = false;
+                      }
+		  }
+                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.')
+		  {
+		    unsigned char str[128];	/* Should be large enough.  */
+# ifdef _LIBC
+		    uint32_t nrules =
+		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+# endif
+
+		    PATFETCH (c);
+		    c1 = 0;
+
+		    /* If pattern is `[[.'.  */
+		    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+		    for (;;)
+		      {
+			PATFETCH (c);
+			if ((c == '.' && *p == ']') || p == pend)
+			  break;
+			if (c1 < sizeof (str))
+			  str[c1++] = c;
+			else
+			  /* This is in any case an invalid class name.  */
+			  str[0] = '\0';
+                      }
+		    str[c1] = '\0';
+
+		    if (c == '.' && *p == ']' && str[0] != '\0')
+		      {
+			/* If we have no collation data we use the default
+			   collation in which each character is the name
+			   for its own class which contains only the one
+			   character.  It also means that ASCII is the
+			   character set and therefore we cannot have character
+			   with more than one byte in the multibyte
+			   representation.  */
+# ifdef _LIBC
+			if (nrules == 0)
+# endif
+			  {
+			    if (c1 != 1)
+			      FREE_STACK_RETURN (REG_ECOLLATE);
+
+			    /* Throw away the ] at the end of the equivalence
+			       class.  */
+			    PATFETCH (c);
+
+			    /* Set the bit for the character.  */
+			    SET_LIST_BIT (str[0]);
+			    range_start = ((const unsigned char *) str)[0];
+			  }
+# ifdef _LIBC
+			else
+			  {
+			    /* Try to match the byte sequence in `str' against
+			       those known to the collate implementation.
+			       First find out whether the bytes in `str' are
+			       actually from exactly one character.  */
+			    int32_t table_size;
+			    const int32_t *symb_table;
+			    const unsigned char *extra;
+			    int32_t idx;
+			    int32_t elem;
+			    int32_t second;
+			    int32_t hash;
+
+			    table_size =
+			      _NL_CURRENT_WORD (LC_COLLATE,
+						_NL_COLLATE_SYMB_HASH_SIZEMB);
+			    symb_table = (const int32_t *)
+			      _NL_CURRENT (LC_COLLATE,
+					   _NL_COLLATE_SYMB_TABLEMB);
+			    extra = (const unsigned char *)
+			      _NL_CURRENT (LC_COLLATE,
+					   _NL_COLLATE_SYMB_EXTRAMB);
+
+			    /* Locate the character in the hashing table.  */
+			    hash = elem_hash (str, c1);
+
+			    idx = 0;
+			    elem = hash % table_size;
+			    second = hash % (table_size - 2);
+			    while (symb_table[2 * elem] != 0)
+			      {
+				/* First compare the hashing value.  */
+				if (symb_table[2 * elem] == hash
+				    && c1 == extra[symb_table[2 * elem + 1]]
+				    && memcmp (str,
+					       &extra[symb_table[2 * elem + 1]
+						     + 1],
+					       c1) == 0)
+				  {
+				    /* Yep, this is the entry.  */
+				    idx = symb_table[2 * elem + 1];
+				    idx += 1 + extra[idx];
+				    break;
+				  }
+
+				/* Next entry.  */
+				elem += second;
+			      }
+
+			    if (symb_table[2 * elem] == 0)
+			      /* This is no valid character.  */
+			      FREE_STACK_RETURN (REG_ECOLLATE);
+
+			    /* Throw away the ] at the end of the equivalence
+			       class.  */
+			    PATFETCH (c);
+
+			    /* Now add the multibyte character(s) we found
+			       to the accept list.
+
+			       XXX Note that this is not entirely correct.
+			       we would have to match multibyte sequences
+			       but this is not possible with the current
+			       implementation.  Also, we have to match
+			       collating symbols, which expand to more than
+			       one file, as a whole and not allow the
+			       individual bytes.  */
+			    c1 = extra[idx++];
+			    if (c1 == 1)
+			      range_start = extra[idx];
+			    while (c1-- > 0)
+			      {
+				SET_LIST_BIT (extra[idx]);
+				++idx;
+			      }
+			  }
+# endif
+			had_char_class = false;
+		      }
+                    else
+                      {
+                        c1++;
+                        while (c1--)
+                          PATUNFETCH;
+                        SET_LIST_BIT ('[');
+                        SET_LIST_BIT ('.');
+			range_start = '.';
+                        had_char_class = false;
+                      }
+		  }
+                else
+                  {
+                    had_char_class = false;
+                    SET_LIST_BIT (c);
+		    range_start = c;
+                  }
+              }
+
+            /* Discard any (non)matching list bytes that are all 0 at the
+               end of the map.  Decrease the map-length byte too.  */
+            while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+              b[-1]--;
+            b += b[-1];
+#endif /* WCHAR */
+          }
+          break;
+
+
+	case '(':
+          if (syntax & RE_NO_BK_PARENS)
+            goto handle_open;
+          else
+            goto normal_char;
+
+
+        case ')':
+          if (syntax & RE_NO_BK_PARENS)
+            goto handle_close;
+          else
+            goto normal_char;
+
+
+        case '\n':
+          if (syntax & RE_NEWLINE_ALT)
+            goto handle_alt;
+          else
+            goto normal_char;
+
+
+	case '|':
+          if (syntax & RE_NO_BK_VBAR)
+            goto handle_alt;
+          else
+            goto normal_char;
+
+
+        case '{':
+           if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+             goto handle_interval;
+           else
+             goto normal_char;
+
+
+        case '\\':
+          if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+          /* Do not translate the character after the \, so that we can
+             distinguish, e.g., \B from \b, even if we normally would
+             translate, e.g., B to b.  */
+          PATFETCH_RAW (c);
+
+          switch (c)
+            {
+            case '(':
+              if (syntax & RE_NO_BK_PARENS)
+                goto normal_backslash;
+
+            handle_open:
+              bufp->re_nsub++;
+              regnum++;
+
+              if (COMPILE_STACK_FULL)
+                {
+                  RETALLOC (compile_stack.stack, compile_stack.size << 1,
+                            compile_stack_elt_t);
+                  if (compile_stack.stack == NULL) return REG_ESPACE;
+
+                  compile_stack.size <<= 1;
+                }
+
+              /* These are the values to restore when we hit end of this
+                 group.  They are all relative offsets, so that if the
+                 whole pattern moves because of realloc, they will still
+                 be valid.  */
+              COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR;
+              COMPILE_STACK_TOP.fixup_alt_jump
+                = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0;
+              COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR;
+              COMPILE_STACK_TOP.regnum = regnum;
+
+              /* We will eventually replace the 0 with the number of
+                 groups inner to this one.  But do not push a
+                 start_memory for groups beyond the last one we can
+                 represent in the compiled pattern.  */
+              if (regnum <= MAX_REGNUM)
+                {
+                  COMPILE_STACK_TOP.inner_group_offset = b
+		    - COMPILED_BUFFER_VAR + 2;
+                  BUF_PUSH_3 (start_memory, regnum, 0);
+                }
+
+              compile_stack.avail++;
+
+              fixup_alt_jump = 0;
+              laststart = 0;
+              begalt = b;
+	      /* If we've reached MAX_REGNUM groups, then this open
+		 won't actually generate any code, so we'll have to
+		 clear pending_exact explicitly.  */
+	      pending_exact = 0;
+              break;
+
+
+            case ')':
+              if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+              if (COMPILE_STACK_EMPTY)
+		{
+		  if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+		    goto normal_backslash;
+		  else
+		    FREE_STACK_RETURN (REG_ERPAREN);
+		}
+
+            handle_close:
+              if (fixup_alt_jump)
+                { /* Push a dummy failure point at the end of the
+                     alternative for a possible future
+                     `pop_failure_jump' to pop.  See comments at
+                     `push_dummy_failure' in `re_match_2'.  */
+                  BUF_PUSH (push_dummy_failure);
+
+                  /* We allocated space for this jump when we assigned
+                     to `fixup_alt_jump', in the `handle_alt' case below.  */
+                  STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
+                }
+
+              /* See similar code for backslashed left paren above.  */
+              if (COMPILE_STACK_EMPTY)
+		{
+		  if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+		    goto normal_char;
+		  else
+		    FREE_STACK_RETURN (REG_ERPAREN);
+		}
+
+              /* Since we just checked for an empty stack above, this
+                 ``can't happen''.  */
+              assert (compile_stack.avail != 0);
+              {
+                /* We don't just want to restore into `regnum', because
+                   later groups should continue to be numbered higher,
+                   as in `(ab)c(de)' -- the second group is #2.  */
+                regnum_t this_group_regnum;
+
+                compile_stack.avail--;
+                begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset;
+                fixup_alt_jump
+                  = COMPILE_STACK_TOP.fixup_alt_jump
+                    ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1
+                    : 0;
+                laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset;
+                this_group_regnum = COMPILE_STACK_TOP.regnum;
+		/* If we've reached MAX_REGNUM groups, then this open
+		   won't actually generate any code, so we'll have to
+		   clear pending_exact explicitly.  */
+		pending_exact = 0;
+
+                /* We're at the end of the group, so now we know how many
+                   groups were inside this one.  */
+                if (this_group_regnum <= MAX_REGNUM)
+                  {
+		    UCHAR_T *inner_group_loc
+                      = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset;
+
+                    *inner_group_loc = regnum - this_group_regnum;
+                    BUF_PUSH_3 (stop_memory, this_group_regnum,
+                                regnum - this_group_regnum);
+                  }
+              }
+              break;
+
+
+            case '|':					/* `\|'.  */
+              if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
+                goto normal_backslash;
+            handle_alt:
+              if (syntax & RE_LIMITED_OPS)
+                goto normal_char;
+
+              /* Insert before the previous alternative a jump which
+                 jumps to this alternative if the former fails.  */
+              GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+              INSERT_JUMP (on_failure_jump, begalt,
+			   b + 2 + 2 * OFFSET_ADDRESS_SIZE);
+              pending_exact = 0;
+              b += 1 + OFFSET_ADDRESS_SIZE;
+
+              /* The alternative before this one has a jump after it
+                 which gets executed if it gets matched.  Adjust that
+                 jump so it will jump to this alternative's analogous
+                 jump (put in below, which in turn will jump to the next
+                 (if any) alternative's such jump, etc.).  The last such
+                 jump jumps to the correct final destination.  A picture:
+                          _____ _____
+                          |   | |   |
+                          |   v |   v
+                         a | b   | c
+
+                 If we are at `b', then fixup_alt_jump right now points to a
+                 three-byte space after `a'.  We'll put in the jump, set
+                 fixup_alt_jump to right after `b', and leave behind three
+                 bytes which we'll fill in when we get to after `c'.  */
+
+              if (fixup_alt_jump)
+                STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+              /* Mark and leave space for a jump after this alternative,
+                 to be filled in later either by next alternative or
+                 when know we're at the end of a series of alternatives.  */
+              fixup_alt_jump = b;
+              GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+              b += 1 + OFFSET_ADDRESS_SIZE;
+
+              laststart = 0;
+              begalt = b;
+              break;
+
+
+            case '{':
+              /* If \{ is a literal.  */
+              if (!(syntax & RE_INTERVALS)
+                     /* If we're at `\{' and it's not the open-interval
+                        operator.  */
+		  || (syntax & RE_NO_BK_BRACES))
+                goto normal_backslash;
+
+            handle_interval:
+              {
+                /* If got here, then the syntax allows intervals.  */
+
+                /* At least (most) this many matches must be made.  */
+                int lower_bound = -1, upper_bound = -1;
+
+		/* Place in the uncompiled pattern (i.e., just after
+		   the '{') to go back to if the interval is invalid.  */
+		const CHAR_T *beg_interval = p;
+
+                if (p == pend)
+		  goto invalid_interval;
+
+                GET_UNSIGNED_NUMBER (lower_bound);
+
+                if (c == ',')
+                  {
+                    GET_UNSIGNED_NUMBER (upper_bound);
+		    if (upper_bound < 0)
+		      upper_bound = RE_DUP_MAX;
+                  }
+                else
+                  /* Interval such as `{1}' => match exactly once. */
+                  upper_bound = lower_bound;
+
+                if (! (0 <= lower_bound && lower_bound <= upper_bound))
+		  goto invalid_interval;
+
+                if (!(syntax & RE_NO_BK_BRACES))
+                  {
+		    if (c != '\\' || p == pend)
+		      goto invalid_interval;
+                    PATFETCH (c);
+                  }
+
+                if (c != '}')
+		  goto invalid_interval;
+
+                /* If it's invalid to have no preceding re.  */
+                if (!laststart)
+                  {
+		    if (syntax & RE_CONTEXT_INVALID_OPS
+			&& !(syntax & RE_INVALID_INTERVAL_ORD))
+                      FREE_STACK_RETURN (REG_BADRPT);
+                    else if (syntax & RE_CONTEXT_INDEP_OPS)
+                      laststart = b;
+                    else
+                      goto unfetch_interval;
+                  }
+
+                /* We just parsed a valid interval.  */
+
+                if (RE_DUP_MAX < upper_bound)
+		  FREE_STACK_RETURN (REG_BADBR);
+
+                /* If the upper bound is zero, don't want to succeed at
+                   all; jump from `laststart' to `b + 3', which will be
+		   the end of the buffer after we insert the jump.  */
+		/* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE'
+		   instead of 'b + 3'.  */
+                 if (upper_bound == 0)
+                   {
+                     GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+                     INSERT_JUMP (jump, laststart, b + 1
+				  + OFFSET_ADDRESS_SIZE);
+                     b += 1 + OFFSET_ADDRESS_SIZE;
+                   }
+
+                 /* Otherwise, we have a nontrivial interval.  When
+                    we're all done, the pattern will look like:
+                      set_number_at <jump count> <upper bound>
+                      set_number_at <succeed_n count> <lower bound>
+                      succeed_n <after jump addr> <succeed_n count>
+                      <body of loop>
+                      jump_n <succeed_n addr> <jump count>
+                    (The upper bound and `jump_n' are omitted if
+                    `upper_bound' is 1, though.)  */
+                 else
+                   { /* If the upper bound is > 1, we need to insert
+                        more at the end of the loop.  */
+                     unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE +
+		       (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE);
+
+                     GET_BUFFER_SPACE (nbytes);
+
+                     /* Initialize lower bound of the `succeed_n', even
+                        though it will be set during matching by its
+                        attendant `set_number_at' (inserted next),
+                        because `re_compile_fastmap' needs to know.
+                        Jump to the `jump_n' we might insert below.  */
+                     INSERT_JUMP2 (succeed_n, laststart,
+                                   b + 1 + 2 * OFFSET_ADDRESS_SIZE
+				   + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE)
+				   , lower_bound);
+                     b += 1 + 2 * OFFSET_ADDRESS_SIZE;
+
+                     /* Code to initialize the lower bound.  Insert
+                        before the `succeed_n'.  The `5' is the last two
+                        bytes of this `set_number_at', plus 3 bytes of
+                        the following `succeed_n'.  */
+		     /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE'
+			is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE'
+			of the following `succeed_n'.  */
+                     PREFIX(insert_op2) (set_number_at, laststart, 1
+				 + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b);
+                     b += 1 + 2 * OFFSET_ADDRESS_SIZE;
+
+                     if (upper_bound > 1)
+                       { /* More than one repetition is allowed, so
+                            append a backward jump to the `succeed_n'
+                            that starts this interval.
+
+                            When we've reached this during matching,
+                            we'll have matched the interval once, so
+                            jump back only `upper_bound - 1' times.  */
+                         STORE_JUMP2 (jump_n, b, laststart
+				      + 2 * OFFSET_ADDRESS_SIZE + 1,
+                                      upper_bound - 1);
+                         b += 1 + 2 * OFFSET_ADDRESS_SIZE;
+
+                         /* The location we want to set is the second
+                            parameter of the `jump_n'; that is `b-2' as
+                            an absolute address.  `laststart' will be
+                            the `set_number_at' we're about to insert;
+                            `laststart+3' the number to set, the source
+                            for the relative address.  But we are
+                            inserting into the middle of the pattern --
+                            so everything is getting moved up by 5.
+                            Conclusion: (b - 2) - (laststart + 3) + 5,
+                            i.e., b - laststart.
+
+                            We insert this at the beginning of the loop
+                            so that if we fail during matching, we'll
+                            reinitialize the bounds.  */
+                         PREFIX(insert_op2) (set_number_at, laststart,
+					     b - laststart,
+					     upper_bound - 1, b);
+                         b += 1 + 2 * OFFSET_ADDRESS_SIZE;
+                       }
+                   }
+                pending_exact = 0;
+		break;
+
+	      invalid_interval:
+		if (!(syntax & RE_INVALID_INTERVAL_ORD))
+		  FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR);
+	      unfetch_interval:
+		/* Match the characters as literals.  */
+		p = beg_interval;
+		c = '{';
+		if (syntax & RE_NO_BK_BRACES)
+		  goto normal_char;
+		else
+		  goto normal_backslash;
+	      }
+
+#ifdef emacs
+            /* There is no way to specify the before_dot and after_dot
+               operators.  rms says this is ok.  --karl  */
+            case '=':
+              BUF_PUSH (at_dot);
+              break;
+
+            case 's':
+              laststart = b;
+              PATFETCH (c);
+              BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
+              break;
+
+            case 'S':
+              laststart = b;
+              PATFETCH (c);
+              BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
+              break;
+#endif /* emacs */
+
+
+            case 'w':
+	      if (syntax & RE_NO_GNU_OPS)
+		goto normal_char;
+              laststart = b;
+              BUF_PUSH (wordchar);
+              break;
+
+
+            case 'W':
+	      if (syntax & RE_NO_GNU_OPS)
+		goto normal_char;
+              laststart = b;
+              BUF_PUSH (notwordchar);
+              break;
+
+
+            case '<':
+	      if (syntax & RE_NO_GNU_OPS)
+		goto normal_char;
+              BUF_PUSH (wordbeg);
+              break;
+
+            case '>':
+	      if (syntax & RE_NO_GNU_OPS)
+		goto normal_char;
+              BUF_PUSH (wordend);
+              break;
+
+            case 'b':
+	      if (syntax & RE_NO_GNU_OPS)
+		goto normal_char;
+              BUF_PUSH (wordbound);
+              break;
+
+            case 'B':
+	      if (syntax & RE_NO_GNU_OPS)
+		goto normal_char;
+              BUF_PUSH (notwordbound);
+              break;
+
+            case '`':
+	      if (syntax & RE_NO_GNU_OPS)
+		goto normal_char;
+              BUF_PUSH (begbuf);
+              break;
+
+            case '\'':
+	      if (syntax & RE_NO_GNU_OPS)
+		goto normal_char;
+              BUF_PUSH (endbuf);
+              break;
+
+            case '1': case '2': case '3': case '4': case '5':
+            case '6': case '7': case '8': case '9':
+              if (syntax & RE_NO_BK_REFS)
+                goto normal_char;
+
+              c1 = c - '0';
+
+              if (c1 > regnum)
+                FREE_STACK_RETURN (REG_ESUBREG);
+
+              /* Can't back reference to a subexpression if inside of it.  */
+              if (group_in_compile_stack (compile_stack, (regnum_t) c1))
+                goto normal_char;
+
+              laststart = b;
+              BUF_PUSH_2 (duplicate, c1);
+              break;
+
+
+            case '+':
+            case '?':
+              if (syntax & RE_BK_PLUS_QM)
+                goto handle_plus;
+              else
+                goto normal_backslash;
+
+            default:
+            normal_backslash:
+              /* You might think it would be useful for \ to mean
+                 not to translate; but if we don't translate it
+                 it will never match anything.  */
+              c = TRANSLATE (c);
+              goto normal_char;
+            }
+          break;
+
+
+	default:
+        /* Expects the character in `c'.  */
+	normal_char:
+	      /* If no exactn currently being built.  */
+          if (!pending_exact
+#ifdef WCHAR
+	      /* If last exactn handle binary(or character) and
+		 new exactn handle character(or binary).  */
+	      || is_exactn_bin != is_binary[p - 1 - pattern]
+#endif /* WCHAR */
+
+              /* If last exactn not at current position.  */
+              || pending_exact + *pending_exact + 1 != b
+
+              /* We have only one byte following the exactn for the count.  */
+	      || *pending_exact == (1 << BYTEWIDTH) - 1
+
+              /* If followed by a repetition operator.  */
+              || *p == '*' || *p == '^'
+	      || ((syntax & RE_BK_PLUS_QM)
+		  ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+		  : (*p == '+' || *p == '?'))
+	      || ((syntax & RE_INTERVALS)
+                  && ((syntax & RE_NO_BK_BRACES)
+		      ? *p == '{'
+                      : (p[0] == '\\' && p[1] == '{'))))
+	    {
+	      /* Start building a new exactn.  */
+
+              laststart = b;
+
+#ifdef WCHAR
+	      /* Is this exactn binary data or character? */
+	      is_exactn_bin = is_binary[p - 1 - pattern];
+	      if (is_exactn_bin)
+		  BUF_PUSH_2 (exactn_bin, 0);
+	      else
+		  BUF_PUSH_2 (exactn, 0);
+#else
+	      BUF_PUSH_2 (exactn, 0);
+#endif /* WCHAR */
+	      pending_exact = b - 1;
+            }
+
+	  BUF_PUSH (c);
+          (*pending_exact)++;
+	  break;
+        } /* switch (c) */
+    } /* while p != pend */
+
+
+  /* Through the pattern now.  */
+
+  if (fixup_alt_jump)
+    STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+  if (!COMPILE_STACK_EMPTY)
+    FREE_STACK_RETURN (REG_EPAREN);
+
+  /* If we don't want backtracking, force success
+     the first time we reach the end of the compiled pattern.  */
+  if (syntax & RE_NO_POSIX_BACKTRACKING)
+    BUF_PUSH (succeed);
+
+#ifdef WCHAR
+  free (pattern);
+  free (mbs_offset);
+  free (is_binary);
+#endif
+  free (compile_stack.stack);
+
+  /* We have succeeded; set the length of the buffer.  */
+#ifdef WCHAR
+  bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR;
+#else
+  bufp->used = b - bufp->buffer;
+#endif
+
+#ifdef DEBUG
+  if (debug)
+    {
+      DEBUG_PRINT1 ("\nCompiled pattern: \n");
+      PREFIX(print_compiled_pattern) (bufp);
+    }
+#endif /* DEBUG */
+
+#ifndef MATCH_MAY_ALLOCATE
+  /* Initialize the failure stack to the largest possible stack.  This
+     isn't necessary unless we're trying to avoid calling alloca in
+     the search and match routines.  */
+  {
+    int num_regs = bufp->re_nsub + 1;
+
+    /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
+       is strictly greater than re_max_failures, the largest possible stack
+       is 2 * re_max_failures failure points.  */
+    if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
+      {
+	fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
+
+# ifdef emacs
+	if (! fail_stack.stack)
+	  fail_stack.stack
+	    = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size
+				    * sizeof (PREFIX(fail_stack_elt_t)));
+	else
+	  fail_stack.stack
+	    = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack,
+				     (fail_stack.size
+				      * sizeof (PREFIX(fail_stack_elt_t))));
+# else /* not emacs */
+	if (! fail_stack.stack)
+	  fail_stack.stack
+	    = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size
+				   * sizeof (PREFIX(fail_stack_elt_t)));
+	else
+	  fail_stack.stack
+	    = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack,
+					    (fail_stack.size
+				     * sizeof (PREFIX(fail_stack_elt_t))));
+# endif /* not emacs */
+      }
+
+   PREFIX(regex_grow_registers) (num_regs);
+  }
+#endif /* not MATCH_MAY_ALLOCATE */
+
+  return REG_NOERROR;
+} /* regex_compile */
+
+/* Subroutines for `regex_compile'.  */
+
+/* Store OP at LOC followed by two-byte integer parameter ARG.  */
+/* ifdef WCHAR, integer parameter is 1 wchar_t.  */
+
+static void
+PREFIX(store_op1) (
+    re_opcode_t op,
+    UCHAR_T *loc,
+    int arg)
+{
+  *loc = (UCHAR_T) op;
+  STORE_NUMBER (loc + 1, arg);
+}
+
+
+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2.  */
+/* ifdef WCHAR, integer parameter is 1 wchar_t.  */
+
+static void
+PREFIX(store_op2) (
+    re_opcode_t op,
+    UCHAR_T *loc,
+    int arg1, int arg2)
+{
+  *loc = (UCHAR_T) op;
+  STORE_NUMBER (loc + 1, arg1);
+  STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2);
+}
+
+
+/* Copy the bytes from LOC to END to open up three bytes of space at LOC
+   for OP followed by two-byte integer parameter ARG.  */
+/* ifdef WCHAR, integer parameter is 1 wchar_t.  */
+
+static void
+PREFIX(insert_op1) (
+    re_opcode_t op,
+    UCHAR_T *loc,
+    int arg,
+    UCHAR_T *end)
+{
+  register UCHAR_T *pfrom = end;
+  register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE;
+
+  while (pfrom != loc)
+    *--pto = *--pfrom;
+
+  PREFIX(store_op1) (op, loc, arg);
+}
+
+
+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2.  */
+/* ifdef WCHAR, integer parameter is 1 wchar_t.  */
+
+static void
+PREFIX(insert_op2) (
+    re_opcode_t op,
+    UCHAR_T *loc,
+    int arg1, int arg2,
+    UCHAR_T *end)
+{
+  register UCHAR_T *pfrom = end;
+  register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE;
+
+  while (pfrom != loc)
+    *--pto = *--pfrom;
+
+  PREFIX(store_op2) (op, loc, arg1, arg2);
+}
+
+
+/* P points to just after a ^ in PATTERN.  Return true if that ^ comes
+   after an alternative or a begin-subexpression.  We assume there is at
+   least one character before the ^.  */
+
+static boolean
+PREFIX(at_begline_loc_p) (
+    const CHAR_T *pattern, const CHAR_T *p,
+    reg_syntax_t syntax)
+{
+  const CHAR_T *prev = p - 2;
+  boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
+
+  return
+       /* After a subexpression?  */
+       (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
+       /* After an alternative?  */
+    || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
+}
+
+
+/* The dual of at_begline_loc_p.  This one is for $.  We assume there is
+   at least one character after the $, i.e., `P < PEND'.  */
+
+static boolean
+PREFIX(at_endline_loc_p) (
+    const CHAR_T *p, const CHAR_T *pend,
+    reg_syntax_t syntax)
+{
+  const CHAR_T *next = p;
+  boolean next_backslash = *next == '\\';
+  const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0;
+
+  return
+       /* Before a subexpression?  */
+       (syntax & RE_NO_BK_PARENS ? *next == ')'
+        : next_backslash && next_next && *next_next == ')')
+       /* Before an alternative?  */
+    || (syntax & RE_NO_BK_VBAR ? *next == '|'
+        : next_backslash && next_next && *next_next == '|');
+}
+
+#else /* not INSIDE_RECURSION */
+
+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
+   false if it's not.  */
+
+static boolean
+group_in_compile_stack (
+    compile_stack_type compile_stack,
+    regnum_t regnum)
+{
+  int this_element;
+
+  for (this_element = compile_stack.avail - 1;
+       this_element >= 0;
+       this_element--)
+    if (compile_stack.stack[this_element].regnum == regnum)
+      return true;
+
+  return false;
+}
+#endif /* not INSIDE_RECURSION */
+
+#ifdef INSIDE_RECURSION
+
+#ifdef WCHAR
+/* This insert space, which size is "num", into the pattern at "loc".
+   "end" must point the end of the allocated buffer.  */
+static void
+insert_space (
+     int num,
+     CHAR_T *loc,
+     CHAR_T *end)
+{
+  register CHAR_T *pto = end;
+  register CHAR_T *pfrom = end - num;
+
+  while (pfrom >= loc)
+    *pto-- = *pfrom--;
+}
+#endif /* WCHAR */
+
+#ifdef WCHAR
+static reg_errcode_t
+wcs_compile_range (
+     CHAR_T range_start_char,
+     const CHAR_T **p_ptr, const CHAR_T *pend,
+     RE_TRANSLATE_TYPE translate,
+     reg_syntax_t syntax,
+     CHAR_T *b, CHAR_T *char_set)
+{
+  const CHAR_T *p = *p_ptr;
+  CHAR_T range_start, range_end;
+  reg_errcode_t ret;
+# ifdef _LIBC
+  uint32_t nrules;
+  uint32_t start_val, end_val;
+# endif
+  if (p == pend)
+    return REG_ERANGE;
+
+# ifdef _LIBC
+  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules != 0)
+    {
+      const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE,
+						       _NL_COLLATE_COLLSEQWC);
+      const unsigned char *extra = (const unsigned char *)
+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+
+      if (range_start_char < -1)
+	{
+	  /* range_start is a collating symbol.  */
+	  int32_t *wextra;
+	  /* Retreive the index and get collation sequence value.  */
+	  wextra = (int32_t*)(extra + char_set[-range_start_char]);
+	  start_val = wextra[1 + *wextra];
+	}
+      else
+	start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char));
+
+      end_val = collseq_table_lookup (collseq, TRANSLATE (p[0]));
+
+      /* Report an error if the range is empty and the syntax prohibits
+	 this.  */
+      ret = ((syntax & RE_NO_EMPTY_RANGES)
+	     && (start_val > end_val))? REG_ERANGE : REG_NOERROR;
+
+      /* Insert space to the end of the char_ranges.  */
+      insert_space(2, b - char_set[5] - 2, b - 1);
+      *(b - char_set[5] - 2) = (wchar_t)start_val;
+      *(b - char_set[5] - 1) = (wchar_t)end_val;
+      char_set[4]++; /* ranges_index */
+    }
+  else
+# endif
+    {
+      range_start = (range_start_char >= 0)? TRANSLATE (range_start_char):
+	range_start_char;
+      range_end = TRANSLATE (p[0]);
+      /* Report an error if the range is empty and the syntax prohibits
+	 this.  */
+      ret = ((syntax & RE_NO_EMPTY_RANGES)
+	     && (range_start > range_end))? REG_ERANGE : REG_NOERROR;
+
+      /* Insert space to the end of the char_ranges.  */
+      insert_space(2, b - char_set[5] - 2, b - 1);
+      *(b - char_set[5] - 2) = range_start;
+      *(b - char_set[5] - 1) = range_end;
+      char_set[4]++; /* ranges_index */
+    }
+  /* Have to increment the pointer into the pattern string, so the
+     caller isn't still at the ending character.  */
+  (*p_ptr)++;
+
+  return ret;
+}
+#else /* BYTE */
+/* Read the ending character of a range (in a bracket expression) from the
+   uncompiled pattern *P_PTR (which ends at PEND).  We assume the
+   starting character is in `P[-2]'.  (`P[-1]' is the character `-'.)
+   Then we set the translation of all bits between the starting and
+   ending characters (inclusive) in the compiled pattern B.
+
+   Return an error code.
+
+   We use these short variable names so we can use the same macros as
+   `regex_compile' itself.  */
+
+static reg_errcode_t
+byte_compile_range (
+     unsigned int range_start_char,
+     const char **p_ptr, const char *pend,
+     RE_TRANSLATE_TYPE translate,
+     reg_syntax_t syntax,
+     unsigned char *b)
+{
+  unsigned this_char;
+  const char *p = *p_ptr;
+  reg_errcode_t ret;
+# ifdef _LIBC
+  const unsigned char *collseq;
+  unsigned int start_colseq;
+  unsigned int end_colseq;
+# else
+  unsigned end_char;
+# endif
+
+  if (p == pend)
+    return REG_ERANGE;
+
+  /* Have to increment the pointer into the pattern string, so the
+     caller isn't still at the ending character.  */
+  (*p_ptr)++;
+
+  /* Report an error if the range is empty and the syntax prohibits this.  */
+  ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+# ifdef _LIBC
+  collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+						 _NL_COLLATE_COLLSEQMB);
+
+  start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)];
+  end_colseq = collseq[(unsigned char) TRANSLATE (p[0])];
+  for (this_char = 0; this_char <= (unsigned char) -1; ++this_char)
+    {
+      unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)];
+
+      if (start_colseq <= this_colseq && this_colseq <= end_colseq)
+	{
+	  SET_LIST_BIT (TRANSLATE (this_char));
+	  ret = REG_NOERROR;
+	}
+    }
+# else
+  /* Here we see why `this_char' has to be larger than an `unsigned
+     char' -- we would otherwise go into an infinite loop, since all
+     characters <= 0xff.  */
+  range_start_char = TRANSLATE (range_start_char);
+  /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE,
+     and some compilers cast it to int implicitly, so following for_loop
+     may fall to (almost) infinite loop.
+     e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff.
+     To avoid this, we cast p[0] to unsigned int and truncate it.  */
+  end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1));
+
+  for (this_char = range_start_char; this_char <= end_char; ++this_char)
+    {
+      SET_LIST_BIT (TRANSLATE (this_char));
+      ret = REG_NOERROR;
+    }
+# endif
+
+  return ret;
+}
+#endif /* WCHAR */
+
+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
+   BUFP.  A fastmap records which of the (1 << BYTEWIDTH) possible
+   characters can start a string that matches the pattern.  This fastmap
+   is used by re_search to skip quickly over impossible starting points.
+
+   The caller must supply the address of a (1 << BYTEWIDTH)-byte data
+   area as BUFP->fastmap.
+
+   We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
+   the pattern buffer.
+
+   Returns 0 if we succeed, -2 if an internal error.   */
+
+#ifdef WCHAR
+/* local function for re_compile_fastmap.
+   truncate wchar_t character to char.  */
+static unsigned char truncate_wchar (CHAR_T c)
+{
+  unsigned char buf[MB_CUR_MAX];
+  mbstate_t state;
+  int retval;
+  memset (&state, '\0', sizeof (state));
+# ifdef _LIBC
+  retval = __wcrtomb (buf, c, &state);
+# else
+  retval = wcrtomb (buf, c, &state);
+# endif
+  return retval > 0 ? buf[0] : (unsigned char) c;
+}
+#endif /* WCHAR */
+
+static int
+PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp)
+{
+  int j, k;
+#ifdef MATCH_MAY_ALLOCATE
+  PREFIX(fail_stack_type) fail_stack;
+#endif
+#ifndef REGEX_MALLOC
+  char *destination;
+#endif
+
+  register char *fastmap = bufp->fastmap;
+
+#ifdef WCHAR
+  /* We need to cast pattern to (wchar_t*), because we casted this compiled
+     pattern to (char*) in regex_compile.  */
+  UCHAR_T *pattern = (UCHAR_T*)bufp->buffer;
+  register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used);
+#else /* BYTE */
+  UCHAR_T *pattern = bufp->buffer;
+  register UCHAR_T *pend = pattern + bufp->used;
+#endif /* WCHAR */
+  UCHAR_T *p = pattern;
+
+#ifdef REL_ALLOC
+  /* This holds the pointer to the failure stack, when
+     it is allocated relocatably.  */
+  fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+  /* Assume that each path through the pattern can be null until
+     proven otherwise.  We set this false at the bottom of switch
+     statement, to which we get only if a particular path doesn't
+     match the empty string.  */
+  boolean path_can_be_null = true;
+
+  /* We aren't doing a `succeed_n' to begin with.  */
+  boolean succeed_n_p = false;
+
+  assert (fastmap != NULL && p != NULL);
+
+  INIT_FAIL_STACK ();
+  bzero (fastmap, 1 << BYTEWIDTH);  /* Assume nothing's valid.  */
+  bufp->fastmap_accurate = 1;	    /* It will be when we're done.  */
+  bufp->can_be_null = 0;
+
+  while (1)
+    {
+      if (p == pend || *p == succeed)
+	{
+	  /* We have reached the (effective) end of pattern.  */
+	  if (!FAIL_STACK_EMPTY ())
+	    {
+	      bufp->can_be_null |= path_can_be_null;
+
+	      /* Reset for next path.  */
+	      path_can_be_null = true;
+
+	      p = fail_stack.stack[--fail_stack.avail].pointer;
+
+	      continue;
+	    }
+	  else
+	    break;
+	}
+
+      /* We should never be about to go beyond the end of the pattern.  */
+      assert (p < pend);
+
+      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+	{
+
+        /* I guess the idea here is to simply not bother with a fastmap
+           if a backreference is used, since it's too hard to figure out
+           the fastmap for the corresponding group.  Setting
+           `can_be_null' stops `re_search_2' from using the fastmap, so
+           that is all we do.  */
+	case duplicate:
+	  bufp->can_be_null = 1;
+          goto done;
+
+
+      /* Following are the cases which match a character.  These end
+         with `break'.  */
+
+#ifdef WCHAR
+	case exactn:
+          fastmap[truncate_wchar(p[1])] = 1;
+	  break;
+#else /* BYTE */
+	case exactn:
+          fastmap[p[1]] = 1;
+	  break;
+#endif /* WCHAR */
+#ifdef MBS_SUPPORT
+	case exactn_bin:
+	  fastmap[p[1]] = 1;
+	  break;
+#endif
+
+#ifdef WCHAR
+        /* It is hard to distinguish fastmap from (multi byte) characters
+           which depends on current locale.  */
+        case charset:
+	case charset_not:
+	case wordchar:
+	case notwordchar:
+          bufp->can_be_null = 1;
+          goto done;
+#else /* BYTE */
+        case charset:
+          for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+	    if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+              fastmap[j] = 1;
+	  break;
+
+
+	case charset_not:
+	  /* Chars beyond end of map must be allowed.  */
+	  for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+            fastmap[j] = 1;
+
+	  for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+	    if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+              fastmap[j] = 1;
+          break;
+
+
+	case wordchar:
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) == Sword)
+	      fastmap[j] = 1;
+	  break;
+
+
+	case notwordchar:
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) != Sword)
+	      fastmap[j] = 1;
+	  break;
+#endif /* WCHAR */
+
+        case anychar:
+	  {
+	    int fastmap_newline = fastmap['\n'];
+
+	    /* `.' matches anything ...  */
+	    for (j = 0; j < (1 << BYTEWIDTH); j++)
+	      fastmap[j] = 1;
+
+	    /* ... except perhaps newline.  */
+	    if (!(bufp->syntax & RE_DOT_NEWLINE))
+	      fastmap['\n'] = fastmap_newline;
+
+	    /* Return if we have already set `can_be_null'; if we have,
+	       then the fastmap is irrelevant.  Something's wrong here.  */
+	    else if (bufp->can_be_null)
+	      goto done;
+
+	    /* Otherwise, have to check alternative paths.  */
+	    break;
+	  }
+
+#ifdef emacs
+        case syntaxspec:
+	  k = *p++;
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) == (enum syntaxcode) k)
+	      fastmap[j] = 1;
+	  break;
+
+
+	case notsyntaxspec:
+	  k = *p++;
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) != (enum syntaxcode) k)
+	      fastmap[j] = 1;
+	  break;
+
+
+      /* All cases after this match the empty string.  These end with
+         `continue'.  */
+
+
+	case before_dot:
+	case at_dot:
+	case after_dot:
+          continue;
+#endif /* emacs */
+
+
+        case no_op:
+        case begline:
+        case endline:
+	case begbuf:
+	case endbuf:
+	case wordbound:
+	case notwordbound:
+	case wordbeg:
+	case wordend:
+        case push_dummy_failure:
+          continue;
+
+
+	case jump_n:
+        case pop_failure_jump:
+	case maybe_pop_jump:
+	case jump:
+        case jump_past_alt:
+	case dummy_failure_jump:
+          EXTRACT_NUMBER_AND_INCR (j, p);
+	  p += j;
+	  if (j > 0)
+	    continue;
+
+          /* Jump backward implies we just went through the body of a
+             loop and matched nothing.  Opcode jumped to should be
+             `on_failure_jump' or `succeed_n'.  Just treat it like an
+             ordinary jump.  For a * loop, it has pushed its failure
+             point already; if so, discard that as redundant.  */
+          if ((re_opcode_t) *p != on_failure_jump
+	      && (re_opcode_t) *p != succeed_n)
+	    continue;
+
+          p++;
+          EXTRACT_NUMBER_AND_INCR (j, p);
+          p += j;
+
+          /* If what's on the stack is where we are now, pop it.  */
+          if (!FAIL_STACK_EMPTY ()
+	      && fail_stack.stack[fail_stack.avail - 1].pointer == p)
+            fail_stack.avail--;
+
+          continue;
+
+
+        case on_failure_jump:
+        case on_failure_keep_string_jump:
+	handle_on_failure_jump:
+          EXTRACT_NUMBER_AND_INCR (j, p);
+
+          /* For some patterns, e.g., `(a?)?', `p+j' here points to the
+             end of the pattern.  We don't want to push such a point,
+             since when we restore it above, entering the switch will
+             increment `p' past the end of the pattern.  We don't need
+             to push such a point since we obviously won't find any more
+             fastmap entries beyond `pend'.  Such a pattern can match
+             the null string, though.  */
+          if (p + j < pend)
+            {
+              if (!PUSH_PATTERN_OP (p + j, fail_stack))
+		{
+		  RESET_FAIL_STACK ();
+		  return -2;
+		}
+            }
+          else
+            bufp->can_be_null = 1;
+
+          if (succeed_n_p)
+            {
+              EXTRACT_NUMBER_AND_INCR (k, p);	/* Skip the n.  */
+              succeed_n_p = false;
+	    }
+
+          continue;
+
+
+	case succeed_n:
+          /* Get to the number of times to succeed.  */
+          p += OFFSET_ADDRESS_SIZE;
+
+          /* Increment p past the n for when k != 0.  */
+          EXTRACT_NUMBER_AND_INCR (k, p);
+          if (k == 0)
+	    {
+              p -= 2 * OFFSET_ADDRESS_SIZE;
+  	      succeed_n_p = true;  /* Spaghetti code alert.  */
+              goto handle_on_failure_jump;
+            }
+          continue;
+
+
+	case set_number_at:
+          p += 2 * OFFSET_ADDRESS_SIZE;
+          continue;
+
+
+	case start_memory:
+        case stop_memory:
+	  p += 2;
+	  continue;
+
+
+	default:
+          abort (); /* We have listed all the cases.  */
+        } /* switch *p++ */
+
+      /* Getting here means we have found the possible starting
+         characters for one path of the pattern -- and that the empty
+         string does not match.  We need not follow this path further.
+         Instead, look at the next alternative (remembered on the
+         stack), or quit if no more.  The test at the top of the loop
+         does these things.  */
+      path_can_be_null = false;
+      p = pend;
+    } /* while p */
+
+  /* Set `can_be_null' for the last path (also the first path, if the
+     pattern is empty).  */
+  bufp->can_be_null |= path_can_be_null;
+
+ done:
+  RESET_FAIL_STACK ();
+  return 0;
+}
+
+#else /* not INSIDE_RECURSION */
+
+int
+re_compile_fastmap (struct re_pattern_buffer *bufp)
+{
+# ifdef MBS_SUPPORT
+  if (MB_CUR_MAX != 1)
+    return wcs_re_compile_fastmap(bufp);
+# endif
+  return byte_re_compile_fastmap(bufp);
+}
+libc_hidden_def(re_compile_fastmap)
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
+   this memory for recording register information.  STARTS and ENDS
+   must be allocated using the malloc library routine, and must each
+   be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+
+void
+re_set_registers (
+    struct re_pattern_buffer *bufp,
+    struct re_registers *regs,
+    unsigned num_regs,
+    regoff_t *starts, regoff_t *ends)
+{
+  if (num_regs)
+    {
+      bufp->regs_allocated = REGS_REALLOCATE;
+      regs->num_regs = num_regs;
+      regs->start = starts;
+      regs->end = ends;
+    }
+  else
+    {
+      bufp->regs_allocated = REGS_UNALLOCATED;
+      regs->num_regs = 0;
+      regs->start = regs->end = (regoff_t *) 0;
+    }
+}
+
+/* Searching routines.  */
+
+/* Like re_search_2, below, but only one string is specified, and
+   doesn't let you say where to stop matching.  */
+
+int
+re_search (
+     struct re_pattern_buffer *bufp,
+     const char *string,
+     int size, int startpos, int range,
+     struct re_registers *regs)
+{
+  return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
+		      regs, size);
+}
+libc_hidden_def(re_search)
+
+
+/* Using the compiled pattern in BUFP->buffer, first tries to match the
+   virtual concatenation of STRING1 and STRING2, starting first at index
+   STARTPOS, then at STARTPOS + 1, and so on.
+
+   STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
+
+   RANGE is how far to scan while trying to match.  RANGE = 0 means try
+   only at STARTPOS; in general, the last start tried is STARTPOS +
+   RANGE.
+
+   In REGS, return the indices of the virtual concatenation of STRING1
+   and STRING2 that matched the entire BUFP->buffer and its contained
+   subexpressions.
+
+   Do not consider matching one past the index STOP in the virtual
+   concatenation of STRING1 and STRING2.
+
+   We return either the position in the strings at which the match was
+   found, -1 if no match, or -2 if error (such as failure
+   stack overflow).  */
+
+int
+re_search_2 (
+     struct re_pattern_buffer *bufp,
+     const char *string1, int size1,
+     const char *string2, int size2,
+     int startpos,
+     int range,
+     struct re_registers *regs,
+     int stop)
+{
+# ifdef MBS_SUPPORT
+  if (MB_CUR_MAX != 1)
+    return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos,
+			    range, regs, stop);
+# endif
+  return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos,
+			   range, regs, stop);
+}
+libc_hidden_def(re_search_2)
+
+#endif /* not INSIDE_RECURSION */
+
+#ifdef INSIDE_RECURSION
+
+#ifdef MATCH_MAY_ALLOCATE
+# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
+#else
+# define FREE_VAR(var) free (var); var = NULL
+#endif
+
+#ifdef WCHAR
+# define MAX_ALLOCA_SIZE	2000
+
+# define FREE_WCS_BUFFERS() \
+  do {									      \
+    if (size1 > MAX_ALLOCA_SIZE)					      \
+      {									      \
+	free (wcs_string1);						      \
+	free (mbs_offset1);						      \
+      }									      \
+    else								      \
+      {									      \
+	FREE_VAR (wcs_string1);						      \
+	FREE_VAR (mbs_offset1);						      \
+      }									      \
+    if (size2 > MAX_ALLOCA_SIZE) 					      \
+      {									      \
+	free (wcs_string2);						      \
+	free (mbs_offset2);						      \
+      }									      \
+    else								      \
+      {									      \
+	FREE_VAR (wcs_string2);						      \
+	FREE_VAR (mbs_offset2);						      \
+      }									      \
+  } while (0)
+
+#endif
+
+
+static int
+PREFIX(re_search_2) (
+     struct re_pattern_buffer *bufp,
+     const char *string1, int size1,
+     const char *string2, int size2,
+     int startpos,
+     int range,
+     struct re_registers *regs,
+     int stop)
+{
+  int val;
+  register char *fastmap = bufp->fastmap;
+  register RE_TRANSLATE_TYPE translate = bufp->translate;
+  int total_size = size1 + size2;
+  int endpos = startpos + range;
+#ifdef WCHAR
+  /* We need wchar_t* buffers correspond to cstring1, cstring2.  */
+  wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL;
+  /* We need the size of wchar_t buffers correspond to csize1, csize2.  */
+  int wcs_size1 = 0, wcs_size2 = 0;
+  /* offset buffer for optimization. See convert_mbs_to_wc.  */
+  int *mbs_offset1 = NULL, *mbs_offset2 = NULL;
+  /* They hold whether each wchar_t is binary data or not.  */
+  char *is_binary = NULL;
+#endif /* WCHAR */
+
+  /* Check for out-of-range STARTPOS.  */
+  if (startpos < 0 || startpos > total_size)
+    return -1;
+
+  /* Fix up RANGE if it might eventually take us outside
+     the virtual concatenation of STRING1 and STRING2.
+     Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE.  */
+  if (endpos < 0)
+    range = 0 - startpos;
+  else if (endpos > total_size)
+    range = total_size - startpos;
+
+  /* If the search isn't to be a backwards one, don't waste time in a
+     search for a pattern that must be anchored.  */
+  if (bufp->used > 0 && range > 0
+      && ((re_opcode_t) bufp->buffer[0] == begbuf
+	  /* `begline' is like `begbuf' if it cannot match at newlines.  */
+	  || ((re_opcode_t) bufp->buffer[0] == begline
+	      && !bufp->newline_anchor)))
+    {
+      if (startpos > 0)
+	return -1;
+      else
+	range = 1;
+    }
+
+#ifdef emacs
+  /* In a forward search for something that starts with \=.
+     don't keep searching past point.  */
+  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
+    {
+      range = PT - startpos;
+      if (range <= 0)
+	return -1;
+    }
+#endif /* emacs */
+
+  /* Update the fastmap now if not correct already.  */
+  if (fastmap && !bufp->fastmap_accurate)
+    if (re_compile_fastmap (bufp) == -2)
+      return -2;
+
+#ifdef WCHAR
+  /* Allocate wchar_t array for wcs_string1 and wcs_string2 and
+     fill them with converted string.  */
+  if (size1 != 0)
+    {
+      if (size1 > MAX_ALLOCA_SIZE)
+	{
+	  wcs_string1 = TALLOC (size1 + 1, CHAR_T);
+	  mbs_offset1 = TALLOC (size1 + 1, int);
+	  is_binary = TALLOC (size1 + 1, char);
+	}
+      else
+	{
+	  wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T);
+	  mbs_offset1 = REGEX_TALLOC (size1 + 1, int);
+	  is_binary = REGEX_TALLOC (size1 + 1, char);
+	}
+      if (!wcs_string1 || !mbs_offset1 || !is_binary)
+	{
+	  if (size1 > MAX_ALLOCA_SIZE)
+	    {
+	      free (wcs_string1);
+	      free (mbs_offset1);
+	      free (is_binary);
+	    }
+	  else
+	    {
+	      FREE_VAR (wcs_string1);
+	      FREE_VAR (mbs_offset1);
+	      FREE_VAR (is_binary);
+	    }
+	  return -2;
+	}
+      wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1,
+				     mbs_offset1, is_binary);
+      wcs_string1[wcs_size1] = L'\0'; /* for a sentinel  */
+      if (size1 > MAX_ALLOCA_SIZE)
+	free (is_binary);
+      else
+	FREE_VAR (is_binary);
+    }
+  if (size2 != 0)
+    {
+      if (size2 > MAX_ALLOCA_SIZE)
+	{
+	  wcs_string2 = TALLOC (size2 + 1, CHAR_T);
+	  mbs_offset2 = TALLOC (size2 + 1, int);
+	  is_binary = TALLOC (size2 + 1, char);
+	}
+      else
+	{
+	  wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T);
+	  mbs_offset2 = REGEX_TALLOC (size2 + 1, int);
+	  is_binary = REGEX_TALLOC (size2 + 1, char);
+	}
+      if (!wcs_string2 || !mbs_offset2 || !is_binary)
+	{
+	  FREE_WCS_BUFFERS ();
+	  if (size2 > MAX_ALLOCA_SIZE)
+	    free (is_binary);
+	  else
+	    FREE_VAR (is_binary);
+	  return -2;
+	}
+      wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2,
+				     mbs_offset2, is_binary);
+      wcs_string2[wcs_size2] = L'\0'; /* for a sentinel  */
+      if (size2 > MAX_ALLOCA_SIZE)
+	free (is_binary);
+      else
+	FREE_VAR (is_binary);
+    }
+#endif /* WCHAR */
+
+
+  /* Loop through the string, looking for a place to start matching.  */
+  for (;;)
+    {
+      /* If a fastmap is supplied, skip quickly over characters that
+         cannot be the start of a match.  If the pattern can match the
+         null string, however, we don't need to skip characters; we want
+         the first null string.  */
+      if (fastmap && startpos < total_size && !bufp->can_be_null)
+	{
+	  if (range > 0)	/* Searching forwards.  */
+	    {
+	      register const char *d;
+	      register int lim = 0;
+	      int irange = range;
+
+              if (startpos < size1 && startpos + range >= size1)
+                lim = range - (size1 - startpos);
+
+	      d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
+
+              /* Written out as an if-else to avoid testing `translate'
+                 inside the loop.  */
+	      if (translate)
+                while (range > lim
+                       && !fastmap[(unsigned char)
+				   translate[(unsigned char) *d++]])
+                  range--;
+	      else
+                while (range > lim && !fastmap[(unsigned char) *d++])
+                  range--;
+
+	      startpos += irange - range;
+	    }
+	  else				/* Searching backwards.  */
+	    {
+	      register CHAR_T c = (size1 == 0 || startpos >= size1
+				      ? string2[startpos - size1]
+				      : string1[startpos]);
+
+	      if (!fastmap[(unsigned char) TRANSLATE (c)])
+		goto advance;
+	    }
+	}
+
+      /* If can't match the null string, and that's all we have left, fail.  */
+      if (range >= 0 && startpos == total_size && fastmap
+          && !bufp->can_be_null)
+       {
+#ifdef WCHAR
+         FREE_WCS_BUFFERS ();
+#endif
+         return -1;
+       }
+
+#ifdef WCHAR
+      val = wcs_re_match_2_internal (bufp, string1, size1, string2,
+				     size2, startpos, regs, stop,
+				     wcs_string1, wcs_size1,
+				     wcs_string2, wcs_size2,
+				     mbs_offset1, mbs_offset2);
+#else /* BYTE */
+      val = byte_re_match_2_internal (bufp, string1, size1, string2,
+				      size2, startpos, regs, stop);
+#endif /* BYTE */
+
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+      alloca (0);
+# endif
+#endif
+
+      if (val >= 0)
+	{
+#ifdef WCHAR
+	  FREE_WCS_BUFFERS ();
+#endif
+	  return startpos;
+	}
+
+      if (val == -2)
+	{
+#ifdef WCHAR
+	  FREE_WCS_BUFFERS ();
+#endif
+	  return -2;
+	}
+
+    advance:
+      if (!range)
+        break;
+      else if (range > 0)
+        {
+          range--;
+          startpos++;
+        }
+      else
+        {
+          range++;
+          startpos--;
+        }
+    }
+#ifdef WCHAR
+  FREE_WCS_BUFFERS ();
+#endif
+  return -1;
+}
+
+#ifdef WCHAR
+/* This converts PTR, a pointer into one of the search wchar_t strings
+   `string1' and `string2' into an multibyte string offset from the
+   beginning of that string. We use mbs_offset to optimize.
+   See convert_mbs_to_wcs.  */
+# define POINTER_TO_OFFSET(ptr)						\
+  (FIRST_STRING_P (ptr)							\
+   ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0))	\
+   : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0)	\
+		 + csize1)))
+#else /* BYTE */
+/* This converts PTR, a pointer into one of the search strings `string1'
+   and `string2' into an offset from the beginning of that string.  */
+# define POINTER_TO_OFFSET(ptr)			\
+  (FIRST_STRING_P (ptr)				\
+   ? ((regoff_t) ((ptr) - string1))		\
+   : ((regoff_t) ((ptr) - string2 + size1)))
+#endif /* WCHAR */
+
+/* Macros for dealing with the split strings in re_match_2.  */
+
+#define MATCHING_IN_FIRST_STRING  (dend == end_match_1)
+
+/* Call before fetching a character with *d.  This switches over to
+   string2 if necessary.  */
+#define PREFETCH()							\
+  while (d == dend)						    	\
+    {									\
+      /* End of string2 => fail.  */					\
+      if (dend == end_match_2) 						\
+        goto fail;							\
+      /* End of string1 => advance to string2.  */ 			\
+      d = string2;						        \
+      dend = end_match_2;						\
+    }
+
+/* Test if at very beginning or at very end of the virtual concatenation
+   of `string1' and `string2'.  If only one string, it's `string2'.  */
+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
+#define AT_STRINGS_END(d) ((d) == end2)
+
+
+/* Test if D points to a character which is word-constituent.  We have
+   two special cases to check for: if past the end of string1, look at
+   the first character in string2; and if before the beginning of
+   string2, look at the last character in string1.  */
+#ifdef WCHAR
+/* Use internationalized API instead of SYNTAX.  */
+# define WORDCHAR_P(d)							\
+  (iswalnum ((wint_t)((d) == end1 ? *string2				\
+           : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0		\
+   || ((d) == end1 ? *string2						\
+       : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_')
+#else /* BYTE */
+# define WORDCHAR_P(d)							\
+  (SYNTAX ((d) == end1 ? *string2					\
+           : (d) == string2 - 1 ? *(end1 - 1) : *(d))			\
+   == Sword)
+#endif /* WCHAR */
+
+/* Disabled due to a compiler bug -- see comment at case wordbound */
+#if 0
+/* Test if the character before D and the one at D differ with respect
+   to being word-constituent.  */
+#define AT_WORD_BOUNDARY(d)						\
+  (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)				\
+   || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
+#endif
+
+/* Free everything we malloc.  */
+#ifdef MATCH_MAY_ALLOCATE
+# ifdef WCHAR
+#  define FREE_VARIABLES()						\
+  do {									\
+    REGEX_FREE_STACK (fail_stack.stack);				\
+    FREE_VAR (regstart);						\
+    FREE_VAR (regend);							\
+    FREE_VAR (old_regstart);						\
+    FREE_VAR (old_regend);						\
+    FREE_VAR (best_regstart);						\
+    FREE_VAR (best_regend);						\
+    FREE_VAR (reg_info);						\
+    FREE_VAR (reg_dummy);						\
+    FREE_VAR (reg_info_dummy);						\
+    if (!cant_free_wcs_buf)						\
+      {									\
+        FREE_VAR (string1);						\
+        FREE_VAR (string2);						\
+        FREE_VAR (mbs_offset1);						\
+        FREE_VAR (mbs_offset2);						\
+      }									\
+  } while (0)
+# else /* BYTE */
+#  define FREE_VARIABLES()						\
+  do {									\
+    REGEX_FREE_STACK (fail_stack.stack);				\
+    FREE_VAR (regstart);						\
+    FREE_VAR (regend);							\
+    FREE_VAR (old_regstart);						\
+    FREE_VAR (old_regend);						\
+    FREE_VAR (best_regstart);						\
+    FREE_VAR (best_regend);						\
+    FREE_VAR (reg_info);						\
+    FREE_VAR (reg_dummy);						\
+    FREE_VAR (reg_info_dummy);						\
+  } while (0)
+# endif /* WCHAR */
+#else
+# ifdef WCHAR
+#  define FREE_VARIABLES()						\
+  do {									\
+    if (!cant_free_wcs_buf)						\
+      {									\
+        FREE_VAR (string1);						\
+        FREE_VAR (string2);						\
+        FREE_VAR (mbs_offset1);						\
+        FREE_VAR (mbs_offset2);						\
+      }									\
+  } while (0)
+# else /* BYTE */
+#  define FREE_VARIABLES() ((void)0) /* Do nothing!  But inhibit gcc warning. */
+# endif /* WCHAR */
+#endif /* not MATCH_MAY_ALLOCATE */
+
+/* These values must meet several constraints.  They must not be valid
+   register values; since we have a limit of 255 registers (because
+   we use only one byte in the pattern for the register number), we can
+   use numbers larger than 255.  They must differ by 1, because of
+   NUM_FAILURE_ITEMS above.  And the value for the lowest register must
+   be larger than the value for the highest register, so we do not try
+   to actually save any registers when none are active.  */
+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
+
+#else /* not INSIDE_RECURSION */
+/* Matching routines.  */
+
+#ifndef emacs   /* Emacs never uses this.  */
+/* re_match is like re_match_2 except it takes only a single string.  */
+
+int
+re_match (
+     struct re_pattern_buffer *bufp,
+     const char *string,
+     int size, int pos,
+     struct re_registers *regs)
+{
+  int result;
+# ifdef MBS_SUPPORT
+  if (MB_CUR_MAX != 1)
+    result = wcs_re_match_2_internal (bufp, NULL, 0, string, size,
+				      pos, regs, size,
+				      NULL, 0, NULL, 0, NULL, NULL);
+  else
+# endif
+    result = byte_re_match_2_internal (bufp, NULL, 0, string, size,
+				  pos, regs, size);
+# ifndef REGEX_MALLOC
+#  ifdef C_ALLOCA
+  alloca (0);
+#  endif
+# endif
+  return result;
+}
+#endif /* not emacs */
+
+#endif /* not INSIDE_RECURSION */
+
+#ifdef INSIDE_RECURSION
+static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p,
+						    UCHAR_T *end,
+					PREFIX(register_info_type) *reg_info);
+static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p,
+						  UCHAR_T *end,
+					PREFIX(register_info_type) *reg_info);
+static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p,
+							UCHAR_T *end,
+					PREFIX(register_info_type) *reg_info);
+static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2,
+				     int len, char *translate);
+#else /* not INSIDE_RECURSION */
+
+/* re_match_2 matches the compiled pattern in BUFP against the
+   the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
+   and SIZE2, respectively).  We start matching at POS, and stop
+   matching at STOP.
+
+   If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
+   store offsets for the substring each group matched in REGS.  See the
+   documentation for exactly how many groups we fill.
+
+   We return -1 if no match, -2 if an internal error (such as the
+   failure stack overflowing).  Otherwise, we return the length of the
+   matched substring.  */
+
+int
+re_match_2 (
+     struct re_pattern_buffer *bufp,
+     const char *string1, int size1,
+     const char *string2, int size2,
+     int pos,
+     struct re_registers *regs,
+     int stop)
+{
+  int result;
+# ifdef MBS_SUPPORT
+  if (MB_CUR_MAX != 1)
+    result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2,
+				      pos, regs, stop,
+				      NULL, 0, NULL, 0, NULL, NULL);
+  else
+# endif
+    result = byte_re_match_2_internal (bufp, string1, size1, string2, size2,
+				  pos, regs, stop);
+
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+  alloca (0);
+# endif
+#endif
+  return result;
+}
+
+#endif /* not INSIDE_RECURSION */
+
+#ifdef INSIDE_RECURSION
+
+#ifdef WCHAR
+static int count_mbs_length (int *, int);
+
+/* This check the substring (from 0, to length) of the multibyte string,
+   to which offset_buffer correspond. And count how many wchar_t_characters
+   the substring occupy. We use offset_buffer to optimization.
+   See convert_mbs_to_wcs.  */
+
+static int
+count_mbs_length(
+     int *offset_buffer,
+     int length)
+{
+  int upper, lower;
+
+  /* Check whether the size is valid.  */
+  if (length < 0)
+    return -1;
+
+  if (offset_buffer == NULL)
+    return 0;
+
+  /* If there are no multibyte character, offset_buffer[i] == i.
+   Optmize for this case.  */
+  if (offset_buffer[length] == length)
+    return length;
+
+  /* Set up upper with length. (because for all i, offset_buffer[i] >= i)  */
+  upper = length;
+  lower = 0;
+
+  while (true)
+    {
+      int middle = (lower + upper) / 2;
+      if (middle == lower || middle == upper)
+	break;
+      if (offset_buffer[middle] > length)
+	upper = middle;
+      else if (offset_buffer[middle] < length)
+	lower = middle;
+      else
+	return middle;
+    }
+
+  return -1;
+}
+#endif /* WCHAR */
+
+/* This is a separate function so that we can force an alloca cleanup
+   afterwards.  */
+#ifdef WCHAR
+static int
+wcs_re_match_2_internal (
+     struct re_pattern_buffer *bufp,
+     const char *cstring1, int csize1,
+     const char *cstring2, int csize2,
+     int pos,
+     struct re_registers *regs,
+     int stop,
+     /* string1 == string2 == NULL means string1/2, size1/2 and
+	mbs_offset1/2 need seting up in this function.  */
+     /* We need wchar_t* buffers correspond to cstring1, cstring2.  */
+     /* We need the size of wchar_t buffers correspond to csize1, csize2.  */
+     wchar_t *string1, int size1,
+     wchar_t *string2, int size2,
+     /* offset buffer for optimization. See convert_mbs_to_wc.  */
+     int *mbs_offset1, int *mbs_offset2)
+#else /* BYTE */
+static int
+byte_re_match_2_internal (
+     struct re_pattern_buffer *bufp,
+     const char *string1, int size1,
+     const char *string2, int size2,
+     int pos,
+     struct re_registers *regs,
+     int stop)
+#endif /* BYTE */
+{
+  /* General temporaries.  */
+  int mcnt;
+  UCHAR_T *p1;
+#ifdef WCHAR
+  /* They hold whether each wchar_t is binary data or not.  */
+  char *is_binary = NULL;
+  /* If true, we can't free string1/2, mbs_offset1/2.  */
+  int cant_free_wcs_buf = 1;
+#endif /* WCHAR */
+
+  /* Just past the end of the corresponding string.  */
+  const CHAR_T *end1, *end2;
+
+  /* Pointers into string1 and string2, just past the last characters in
+     each to consider matching.  */
+  const CHAR_T *end_match_1, *end_match_2;
+
+  /* Where we are in the data, and the end of the current string.  */
+  const CHAR_T *d, *dend;
+
+  /* Where we are in the pattern, and the end of the pattern.  */
+#ifdef WCHAR
+  UCHAR_T *pattern, *p;
+  register UCHAR_T *pend;
+#else /* BYTE */
+  UCHAR_T *p = bufp->buffer;
+  register UCHAR_T *pend = p + bufp->used;
+#endif /* WCHAR */
+
+  /* Mark the opcode just after a start_memory, so we can test for an
+     empty subpattern when we get to the stop_memory.  */
+  UCHAR_T *just_past_start_mem = 0;
+
+  /* We use this to map every character in the string.  */
+  RE_TRANSLATE_TYPE translate = bufp->translate;
+
+  /* Failure point stack.  Each place that can handle a failure further
+     down the line pushes a failure point on this stack.  It consists of
+     restart, regend, and reg_info for all registers corresponding to
+     the subexpressions we're currently inside, plus the number of such
+     registers, and, finally, two char *'s.  The first char * is where
+     to resume scanning the pattern; the second one is where to resume
+     scanning the strings.  If the latter is zero, the failure point is
+     a ``dummy''; if a failure happens and the failure point is a dummy,
+     it gets discarded and the next next one is tried.  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
+  PREFIX(fail_stack_type) fail_stack;
+#endif
+#ifdef DEBUG
+  static unsigned failure_id;
+  unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#endif
+
+#ifdef REL_ALLOC
+  /* This holds the pointer to the failure stack, when
+     it is allocated relocatably.  */
+  fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+  /* We fill all the registers internally, independent of what we
+     return, for use in backreferences.  The number here includes
+     an element for register zero.  */
+  size_t num_regs = bufp->re_nsub + 1;
+
+  /* The currently active registers.  */
+  active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+  active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+
+  /* Information on the contents of registers. These are pointers into
+     the input strings; they record just what was matched (on this
+     attempt) by a subexpression part of the pattern, that is, the
+     regnum-th regstart pointer points to where in the pattern we began
+     matching and the regnum-th regend points to right after where we
+     stopped matching the regnum-th subexpression.  (The zeroth register
+     keeps track of what the whole pattern matches.)  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
+  const CHAR_T **regstart, **regend;
+#endif
+
+  /* If a group that's operated upon by a repetition operator fails to
+     match anything, then the register for its start will need to be
+     restored because it will have been set to wherever in the string we
+     are when we last see its open-group operator.  Similarly for a
+     register's end.  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
+  const CHAR_T **old_regstart, **old_regend;
+#endif
+
+  /* The is_active field of reg_info helps us keep track of which (possibly
+     nested) subexpressions we are currently in. The matched_something
+     field of reg_info[reg_num] helps us tell whether or not we have
+     matched any of the pattern so far this time through the reg_num-th
+     subexpression.  These two fields get reset each time through any
+     loop their register is in.  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
+  PREFIX(register_info_type) *reg_info;
+#endif
+
+  /* The following record the register info as found in the above
+     variables when we find a match better than any we've seen before.
+     This happens as we backtrack through the failure points, which in
+     turn happens only if we have not yet matched the entire string. */
+  unsigned best_regs_set = false;
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
+  const CHAR_T **best_regstart, **best_regend;
+#endif
+
+  /* Logically, this is `best_regend[0]'.  But we don't want to have to
+     allocate space for that if we're not allocating space for anything
+     else (see below).  Also, we never need info about register 0 for
+     any of the other register vectors, and it seems rather a kludge to
+     treat `best_regend' differently than the rest.  So we keep track of
+     the end of the best match so far in a separate variable.  We
+     initialize this to NULL so that when we backtrack the first time
+     and need to test it, it's not garbage.  */
+  const CHAR_T *match_end = NULL;
+
+  /* This helps SET_REGS_MATCHED avoid doing redundant work.  */
+  int set_regs_matched_done = 0;
+
+  /* Used when we pop values we don't care about.  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
+  const CHAR_T **reg_dummy;
+  PREFIX(register_info_type) *reg_info_dummy;
+#endif
+
+#ifdef DEBUG
+  /* Counts the total number of registers pushed.  */
+  unsigned num_regs_pushed = 0;
+#endif
+
+  DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+
+  INIT_FAIL_STACK ();
+
+#ifdef MATCH_MAY_ALLOCATE
+  /* Do not bother to initialize all the register variables if there are
+     no groups in the pattern, as it takes a fair amount of time.  If
+     there are groups, we include space for register 0 (the whole
+     pattern), even though we never use it, since it simplifies the
+     array indexing.  We should fix this.  */
+  if (bufp->re_nsub)
+    {
+      regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
+      regend = REGEX_TALLOC (num_regs, const CHAR_T *);
+      old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
+      old_regend = REGEX_TALLOC (num_regs, const CHAR_T *);
+      best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
+      best_regend = REGEX_TALLOC (num_regs, const CHAR_T *);
+      reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type));
+      reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *);
+      reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type));
+
+      if (!(regstart && regend && old_regstart && old_regend && reg_info
+            && best_regstart && best_regend && reg_dummy && reg_info_dummy))
+        {
+          FREE_VARIABLES ();
+          return -2;
+        }
+    }
+  else
+    {
+      /* We must initialize all our variables to NULL, so that
+         `FREE_VARIABLES' doesn't try to free them.  */
+      regstart = regend = old_regstart = old_regend = best_regstart
+        = best_regend = reg_dummy = NULL;
+      reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL;
+    }
+#endif /* MATCH_MAY_ALLOCATE */
+
+  /* The starting position is bogus.  */
+#ifdef WCHAR
+  if (pos < 0 || pos > csize1 + csize2)
+#else /* BYTE */
+  if (pos < 0 || pos > size1 + size2)
+#endif
+    {
+      FREE_VARIABLES ();
+      return -1;
+    }
+
+#ifdef WCHAR
+  /* Allocate wchar_t array for string1 and string2 and
+     fill them with converted string.  */
+  if (string1 == NULL && string2 == NULL)
+    {
+      /* We need seting up buffers here.  */
+
+      /* We must free wcs buffers in this function.  */
+      cant_free_wcs_buf = 0;
+
+      if (csize1 != 0)
+	{
+	  string1 = REGEX_TALLOC (csize1 + 1, CHAR_T);
+	  mbs_offset1 = REGEX_TALLOC (csize1 + 1, int);
+	  is_binary = REGEX_TALLOC (csize1 + 1, char);
+	  if (!string1 || !mbs_offset1 || !is_binary)
+	    {
+	      FREE_VAR (string1);
+	      FREE_VAR (mbs_offset1);
+	      FREE_VAR (is_binary);
+	      return -2;
+	    }
+	}
+      if (csize2 != 0)
+	{
+	  string2 = REGEX_TALLOC (csize2 + 1, CHAR_T);
+	  mbs_offset2 = REGEX_TALLOC (csize2 + 1, int);
+	  is_binary = REGEX_TALLOC (csize2 + 1, char);
+	  if (!string2 || !mbs_offset2 || !is_binary)
+	    {
+	      FREE_VAR (string1);
+	      FREE_VAR (mbs_offset1);
+	      FREE_VAR (string2);
+	      FREE_VAR (mbs_offset2);
+	      FREE_VAR (is_binary);
+	      return -2;
+	    }
+	  size2 = convert_mbs_to_wcs(string2, cstring2, csize2,
+				     mbs_offset2, is_binary);
+	  string2[size2] = L'\0'; /* for a sentinel  */
+	  FREE_VAR (is_binary);
+	}
+    }
+
+  /* We need to cast pattern to (wchar_t*), because we casted this compiled
+     pattern to (char*) in regex_compile.  */
+  p = pattern = (CHAR_T*)bufp->buffer;
+  pend = (CHAR_T*)(bufp->buffer + bufp->used);
+
+#endif /* WCHAR */
+
+  /* Initialize subexpression text positions to -1 to mark ones that no
+     start_memory/stop_memory has been seen for. Also initialize the
+     register information struct.  */
+  for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+    {
+      regstart[mcnt] = regend[mcnt]
+        = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
+
+      REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
+      IS_ACTIVE (reg_info[mcnt]) = 0;
+      MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+      EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+    }
+
+  /* We move `string1' into `string2' if the latter's empty -- but not if
+     `string1' is null.  */
+  if (size2 == 0 && string1 != NULL)
+    {
+      string2 = string1;
+      size2 = size1;
+      string1 = 0;
+      size1 = 0;
+#ifdef WCHAR
+      mbs_offset2 = mbs_offset1;
+      csize2 = csize1;
+      mbs_offset1 = NULL;
+      csize1 = 0;
+#endif
+    }
+  end1 = string1 + size1;
+  end2 = string2 + size2;
+
+  /* Compute where to stop matching, within the two strings.  */
+#ifdef WCHAR
+  if (stop <= csize1)
+    {
+      mcnt = count_mbs_length(mbs_offset1, stop);
+      end_match_1 = string1 + mcnt;
+      end_match_2 = string2;
+    }
+  else
+    {
+      if (stop > csize1 + csize2)
+	stop = csize1 + csize2;
+      end_match_1 = end1;
+      mcnt = count_mbs_length(mbs_offset2, stop-csize1);
+      end_match_2 = string2 + mcnt;
+    }
+  if (mcnt < 0)
+    { /* count_mbs_length return error.  */
+      FREE_VARIABLES ();
+      return -1;
+    }
+#else
+  if (stop <= size1)
+    {
+      end_match_1 = string1 + stop;
+      end_match_2 = string2;
+    }
+  else
+    {
+      end_match_1 = end1;
+      end_match_2 = string2 + stop - size1;
+    }
+#endif /* WCHAR */
+
+  /* `p' scans through the pattern as `d' scans through the data.
+     `dend' is the end of the input string that `d' points within.  `d'
+     is advanced into the following input string whenever necessary, but
+     this happens before fetching; therefore, at the beginning of the
+     loop, `d' can be pointing at the end of a string, but it cannot
+     equal `string2'.  */
+#ifdef WCHAR
+  if (size1 > 0 && pos <= csize1)
+    {
+      mcnt = count_mbs_length(mbs_offset1, pos);
+      d = string1 + mcnt;
+      dend = end_match_1;
+    }
+  else
+    {
+      mcnt = count_mbs_length(mbs_offset2, pos-csize1);
+      d = string2 + mcnt;
+      dend = end_match_2;
+    }
+
+  if (mcnt < 0)
+    { /* count_mbs_length return error.  */
+      FREE_VARIABLES ();
+      return -1;
+    }
+#else
+  if (size1 > 0 && pos <= size1)
+    {
+      d = string1 + pos;
+      dend = end_match_1;
+    }
+  else
+    {
+      d = string2 + pos - size1;
+      dend = end_match_2;
+    }
+#endif /* WCHAR */
+
+  DEBUG_PRINT1 ("The compiled pattern is:\n");
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
+  DEBUG_PRINT1 ("The string to match is: `");
+  DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+  DEBUG_PRINT1 ("'\n");
+
+  /* This loops over pattern commands.  It exits by returning from the
+     function if the match is complete, or it drops through if the match
+     fails at this starting point in the input data.  */
+  for (;;)
+    {
+#ifdef _LIBC
+      DEBUG_PRINT2 ("\n%p: ", p);
+#else
+      DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+
+      if (p == pend)
+	{ /* End of pattern means we might have succeeded.  */
+          DEBUG_PRINT1 ("end of pattern ... ");
+
+	  /* If we haven't matched the entire string, and we want the
+             longest match, try backtracking.  */
+          if (d != end_match_2)
+	    {
+	      /* 1 if this match ends in the same string (string1 or string2)
+		 as the best previous match.  */
+	      boolean same_str_p = (FIRST_STRING_P (match_end)
+				    == MATCHING_IN_FIRST_STRING);
+	      /* 1 if this match is the best seen so far.  */
+	      boolean best_match_p;
+
+	      /* AIX compiler got confused when this was combined
+		 with the previous declaration.  */
+	      if (same_str_p)
+		best_match_p = d > match_end;
+	      else
+		best_match_p = !MATCHING_IN_FIRST_STRING;
+
+              DEBUG_PRINT1 ("backtracking.\n");
+
+              if (!FAIL_STACK_EMPTY ())
+                { /* More failure points to try.  */
+
+                  /* If exceeds best match so far, save it.  */
+                  if (!best_regs_set || best_match_p)
+                    {
+                      best_regs_set = true;
+                      match_end = d;
+
+                      DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+                      for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+                        {
+                          best_regstart[mcnt] = regstart[mcnt];
+                          best_regend[mcnt] = regend[mcnt];
+                        }
+                    }
+                  goto fail;
+                }
+
+              /* If no failure points, don't restore garbage.  And if
+                 last match is real best match, don't restore second
+                 best one. */
+              else if (best_regs_set && !best_match_p)
+                {
+  	        restore_best_regs:
+                  /* Restore best match.  It may happen that `dend ==
+                     end_match_1' while the restored d is in string2.
+                     For example, the pattern `x.*y.*z' against the
+                     strings `x-' and `y-z-', if the two strings are
+                     not consecutive in memory.  */
+                  DEBUG_PRINT1 ("Restoring best registers.\n");
+
+                  d = match_end;
+                  dend = ((d >= string1 && d <= end1)
+		           ? end_match_1 : end_match_2);
+
+		  for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+		    {
+		      regstart[mcnt] = best_regstart[mcnt];
+		      regend[mcnt] = best_regend[mcnt];
+		    }
+                }
+            } /* d != end_match_2 */
+
+	succeed_label:
+          DEBUG_PRINT1 ("Accepting match.\n");
+          /* If caller wants register contents data back, do it.  */
+          if (regs && !bufp->no_sub)
+	    {
+	      /* Have the register data arrays been allocated?  */
+              if (bufp->regs_allocated == REGS_UNALLOCATED)
+                { /* No.  So allocate them with malloc.  We need one
+                     extra element beyond `num_regs' for the `-1' marker
+                     GNU code uses.  */
+/* regex specs say:
+ *  "If REGS_UNALLOCATED, allocate space in the regs structure
+ *   for max(RE_NREGS, re_nsub + 1) groups"
+ * but real-world testsuites fail with contrived examples
+ * with lots of groups.
+ * I don't see why we can't just allocate exact needed number.
+ * Incidentally, it makes RE_NREGS unused.
+ *
+ * regs->num_regs = MAX (RE_NREGS, num_regs + 1); - VERY WRONG
+ * regs->num_regs = MIN (RE_NREGS, num_regs + 1); - slightly less wrong
+ * good one which passes uclibc test/regex/tst-regex2.c:
+ */
+                  regs->num_regs = num_regs + 1;
+                  regs->start = TALLOC (regs->num_regs, regoff_t);
+                  regs->end = TALLOC (regs->num_regs, regoff_t);
+                  if (regs->start == NULL || regs->end == NULL)
+		    {
+		      FREE_VARIABLES ();
+		      return -2;
+		    }
+                  bufp->regs_allocated = REGS_REALLOCATE;
+                }
+              else if (bufp->regs_allocated == REGS_REALLOCATE)
+                { /* Yes.  If we need more elements than were already
+                     allocated, reallocate them.  If we need fewer, just
+                     leave it alone.  */
+                  if (regs->num_regs < num_regs + 1)
+                    {
+                      regs->num_regs = num_regs + 1;
+                      RETALLOC (regs->start, regs->num_regs, regoff_t);
+                      RETALLOC (regs->end, regs->num_regs, regoff_t);
+                      if (regs->start == NULL || regs->end == NULL)
+			{
+			  FREE_VARIABLES ();
+			  return -2;
+			}
+                    }
+                }
+              else
+		{
+		  /* These braces fend off a "empty body in an else-statement"
+		     warning under GCC when assert expands to nothing.  */
+		  assert (bufp->regs_allocated == REGS_FIXED);
+		}
+
+              /* Convert the pointer data in `regstart' and `regend' to
+                 indices.  Register zero has to be set differently,
+                 since we haven't kept track of any info for it.  */
+              if (regs->num_regs > 0)
+                {
+                  regs->start[0] = pos;
+#ifdef WCHAR
+		  if (MATCHING_IN_FIRST_STRING)
+		    regs->end[0] = mbs_offset1 != NULL ?
+					mbs_offset1[d-string1] : 0;
+		  else
+		    regs->end[0] = csize1 + (mbs_offset2 != NULL ?
+					     mbs_offset2[d-string2] : 0);
+#else
+                  regs->end[0] = (MATCHING_IN_FIRST_STRING
+				  ? ((regoff_t) (d - string1))
+			          : ((regoff_t) (d - string2 + size1)));
+#endif /* WCHAR */
+                }
+
+              /* Go through the first `min (num_regs, regs->num_regs)'
+                 registers, since that is all we initialized.  */
+	      for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
+		   mcnt++)
+		{
+                  if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
+                    regs->start[mcnt] = regs->end[mcnt] = -1;
+                  else
+                    {
+		      regs->start[mcnt]
+			= (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
+                      regs->end[mcnt]
+			= (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
+                    }
+		}
+
+              /* If the regs structure we return has more elements than
+                 were in the pattern, set the extra elements to -1.  If
+                 we (re)allocated the registers, this is the case,
+                 because we always allocate enough to have at least one
+                 -1 at the end.  */
+              for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
+                regs->start[mcnt] = regs->end[mcnt] = -1;
+	    } /* regs && !bufp->no_sub */
+
+          DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+                        nfailure_points_pushed, nfailure_points_popped,
+                        nfailure_points_pushed - nfailure_points_popped);
+          DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+
+#ifdef WCHAR
+	  if (MATCHING_IN_FIRST_STRING)
+	    mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0;
+	  else
+	    mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) +
+			csize1;
+          mcnt -= pos;
+#else
+          mcnt = d - pos - (MATCHING_IN_FIRST_STRING
+			    ? string1
+			    : string2 - size1);
+#endif /* WCHAR */
+
+          DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+
+          FREE_VARIABLES ();
+          return mcnt;
+        }
+
+      /* Otherwise match next pattern command.  */
+      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+	{
+        /* Ignore these.  Used to ignore the n of succeed_n's which
+           currently have n == 0.  */
+        case no_op:
+          DEBUG_PRINT1 ("EXECUTING no_op.\n");
+          break;
+
+	case succeed:
+          DEBUG_PRINT1 ("EXECUTING succeed.\n");
+	  goto succeed_label;
+
+        /* Match the next n pattern characters exactly.  The following
+           byte in the pattern defines n, and the n bytes after that
+           are the characters to match.  */
+	case exactn:
+#ifdef MBS_SUPPORT
+	case exactn_bin:
+#endif
+	  mcnt = *p++;
+          DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
+
+          /* This is written out as an if-else so we don't waste time
+             testing `translate' inside the loop.  */
+          if (translate)
+	    {
+	      do
+		{
+		  PREFETCH ();
+#ifdef WCHAR
+		  if (*d <= 0xff)
+		    {
+		      if ((UCHAR_T) translate[(unsigned char) *d++]
+			  != (UCHAR_T) *p++)
+			goto fail;
+		    }
+		  else
+		    {
+		      if (*d++ != (CHAR_T) *p++)
+			goto fail;
+		    }
+#else
+		  if ((UCHAR_T) translate[(unsigned char) *d++]
+		      != (UCHAR_T) *p++)
+                    goto fail;
+#endif /* WCHAR */
+		}
+	      while (--mcnt);
+	    }
+	  else
+	    {
+	      do
+		{
+		  PREFETCH ();
+		  if (*d++ != (CHAR_T) *p++) goto fail;
+		}
+	      while (--mcnt);
+	    }
+	  SET_REGS_MATCHED ();
+          break;
+
+
+        /* Match any character except possibly a newline or a null.  */
+	case anychar:
+          DEBUG_PRINT1 ("EXECUTING anychar.\n");
+
+          PREFETCH ();
+
+          if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
+              || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
+	    goto fail;
+
+          SET_REGS_MATCHED ();
+          DEBUG_PRINT2 ("  Matched `%ld'.\n", (long int) *d);
+          d++;
+	  break;
+
+
+	case charset:
+	case charset_not:
+	  {
+	    register UCHAR_T c;
+#ifdef WCHAR
+	    unsigned int i, char_class_length, coll_symbol_length,
+              equiv_class_length, ranges_length, chars_length, length;
+	    CHAR_T *workp, *workp2, *charset_top;
+#define WORK_BUFFER_SIZE 128
+            CHAR_T str_buf[WORK_BUFFER_SIZE];
+# ifdef _LIBC
+	    uint32_t nrules;
+# endif /* _LIBC */
+#endif /* WCHAR */
+	    boolean not = (re_opcode_t) *(p - 1) == charset_not;
+
+            DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
+	    PREFETCH ();
+	    c = TRANSLATE (*d); /* The character to match.  */
+#ifdef WCHAR
+# ifdef _LIBC
+	    nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+# endif /* _LIBC */
+	    charset_top = p - 1;
+	    char_class_length = *p++;
+	    coll_symbol_length = *p++;
+	    equiv_class_length = *p++;
+	    ranges_length = *p++;
+	    chars_length = *p++;
+	    /* p points charset[6], so the address of the next instruction
+	       (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'],
+	       where l=length of char_classes, m=length of collating_symbol,
+	       n=equivalence_class, o=length of char_range,
+	       p'=length of character.  */
+	    workp = p;
+	    /* Update p to indicate the next instruction.  */
+	    p += char_class_length + coll_symbol_length+ equiv_class_length +
+              2*ranges_length + chars_length;
+
+            /* match with char_class?  */
+	    for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE)
+	      {
+		wctype_t wctype;
+		uintptr_t alignedp = ((uintptr_t)workp
+				      + __alignof__(wctype_t) - 1)
+		  		      & ~(uintptr_t)(__alignof__(wctype_t) - 1);
+		wctype = *((wctype_t*)alignedp);
+		workp += CHAR_CLASS_SIZE;
+# ifdef _LIBC
+		if (__iswctype((wint_t)c, wctype))
+		  goto char_set_matched;
+# else
+		if (iswctype((wint_t)c, wctype))
+		  goto char_set_matched;
+# endif
+	      }
+
+            /* match with collating_symbol?  */
+# ifdef _LIBC
+	    if (nrules != 0)
+	      {
+		const unsigned char *extra = (const unsigned char *)
+		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+
+		for (workp2 = workp + coll_symbol_length ; workp < workp2 ;
+		     workp++)
+		  {
+		    int32_t *wextra;
+		    wextra = (int32_t*)(extra + *workp++);
+		    for (i = 0; i < *wextra; ++i)
+		      if (TRANSLATE(d[i]) != wextra[1 + i])
+			break;
+
+		    if (i == *wextra)
+		      {
+			/* Update d, however d will be incremented at
+			   char_set_matched:, we decrement d here.  */
+			d += i - 1;
+			goto char_set_matched;
+		      }
+		  }
+	      }
+	    else /* (nrules == 0) */
+# endif
+	      /* If we can't look up collation data, we use wcscoll
+		 instead.  */
+	      {
+		for (workp2 = workp + coll_symbol_length ; workp < workp2 ;)
+		  {
+		    const CHAR_T *backup_d = d, *backup_dend = dend;
+# ifdef _LIBC
+		    length = __wcslen (workp);
+# else
+		    length = wcslen (workp);
+# endif
+
+		    /* If wcscoll(the collating symbol, whole string) > 0,
+		       any substring of the string never match with the
+		       collating symbol.  */
+# ifdef _LIBC
+		    if (__wcscoll (workp, d) > 0)
+# else
+		    if (wcscoll (workp, d) > 0)
+# endif
+		      {
+			workp += length + 1;
+			continue;
+		      }
+
+		    /* First, we compare the collating symbol with
+		       the first character of the string.
+		       If it don't match, we add the next character to
+		       the compare buffer in turn.  */
+		    for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++)
+		      {
+			int match;
+			if (d == dend)
+			  {
+			    if (dend == end_match_2)
+			      break;
+			    d = string2;
+			    dend = end_match_2;
+			  }
+
+			/* add next character to the compare buffer.  */
+			str_buf[i] = TRANSLATE(*d);
+			str_buf[i+1] = '\0';
+
+# ifdef _LIBC
+			match = __wcscoll (workp, str_buf);
+# else
+			match = wcscoll (workp, str_buf);
+# endif
+			if (match == 0)
+			  goto char_set_matched;
+
+			if (match < 0)
+			  /* (str_buf > workp) indicate (str_buf + X > workp),
+			     because for all X (str_buf + X > str_buf).
+			     So we don't need continue this loop.  */
+			  break;
+
+			/* Otherwise(str_buf < workp),
+			   (str_buf+next_character) may equals (workp).
+			   So we continue this loop.  */
+		      }
+		    /* not matched */
+		    d = backup_d;
+		    dend = backup_dend;
+		    workp += length + 1;
+		  }
+              }
+            /* match with equivalence_class?  */
+# ifdef _LIBC
+	    if (nrules != 0)
+	      {
+                const CHAR_T *backup_d = d, *backup_dend = dend;
+		/* Try to match the equivalence class against
+		   those known to the collate implementation.  */
+		const int32_t *table;
+		const int32_t *weights;
+		const int32_t *extra;
+		const int32_t *indirect;
+		int32_t idx, idx2;
+		wint_t *cp;
+		size_t len;
+
+		/* This #include defines a local function!  */
+#  include <locale/weightwc.h>
+
+		table = (const int32_t *)
+		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
+		weights = (const wint_t *)
+		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
+		extra = (const wint_t *)
+		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
+		indirect = (const int32_t *)
+		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
+
+		/* Write 1 collating element to str_buf, and
+		   get its index.  */
+		idx2 = 0;
+
+		for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++)
+		  {
+		    cp = (wint_t*)str_buf;
+		    if (d == dend)
+		      {
+			if (dend == end_match_2)
+			  break;
+			d = string2;
+			dend = end_match_2;
+		      }
+		    str_buf[i] = TRANSLATE(*(d+i));
+		    str_buf[i+1] = '\0'; /* sentinel */
+		    idx2 = findidx ((const wint_t**)&cp);
+		  }
+
+		/* Update d, however d will be incremented at
+		   char_set_matched:, we decrement d here.  */
+		d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1);
+		if (d >= dend)
+		  {
+		    if (dend == end_match_2)
+			d = dend;
+		    else
+		      {
+			d = string2;
+			dend = end_match_2;
+		      }
+		  }
+
+		len = weights[idx2];
+
+		for (workp2 = workp + equiv_class_length ; workp < workp2 ;
+		     workp++)
+		  {
+		    idx = (int32_t)*workp;
+		    /* We already checked idx != 0 in regex_compile. */
+
+		    if (idx2 != 0 && len == weights[idx])
+		      {
+			int cnt = 0;
+			while (cnt < len && (weights[idx + 1 + cnt]
+					     == weights[idx2 + 1 + cnt]))
+			  ++cnt;
+
+			if (cnt == len)
+			  goto char_set_matched;
+		      }
+		  }
+		/* not matched */
+                d = backup_d;
+                dend = backup_dend;
+	      }
+	    else /* (nrules == 0) */
+# endif
+	      /* If we can't look up collation data, we use wcscoll
+		 instead.  */
+	      {
+		for (workp2 = workp + equiv_class_length ; workp < workp2 ;)
+		  {
+		    const CHAR_T *backup_d = d, *backup_dend = dend;
+# ifdef _LIBC
+		    length = __wcslen (workp);
+# else
+		    length = wcslen (workp);
+# endif
+
+		    /* If wcscoll(the collating symbol, whole string) > 0,
+		       any substring of the string never match with the
+		       collating symbol.  */
+# ifdef _LIBC
+		    if (__wcscoll (workp, d) > 0)
+# else
+		    if (wcscoll (workp, d) > 0)
+# endif
+		      {
+			workp += length + 1;
+			break;
+		      }
+
+		    /* First, we compare the equivalence class with
+		       the first character of the string.
+		       If it don't match, we add the next character to
+		       the compare buffer in turn.  */
+		    for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++)
+		      {
+			int match;
+			if (d == dend)
+			  {
+			    if (dend == end_match_2)
+			      break;
+			    d = string2;
+			    dend = end_match_2;
+			  }
+
+			/* add next character to the compare buffer.  */
+			str_buf[i] = TRANSLATE(*d);
+			str_buf[i+1] = '\0';
+
+# ifdef _LIBC
+			match = __wcscoll (workp, str_buf);
+# else
+			match = wcscoll (workp, str_buf);
+# endif
+
+			if (match == 0)
+			  goto char_set_matched;
+
+			if (match < 0)
+			/* (str_buf > workp) indicate (str_buf + X > workp),
+			   because for all X (str_buf + X > str_buf).
+			   So we don't need continue this loop.  */
+			  break;
+
+			/* Otherwise(str_buf < workp),
+			   (str_buf+next_character) may equals (workp).
+			   So we continue this loop.  */
+		      }
+		    /* not matched */
+		    d = backup_d;
+		    dend = backup_dend;
+		    workp += length + 1;
+		  }
+	      }
+
+            /* match with char_range?  */
+# ifdef _LIBC
+	    if (nrules != 0)
+	      {
+		uint32_t collseqval;
+		const char *collseq = (const char *)
+		  _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+
+		collseqval = collseq_table_lookup (collseq, c);
+
+		for (; workp < p - chars_length ;)
+		  {
+		    uint32_t start_val, end_val;
+
+		    /* We already compute the collation sequence value
+		       of the characters (or collating symbols).  */
+		    start_val = (uint32_t) *workp++; /* range_start */
+		    end_val = (uint32_t) *workp++; /* range_end */
+
+		    if (start_val <= collseqval && collseqval <= end_val)
+		      goto char_set_matched;
+		  }
+	      }
+	    else
+# endif
+	      {
+		/* We set range_start_char at str_buf[0], range_end_char
+		   at str_buf[4], and compared char at str_buf[2].  */
+		str_buf[1] = 0;
+		str_buf[2] = c;
+		str_buf[3] = 0;
+		str_buf[5] = 0;
+		for (; workp < p - chars_length ;)
+		  {
+		    wchar_t *range_start_char, *range_end_char;
+
+		    /* match if (range_start_char <= c <= range_end_char).  */
+
+		    /* If range_start(or end) < 0, we assume -range_start(end)
+		       is the offset of the collating symbol which is specified
+		       as the character of the range start(end).  */
+
+		    /* range_start */
+		    if (*workp < 0)
+		      range_start_char = charset_top - (*workp++);
+		    else
+		      {
+			str_buf[0] = *workp++;
+			range_start_char = str_buf;
+		      }
+
+		    /* range_end */
+		    if (*workp < 0)
+		      range_end_char = charset_top - (*workp++);
+		    else
+		      {
+			str_buf[4] = *workp++;
+			range_end_char = str_buf + 4;
+		      }
+
+# ifdef _LIBC
+		    if (__wcscoll (range_start_char, str_buf+2) <= 0
+			&& __wcscoll (str_buf+2, range_end_char) <= 0)
+# else
+		    if (wcscoll (range_start_char, str_buf+2) <= 0
+			&& wcscoll (str_buf+2, range_end_char) <= 0)
+# endif
+		      goto char_set_matched;
+		  }
+	      }
+
+            /* match with char?  */
+	    for (; workp < p ; workp++)
+	      if (c == *workp)
+		goto char_set_matched;
+
+	    not = !not;
+
+	  char_set_matched:
+	    if (not) goto fail;
+#else
+            /* Cast to `unsigned' instead of `unsigned char' in case the
+               bit list is a full 32 bytes long.  */
+	    if (c < (unsigned) (*p * BYTEWIDTH)
+		&& p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+	      not = !not;
+
+	    p += 1 + *p;
+
+	    if (!not) goto fail;
+#undef WORK_BUFFER_SIZE
+#endif /* WCHAR */
+	    SET_REGS_MATCHED ();
+            d++;
+	    break;
+	  }
+
+
+        /* The beginning of a group is represented by start_memory.
+           The arguments are the register number in the next byte, and the
+           number of groups inner to this one in the next.  The text
+           matched within the group is recorded (in the internal
+           registers data structure) under the register number.  */
+        case start_memory:
+	  DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n",
+			(long int) *p, (long int) p[1]);
+
+          /* Find out if this group can match the empty string.  */
+	  p1 = p;		/* To send to group_match_null_string_p.  */
+
+          if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
+            REG_MATCH_NULL_STRING_P (reg_info[*p])
+              = PREFIX(group_match_null_string_p) (&p1, pend, reg_info);
+
+          /* Save the position in the string where we were the last time
+             we were at this open-group operator in case the group is
+             operated upon by a repetition operator, e.g., with `(a*)*b'
+             against `ab'; then we want to ignore where we are now in
+             the string in case this attempt to match fails.  */
+          old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+                             ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
+                             : regstart[*p];
+	  DEBUG_PRINT2 ("  old_regstart: %d\n",
+			 POINTER_TO_OFFSET (old_regstart[*p]));
+
+          regstart[*p] = d;
+	  DEBUG_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+
+          IS_ACTIVE (reg_info[*p]) = 1;
+          MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+	  /* Clear this whenever we change the register activity status.  */
+	  set_regs_matched_done = 0;
+
+          /* This is the new highest active register.  */
+          highest_active_reg = *p;
+
+          /* If nothing was active before, this is the new lowest active
+             register.  */
+          if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+            lowest_active_reg = *p;
+
+          /* Move past the register number and inner group count.  */
+          p += 2;
+	  just_past_start_mem = p;
+
+          break;
+
+
+        /* The stop_memory opcode represents the end of a group.  Its
+           arguments are the same as start_memory's: the register
+           number, and the number of inner groups.  */
+	case stop_memory:
+	  DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n",
+			(long int) *p, (long int) p[1]);
+
+          /* We need to save the string position the last time we were at
+             this close-group operator in case the group is operated
+             upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
+             against `aba'; then we want to ignore where we are now in
+             the string in case this attempt to match fails.  */
+          old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+                           ? REG_UNSET (regend[*p]) ? d : regend[*p]
+			   : regend[*p];
+	  DEBUG_PRINT2 ("      old_regend: %d\n",
+			 POINTER_TO_OFFSET (old_regend[*p]));
+
+          regend[*p] = d;
+	  DEBUG_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+
+          /* This register isn't active anymore.  */
+          IS_ACTIVE (reg_info[*p]) = 0;
+
+	  /* Clear this whenever we change the register activity status.  */
+	  set_regs_matched_done = 0;
+
+          /* If this was the only register active, nothing is active
+             anymore.  */
+          if (lowest_active_reg == highest_active_reg)
+            {
+              lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+              highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+            }
+          else
+            { /* We must scan for the new highest active register, since
+                 it isn't necessarily one less than now: consider
+                 (a(b)c(d(e)f)g).  When group 3 ends, after the f), the
+                 new highest active register is 1.  */
+              UCHAR_T r = *p - 1;
+              while (r > 0 && !IS_ACTIVE (reg_info[r]))
+                r--;
+
+              /* If we end up at register zero, that means that we saved
+                 the registers as the result of an `on_failure_jump', not
+                 a `start_memory', and we jumped to past the innermost
+                 `stop_memory'.  For example, in ((.)*) we save
+                 registers 1 and 2 as a result of the *, but when we pop
+                 back to the second ), we are at the stop_memory 1.
+                 Thus, nothing is active.  */
+	      if (r == 0)
+                {
+                  lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+                  highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+                }
+              else
+                highest_active_reg = r;
+            }
+
+          /* If just failed to match something this time around with a
+             group that's operated on by a repetition operator, try to
+             force exit from the ``loop'', and restore the register
+             information for this group that we had before trying this
+             last match.  */
+          if ((!MATCHED_SOMETHING (reg_info[*p])
+               || just_past_start_mem == p - 1)
+	      && (p + 2) < pend)
+            {
+              boolean is_a_jump_n = false;
+
+              p1 = p + 2;
+              mcnt = 0;
+              switch ((re_opcode_t) *p1++)
+                {
+                  case jump_n:
+		    is_a_jump_n = true;
+                  case pop_failure_jump:
+		  case maybe_pop_jump:
+		  case jump:
+		  case dummy_failure_jump:
+                    EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+		    if (is_a_jump_n)
+		      p1 += OFFSET_ADDRESS_SIZE;
+                    break;
+
+                  default:
+                    /* do nothing */ ;
+                }
+	      p1 += mcnt;
+
+              /* If the next operation is a jump backwards in the pattern
+	         to an on_failure_jump right before the start_memory
+                 corresponding to this stop_memory, exit from the loop
+                 by forcing a failure after pushing on the stack the
+                 on_failure_jump's jump in the pattern, and d.  */
+              if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
+                  && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory
+		  && p1[2+OFFSET_ADDRESS_SIZE] == *p)
+		{
+                  /* If this group ever matched anything, then restore
+                     what its registers were before trying this last
+                     failed match, e.g., with `(a*)*b' against `ab' for
+                     regstart[1], and, e.g., with `((a*)*(b*)*)*'
+                     against `aba' for regend[3].
+
+                     Also restore the registers for inner groups for,
+                     e.g., `((a*)(b*))*' against `aba' (register 3 would
+                     otherwise get trashed).  */
+
+                  if (EVER_MATCHED_SOMETHING (reg_info[*p]))
+		    {
+		      unsigned r;
+
+                      EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+		      /* Restore this and inner groups' (if any) registers.  */
+                      for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
+			   r++)
+                        {
+                          regstart[r] = old_regstart[r];
+
+                          /* xx why this test?  */
+                          if (old_regend[r] >= regstart[r])
+                            regend[r] = old_regend[r];
+                        }
+                    }
+		  p1++;
+                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                  PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+
+                  goto fail;
+                }
+            }
+
+          /* Move past the register number and the inner group count.  */
+          p += 2;
+          break;
+
+
+	/* \<digit> has been turned into a `duplicate' command which is
+           followed by the numeric value of <digit> as the register number.  */
+        case duplicate:
+	  {
+	    register const CHAR_T *d2, *dend2;
+	    int regno = *p++;   /* Get which register to match against.  */
+	    DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
+
+	    /* Can't back reference a group which we've never matched.  */
+            if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
+              goto fail;
+
+            /* Where in input to try to start matching.  */
+            d2 = regstart[regno];
+
+            /* Where to stop matching; if both the place to start and
+               the place to stop matching are in the same string, then
+               set to the place to stop, otherwise, for now have to use
+               the end of the first string.  */
+
+            dend2 = ((FIRST_STRING_P (regstart[regno])
+		      == FIRST_STRING_P (regend[regno]))
+		     ? regend[regno] : end_match_1);
+	    for (;;)
+	      {
+		/* If necessary, advance to next segment in register
+                   contents.  */
+		while (d2 == dend2)
+		  {
+		    if (dend2 == end_match_2) break;
+		    if (dend2 == regend[regno]) break;
+
+                    /* End of string1 => advance to string2. */
+                    d2 = string2;
+                    dend2 = regend[regno];
+		  }
+		/* At end of register contents => success */
+		if (d2 == dend2) break;
+
+		/* If necessary, advance to next segment in data.  */
+		PREFETCH ();
+
+		/* How many characters left in this segment to match.  */
+		mcnt = dend - d;
+
+		/* Want how many consecutive characters we can match in
+                   one shot, so, if necessary, adjust the count.  */
+                if (mcnt > dend2 - d2)
+		  mcnt = dend2 - d2;
+
+		/* Compare that many; failure if mismatch, else move
+                   past them.  */
+		if (translate
+                    ? PREFIX(bcmp_translate) (d, d2, mcnt, translate)
+                    : memcmp (d, d2, mcnt*sizeof(UCHAR_T)))
+		  goto fail;
+		d += mcnt, d2 += mcnt;
+
+		/* Do this because we've match some characters.  */
+		SET_REGS_MATCHED ();
+	      }
+	  }
+	  break;
+
+
+        /* begline matches the empty string at the beginning of the string
+           (unless `not_bol' is set in `bufp'), and, if
+           `newline_anchor' is set, after newlines.  */
+	case begline:
+          DEBUG_PRINT1 ("EXECUTING begline.\n");
+
+          if (AT_STRINGS_BEG (d))
+            {
+              if (!bufp->not_bol) break;
+            }
+          else if (d[-1] == '\n' && bufp->newline_anchor)
+            {
+              break;
+            }
+          /* In all other cases, we fail.  */
+          goto fail;
+
+
+        /* endline is the dual of begline.  */
+	case endline:
+          DEBUG_PRINT1 ("EXECUTING endline.\n");
+
+          if (AT_STRINGS_END (d))
+            {
+              if (!bufp->not_eol) break;
+            }
+
+          /* We have to ``prefetch'' the next character.  */
+          else if ((d == end1 ? *string2 : *d) == '\n'
+                   && bufp->newline_anchor)
+            {
+              break;
+            }
+          goto fail;
+
+
+	/* Match at the very beginning of the data.  */
+        case begbuf:
+          DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+          if (AT_STRINGS_BEG (d))
+            break;
+          goto fail;
+
+
+	/* Match at the very end of the data.  */
+        case endbuf:
+          DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+	  if (AT_STRINGS_END (d))
+	    break;
+          goto fail;
+
+
+        /* on_failure_keep_string_jump is used to optimize `.*\n'.  It
+           pushes NULL as the value for the string on the stack.  Then
+           `pop_failure_point' will keep the current value for the
+           string, instead of restoring it.  To see why, consider
+           matching `foo\nbar' against `.*\n'.  The .* matches the foo;
+           then the . fails against the \n.  But the next thing we want
+           to do is match the \n against the \n; if we restored the
+           string value, we would be back at the foo.
+
+           Because this is used only in specific cases, we don't need to
+           check all the things that `on_failure_jump' does, to make
+           sure the right things get saved on the stack.  Hence we don't
+           share its code.  The only reason to push anything on the
+           stack at all is that otherwise we would have to change
+           `anychar's code to do something besides goto fail in this
+           case; that seems worse than this.  */
+        case on_failure_keep_string_jump:
+          DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+
+          EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+          DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
+#else
+          DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+#endif
+
+          PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+          break;
+
+
+	/* Uses of on_failure_jump:
+
+           Each alternative starts with an on_failure_jump that points
+           to the beginning of the next alternative.  Each alternative
+           except the last ends with a jump that in effect jumps past
+           the rest of the alternatives.  (They really jump to the
+           ending jump of the following alternative, because tensioning
+           these jumps is a hassle.)
+
+           Repeats start with an on_failure_jump that points past both
+           the repetition text and either the following jump or
+           pop_failure_jump back to this on_failure_jump.  */
+	case on_failure_jump:
+        on_failure:
+          DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+
+          EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+          DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
+#else
+          DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+#endif
+
+          /* If this on_failure_jump comes right before a group (i.e.,
+             the original * applied to a group), save the information
+             for that group and all inner ones, so that if we fail back
+             to this point, the group's information will be correct.
+             For example, in \(a*\)*\1, we need the preceding group,
+             and in \(zz\(a*\)b*\)\2, we need the inner group.  */
+
+          /* We can't use `p' to check ahead because we push
+             a failure point to `p + mcnt' after we do this.  */
+          p1 = p;
+
+          /* We need to skip no_op's before we look for the
+             start_memory in case this on_failure_jump is happening as
+             the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
+             against aba.  */
+          while (p1 < pend && (re_opcode_t) *p1 == no_op)
+            p1++;
+
+          if (p1 < pend && (re_opcode_t) *p1 == start_memory)
+            {
+              /* We have a new highest active register now.  This will
+                 get reset at the start_memory we are about to get to,
+                 but we will have saved all the registers relevant to
+                 this repetition op, as described above.  */
+              highest_active_reg = *(p1 + 1) + *(p1 + 2);
+              if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+                lowest_active_reg = *(p1 + 1);
+            }
+
+          DEBUG_PRINT1 (":\n");
+          PUSH_FAILURE_POINT (p + mcnt, d, -2);
+          break;
+
+
+        /* A smart repeat ends with `maybe_pop_jump'.
+	   We change it to either `pop_failure_jump' or `jump'.  */
+        case maybe_pop_jump:
+          EXTRACT_NUMBER_AND_INCR (mcnt, p);
+          DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
+          {
+	    register UCHAR_T *p2 = p;
+
+            /* Compare the beginning of the repeat with what in the
+               pattern follows its end. If we can establish that there
+               is nothing that they would both match, i.e., that we
+               would have to backtrack because of (as in, e.g., `a*a')
+               then we can change to pop_failure_jump, because we'll
+               never have to backtrack.
+
+               This is not true in the case of alternatives: in
+               `(a|ab)*' we do need to backtrack to the `ab' alternative
+               (e.g., if the string was `ab').  But instead of trying to
+               detect that here, the alternative has put on a dummy
+               failure point which is what we will end up popping.  */
+
+	    /* Skip over open/close-group commands.
+	       If what follows this loop is a ...+ construct,
+	       look at what begins its body, since we will have to
+	       match at least one of that.  */
+	    while (1)
+	      {
+		if (p2 + 2 < pend
+		    && ((re_opcode_t) *p2 == stop_memory
+			|| (re_opcode_t) *p2 == start_memory))
+		  p2 += 3;
+		else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend
+			 && (re_opcode_t) *p2 == dummy_failure_jump)
+		  p2 += 2 + 2 * OFFSET_ADDRESS_SIZE;
+		else
+		  break;
+	      }
+
+	    p1 = p + mcnt;
+	    /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
+	       to the `maybe_finalize_jump' of this case.  Examine what
+	       follows.  */
+
+            /* If we're at the end of the pattern, we can change.  */
+            if (p2 == pend)
+	      {
+		/* Consider what happens when matching ":\(.*\)"
+		   against ":/".  I don't really understand this code
+		   yet.  */
+  	        p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T)
+		  pop_failure_jump;
+                DEBUG_PRINT1
+                  ("  End of pattern: change to `pop_failure_jump'.\n");
+              }
+
+            else if ((re_opcode_t) *p2 == exactn
+#ifdef MBS_SUPPORT
+		     || (re_opcode_t) *p2 == exactn_bin
+#endif
+		     || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
+	      {
+		register UCHAR_T c
+                  = *p2 == (UCHAR_T) endline ? '\n' : p2[2];
+
+                if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn
+#ifdef MBS_SUPPORT
+		     || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin
+#endif
+		    ) && p1[3+OFFSET_ADDRESS_SIZE] != c)
+                  {
+  		    p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T)
+		      pop_failure_jump;
+#ifdef WCHAR
+		      DEBUG_PRINT3 ("  %C != %C => pop_failure_jump.\n",
+				    (wint_t) c,
+				    (wint_t) p1[3+OFFSET_ADDRESS_SIZE]);
+#else
+		      DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
+				    (char) c,
+				    (char) p1[3+OFFSET_ADDRESS_SIZE]);
+#endif
+                  }
+
+#ifndef WCHAR
+		else if ((re_opcode_t) p1[3] == charset
+			 || (re_opcode_t) p1[3] == charset_not)
+		  {
+		    int not = (re_opcode_t) p1[3] == charset_not;
+
+		    if (c < (unsigned) (p1[4] * BYTEWIDTH)
+			&& p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+		      not = !not;
+
+                    /* `not' is equal to 1 if c would match, which means
+                        that we can't change to pop_failure_jump.  */
+		    if (!not)
+                      {
+  		        p[-3] = (unsigned char) pop_failure_jump;
+                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                      }
+		  }
+#endif /* not WCHAR */
+	      }
+#ifndef WCHAR
+            else if ((re_opcode_t) *p2 == charset)
+	      {
+		/* We win if the first character of the loop is not part
+                   of the charset.  */
+                if ((re_opcode_t) p1[3] == exactn
+ 		    && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
+ 			  && (p2[2 + p1[5] / BYTEWIDTH]
+ 			      & (1 << (p1[5] % BYTEWIDTH)))))
+		  {
+		    p[-3] = (unsigned char) pop_failure_jump;
+		    DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                  }
+
+		else if ((re_opcode_t) p1[3] == charset_not)
+		  {
+		    int idx;
+		    /* We win if the charset_not inside the loop
+		       lists every character listed in the charset after.  */
+		    for (idx = 0; idx < (int) p2[1]; idx++)
+		      if (! (p2[2 + idx] == 0
+			     || (idx < (int) p1[4]
+				 && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
+			break;
+
+		    if (idx == p2[1])
+                      {
+  		        p[-3] = (unsigned char) pop_failure_jump;
+                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                      }
+		  }
+		else if ((re_opcode_t) p1[3] == charset)
+		  {
+		    int idx;
+		    /* We win if the charset inside the loop
+		       has no overlap with the one after the loop.  */
+		    for (idx = 0;
+			 idx < (int) p2[1] && idx < (int) p1[4];
+			 idx++)
+		      if ((p2[2 + idx] & p1[5 + idx]) != 0)
+			break;
+
+		    if (idx == p2[1] || idx == p1[4])
+                      {
+  		        p[-3] = (unsigned char) pop_failure_jump;
+                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                      }
+		  }
+	      }
+#endif /* not WCHAR */
+	  }
+	  p -= OFFSET_ADDRESS_SIZE;	/* Point at relative address again.  */
+	  if ((re_opcode_t) p[-1] != pop_failure_jump)
+	    {
+	      p[-1] = (UCHAR_T) jump;
+              DEBUG_PRINT1 ("  Match => jump.\n");
+	      goto unconditional_jump;
+	    }
+        /* Note fall through.  */
+
+
+	/* The end of a simple repeat has a pop_failure_jump back to
+           its matching on_failure_jump, where the latter will push a
+           failure point.  The pop_failure_jump takes off failure
+           points put on by this pop_failure_jump's matching
+           on_failure_jump; we got through the pattern to here from the
+           matching on_failure_jump, so didn't fail.  */
+        case pop_failure_jump:
+          {
+            /* We need to pass separate storage for the lowest and
+               highest registers, even though we don't care about the
+               actual values.  Otherwise, we will restore only one
+               register from the stack, since lowest will == highest in
+               `pop_failure_point'.  */
+            active_reg_t dummy_low_reg, dummy_high_reg;
+            UCHAR_T *pdummy = NULL;
+            const CHAR_T *sdummy = NULL;
+
+            DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+            POP_FAILURE_POINT (sdummy, pdummy,
+                               dummy_low_reg, dummy_high_reg,
+                               reg_dummy, reg_dummy, reg_info_dummy);
+          }
+	  /* Note fall through.  */
+
+	unconditional_jump:
+#ifdef _LIBC
+	  DEBUG_PRINT2 ("\n%p: ", p);
+#else
+	  DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+          /* Note fall through.  */
+
+        /* Unconditionally jump (without popping any failure points).  */
+        case jump:
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p);	/* Get the amount to jump.  */
+          DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+	  p += mcnt;				/* Do the jump.  */
+#ifdef _LIBC
+          DEBUG_PRINT2 ("(to %p).\n", p);
+#else
+          DEBUG_PRINT2 ("(to 0x%x).\n", p);
+#endif
+	  break;
+
+
+        /* We need this opcode so we can detect where alternatives end
+           in `group_match_null_string_p' et al.  */
+        case jump_past_alt:
+          DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+          goto unconditional_jump;
+
+
+        /* Normally, the on_failure_jump pushes a failure point, which
+           then gets popped at pop_failure_jump.  We will end up at
+           pop_failure_jump, also, and with a pattern of, say, `a+', we
+           are skipping over the on_failure_jump, so we have to push
+           something meaningless for pop_failure_jump to pop.  */
+        case dummy_failure_jump:
+          DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+          /* It doesn't matter what we push for the string here.  What
+             the code at `fail' tests is the value for the pattern.  */
+          PUSH_FAILURE_POINT (NULL, NULL, -2);
+          goto unconditional_jump;
+
+
+        /* At the end of an alternative, we need to push a dummy failure
+           point in case we are followed by a `pop_failure_jump', because
+           we don't want the failure point for the alternative to be
+           popped.  For example, matching `(a|ab)*' against `aab'
+           requires that we match the `ab' alternative.  */
+        case push_dummy_failure:
+          DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+          /* See comments just above at `dummy_failure_jump' about the
+             two zeroes.  */
+          PUSH_FAILURE_POINT (NULL, NULL, -2);
+          break;
+
+        /* Have to succeed matching what follows at least n times.
+           After that, handle like `on_failure_jump'.  */
+        case succeed_n:
+          EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
+          DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
+
+          assert (mcnt >= 0);
+          /* Originally, this is how many times we HAVE to succeed.  */
+          if (mcnt > 0)
+            {
+               mcnt--;
+	       p += OFFSET_ADDRESS_SIZE;
+               STORE_NUMBER_AND_INCR (p, mcnt);
+#ifdef _LIBC
+               DEBUG_PRINT3 ("  Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE
+			     , mcnt);
+#else
+               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE
+			     , mcnt);
+#endif
+            }
+	  else if (mcnt == 0)
+            {
+#ifdef _LIBC
+              DEBUG_PRINT2 ("  Setting two bytes from %p to no_op.\n",
+			    p + OFFSET_ADDRESS_SIZE);
+#else
+              DEBUG_PRINT2 ("  Setting two bytes from 0x%x to no_op.\n",
+			    p + OFFSET_ADDRESS_SIZE);
+#endif /* _LIBC */
+
+#ifdef WCHAR
+	      p[1] = (UCHAR_T) no_op;
+#else
+	      p[2] = (UCHAR_T) no_op;
+              p[3] = (UCHAR_T) no_op;
+#endif /* WCHAR */
+              goto on_failure;
+            }
+          break;
+
+        case jump_n:
+          EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
+          DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+
+          /* Originally, this is how many times we CAN jump.  */
+          if (mcnt)
+            {
+               mcnt--;
+               STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt);
+
+#ifdef _LIBC
+               DEBUG_PRINT3 ("  Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE,
+			     mcnt);
+#else
+               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE,
+			     mcnt);
+#endif /* _LIBC */
+	       goto unconditional_jump;
+            }
+          /* If don't have to jump any more, skip over the rest of command.  */
+	  else
+	    p += 2 * OFFSET_ADDRESS_SIZE;
+          break;
+
+	case set_number_at:
+	  {
+            DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+
+            EXTRACT_NUMBER_AND_INCR (mcnt, p);
+            p1 = p + mcnt;
+            EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+            DEBUG_PRINT3 ("  Setting %p to %d.\n", p1, mcnt);
+#else
+            DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p1, mcnt);
+#endif
+	    STORE_NUMBER (p1, mcnt);
+            break;
+          }
+
+#if 0
+	/* The DEC Alpha C compiler 3.x generates incorrect code for the
+	   test  WORDCHAR_P (d - 1) != WORDCHAR_P (d)  in the expansion of
+	   AT_WORD_BOUNDARY, so this code is disabled.  Expanding the
+	   macro and introducing temporary variables works around the bug.  */
+
+	case wordbound:
+	  DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+	  if (AT_WORD_BOUNDARY (d))
+	    break;
+	  goto fail;
+
+	case notwordbound:
+	  DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+	  if (AT_WORD_BOUNDARY (d))
+	    goto fail;
+	  break;
+#else
+	case wordbound:
+	{
+	  boolean prevchar, thischar;
+
+	  DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+	  if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+	    break;
+
+	  prevchar = WORDCHAR_P (d - 1);
+	  thischar = WORDCHAR_P (d);
+	  if (prevchar != thischar)
+	    break;
+	  goto fail;
+	}
+
+      case notwordbound:
+	{
+	  boolean prevchar, thischar;
+
+	  DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+	  if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+	    goto fail;
+
+	  prevchar = WORDCHAR_P (d - 1);
+	  thischar = WORDCHAR_P (d);
+	  if (prevchar != thischar)
+	    goto fail;
+	  break;
+	}
+#endif
+
+	case wordbeg:
+          DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+	  if (!AT_STRINGS_END (d) && WORDCHAR_P (d)
+	      && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
+	    break;
+          goto fail;
+
+	case wordend:
+          DEBUG_PRINT1 ("EXECUTING wordend.\n");
+	  if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
+              && (AT_STRINGS_END (d) || !WORDCHAR_P (d)))
+	    break;
+          goto fail;
+
+#ifdef emacs
+  	case before_dot:
+          DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+ 	  if (PTR_CHAR_POS ((unsigned char *) d) >= point)
+  	    goto fail;
+  	  break;
+
+  	case at_dot:
+          DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+ 	  if (PTR_CHAR_POS ((unsigned char *) d) != point)
+  	    goto fail;
+  	  break;
+
+  	case after_dot:
+          DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+          if (PTR_CHAR_POS ((unsigned char *) d) <= point)
+  	    goto fail;
+  	  break;
+
+	case syntaxspec:
+          DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+	  mcnt = *p++;
+	  goto matchsyntax;
+
+        case wordchar:
+          DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+	  mcnt = (int) Sword;
+        matchsyntax:
+	  PREFETCH ();
+	  /* Can't use *d++ here; SYNTAX may be an unsafe macro.  */
+	  d++;
+	  if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
+	    goto fail;
+          SET_REGS_MATCHED ();
+	  break;
+
+	case notsyntaxspec:
+          DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+	  mcnt = *p++;
+	  goto matchnotsyntax;
+
+        case notwordchar:
+          DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+	  mcnt = (int) Sword;
+        matchnotsyntax:
+	  PREFETCH ();
+	  /* Can't use *d++ here; SYNTAX may be an unsafe macro.  */
+	  d++;
+	  if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
+	    goto fail;
+	  SET_REGS_MATCHED ();
+          break;
+
+#else /* not emacs */
+	case wordchar:
+          DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+	  PREFETCH ();
+          if (!WORDCHAR_P (d))
+            goto fail;
+	  SET_REGS_MATCHED ();
+          d++;
+	  break;
+
+	case notwordchar:
+          DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+	  PREFETCH ();
+	  if (WORDCHAR_P (d))
+            goto fail;
+          SET_REGS_MATCHED ();
+          d++;
+	  break;
+#endif /* not emacs */
+
+        default:
+          abort ();
+	}
+      continue;  /* Successfully executed one pattern command; keep going.  */
+
+
+    /* We goto here if a matching operation fails. */
+    fail:
+      if (!FAIL_STACK_EMPTY ())
+	{ /* A restart point is known.  Restore to that state.  */
+          DEBUG_PRINT1 ("\nFAIL:\n");
+          POP_FAILURE_POINT (d, p,
+                             lowest_active_reg, highest_active_reg,
+                             regstart, regend, reg_info);
+
+          /* If this failure point is a dummy, try the next one.  */
+          if (!p)
+	    goto fail;
+
+          /* If we failed to the end of the pattern, don't examine *p.  */
+	  assert (p <= pend);
+          if (p < pend)
+            {
+              boolean is_a_jump_n = false;
+
+              /* If failed to a backwards jump that's part of a repetition
+                 loop, need to pop this failure point and use the next one.  */
+              switch ((re_opcode_t) *p)
+                {
+                case jump_n:
+                  is_a_jump_n = true;
+                case maybe_pop_jump:
+                case pop_failure_jump:
+                case jump:
+                  p1 = p + 1;
+                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                  p1 += mcnt;
+
+                  if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
+                      || (!is_a_jump_n
+                          && (re_opcode_t) *p1 == on_failure_jump))
+                    goto fail;
+                  break;
+                default:
+                  /* do nothing */ ;
+                }
+            }
+
+          if (d >= string1 && d <= end1)
+	    dend = end_match_1;
+        }
+      else
+        break;   /* Matching at this starting point really fails.  */
+    } /* for (;;) */
+
+  if (best_regs_set)
+    goto restore_best_regs;
+
+  FREE_VARIABLES ();
+
+  return -1;         			/* Failure to match.  */
+} /* re_match_2 */
+
+/* Subroutine definitions for re_match_2.  */
+
+
+/* We are passed P pointing to a register number after a start_memory.
+
+   Return true if the pattern up to the corresponding stop_memory can
+   match the empty string, and false otherwise.
+
+   If we find the matching stop_memory, sets P to point to one past its number.
+   Otherwise, sets P to an undefined byte less than or equal to END.
+
+   We don't handle duplicates properly (yet).  */
+
+static boolean
+PREFIX(group_match_null_string_p) (
+    UCHAR_T **p, UCHAR_T *end,
+    PREFIX(register_info_type) *reg_info)
+{
+  int mcnt;
+  /* Point to after the args to the start_memory.  */
+  UCHAR_T *p1 = *p + 2;
+
+  while (p1 < end)
+    {
+      /* Skip over opcodes that can match nothing, and return true or
+	 false, as appropriate, when we get to one that can't, or to the
+         matching stop_memory.  */
+
+      switch ((re_opcode_t) *p1)
+        {
+        /* Could be either a loop or a series of alternatives.  */
+        case on_failure_jump:
+          p1++;
+          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+          /* If the next operation is not a jump backwards in the
+	     pattern.  */
+
+	  if (mcnt >= 0)
+	    {
+              /* Go through the on_failure_jumps of the alternatives,
+                 seeing if any of the alternatives cannot match nothing.
+                 The last alternative starts with only a jump,
+                 whereas the rest start with on_failure_jump and end
+                 with a jump, e.g., here is the pattern for `a|b|c':
+
+                 /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
+                 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
+                 /exactn/1/c
+
+                 So, we have to first go through the first (n-1)
+                 alternatives and then deal with the last one separately.  */
+
+
+              /* Deal with the first (n-1) alternatives, which start
+                 with an on_failure_jump (see above) that jumps to right
+                 past a jump_past_alt.  */
+
+              while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] ==
+		     jump_past_alt)
+                {
+                  /* `mcnt' holds how many bytes long the alternative
+                     is, including the ending `jump_past_alt' and
+                     its number.  */
+
+                  if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt -
+						(1 + OFFSET_ADDRESS_SIZE),
+						reg_info))
+                    return false;
+
+                  /* Move to right after this alternative, including the
+		     jump_past_alt.  */
+                  p1 += mcnt;
+
+                  /* Break if it's the beginning of an n-th alternative
+                     that doesn't begin with an on_failure_jump.  */
+                  if ((re_opcode_t) *p1 != on_failure_jump)
+                    break;
+
+		  /* Still have to check that it's not an n-th
+		     alternative that starts with an on_failure_jump.  */
+		  p1++;
+                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                  if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] !=
+		      jump_past_alt)
+                    {
+		      /* Get to the beginning of the n-th alternative.  */
+                      p1 -= 1 + OFFSET_ADDRESS_SIZE;
+                      break;
+                    }
+                }
+
+              /* Deal with the last alternative: go back and get number
+                 of the `jump_past_alt' just before it.  `mcnt' contains
+                 the length of the alternative.  */
+              EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE);
+
+              if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info))
+                return false;
+
+              p1 += mcnt;	/* Get past the n-th alternative.  */
+            } /* if mcnt > 0 */
+          break;
+
+
+        case stop_memory:
+	  assert (p1[1] == **p);
+          *p = p1 + 2;
+          return true;
+
+
+        default:
+          if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info))
+            return false;
+        }
+    } /* while p1 < end */
+
+  return false;
+} /* group_match_null_string_p */
+
+
+/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
+   It expects P to be the first byte of a single alternative and END one
+   byte past the last. The alternative can contain groups.  */
+
+static boolean
+PREFIX(alt_match_null_string_p) (
+    UCHAR_T *p, UCHAR_T *end,
+    PREFIX(register_info_type) *reg_info)
+{
+  int mcnt;
+  UCHAR_T *p1 = p;
+
+  while (p1 < end)
+    {
+      /* Skip over opcodes that can match nothing, and break when we get
+         to one that can't.  */
+
+      switch ((re_opcode_t) *p1)
+        {
+	/* It's a loop.  */
+        case on_failure_jump:
+          p1++;
+          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+          p1 += mcnt;
+          break;
+
+	default:
+          if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info))
+            return false;
+        }
+    }  /* while p1 < end */
+
+  return true;
+} /* alt_match_null_string_p */
+
+
+/* Deals with the ops common to group_match_null_string_p and
+   alt_match_null_string_p.
+
+   Sets P to one after the op and its arguments, if any.  */
+
+static boolean
+PREFIX(common_op_match_null_string_p) (
+    UCHAR_T **p, UCHAR_T *end,
+    PREFIX(register_info_type) *reg_info)
+{
+  int mcnt;
+  boolean ret;
+  int reg_no;
+  UCHAR_T *p1 = *p;
+
+  switch ((re_opcode_t) *p1++)
+    {
+    case no_op:
+    case begline:
+    case endline:
+    case begbuf:
+    case endbuf:
+    case wordbeg:
+    case wordend:
+    case wordbound:
+    case notwordbound:
+#ifdef emacs
+    case before_dot:
+    case at_dot:
+    case after_dot:
+#endif
+      break;
+
+    case start_memory:
+      reg_no = *p1;
+      assert (reg_no > 0 && reg_no <= MAX_REGNUM);
+      ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info);
+
+      /* Have to set this here in case we're checking a group which
+         contains a group and a back reference to it.  */
+
+      if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
+        REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
+
+      if (!ret)
+        return false;
+      break;
+
+    /* If this is an optimized succeed_n for zero times, make the jump.  */
+    case jump:
+      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+      if (mcnt >= 0)
+        p1 += mcnt;
+      else
+        return false;
+      break;
+
+    case succeed_n:
+      /* Get to the number of times to succeed.  */
+      p1 += OFFSET_ADDRESS_SIZE;
+      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+      if (mcnt == 0)
+        {
+          p1 -= 2 * OFFSET_ADDRESS_SIZE;
+          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+          p1 += mcnt;
+        }
+      else
+        return false;
+      break;
+
+    case duplicate:
+      if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
+        return false;
+      break;
+
+    case set_number_at:
+      p1 += 2 * OFFSET_ADDRESS_SIZE;
+
+    default:
+      /* All other opcodes mean we cannot match the empty string.  */
+      return false;
+  }
+
+  *p = p1;
+  return true;
+} /* common_op_match_null_string_p */
+
+
+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
+   bytes; nonzero otherwise.  */
+
+static int
+PREFIX(bcmp_translate) (
+     const CHAR_T *s1, const CHAR_T *s2,
+     register int len,
+     RE_TRANSLATE_TYPE translate)
+{
+  register const UCHAR_T *p1 = (const UCHAR_T *) s1;
+  register const UCHAR_T *p2 = (const UCHAR_T *) s2;
+  while (len)
+    {
+#ifdef WCHAR
+      if (((*p1<=0xff)?translate[*p1++]:*p1++)
+	  != ((*p2<=0xff)?translate[*p2++]:*p2++))
+	return 1;
+#else /* BYTE */
+      if (translate[*p1++] != translate[*p2++]) return 1;
+#endif /* WCHAR */
+      len--;
+    }
+  return 0;
+}
+
+
+#else /* not INSIDE_RECURSION */
+
+/* Entry points for GNU code.  */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+   compiles PATTERN (of length SIZE) and puts the result in BUFP.
+   Returns 0 if the pattern was valid, otherwise an error string.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+   are set in BUFP on entry.
+
+   We call regex_compile to do the actual compilation.  */
+
+const char *
+re_compile_pattern (const char *pattern,
+		size_t length,
+		struct re_pattern_buffer *bufp)
+{
+  reg_errcode_t ret;
+
+  /* GNU code is written to assume at least RE_NREGS registers will be set
+     (and at least one extra will be -1).  */
+  bufp->regs_allocated = REGS_UNALLOCATED;
+
+  /* And GNU code determines whether or not to get register information
+     by passing null for the REGS argument to re_match, etc., not by
+     setting no_sub.  */
+  bufp->no_sub = 0;
+
+  /* Match anchors at newline.  */
+  bufp->newline_anchor = 1;
+
+# ifdef MBS_SUPPORT
+  if (MB_CUR_MAX != 1)
+    ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp);
+  else
+# endif
+    ret = byte_regex_compile (pattern, length, re_syntax_options, bufp);
+
+  if (!ret)
+    return NULL;
+  return gettext (re_error_msgid + re_error_msgid_idx[(int) ret]);
+}
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+
+/* BSD has one and only one pattern buffer.  */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+#ifdef _LIBC
+/* Make these definitions weak in libc, so POSIX programs can redefine
+   these names if they don't use our functions, and still use
+   regcomp/regexec below without link errors.  */
+weak_function
+#endif
+re_comp (const char *s)
+{
+  reg_errcode_t ret;
+
+  if (!s)
+    {
+      if (!re_comp_buf.buffer)
+	return gettext ("No previous regular expression");
+      return 0;
+    }
+
+  if (!re_comp_buf.buffer)
+    {
+      re_comp_buf.buffer = (unsigned char *) malloc (200);
+      if (re_comp_buf.buffer == NULL)
+        return (char *) gettext (re_error_msgid
+				 + re_error_msgid_idx[(int) REG_ESPACE]);
+      re_comp_buf.allocated = 200;
+
+      re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+      if (re_comp_buf.fastmap == NULL)
+	return (char *) gettext (re_error_msgid
+				 + re_error_msgid_idx[(int) REG_ESPACE]);
+    }
+
+  /* Since `re_exec' always passes NULL for the `regs' argument, we
+     don't need to initialize the pattern buffer fields which affect it.  */
+
+  /* Match anchors at newlines.  */
+  re_comp_buf.newline_anchor = 1;
+
+# ifdef MBS_SUPPORT
+  if (MB_CUR_MAX != 1)
+    ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+  else
+# endif
+    ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+
+  if (!ret)
+    return NULL;
+
+  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
+  return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) ret]);
+}
+
+
+int
+#if defined _LIBC || defined __UCLIBC__
+weak_function
+#endif
+re_exec (const char *s)
+{
+  const int len = strlen (s);
+  return
+    0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
+}
+
+#endif /* _REGEX_RE_COMP */
+
+/* POSIX.2 functions.  Don't define these for Emacs.  */
+
+#ifndef emacs
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+   PREG is a regex_t *.  We do not expect any fields to be initialized,
+   since POSIX says we shouldn't.  Thus, we set
+
+     `buffer' to the compiled pattern;
+     `used' to the length of the compiled pattern;
+     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+       REG_EXTENDED bit in CFLAGS is set; otherwise, to
+       RE_SYNTAX_POSIX_BASIC;
+     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+     `fastmap' to an allocated space for the fastmap;
+     `fastmap_accurate' to zero;
+     `re_nsub' to the number of subexpressions in PATTERN.
+
+   PATTERN is the address of the pattern string.
+
+   CFLAGS is a series of bits which affect compilation.
+
+     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+     use POSIX basic syntax.
+
+     If REG_NEWLINE is set, then . and [^...] don't match newline.
+     Also, regexec will try a match beginning after every newline.
+
+     If REG_ICASE is set, then we considers upper- and lowercase
+     versions of letters to be equivalent when matching.
+
+     If REG_NOSUB is set, then when PREG is passed to regexec, that
+     routine will report only success or failure, and nothing about the
+     registers.
+
+   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
+   the return codes and their meanings.)  */
+
+int
+regcomp (
+    regex_t *preg,
+    const char *pattern,
+    int cflags)
+{
+  reg_errcode_t ret;
+  reg_syntax_t syntax
+    = (cflags & REG_EXTENDED) ?
+      RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+  /* regex_compile will allocate the space for the compiled pattern.  */
+  preg->buffer = 0;
+  preg->allocated = 0;
+  preg->used = 0;
+
+  /* Try to allocate space for the fastmap.  */
+  preg->fastmap = (char *) malloc (1 << BYTEWIDTH);
+
+  if (cflags & REG_ICASE)
+    {
+      unsigned i;
+
+      preg->translate
+	= (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE
+				      * sizeof (*(RE_TRANSLATE_TYPE)0));
+      if (preg->translate == NULL)
+        return (int) REG_ESPACE;
+
+      /* Map uppercase characters to corresponding lowercase ones.  */
+      for (i = 0; i < CHAR_SET_SIZE; i++)
+        preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i;
+    }
+  else
+    preg->translate = NULL;
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (cflags & REG_NEWLINE)
+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~RE_DOT_NEWLINE;
+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+      /* It also changes the matching behavior.  */
+      preg->newline_anchor = 1;
+    }
+  else
+    preg->newline_anchor = 0;
+
+  preg->no_sub = !!(cflags & REG_NOSUB);
+
+  /* POSIX says a null character in the pattern terminates it, so we
+     can use strlen here in compiling the pattern.  */
+# ifdef MBS_SUPPORT
+  if (MB_CUR_MAX != 1)
+    ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg);
+  else
+# endif
+    ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg);
+
+  /* POSIX doesn't distinguish between an unmatched open-group and an
+     unmatched close-group: both are REG_EPAREN.  */
+  if (ret == REG_ERPAREN) ret = REG_EPAREN;
+
+  if (ret == REG_NOERROR && preg->fastmap)
+    {
+      /* Compute the fastmap now, since regexec cannot modify the pattern
+	 buffer.  */
+      if (re_compile_fastmap (preg) == -2)
+	{
+	  /* Some error occurred while computing the fastmap, just forget
+	     about it.  */
+	  free (preg->fastmap);
+	  preg->fastmap = NULL;
+	}
+    }
+
+  return (int) ret;
+}
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+   string STRING.
+
+   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
+   least NMATCH elements, and we set them to the offsets of the
+   corresponding matched substrings.
+
+   EFLAGS specifies `execution flags' which affect matching: if
+   REG_NOTBOL is set, then ^ does not match at the beginning of the
+   string; if REG_NOTEOL is set, then $ does not match at the end.
+
+   We return 0 if we find a match and REG_NOMATCH if not.  */
+
+int
+regexec (
+    const regex_t *preg,
+    const char *string,
+    size_t nmatch,
+    regmatch_t pmatch[],
+    int eflags)
+{
+  int ret;
+  struct re_registers regs;
+  regex_t private_preg;
+  int len = strlen (string);
+  boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+  /* use hidden memcpy() ourselves rather than gcc calling public memcpy() */
+  memcpy(&private_preg, preg, sizeof(*preg));
+
+  private_preg.not_bol = !!(eflags & REG_NOTBOL);
+  private_preg.not_eol = !!(eflags & REG_NOTEOL);
+
+  /* The user has told us exactly how many registers to return
+     information about, via `nmatch'.  We have to pass that on to the
+     matching routines.  */
+  private_preg.regs_allocated = REGS_FIXED;
+
+  if (want_reg_info)
+    {
+      regs.num_regs = nmatch;
+      regs.start = TALLOC (nmatch * 2, regoff_t);
+      if (regs.start == NULL)
+        return (int) REG_NOMATCH;
+      regs.end = regs.start + nmatch;
+    }
+
+  /* Perform the searching operation.  */
+  ret = re_search (&private_preg, string, len,
+                   /* start: */ 0, /* range: */ len,
+                   want_reg_info ? &regs : (struct re_registers *) 0);
+
+  /* Copy the register information to the POSIX structure.  */
+  if (want_reg_info)
+    {
+      if (ret >= 0)
+        {
+          unsigned r;
+
+          for (r = 0; r < nmatch; r++)
+            {
+              pmatch[r].rm_so = regs.start[r];
+              pmatch[r].rm_eo = regs.end[r];
+            }
+        }
+
+      /* If we needed the temporary register info, free the space now.  */
+      free (regs.start);
+    }
+
+  /* We want zero return to mean success, unlike `re_search'.  */
+  return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+libc_hidden_def(regexec)
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   We don't use PREG here.  */
+
+size_t
+regerror (
+    int errcode,
+    const regex_t * preg attribute_unused,
+    char *errbuf,
+    size_t errbuf_size)
+{
+  const char *msg;
+  size_t msg_size;
+
+  if (errcode < 0
+      || errcode >= (int) (sizeof (re_error_msgid_idx)
+			   / sizeof (re_error_msgid_idx[0])))
+    /* Only error codes returned by the rest of the code should be passed
+       to this routine.  If we are given anything else, or if other regex
+       code generates an invalid error code, then the program has a bug.
+       Dump core so we can fix it.  */
+    abort ();
+
+  msg = gettext (re_error_msgid + re_error_msgid_idx[errcode]);
+
+  msg_size = strlen (msg) + 1; /* Includes the null.  */
+
+  if (errbuf_size != 0)
+    {
+      if (msg_size > errbuf_size)
+        {
+          memcpy (errbuf, msg, errbuf_size - 1);
+          errbuf[errbuf_size - 1] = 0;
+        }
+      else
+        memcpy (errbuf, msg, msg_size);
+    }
+
+  return msg_size;
+}
+
+
+/* Free dynamically allocated space used by PREG.  */
+
+void
+regfree (regex_t *preg)
+{
+  free (preg->buffer);
+  preg->buffer = NULL;
+
+  preg->allocated = 0;
+  preg->used = 0;
+
+  free (preg->fastmap);
+  preg->fastmap = NULL;
+  preg->fastmap_accurate = 0;
+
+  free (preg->translate);
+  preg->translate = NULL;
+}
+libc_hidden_def(regfree)
+
+#endif /* not emacs  */
+
+#endif /* not INSIDE_RECURSION */
+
+
+#undef STORE_NUMBER
+#undef STORE_NUMBER_AND_INCR
+#undef EXTRACT_NUMBER
+#undef EXTRACT_NUMBER_AND_INCR
+
+#undef DEBUG_PRINT_COMPILED_PATTERN
+#undef DEBUG_PRINT_DOUBLE_STRING
+
+#undef INIT_FAIL_STACK
+#undef RESET_FAIL_STACK
+#undef DOUBLE_FAIL_STACK
+#undef PUSH_PATTERN_OP
+#undef PUSH_FAILURE_POINTER
+#undef PUSH_FAILURE_INT
+#undef PUSH_FAILURE_ELT
+#undef POP_FAILURE_POINTER
+#undef POP_FAILURE_INT
+#undef POP_FAILURE_ELT
+#undef DEBUG_PUSH
+#undef DEBUG_POP
+#undef PUSH_FAILURE_POINT
+#undef POP_FAILURE_POINT
+
+#undef REG_UNSET_VALUE
+#undef REG_UNSET
+
+#undef PATFETCH
+#undef PATFETCH_RAW
+#undef PATUNFETCH
+#undef TRANSLATE
+
+#undef INIT_BUF_SIZE
+#undef GET_BUFFER_SPACE
+#undef BUF_PUSH
+#undef BUF_PUSH_2
+#undef BUF_PUSH_3
+#undef STORE_JUMP
+#undef STORE_JUMP2
+#undef INSERT_JUMP
+#undef INSERT_JUMP2
+#undef EXTEND_BUFFER
+#undef GET_UNSIGNED_NUMBER
+#undef FREE_STACK_RETURN
+
+# undef POINTER_TO_OFFSET
+# undef MATCHING_IN_FRST_STRING
+# undef PREFETCH
+# undef AT_STRINGS_BEG
+# undef AT_STRINGS_END
+# undef WORDCHAR_P
+# undef FREE_VAR
+# undef FREE_VARIABLES
+# undef NO_HIGHEST_ACTIVE_REG
+# undef NO_LOWEST_ACTIVE_REG
+
+# undef CHAR_T
+# undef UCHAR_T
+# undef COMPILED_BUFFER_VAR
+# undef OFFSET_ADDRESS_SIZE
+# undef CHAR_CLASS_SIZE
+# undef PREFIX
+# undef ARG_PREFIX
+# undef PUT_CHAR
+# undef BYTE
+# undef WCHAR
+
+# define DEFINED_ONCE
diff --git a/ap/build/uClibc/libc/misc/regex/regexec.c b/ap/build/uClibc/libc/misc/regex/regexec.c
new file mode 100644
index 0000000..c13c64e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/regex/regexec.c
@@ -0,0 +1,4247 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
+				     int n) internal_function;
+static void match_ctx_clean (re_match_context_t *mctx) internal_function;
+static void match_ctx_free (re_match_context_t *cache) internal_function;
+static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node,
+					  int str_idx, int from, int to)
+     internal_function;
+static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
+     internal_function;
+static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node,
+					   int str_idx) internal_function;
+static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,
+						   int node, int str_idx)
+     internal_function;
+static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
+			   re_dfastate_t **limited_sts, int last_node,
+			   int last_str_idx)
+     internal_function;
+static reg_errcode_t re_search_internal (const regex_t *preg,
+					 const char *string, int length,
+					 int start, int range, int stop,
+					 size_t nmatch, regmatch_t pmatch[],
+					 int eflags) internal_function;
+static int re_search_2_stub (struct re_pattern_buffer *bufp,
+			     const char *string1, int length1,
+			     const char *string2, int length2,
+			     int start, int range, struct re_registers *regs,
+			     int stop, int ret_len) internal_function;
+static int re_search_stub (struct re_pattern_buffer *bufp,
+			   const char *string, int length, int start,
+			   int range, int stop, struct re_registers *regs,
+			   int ret_len) internal_function;
+static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
+			      int nregs, int regs_allocated) internal_function;
+static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx)
+     internal_function;
+static int check_matching (re_match_context_t *mctx, int fl_longest_match,
+			   int *p_match_first) internal_function;
+static int check_halt_state_context (const re_match_context_t *mctx,
+				     const re_dfastate_t *state, int idx)
+     internal_function;
+static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
+			 regmatch_t *prev_idx_match, int cur_node,
+			 int cur_idx, int nmatch) internal_function;
+static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
+				      int str_idx, int dest_node, int nregs,
+				      regmatch_t *regs,
+				      re_node_set *eps_via_nodes)
+     internal_function;
+static reg_errcode_t set_regs (const regex_t *preg,
+			       const re_match_context_t *mctx,
+			       size_t nmatch, regmatch_t *pmatch,
+			       int fl_backtrack) internal_function;
+static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs)
+     internal_function;
+
+#ifdef RE_ENABLE_I18N
+static int sift_states_iter_mb (const re_match_context_t *mctx,
+				re_sift_context_t *sctx,
+				int node_idx, int str_idx, int max_str_idx)
+     internal_function;
+#endif
+static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,
+					   re_sift_context_t *sctx)
+     internal_function;
+static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,
+					  re_sift_context_t *sctx, int str_idx,
+					  re_node_set *cur_dest)
+     internal_function;
+static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx,
+					      re_sift_context_t *sctx,
+					      int str_idx,
+					      re_node_set *dest_nodes)
+     internal_function;
+static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa,
+					    re_node_set *dest_nodes,
+					    const re_node_set *candidates)
+     internal_function;
+static int check_dst_limits (const re_match_context_t *mctx,
+			     re_node_set *limits,
+			     int dst_node, int dst_idx, int src_node,
+			     int src_idx) internal_function;
+static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx,
+					int boundaries, int subexp_idx,
+					int from_node, int bkref_idx)
+     internal_function;
+static int check_dst_limits_calc_pos (const re_match_context_t *mctx,
+				      int limit, int subexp_idx,
+				      int node, int str_idx,
+				      int bkref_idx) internal_function;
+static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa,
+					  re_node_set *dest_nodes,
+					  const re_node_set *candidates,
+					  re_node_set *limits,
+					  struct re_backref_cache_entry *bkref_ents,
+					  int str_idx) internal_function;
+static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx,
+					re_sift_context_t *sctx,
+					int str_idx, const re_node_set *candidates)
+     internal_function;
+static reg_errcode_t merge_state_array (const re_dfa_t *dfa,
+					re_dfastate_t **dst,
+					re_dfastate_t **src, int num)
+     internal_function;
+static re_dfastate_t *find_recover_state (reg_errcode_t *err,
+					 re_match_context_t *mctx) internal_function;
+static re_dfastate_t *transit_state (reg_errcode_t *err,
+				     re_match_context_t *mctx,
+				     re_dfastate_t *state) internal_function;
+static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,
+					    re_match_context_t *mctx,
+					    re_dfastate_t *next_state)
+     internal_function;
+static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
+						re_node_set *cur_nodes,
+						int str_idx) internal_function;
+#if 0
+static re_dfastate_t *transit_state_sb (reg_errcode_t *err,
+					re_match_context_t *mctx,
+					re_dfastate_t *pstate)
+     internal_function;
+#endif
+#ifdef RE_ENABLE_I18N
+static reg_errcode_t transit_state_mb (re_match_context_t *mctx,
+				       re_dfastate_t *pstate)
+     internal_function;
+#endif
+static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,
+					  const re_node_set *nodes)
+     internal_function;
+static reg_errcode_t get_subexp (re_match_context_t *mctx,
+				 int bkref_node, int bkref_str_idx)
+     internal_function;
+static reg_errcode_t get_subexp_sub (re_match_context_t *mctx,
+				     const re_sub_match_top_t *sub_top,
+				     re_sub_match_last_t *sub_last,
+				     int bkref_node, int bkref_str)
+     internal_function;
+static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
+			     int subexp_idx, int type) internal_function;
+static reg_errcode_t check_arrival (re_match_context_t *mctx,
+				    state_array_t *path, int top_node,
+				    int top_str, int last_node, int last_str,
+				    int type) internal_function;
+static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx,
+						   int str_idx,
+						   re_node_set *cur_nodes,
+						   re_node_set *next_nodes)
+     internal_function;
+static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa,
+					       re_node_set *cur_nodes,
+					       int ex_subexp, int type)
+     internal_function;
+static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa,
+						   re_node_set *dst_nodes,
+						   int target, int ex_subexp,
+						   int type) internal_function;
+static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx,
+					 re_node_set *cur_nodes, int cur_str,
+					 int subexp_num, int type)
+     internal_function;
+static int build_trtable (const re_dfa_t *dfa,
+			  re_dfastate_t *state) internal_function;
+#ifdef RE_ENABLE_I18N
+static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
+				    const re_string_t *input, int idx)
+     internal_function;
+#endif
+static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
+				       const re_dfastate_t *state,
+				       re_node_set *states_node,
+				       bitset_t *states_ch) internal_function;
+static int check_node_accept (const re_match_context_t *mctx,
+			      const re_token_t *node, int idx)
+     internal_function;
+static reg_errcode_t extend_buffers (re_match_context_t *mctx)
+     internal_function;
+
+/* Entry point for POSIX code.  */
+
+/* regexec searches for a given pattern, specified by PREG, in the
+   string STRING.
+
+   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
+   least NMATCH elements, and we set them to the offsets of the
+   corresponding matched substrings.
+
+   EFLAGS specifies `execution flags' which affect matching: if
+   REG_NOTBOL is set, then ^ does not match at the beginning of the
+   string; if REG_NOTEOL is set, then $ does not match at the end.
+
+   We return 0 if we find a match and REG_NOMATCH if not.  */
+
+int
+regexec (const regex_t *__restrict preg, const char *__restrict string,
+	 size_t nmatch, regmatch_t pmatch[], int eflags)
+{
+  reg_errcode_t err;
+  int start, length;
+#ifdef __UCLIBC_HAS_THREADS__
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+#endif
+
+  if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND))
+    return REG_BADPAT;
+
+  if (eflags & REG_STARTEND)
+    {
+      start = pmatch[0].rm_so;
+      length = pmatch[0].rm_eo;
+    }
+  else
+    {
+      start = 0;
+      length = strlen (string);
+    }
+
+  __libc_lock_lock (dfa->lock);
+  if (preg->no_sub)
+    err = re_search_internal (preg, string, length, start, length - start,
+			      length, 0, NULL, eflags);
+  else
+    err = re_search_internal (preg, string, length, start, length - start,
+			      length, nmatch, pmatch, eflags);
+  __libc_lock_unlock (dfa->lock);
+  return err != REG_NOERROR;
+}
+libc_hidden_def(regexec)
+
+/* Entry points for GNU code.  */
+
+/* re_match, re_search, re_match_2, re_search_2
+
+   The former two functions operate on STRING with length LENGTH,
+   while the later two operate on concatenation of STRING1 and STRING2
+   with lengths LENGTH1 and LENGTH2, respectively.
+
+   re_match() matches the compiled pattern in BUFP against the string,
+   starting at index START.
+
+   re_search() first tries matching at index START, then it tries to match
+   starting from index START + 1, and so on.  The last start position tried
+   is START + RANGE.  (Thus RANGE = 0 forces re_search to operate the same
+   way as re_match().)
+
+   The parameter STOP of re_{match,search}_2 specifies that no match exceeding
+   the first STOP characters of the concatenation of the strings should be
+   concerned.
+
+   If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
+   and all groups is stroed in REGS.  (For the "_2" variants, the offsets are
+   computed relative to the concatenation, not relative to the individual
+   strings.)
+
+   On success, re_match* functions return the length of the match, re_search*
+   return the position of the start of the match.  Return value -1 means no
+   match was found and -2 indicates an internal error.  */
+
+int
+re_match (struct re_pattern_buffer *bufp, const char *string, int length,
+		  int start, struct re_registers *regs)
+{
+  return re_search_stub (bufp, string, length, start, 0, length, regs, 1);
+}
+
+int
+re_search (struct re_pattern_buffer *bufp, const char *string, int length,
+		   int start, int range, struct re_registers *regs)
+{
+  return re_search_stub (bufp, string, length, start, range, length, regs, 0);
+}
+libc_hidden_def(re_search)
+
+int
+re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int length1,
+		   const char *string2, int length2, int start,
+		   struct re_registers *regs, int stop)
+{
+  return re_search_2_stub (bufp, string1, length1, string2, length2,
+			   start, 0, regs, stop, 1);
+}
+
+int
+re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int lenght1,
+			 const char *string2, int length2, int start, int range,
+			 struct re_registers *regs,  int stop)
+{
+  return re_search_2_stub (bufp, string1, lenght1, string2, length2,
+			   start, range, regs, stop, 0);
+}
+libc_hidden_def(re_search_2)
+
+static int internal_function
+re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1,
+				  int length1, const char *string2, int length2, int start,
+				  int range, struct re_registers *regs, int stop, int ret_len)
+{
+  const char *str;
+  int rval;
+  int len = length1 + length2;
+  int free_str = 0;
+
+  if (BE (length1 < 0 || length2 < 0 || stop < 0, 0))
+    return -2;
+
+  /* Concatenate the strings.  */
+  if (length2 > 0)
+    if (length1 > 0)
+      {
+	char *s = re_malloc (char, len);
+
+	if (BE (s == NULL, 0))
+	  return -2;
+	memcpy (s, string1, length1);
+	memcpy (s + length1, string2, length2);
+	str = s;
+	free_str = 1;
+      }
+    else
+      str = string2;
+  else
+    str = string1;
+
+  rval = re_search_stub (bufp, str, len, start, range, stop, regs,
+			 ret_len);
+  if (free_str)
+    re_free ((char *) str);
+  return rval;
+}
+
+/* The parameters have the same meaning as those of re_search.
+   Additional parameters:
+   If RET_LEN is nonzero the length of the match is returned (re_match style);
+   otherwise the position of the match is returned.  */
+
+static int internal_function
+re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length,
+				int start, int range, int stop, struct re_registers *regs,
+				int ret_len)
+{
+  reg_errcode_t result;
+  regmatch_t *pmatch;
+  int nregs, rval;
+  int eflags = 0;
+#ifdef __UCLIBC_HAS_THREADS__
+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+#endif
+  /* Check for out-of-range.  */
+  if (BE (start < 0 || start > length, 0))
+    return -1;
+  if (BE (start + range > length, 0))
+    range = length - start;
+  else if (BE (start + range < 0, 0))
+    range = -start;
+
+  __libc_lock_lock (dfa->lock);
+
+  eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
+  eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
+
+  /* Compile fastmap if we haven't yet.  */
+  if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate)
+    re_compile_fastmap (bufp);
+
+  if (BE (bufp->no_sub, 0))
+    regs = NULL;
+
+  /* We need at least 1 register.  */
+  if (regs == NULL)
+    nregs = 1;
+  else if (BE (bufp->regs_allocated == REGS_FIXED &&
+	       regs->num_regs < bufp->re_nsub + 1, 0))
+    {
+      nregs = regs->num_regs;
+      if (BE (nregs < 1, 0))
+	{
+	  /* Nothing can be copied to regs.  */
+	  regs = NULL;
+	  nregs = 1;
+	}
+    }
+  else
+    nregs = bufp->re_nsub + 1;
+  pmatch = re_malloc (regmatch_t, nregs);
+  if (BE (pmatch == NULL, 0))
+    {
+      rval = -2;
+      goto out;
+    }
+
+  result = re_search_internal (bufp, string, length, start, range, stop,
+			       nregs, pmatch, eflags);
+
+  rval = 0;
+
+  /* I hope we needn't fill ther regs with -1's when no match was found.  */
+  if (result != REG_NOERROR)
+    rval = -1;
+  else if (regs != NULL)
+    {
+      /* If caller wants register contents data back, copy them.  */
+      bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
+					   bufp->regs_allocated);
+      if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0))
+	rval = -2;
+    }
+
+  if (BE (rval == 0, 1))
+    {
+      if (ret_len)
+	{
+	  assert (pmatch[0].rm_so == start);
+	  rval = pmatch[0].rm_eo - start;
+	}
+      else
+	rval = pmatch[0].rm_so;
+    }
+  re_free (pmatch);
+ out:
+  __libc_lock_unlock (dfa->lock);
+  return rval;
+}
+
+static unsigned internal_function
+re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, int nregs,
+			  int regs_allocated)
+{
+  int rval = REGS_REALLOCATE;
+  int i;
+  int need_regs = nregs + 1;
+  /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
+     uses.  */
+
+  /* Have the register data arrays been allocated?  */
+  if (regs_allocated == REGS_UNALLOCATED)
+    { /* No.  So allocate them with malloc.  */
+      regs->start = re_malloc (regoff_t, need_regs);
+      regs->end = re_malloc (regoff_t, need_regs);
+      if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0))
+	return REGS_UNALLOCATED;
+      regs->num_regs = need_regs;
+    }
+  else if (regs_allocated == REGS_REALLOCATE)
+    { /* Yes.  If we need more elements than were already
+	 allocated, reallocate them.  If we need fewer, just
+	 leave it alone.  */
+      if (BE (need_regs > regs->num_regs, 0))
+	{
+	  regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs);
+	  regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs);
+	  if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0))
+	    return REGS_UNALLOCATED;
+	  regs->start = new_start;
+	  regs->end = new_end;
+	  regs->num_regs = need_regs;
+	}
+    }
+  else
+    {
+      assert (regs_allocated == REGS_FIXED);
+      /* This function may not be called with REGS_FIXED and nregs too big.  */
+      assert (regs->num_regs >= nregs);
+      rval = REGS_FIXED;
+    }
+
+  /* Copy the regs.  */
+  for (i = 0; i < nregs; ++i)
+    {
+      regs->start[i] = pmatch[i].rm_so;
+      regs->end[i] = pmatch[i].rm_eo;
+    }
+  for ( ; i < regs->num_regs; ++i)
+    regs->start[i] = regs->end[i] = -1;
+
+  return rval;
+}
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
+   this memory for recording register information.  STARTS and ENDS
+   must be allocated using the malloc library routine, and must each
+   be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+
+void
+re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs,
+				  unsigned num_regs, regoff_t *starts, regoff_t *ends)
+{
+  if (num_regs)
+    {
+      bufp->regs_allocated = REGS_REALLOCATE;
+      regs->num_regs = num_regs;
+      regs->start = starts;
+      regs->end = ends;
+    }
+  else
+    {
+      bufp->regs_allocated = REGS_UNALLOCATED;
+      regs->num_regs = 0;
+      regs->start = regs->end = (regoff_t *) 0;
+    }
+}
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#if defined _REGEX_RE_COMP || defined __UCLIBC__
+int
+weak_function
+re_exec (const char *s)
+{
+  return 0 == regexec (re_comp_buf, s, 0, NULL, 0);
+}
+#endif
+
+/* Internal entry point.  */
+
+/* Searches for a compiled pattern PREG in the string STRING, whose
+   length is LENGTH.  NMATCH, PMATCH, and EFLAGS have the same
+   mingings with regexec.  START, and RANGE have the same meanings
+   with re_search.
+   Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
+   otherwise return the error code.
+   Note: We assume front end functions already check ranges.
+   (START + RANGE >= 0 && START + RANGE <= LENGTH)  */
+static reg_errcode_t internal_function
+re_search_internal (const regex_t *preg, const char *string, int length,
+					int start, int range, int stop, size_t nmatch,
+					regmatch_t pmatch[], int eflags)
+{
+  reg_errcode_t err;
+  const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
+  int left_lim, right_lim, incr;
+  int fl_longest_match, match_first, match_kind, match_last = -1;
+  int extra_nmatch;
+  int sb, ch;
+  re_match_context_t mctx;
+  char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate
+		   && range && !preg->can_be_null) ? preg->fastmap : NULL;
+  RE_TRANSLATE_TYPE t = preg->translate;
+
+  memset (&mctx, '\0', sizeof (re_match_context_t));
+  mctx.dfa = dfa;
+
+  extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;
+  nmatch -= extra_nmatch;
+
+  /* Check if the DFA haven't been compiled.  */
+  if (BE (preg->used == 0 || dfa->init_state == NULL
+	  || dfa->init_state_word == NULL || dfa->init_state_nl == NULL
+	  || dfa->init_state_begbuf == NULL, 0))
+    return REG_NOMATCH;
+
+#ifdef DEBUG
+  /* We assume front-end functions already check them.  */
+  assert (start + range >= 0 && start + range <= length);
+#endif
+
+  /* If initial states with non-begbuf contexts have no elements,
+     the regex must be anchored.  If preg->newline_anchor is set,
+     we'll never use init_state_nl, so do not check it.  */
+  if (dfa->init_state->nodes.nelem == 0
+      && dfa->init_state_word->nodes.nelem == 0
+      && (dfa->init_state_nl->nodes.nelem == 0
+	  || !preg->newline_anchor))
+    {
+      if (start != 0 && start + range != 0)
+        return REG_NOMATCH;
+      start = range = 0;
+    }
+
+  /* We must check the longest matching, if nmatch > 0.  */
+  fl_longest_match = (nmatch != 0 || dfa->nbackref);
+
+  err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1,
+			    preg->translate, preg->syntax & RE_ICASE, dfa);
+  if (BE (err != REG_NOERROR, 0))
+    goto free_return;
+  mctx.input.stop = stop;
+  mctx.input.raw_stop = stop;
+  mctx.input.newline_anchor = preg->newline_anchor;
+
+  err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2);
+  if (BE (err != REG_NOERROR, 0))
+    goto free_return;
+
+  /* We will log all the DFA states through which the dfa pass,
+     if nmatch > 1, or this dfa has "multibyte node", which is a
+     back-reference or a node which can accept multibyte character or
+     multi character collating element.  */
+  if (nmatch > 1 || dfa->has_mb_node)
+    {
+      mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);
+      if (BE (mctx.state_log == NULL, 0))
+	{
+	  err = REG_ESPACE;
+	  goto free_return;
+	}
+    }
+  else
+    mctx.state_log = NULL;
+
+  match_first = start;
+  mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
+			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF;
+
+  /* Check incrementally whether of not the input string match.  */
+  incr = (range < 0) ? -1 : 1;
+  left_lim = (range < 0) ? start + range : start;
+  right_lim = (range < 0) ? start : start + range;
+  sb = dfa->mb_cur_max == 1;
+  match_kind =
+    (fastmap
+     ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
+	| (range >= 0 ? 2 : 0)
+	| (t != NULL ? 1 : 0))
+     : 8);
+
+  for (;; match_first += incr)
+    {
+      err = REG_NOMATCH;
+      if (match_first < left_lim || right_lim < match_first)
+	goto free_return;
+
+      /* Advance as rapidly as possible through the string, until we
+	 find a plausible place to start matching.  This may be done
+	 with varying efficiency, so there are various possibilities:
+	 only the most common of them are specialized, in order to
+	 save on code size.  We use a switch statement for speed.  */
+      switch (match_kind)
+	{
+	case 8:
+	  /* No fastmap.  */
+	  break;
+
+	case 7:
+	  /* Fastmap with single-byte translation, match forward.  */
+	  while (BE (match_first < right_lim, 1)
+		 && !fastmap[t[(unsigned char) string[match_first]]])
+	    ++match_first;
+	  goto forward_match_found_start_or_reached_end;
+
+	case 6:
+	  /* Fastmap without translation, match forward.  */
+	  while (BE (match_first < right_lim, 1)
+		 && !fastmap[(unsigned char) string[match_first]])
+	    ++match_first;
+
+	forward_match_found_start_or_reached_end:
+	  if (BE (match_first == right_lim, 0))
+	    {
+	      ch = match_first >= length
+		       ? 0 : (unsigned char) string[match_first];
+	      if (!fastmap[t ? t[ch] : ch])
+		goto free_return;
+	    }
+	  break;
+
+	case 4:
+	case 5:
+	  /* Fastmap without multi-byte translation, match backwards.  */
+	  while (match_first >= left_lim)
+	    {
+	      ch = match_first >= length
+		       ? 0 : (unsigned char) string[match_first];
+	      if (fastmap[t ? t[ch] : ch])
+		break;
+	      --match_first;
+	    }
+	  if (match_first < left_lim)
+	    goto free_return;
+	  break;
+
+	default:
+	  /* In this case, we can't determine easily the current byte,
+	     since it might be a component byte of a multibyte
+	     character.  Then we use the constructed buffer instead.  */
+	  for (;;)
+	    {
+	      /* If MATCH_FIRST is out of the valid range, reconstruct the
+		 buffers.  */
+	      unsigned int offset = match_first - mctx.input.raw_mbs_idx;
+	      if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0))
+		{
+		  err = re_string_reconstruct (&mctx.input, match_first,
+					       eflags);
+		  if (BE (err != REG_NOERROR, 0))
+		    goto free_return;
+
+		  offset = match_first - mctx.input.raw_mbs_idx;
+		}
+	      /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
+		 Note that MATCH_FIRST must not be smaller than 0.  */
+	      ch = (match_first >= length
+		    ? 0 : re_string_byte_at (&mctx.input, offset));
+	      if (fastmap[ch])
+		break;
+	      match_first += incr;
+	      if (match_first < left_lim || match_first > right_lim)
+	        {
+	          err = REG_NOMATCH;
+	          goto free_return;
+	        }
+	    }
+	  break;
+	}
+
+      /* Reconstruct the buffers so that the matcher can assume that
+	 the matching starts from the beginning of the buffer.  */
+      err = re_string_reconstruct (&mctx.input, match_first, eflags);
+      if (BE (err != REG_NOERROR, 0))
+	goto free_return;
+
+#ifdef RE_ENABLE_I18N
+     /* Don't consider this char as a possible match start if it part,
+	yet isn't the head, of a multibyte character.  */
+      if (!sb && !re_string_first_byte (&mctx.input, 0))
+	continue;
+#endif
+
+      /* It seems to be appropriate one, then use the matcher.  */
+      /* We assume that the matching starts from 0.  */
+      mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
+      match_last = check_matching (&mctx, fl_longest_match,
+				   range >= 0 ? &match_first : NULL);
+      if (match_last != -1)
+	{
+	  if (BE (match_last == -2, 0))
+	    {
+	      err = REG_ESPACE;
+	      goto free_return;
+	    }
+	  else
+	    {
+	      mctx.match_last = match_last;
+	      if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
+		{
+		  re_dfastate_t *pstate = mctx.state_log[match_last];
+		  mctx.last_node = check_halt_state_context (&mctx, pstate,
+							     match_last);
+		}
+	      if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
+		  || dfa->nbackref)
+		{
+		  err = prune_impossible_nodes (&mctx);
+		  if (err == REG_NOERROR)
+		    break;
+		  if (BE (err != REG_NOMATCH, 0))
+		    goto free_return;
+		  match_last = -1;
+		}
+	      else
+		break; /* We found a match.  */
+	    }
+	}
+
+      match_ctx_clean (&mctx);
+    }
+
+#ifdef DEBUG
+  assert (match_last != -1);
+  assert (err == REG_NOERROR);
+#endif
+
+  /* Set pmatch[] if we need.  */
+  if (nmatch > 0)
+    {
+      int reg_idx;
+
+      /* Initialize registers.  */
+      for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)
+	pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;
+
+      /* Set the points where matching start/end.  */
+      pmatch[0].rm_so = 0;
+      pmatch[0].rm_eo = mctx.match_last;
+
+      if (!preg->no_sub && nmatch > 1)
+	{
+	  err = set_regs (preg, &mctx, nmatch, pmatch,
+			  dfa->has_plural_match && dfa->nbackref > 0);
+	  if (BE (err != REG_NOERROR, 0))
+	    goto free_return;
+	}
+
+      /* At last, add the offset to the each registers, since we slided
+	 the buffers so that we could assume that the matching starts
+	 from 0.  */
+      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
+	if (pmatch[reg_idx].rm_so != -1)
+	  {
+#ifdef RE_ENABLE_I18N
+	    if (BE (mctx.input.offsets_needed != 0, 0))
+	      {
+		pmatch[reg_idx].rm_so =
+		  (pmatch[reg_idx].rm_so == mctx.input.valid_len
+		   ? mctx.input.valid_raw_len
+		   : mctx.input.offsets[pmatch[reg_idx].rm_so]);
+		pmatch[reg_idx].rm_eo =
+		  (pmatch[reg_idx].rm_eo == mctx.input.valid_len
+		   ? mctx.input.valid_raw_len
+		   : mctx.input.offsets[pmatch[reg_idx].rm_eo]);
+	      }
+#else
+	    assert (mctx.input.offsets_needed == 0);
+#endif
+	    pmatch[reg_idx].rm_so += match_first;
+	    pmatch[reg_idx].rm_eo += match_first;
+	  }
+      for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)
+	{
+	  pmatch[nmatch + reg_idx].rm_so = -1;
+	  pmatch[nmatch + reg_idx].rm_eo = -1;
+	}
+
+      if (dfa->subexp_map)
+        for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)
+          if (dfa->subexp_map[reg_idx] != reg_idx)
+            {
+              pmatch[reg_idx + 1].rm_so
+                = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;
+              pmatch[reg_idx + 1].rm_eo
+                = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo;
+            }
+    }
+
+ free_return:
+  re_free (mctx.state_log);
+  if (dfa->nbackref)
+    match_ctx_free (&mctx);
+  re_string_destruct (&mctx.input);
+  return err;
+}
+
+static reg_errcode_t internal_function
+prune_impossible_nodes (re_match_context_t *mctx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int halt_node, match_last;
+  reg_errcode_t ret;
+  re_dfastate_t **sifted_states;
+  re_dfastate_t **lim_states = NULL;
+  re_sift_context_t sctx;
+#ifdef DEBUG
+  assert (mctx->state_log != NULL);
+#endif
+  match_last = mctx->match_last;
+  halt_node = mctx->last_node;
+  sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
+  if (BE (sifted_states == NULL, 0))
+    {
+      ret = REG_ESPACE;
+      goto free_return;
+    }
+  if (dfa->nbackref)
+    {
+      lim_states = re_malloc (re_dfastate_t *, match_last + 1);
+      if (BE (lim_states == NULL, 0))
+	{
+	  ret = REG_ESPACE;
+	  goto free_return;
+	}
+      while (1)
+	{
+	  memset (lim_states, '\0',
+		  sizeof (re_dfastate_t *) * (match_last + 1));
+	  sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
+			 match_last);
+	  ret = sift_states_backward (mctx, &sctx);
+	  re_node_set_free (&sctx.limits);
+	  if (BE (ret != REG_NOERROR, 0))
+	      goto free_return;
+	  if (sifted_states[0] != NULL || lim_states[0] != NULL)
+	    break;
+	  do
+	    {
+	      --match_last;
+	      if (match_last < 0)
+		{
+		  ret = REG_NOMATCH;
+		  goto free_return;
+		}
+	    } while (mctx->state_log[match_last] == NULL
+		     || !mctx->state_log[match_last]->halt);
+	  halt_node = check_halt_state_context (mctx,
+						mctx->state_log[match_last],
+						match_last);
+	}
+      ret = merge_state_array (dfa, sifted_states, lim_states,
+			       match_last + 1);
+      re_free (lim_states);
+      lim_states = NULL;
+      if (BE (ret != REG_NOERROR, 0))
+	goto free_return;
+    }
+  else
+    {
+      sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last);
+      ret = sift_states_backward (mctx, &sctx);
+      re_node_set_free (&sctx.limits);
+      if (BE (ret != REG_NOERROR, 0))
+	goto free_return;
+    }
+  re_free (mctx->state_log);
+  mctx->state_log = sifted_states;
+  sifted_states = NULL;
+  mctx->last_node = halt_node;
+  mctx->match_last = match_last;
+  ret = REG_NOERROR;
+ free_return:
+  re_free (sifted_states);
+  re_free (lim_states);
+  return ret;
+}
+
+/* Acquire an initial state and return it.
+   We must select appropriate initial state depending on the context,
+   since initial states may have constraints like "\<", "^", etc..  */
+
+static __inline__ re_dfastate_t *
+__attribute ((always_inline)) internal_function
+acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
+			    int idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  if (dfa->init_state->has_constraint)
+    {
+      unsigned int context;
+      context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags);
+      if (IS_WORD_CONTEXT (context))
+	return dfa->init_state_word;
+      else if (IS_ORDINARY_CONTEXT (context))
+	return dfa->init_state;
+      else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
+	return dfa->init_state_begbuf;
+      else if (IS_NEWLINE_CONTEXT (context))
+	return dfa->init_state_nl;
+      else if (IS_BEGBUF_CONTEXT (context))
+	{
+	  /* It is relatively rare case, then calculate on demand.  */
+	  return re_acquire_state_context (err, dfa,
+					   dfa->init_state->entrance_nodes,
+					   context);
+	}
+      else
+	/* Must not happen?  */
+	return dfa->init_state;
+    }
+  else
+    return dfa->init_state;
+}
+
+/* Check whether the regular expression match input string INPUT or not,
+   and return the index where the matching end, return -1 if not match,
+   or return -2 in case of an error.
+   FL_LONGEST_MATCH means we want the POSIX longest matching.
+   If P_MATCH_FIRST is not NULL, and the match fails, it is set to the
+   next place where we may want to try matching.
+   Note that the matcher assume that the maching starts from the current
+   index of the buffer.  */
+
+static int
+internal_function
+check_matching (re_match_context_t *mctx, int fl_longest_match,
+		int *p_match_first)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int match = 0;
+  int match_last = -1;
+  int cur_str_idx = re_string_cur_idx (&mctx->input);
+  re_dfastate_t *cur_state;
+  int at_init_state = p_match_first != NULL;
+  int next_start_idx = cur_str_idx;
+
+  err = REG_NOERROR;
+  cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
+  /* An initial state must not be NULL (invalid).  */
+  if (BE (cur_state == NULL, 0))
+    {
+      assert (err == REG_ESPACE);
+      return -2;
+    }
+
+  if (mctx->state_log != NULL)
+    {
+      mctx->state_log[cur_str_idx] = cur_state;
+
+      /* Check OP_OPEN_SUBEXP in the initial state in case that we use them
+	 later.  E.g. Processing back references.  */
+      if (BE (dfa->nbackref, 0))
+	{
+	  at_init_state = 0;
+	  err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+
+	  if (cur_state->has_backref)
+	    {
+	      err = transit_state_bkref (mctx, &cur_state->nodes);
+	      if (BE (err != REG_NOERROR, 0))
+	        return err;
+	    }
+	}
+    }
+
+  /* If the RE accepts NULL string.  */
+  if (BE (cur_state->halt, 0))
+    {
+      if (!cur_state->has_constraint
+	  || check_halt_state_context (mctx, cur_state, cur_str_idx))
+	{
+	  if (!fl_longest_match)
+	    return cur_str_idx;
+	  else
+	    {
+	      match_last = cur_str_idx;
+	      match = 1;
+	    }
+	}
+    }
+
+  while (!re_string_eoi (&mctx->input))
+    {
+      re_dfastate_t *old_state = cur_state;
+      int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
+
+      if (BE (next_char_idx >= mctx->input.bufs_len, 0)
+          || (BE (next_char_idx >= mctx->input.valid_len, 0)
+              && mctx->input.valid_len < mctx->input.len))
+        {
+          err = extend_buffers (mctx);
+          if (BE (err != REG_NOERROR, 0))
+	    {
+	      assert (err == REG_ESPACE);
+	      return -2;
+	    }
+        }
+
+      cur_state = transit_state (&err, mctx, cur_state);
+      if (mctx->state_log != NULL)
+	cur_state = merge_state_with_log (&err, mctx, cur_state);
+
+      if (cur_state == NULL)
+	{
+	  /* Reached the invalid state or an error.  Try to recover a valid
+	     state using the state log, if available and if we have not
+	     already found a valid (even if not the longest) match.  */
+	  if (BE (err != REG_NOERROR, 0))
+	    return -2;
+
+	  if (mctx->state_log == NULL
+	      || (match && !fl_longest_match)
+	      || (cur_state = find_recover_state (&err, mctx)) == NULL)
+	    break;
+	}
+
+      if (BE (at_init_state, 0))
+	{
+	  if (old_state == cur_state)
+	    next_start_idx = next_char_idx;
+	  else
+	    at_init_state = 0;
+	}
+
+      if (cur_state->halt)
+	{
+	  /* Reached a halt state.
+	     Check the halt state can satisfy the current context.  */
+	  if (!cur_state->has_constraint
+	      || check_halt_state_context (mctx, cur_state,
+					   re_string_cur_idx (&mctx->input)))
+	    {
+	      /* We found an appropriate halt state.  */
+	      match_last = re_string_cur_idx (&mctx->input);
+	      match = 1;
+
+	      /* We found a match, do not modify match_first below.  */
+	      p_match_first = NULL;
+	      if (!fl_longest_match)
+		break;
+	    }
+	}
+    }
+
+  if (p_match_first)
+    *p_match_first += next_start_idx;
+
+  return match_last;
+}
+
+/* Check NODE match the current context.  */
+
+static int
+internal_function
+check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context)
+{
+  re_token_type_t type = dfa->nodes[node].type;
+  unsigned int constraint = dfa->nodes[node].constraint;
+  if (type != END_OF_RE)
+    return 0;
+  if (!constraint)
+    return 1;
+  if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))
+    return 0;
+  return 1;
+}
+
+/* Check the halt state STATE match the current context.
+   Return 0 if not match, if the node, STATE has, is a halt node and
+   match the context, return the node.  */
+
+static int
+internal_function
+check_halt_state_context (const re_match_context_t *mctx,
+			  const re_dfastate_t *state, int idx)
+{
+  int i;
+  unsigned int context;
+#ifdef DEBUG
+  assert (state->halt);
+#endif
+  context = re_string_context_at (&mctx->input, idx, mctx->eflags);
+  for (i = 0; i < state->nodes.nelem; ++i)
+    if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context))
+      return state->nodes.elems[i];
+  return 0;
+}
+
+/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
+   corresponding to the DFA).
+   Return the destination node, and update EPS_VIA_NODES, return -1 in case
+   of errors.  */
+
+static int
+internal_function
+proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
+		   int *pidx, int node, re_node_set *eps_via_nodes,
+		   struct re_fail_stack_t *fs)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int i, err;
+  if (IS_EPSILON_NODE (dfa->nodes[node].type))
+    {
+      re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
+      re_node_set *edests = &dfa->edests[node];
+      int dest_node;
+      err = re_node_set_insert (eps_via_nodes, node);
+      if (BE (err < 0, 0))
+	return -2;
+      /* Pick up a valid destination, or return -1 if none is found.  */
+      for (dest_node = -1, i = 0; i < edests->nelem; ++i)
+	{
+	  int candidate = edests->elems[i];
+	  if (!re_node_set_contains (cur_nodes, candidate))
+	    continue;
+          if (dest_node == -1)
+	    dest_node = candidate;
+
+          else
+	    {
+	      /* In order to avoid infinite loop like "(a*)*", return the second
+	         epsilon-transition if the first was already considered.  */
+	      if (re_node_set_contains (eps_via_nodes, dest_node))
+	        return candidate;
+
+	      /* Otherwise, push the second epsilon-transition on the fail stack.  */
+	      else if (fs != NULL
+		       && push_fail_stack (fs, *pidx, candidate, nregs, regs,
+				           eps_via_nodes))
+		return -2;
+
+	      /* We know we are going to exit.  */
+	      break;
+	    }
+	}
+      return dest_node;
+    }
+  else
+    {
+      int naccepted = 0;
+      re_token_type_t type = dfa->nodes[node].type;
+
+#ifdef RE_ENABLE_I18N
+      if (dfa->nodes[node].accept_mb)
+	naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);
+      else
+#endif /* RE_ENABLE_I18N */
+      if (type == OP_BACK_REF)
+	{
+	  int subexp_idx = dfa->nodes[node].opr.idx + 1;
+	  naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
+	  if (fs != NULL)
+	    {
+	      if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)
+		return -1;
+	      else if (naccepted)
+		{
+		  char *buf = (char *) re_string_get_buffer (&mctx->input);
+		  if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
+			      naccepted) != 0)
+		    return -1;
+		}
+	    }
+
+	  if (naccepted == 0)
+	    {
+	      int dest_node;
+	      err = re_node_set_insert (eps_via_nodes, node);
+	      if (BE (err < 0, 0))
+		return -2;
+	      dest_node = dfa->edests[node].elems[0];
+	      if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
+					dest_node))
+		return dest_node;
+	    }
+	}
+
+      if (naccepted != 0
+	  || check_node_accept (mctx, dfa->nodes + node, *pidx))
+	{
+	  int dest_node = dfa->nexts[node];
+	  *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
+	  if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
+		     || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
+					       dest_node)))
+	    return -1;
+	  re_node_set_empty (eps_via_nodes);
+	  return dest_node;
+	}
+    }
+  return -1;
+}
+
+static reg_errcode_t
+internal_function
+push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node,
+		 int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
+{
+  reg_errcode_t err;
+  int num = fs->num++;
+  if (fs->num == fs->alloc)
+    {
+      struct re_fail_stack_ent_t *new_array;
+      new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)
+				       * fs->alloc * 2));
+      if (new_array == NULL)
+	return REG_ESPACE;
+      fs->alloc *= 2;
+      fs->stack = new_array;
+    }
+  fs->stack[num].idx = str_idx;
+  fs->stack[num].node = dest_node;
+  fs->stack[num].regs = re_malloc (regmatch_t, nregs);
+  if (fs->stack[num].regs == NULL)
+    return REG_ESPACE;
+  memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
+  err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
+  return err;
+}
+
+static int
+internal_function
+pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
+		regmatch_t *regs, re_node_set *eps_via_nodes)
+{
+  int num = --fs->num;
+  assert (num >= 0);
+  *pidx = fs->stack[num].idx;
+  memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
+  re_node_set_free (eps_via_nodes);
+  re_free (fs->stack[num].regs);
+  *eps_via_nodes = fs->stack[num].eps_via_nodes;
+  return fs->stack[num].node;
+}
+
+/* Set the positions where the subexpressions are starts/ends to registers
+   PMATCH.
+   Note: We assume that pmatch[0] is already set, and
+   pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch.  */
+
+static reg_errcode_t
+internal_function
+set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
+	  regmatch_t *pmatch, int fl_backtrack)
+{
+  const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
+  int idx, cur_node;
+  re_node_set eps_via_nodes;
+  struct re_fail_stack_t *fs;
+  struct re_fail_stack_t fs_body = { 0, 2, NULL };
+  regmatch_t *prev_idx_match;
+  int prev_idx_match_malloced = 0;
+
+#ifdef DEBUG
+  assert (nmatch > 1);
+  assert (mctx->state_log != NULL);
+#endif
+  if (fl_backtrack)
+    {
+      fs = &fs_body;
+      fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
+      if (fs->stack == NULL)
+	return REG_ESPACE;
+    }
+  else
+    fs = NULL;
+
+  cur_node = dfa->init_node;
+  re_node_set_init_empty (&eps_via_nodes);
+
+  if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
+    prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
+  else
+    {
+      prev_idx_match = re_malloc (regmatch_t, nmatch);
+      if (prev_idx_match == NULL)
+	{
+	  free_fail_stack_return (fs);
+	  return REG_ESPACE;
+	}
+      prev_idx_match_malloced = 1;
+    }
+  memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
+
+  for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
+    {
+      update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
+
+      if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
+	{
+	  int reg_idx;
+	  if (fs)
+	    {
+	      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
+		if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
+		  break;
+	      if (reg_idx == nmatch)
+		{
+		  re_node_set_free (&eps_via_nodes);
+		  if (prev_idx_match_malloced)
+		    re_free (prev_idx_match);
+		  return free_fail_stack_return (fs);
+		}
+	      cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+					 &eps_via_nodes);
+	    }
+	  else
+	    {
+	      re_node_set_free (&eps_via_nodes);
+	      if (prev_idx_match_malloced)
+		re_free (prev_idx_match);
+	      return REG_NOERROR;
+	    }
+	}
+
+      /* Proceed to next node.  */
+      cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node,
+				    &eps_via_nodes, fs);
+
+      if (BE (cur_node < 0, 0))
+	{
+	  if (BE (cur_node == -2, 0))
+	    {
+	      re_node_set_free (&eps_via_nodes);
+	      if (prev_idx_match_malloced)
+		re_free (prev_idx_match);
+	      free_fail_stack_return (fs);
+	      return REG_ESPACE;
+	    }
+	  if (fs)
+	    cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+				       &eps_via_nodes);
+	  else
+	    {
+	      re_node_set_free (&eps_via_nodes);
+	      if (prev_idx_match_malloced)
+		re_free (prev_idx_match);
+	      return REG_NOMATCH;
+	    }
+	}
+    }
+  re_node_set_free (&eps_via_nodes);
+  if (prev_idx_match_malloced)
+    re_free (prev_idx_match);
+  return free_fail_stack_return (fs);
+}
+
+static reg_errcode_t
+internal_function
+free_fail_stack_return (struct re_fail_stack_t *fs)
+{
+  if (fs)
+    {
+      int fs_idx;
+      for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)
+	{
+	  re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);
+	  re_free (fs->stack[fs_idx].regs);
+	}
+      re_free (fs->stack);
+    }
+  return REG_NOERROR;
+}
+
+static void
+internal_function
+update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
+	     regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch)
+{
+  int type = dfa->nodes[cur_node].type;
+  if (type == OP_OPEN_SUBEXP)
+    {
+      int reg_num = dfa->nodes[cur_node].opr.idx + 1;
+
+      /* We are at the first node of this sub expression.  */
+      if (reg_num < nmatch)
+	{
+	  pmatch[reg_num].rm_so = cur_idx;
+	  pmatch[reg_num].rm_eo = -1;
+	}
+    }
+  else if (type == OP_CLOSE_SUBEXP)
+    {
+      int reg_num = dfa->nodes[cur_node].opr.idx + 1;
+      if (reg_num < nmatch)
+	{
+	  /* We are at the last node of this sub expression.  */
+	  if (pmatch[reg_num].rm_so < cur_idx)
+	    {
+	      pmatch[reg_num].rm_eo = cur_idx;
+	      /* This is a non-empty match or we are not inside an optional
+		 subexpression.  Accept this right away.  */
+	      memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
+	    }
+	  else
+	    {
+	      if (dfa->nodes[cur_node].opt_subexp
+		  && prev_idx_match[reg_num].rm_so != -1)
+		/* We transited through an empty match for an optional
+		   subexpression, like (a?)*, and this is not the subexp's
+		   first match.  Copy back the old content of the registers
+		   so that matches of an inner subexpression are undone as
+		   well, like in ((a?))*.  */
+		memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch);
+	      else
+		/* We completed a subexpression, but it may be part of
+		   an optional one, so do not update PREV_IDX_MATCH.  */
+		pmatch[reg_num].rm_eo = cur_idx;
+	    }
+	}
+    }
+}
+
+/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0
+   and sift the nodes in each states according to the following rules.
+   Updated state_log will be wrote to STATE_LOG.
+
+   Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...
+     1. When STR_IDX == MATCH_LAST(the last index in the state_log):
+	If `a' isn't the LAST_NODE and `a' can't epsilon transit to
+	the LAST_NODE, we throw away the node `a'.
+     2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts
+	string `s' and transit to `b':
+	i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
+	   away the node `a'.
+	ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
+	    thrown away, we throw away the node `a'.
+     3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b':
+	i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
+	   node `a'.
+	ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away,
+	    we throw away the node `a'.  */
+
+#define STATE_NODE_CONTAINS(state,node) \
+  ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
+
+static reg_errcode_t
+internal_function
+sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
+{
+  reg_errcode_t err;
+  int null_cnt = 0;
+  int str_idx = sctx->last_str_idx;
+  re_node_set cur_dest;
+
+#ifdef DEBUG
+  assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
+#endif
+
+  /* Build sifted state_log[str_idx].  It has the nodes which can epsilon
+     transit to the last_node and the last_node itself.  */
+  err = re_node_set_init_1 (&cur_dest, sctx->last_node);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+  err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
+  if (BE (err != REG_NOERROR, 0))
+    goto free_return;
+
+  /* Then check each states in the state_log.  */
+  while (str_idx > 0)
+    {
+      /* Update counters.  */
+      null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;
+      if (null_cnt > mctx->max_mb_elem_len)
+	{
+	  memset (sctx->sifted_states, '\0',
+		  sizeof (re_dfastate_t *) * str_idx);
+	  re_node_set_free (&cur_dest);
+	  return REG_NOERROR;
+	}
+      re_node_set_empty (&cur_dest);
+      --str_idx;
+
+      if (mctx->state_log[str_idx])
+	{
+	  err = build_sifted_states (mctx, sctx, str_idx, &cur_dest);
+          if (BE (err != REG_NOERROR, 0))
+	    goto free_return;
+	}
+
+      /* Add all the nodes which satisfy the following conditions:
+	 - It can epsilon transit to a node in CUR_DEST.
+	 - It is in CUR_SRC.
+	 And update state_log.  */
+      err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
+      if (BE (err != REG_NOERROR, 0))
+	goto free_return;
+    }
+  err = REG_NOERROR;
+ free_return:
+  re_node_set_free (&cur_dest);
+  return err;
+}
+
+static reg_errcode_t
+internal_function
+build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
+		     int str_idx, re_node_set *cur_dest)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes;
+  int i;
+
+  /* Then build the next sifted state.
+     We build the next sifted state on `cur_dest', and update
+     `sifted_states[str_idx]' with `cur_dest'.
+     Note:
+     `cur_dest' is the sifted state from `state_log[str_idx + 1]'.
+     `cur_src' points the node_set of the old `state_log[str_idx]'
+     (with the epsilon nodes pre-filtered out).  */
+  for (i = 0; i < cur_src->nelem; i++)
+    {
+      int prev_node = cur_src->elems[i];
+      int naccepted = 0;
+      int ret;
+
+#ifdef DEBUG
+      re_token_type_t type = dfa->nodes[prev_node].type;
+      assert (!IS_EPSILON_NODE (type));
+#endif
+#ifdef RE_ENABLE_I18N
+      /* If the node may accept `multi byte'.  */
+      if (dfa->nodes[prev_node].accept_mb)
+	naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
+					 str_idx, sctx->last_str_idx);
+#endif /* RE_ENABLE_I18N */
+
+      /* We don't check backreferences here.
+	 See update_cur_sifted_state().  */
+      if (!naccepted
+	  && check_node_accept (mctx, dfa->nodes + prev_node, str_idx)
+	  && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],
+				  dfa->nexts[prev_node]))
+	naccepted = 1;
+
+      if (naccepted == 0)
+	continue;
+
+      if (sctx->limits.nelem)
+	{
+	  int to_idx = str_idx + naccepted;
+	  if (check_dst_limits (mctx, &sctx->limits,
+				dfa->nexts[prev_node], to_idx,
+				prev_node, str_idx))
+	    continue;
+	}
+      ret = re_node_set_insert (cur_dest, prev_node);
+      if (BE (ret == -1, 0))
+	return REG_ESPACE;
+    }
+
+  return REG_NOERROR;
+}
+
+/* Helper functions.  */
+
+static reg_errcode_t
+internal_function
+clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)
+{
+  int top = mctx->state_log_top;
+
+  if (next_state_log_idx >= mctx->input.bufs_len
+      || (next_state_log_idx >= mctx->input.valid_len
+	  && mctx->input.valid_len < mctx->input.len))
+    {
+      reg_errcode_t err;
+      err = extend_buffers (mctx);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+    }
+
+  if (top < next_state_log_idx)
+    {
+      memset (mctx->state_log + top + 1, '\0',
+	      sizeof (re_dfastate_t *) * (next_state_log_idx - top));
+      mctx->state_log_top = next_state_log_idx;
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,
+		   re_dfastate_t **src, int num)
+{
+  int st_idx;
+  reg_errcode_t err;
+  for (st_idx = 0; st_idx < num; ++st_idx)
+    {
+      if (dst[st_idx] == NULL)
+	dst[st_idx] = src[st_idx];
+      else if (src[st_idx] != NULL)
+	{
+	  re_node_set merged_set;
+	  err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,
+					&src[st_idx]->nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	  dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);
+	  re_node_set_free (&merged_set);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+update_cur_sifted_state (const re_match_context_t *mctx,
+			 re_sift_context_t *sctx, int str_idx,
+			 re_node_set *dest_nodes)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err = REG_NOERROR;
+  const re_node_set *candidates;
+  candidates = ((mctx->state_log[str_idx] == NULL) ? NULL
+		: &mctx->state_log[str_idx]->nodes);
+
+  if (dest_nodes->nelem == 0)
+    sctx->sifted_states[str_idx] = NULL;
+  else
+    {
+      if (candidates)
+	{
+	  /* At first, add the nodes which can epsilon transit to a node in
+	     DEST_NODE.  */
+	  err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+
+	  /* Then, check the limitations in the current sift_context.  */
+	  if (sctx->limits.nelem)
+	    {
+	      err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,
+					 mctx->bkref_ents, str_idx);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	    }
+	}
+
+      sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+    }
+
+  if (candidates && mctx->state_log[str_idx]->has_backref)
+    {
+      err = sift_states_bkref (mctx, sctx, str_idx, candidates);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
+		       const re_node_set *candidates)
+{
+  reg_errcode_t err = REG_NOERROR;
+  int i;
+
+  re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+
+  if (!state->inveclosure.alloc)
+    {
+      err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem);
+      if (BE (err != REG_NOERROR, 0))
+        return REG_ESPACE;
+      for (i = 0; i < dest_nodes->nelem; i++)
+        re_node_set_merge (&state->inveclosure,
+			   dfa->inveclosures + dest_nodes->elems[i]);
+    }
+  return re_node_set_add_intersect (dest_nodes, candidates,
+				    &state->inveclosure);
+}
+
+static reg_errcode_t
+internal_function
+sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes,
+		       const re_node_set *candidates)
+{
+    int ecl_idx;
+    reg_errcode_t err;
+    re_node_set *inv_eclosure = dfa->inveclosures + node;
+    re_node_set except_nodes;
+    re_node_set_init_empty (&except_nodes);
+    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
+      {
+	int cur_node = inv_eclosure->elems[ecl_idx];
+	if (cur_node == node)
+	  continue;
+	if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))
+	  {
+	    int edst1 = dfa->edests[cur_node].elems[0];
+	    int edst2 = ((dfa->edests[cur_node].nelem > 1)
+			 ? dfa->edests[cur_node].elems[1] : -1);
+	    if ((!re_node_set_contains (inv_eclosure, edst1)
+		 && re_node_set_contains (dest_nodes, edst1))
+		|| (edst2 > 0
+		    && !re_node_set_contains (inv_eclosure, edst2)
+		    && re_node_set_contains (dest_nodes, edst2)))
+	      {
+		err = re_node_set_add_intersect (&except_nodes, candidates,
+						 dfa->inveclosures + cur_node);
+		if (BE (err != REG_NOERROR, 0))
+		  {
+		    re_node_set_free (&except_nodes);
+		    return err;
+		  }
+	      }
+	  }
+      }
+    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
+      {
+	int cur_node = inv_eclosure->elems[ecl_idx];
+	if (!re_node_set_contains (&except_nodes, cur_node))
+	  {
+	    int idx = re_node_set_contains (dest_nodes, cur_node) - 1;
+	    re_node_set_remove_at (dest_nodes, idx);
+	  }
+      }
+    re_node_set_free (&except_nodes);
+    return REG_NOERROR;
+}
+
+static int
+internal_function
+check_dst_limits (const re_match_context_t *mctx, re_node_set *limits,
+		  int dst_node, int dst_idx, int src_node, int src_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int lim_idx, src_pos, dst_pos;
+
+  int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);
+  int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);
+  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
+    {
+      int subexp_idx;
+      struct re_backref_cache_entry *ent;
+      ent = mctx->bkref_ents + limits->elems[lim_idx];
+      subexp_idx = dfa->nodes[ent->node].opr.idx;
+
+      dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
+					   subexp_idx, dst_node, dst_idx,
+					   dst_bkref_idx);
+      src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
+					   subexp_idx, src_node, src_idx,
+					   src_bkref_idx);
+
+      /* In case of:
+	 <src> <dst> ( <subexp> )
+	 ( <subexp> ) <src> <dst>
+	 ( <subexp1> <src> <subexp2> <dst> <subexp3> )  */
+      if (src_pos == dst_pos)
+	continue; /* This is unrelated limitation.  */
+      else
+	return 1;
+    }
+  return 0;
+}
+
+static int
+internal_function
+check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
+			     int subexp_idx, int from_node, int bkref_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  const re_node_set *eclosures = dfa->eclosures + from_node;
+  int node_idx;
+
+  /* Else, we are on the boundary: examine the nodes on the epsilon
+     closure.  */
+  for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
+    {
+      int node = eclosures->elems[node_idx];
+      switch (dfa->nodes[node].type)
+	{
+	case OP_BACK_REF:
+	  if (bkref_idx != -1)
+	    {
+	      struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx;
+	      do
+	        {
+		  int dst, cpos;
+
+		  if (ent->node != node)
+		    continue;
+
+		  if (subexp_idx < BITSET_WORD_BITS
+		      && !(ent->eps_reachable_subexps_map
+			   & ((bitset_word_t) 1 << subexp_idx)))
+		    continue;
+
+		  /* Recurse trying to reach the OP_OPEN_SUBEXP and
+		     OP_CLOSE_SUBEXP cases below.  But, if the
+		     destination node is the same node as the source
+		     node, don't recurse because it would cause an
+		     infinite loop: a regex that exhibits this behavior
+		     is ()\1*\1*  */
+		  dst = dfa->edests[node].elems[0];
+		  if (dst == from_node)
+		    {
+		      if (boundaries & 1)
+		        return -1;
+		      else /* if (boundaries & 2) */
+		        return 0;
+		    }
+
+		  cpos =
+		    check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
+						 dst, bkref_idx);
+		  if (cpos == -1 /* && (boundaries & 1) */)
+		    return -1;
+		  if (cpos == 0 && (boundaries & 2))
+		    return 0;
+
+		  if (subexp_idx < BITSET_WORD_BITS)
+		    ent->eps_reachable_subexps_map
+		      &= ~((bitset_word_t) 1 << subexp_idx);
+	        }
+	      while (ent++->more);
+	    }
+	  break;
+
+	case OP_OPEN_SUBEXP:
+	  if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx)
+	    return -1;
+	  break;
+
+	case OP_CLOSE_SUBEXP:
+	  if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx)
+	    return 0;
+	  break;
+
+	default:
+	    break;
+	}
+    }
+
+  return (boundaries & 2) ? 1 : 0;
+}
+
+static int
+internal_function
+check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit,
+			   int subexp_idx, int from_node, int str_idx,
+			   int bkref_idx)
+{
+  struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
+  int boundaries;
+
+  /* If we are outside the range of the subexpression, return -1 or 1.  */
+  if (str_idx < lim->subexp_from)
+    return -1;
+
+  if (lim->subexp_to < str_idx)
+    return 1;
+
+  /* If we are within the subexpression, return 0.  */
+  boundaries = (str_idx == lim->subexp_from);
+  boundaries |= (str_idx == lim->subexp_to) << 1;
+  if (boundaries == 0)
+    return 0;
+
+  /* Else, examine epsilon closure.  */
+  return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
+				      from_node, bkref_idx);
+}
+
+/* Check the limitations of sub expressions LIMITS, and remove the nodes
+   which are against limitations from DEST_NODES. */
+
+static reg_errcode_t
+internal_function
+check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
+		     const re_node_set *candidates, re_node_set *limits,
+		     struct re_backref_cache_entry *bkref_ents, int str_idx)
+{
+  reg_errcode_t err;
+  int node_idx, lim_idx;
+
+  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
+    {
+      int subexp_idx;
+      struct re_backref_cache_entry *ent;
+      ent = bkref_ents + limits->elems[lim_idx];
+
+      if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)
+	continue; /* This is unrelated limitation.  */
+
+      subexp_idx = dfa->nodes[ent->node].opr.idx;
+      if (ent->subexp_to == str_idx)
+	{
+	  int ops_node = -1;
+	  int cls_node = -1;
+	  for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+	    {
+	      int node = dest_nodes->elems[node_idx];
+	      re_token_type_t type = dfa->nodes[node].type;
+	      if (type == OP_OPEN_SUBEXP
+		  && subexp_idx == dfa->nodes[node].opr.idx)
+		ops_node = node;
+	      else if (type == OP_CLOSE_SUBEXP
+		       && subexp_idx == dfa->nodes[node].opr.idx)
+		cls_node = node;
+	    }
+
+	  /* Check the limitation of the open subexpression.  */
+	  /* Note that (ent->subexp_to = str_idx != ent->subexp_from).  */
+	  if (ops_node >= 0)
+	    {
+	      err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes,
+					   candidates);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	    }
+
+	  /* Check the limitation of the close subexpression.  */
+	  if (cls_node >= 0)
+	    for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+	      {
+		int node = dest_nodes->elems[node_idx];
+		if (!re_node_set_contains (dfa->inveclosures + node,
+					   cls_node)
+		    && !re_node_set_contains (dfa->eclosures + node,
+					      cls_node))
+		  {
+		    /* It is against this limitation.
+		       Remove it form the current sifted state.  */
+		    err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
+						 candidates);
+		    if (BE (err != REG_NOERROR, 0))
+		      return err;
+		    --node_idx;
+		  }
+	      }
+	}
+      else /* (ent->subexp_to != str_idx)  */
+	{
+	  for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+	    {
+	      int node = dest_nodes->elems[node_idx];
+	      re_token_type_t type = dfa->nodes[node].type;
+	      if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
+		{
+		  if (subexp_idx != dfa->nodes[node].opr.idx)
+		    continue;
+		  /* It is against this limitation.
+		     Remove it form the current sifted state.  */
+		  err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
+					       candidates);
+		  if (BE (err != REG_NOERROR, 0))
+		    return err;
+		}
+	    }
+	}
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
+		   int str_idx, const re_node_set *candidates)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int node_idx, node;
+  re_sift_context_t local_sctx;
+  int first_idx = search_cur_bkref_entry (mctx, str_idx);
+
+  if (first_idx == -1)
+    return REG_NOERROR;
+
+  local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized.  */
+
+  for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
+    {
+      int enabled_idx;
+      re_token_type_t type;
+      struct re_backref_cache_entry *entry;
+      node = candidates->elems[node_idx];
+      type = dfa->nodes[node].type;
+      /* Avoid infinite loop for the REs like "()\1+".  */
+      if (node == sctx->last_node && str_idx == sctx->last_str_idx)
+	continue;
+      if (type != OP_BACK_REF)
+	continue;
+
+      entry = mctx->bkref_ents + first_idx;
+      enabled_idx = first_idx;
+      do
+	{
+	  int subexp_len;
+	  int to_idx;
+	  int dst_node;
+	  int ret;
+	  re_dfastate_t *cur_state;
+
+	  if (entry->node != node)
+	    continue;
+	  subexp_len = entry->subexp_to - entry->subexp_from;
+	  to_idx = str_idx + subexp_len;
+	  dst_node = (subexp_len ? dfa->nexts[node]
+		      : dfa->edests[node].elems[0]);
+
+	  if (to_idx > sctx->last_str_idx
+	      || sctx->sifted_states[to_idx] == NULL
+	      || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node)
+	      || check_dst_limits (mctx, &sctx->limits, node,
+				   str_idx, dst_node, to_idx))
+	    continue;
+
+	  if (local_sctx.sifted_states == NULL)
+	    {
+	      local_sctx = *sctx;
+	      err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits);
+	      if (BE (err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	  local_sctx.last_node = node;
+	  local_sctx.last_str_idx = str_idx;
+	  ret = re_node_set_insert (&local_sctx.limits, enabled_idx);
+	  if (BE (ret < 0, 0))
+	    {
+	      err = REG_ESPACE;
+	      goto free_return;
+	    }
+	  cur_state = local_sctx.sifted_states[str_idx];
+	  err = sift_states_backward (mctx, &local_sctx);
+	  if (BE (err != REG_NOERROR, 0))
+	    goto free_return;
+	  if (sctx->limited_states != NULL)
+	    {
+	      err = merge_state_array (dfa, sctx->limited_states,
+				       local_sctx.sifted_states,
+				       str_idx + 1);
+	      if (BE (err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	  local_sctx.sifted_states[str_idx] = cur_state;
+	  re_node_set_remove (&local_sctx.limits, enabled_idx);
+
+	  /* mctx->bkref_ents may have changed, reload the pointer.  */
+          entry = mctx->bkref_ents + enabled_idx;
+	}
+      while (enabled_idx++, entry++->more);
+    }
+  err = REG_NOERROR;
+ free_return:
+  if (local_sctx.sifted_states != NULL)
+    {
+      re_node_set_free (&local_sctx.limits);
+    }
+
+  return err;
+}
+
+
+#ifdef RE_ENABLE_I18N
+static int
+internal_function
+sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
+		     int node_idx, int str_idx, int max_str_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int naccepted;
+  /* Check the node can accept `multi byte'.  */
+  naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx);
+  if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
+      !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
+			    dfa->nexts[node_idx]))
+    /* The node can't accept the `multi byte', or the
+       destination was already thrown away, then the node
+       could't accept the current input `multi byte'.   */
+    naccepted = 0;
+  /* Otherwise, it is sure that the node could accept
+     `naccepted' bytes input.  */
+  return naccepted;
+}
+#endif /* RE_ENABLE_I18N */
+
+
+/* Functions for state transition.  */
+
+/* Return the next state to which the current state STATE will transit by
+   accepting the current input byte, and update STATE_LOG if necessary.
+   If STATE can accept a multibyte char/collating element/back reference
+   update the destination of STATE_LOG.  */
+
+static re_dfastate_t *
+internal_function
+transit_state (reg_errcode_t *err, re_match_context_t *mctx,
+	       re_dfastate_t *state)
+{
+  re_dfastate_t **trtable;
+  unsigned char ch;
+
+#ifdef RE_ENABLE_I18N
+  /* If the current state can accept multibyte.  */
+  if (BE (state->accept_mb, 0))
+    {
+      *err = transit_state_mb (mctx, state);
+      if (BE (*err != REG_NOERROR, 0))
+	return NULL;
+    }
+#endif /* RE_ENABLE_I18N */
+
+  /* Then decide the next state with the single byte.  */
+#if 0
+  if (0)
+    /* don't use transition table  */
+    return transit_state_sb (err, mctx, state);
+#endif
+
+  /* Use transition table  */
+  ch = re_string_fetch_byte (&mctx->input);
+  for (;;)
+    {
+      trtable = state->trtable;
+      if (BE (trtable != NULL, 1))
+	return trtable[ch];
+
+      trtable = state->word_trtable;
+      if (BE (trtable != NULL, 1))
+        {
+	  unsigned int context;
+	  context
+	    = re_string_context_at (&mctx->input,
+				    re_string_cur_idx (&mctx->input) - 1,
+				    mctx->eflags);
+	  if (IS_WORD_CONTEXT (context))
+	    return trtable[ch + SBC_MAX];
+	  else
+	    return trtable[ch];
+	}
+
+      if (!build_trtable (mctx->dfa, state))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+
+      /* Retry, we now have a transition table.  */
+    }
+}
+
+/* Update the state_log if we need */
+re_dfastate_t *
+internal_function
+merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
+		      re_dfastate_t *next_state)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int cur_idx = re_string_cur_idx (&mctx->input);
+
+  if (cur_idx > mctx->state_log_top)
+    {
+      mctx->state_log[cur_idx] = next_state;
+      mctx->state_log_top = cur_idx;
+    }
+  else if (mctx->state_log[cur_idx] == 0)
+    {
+      mctx->state_log[cur_idx] = next_state;
+    }
+  else
+    {
+      re_dfastate_t *pstate;
+      unsigned int context;
+      re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
+      /* If (state_log[cur_idx] != 0), it implies that cur_idx is
+         the destination of a multibyte char/collating element/
+         back reference.  Then the next state is the union set of
+         these destinations and the results of the transition table.  */
+      pstate = mctx->state_log[cur_idx];
+      log_nodes = pstate->entrance_nodes;
+      if (next_state != NULL)
+        {
+          table_nodes = next_state->entrance_nodes;
+          *err = re_node_set_init_union (&next_nodes, table_nodes,
+					     log_nodes);
+          if (BE (*err != REG_NOERROR, 0))
+	    return NULL;
+        }
+      else
+        next_nodes = *log_nodes;
+      /* Note: We already add the nodes of the initial state,
+	 then we don't need to add them here.  */
+
+      context = re_string_context_at (&mctx->input,
+				      re_string_cur_idx (&mctx->input) - 1,
+				      mctx->eflags);
+      next_state = mctx->state_log[cur_idx]
+        = re_acquire_state_context (err, dfa, &next_nodes, context);
+      /* We don't need to check errors here, since the return value of
+         this function is next_state and ERR is already set.  */
+
+      if (table_nodes != NULL)
+        re_node_set_free (&next_nodes);
+    }
+
+  if (BE (dfa->nbackref, 0) && next_state != NULL)
+    {
+      /* Check OP_OPEN_SUBEXP in the current state in case that we use them
+	 later.  We must check them here, since the back references in the
+	 next state might use them.  */
+      *err = check_subexp_matching_top (mctx, &next_state->nodes,
+					cur_idx);
+      if (BE (*err != REG_NOERROR, 0))
+	return NULL;
+
+      /* If the next state has back references.  */
+      if (next_state->has_backref)
+	{
+	  *err = transit_state_bkref (mctx, &next_state->nodes);
+	  if (BE (*err != REG_NOERROR, 0))
+	    return NULL;
+	  next_state = mctx->state_log[cur_idx];
+	}
+    }
+
+  return next_state;
+}
+
+/* Skip bytes in the input that correspond to part of a
+   multi-byte match, then look in the log for a state
+   from which to restart matching.  */
+re_dfastate_t *
+internal_function
+find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
+{
+  re_dfastate_t *cur_state;
+  do
+    {
+      int max = mctx->state_log_top;
+      int cur_str_idx = re_string_cur_idx (&mctx->input);
+
+      do
+	{
+          if (++cur_str_idx > max)
+            return NULL;
+          re_string_skip_bytes (&mctx->input, 1);
+	}
+      while (mctx->state_log[cur_str_idx] == NULL);
+
+      cur_state = merge_state_with_log (err, mctx, NULL);
+    }
+  while (*err == REG_NOERROR && cur_state == NULL);
+  return cur_state;
+}
+
+/* Helper functions for transit_state.  */
+
+/* From the node set CUR_NODES, pick up the nodes whose types are
+   OP_OPEN_SUBEXP and which have corresponding back references in the regular
+   expression. And register them to use them later for evaluating the
+   correspoding back references.  */
+
+static reg_errcode_t
+internal_function
+check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
+			   int str_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int node_idx;
+  reg_errcode_t err;
+
+  /* TODO: This isn't efficient.
+	   Because there might be more than one nodes whose types are
+	   OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
+	   nodes.
+	   E.g. RE: (a){2}  */
+  for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)
+    {
+      int node = cur_nodes->elems[node_idx];
+      if (dfa->nodes[node].type == OP_OPEN_SUBEXP
+	  && dfa->nodes[node].opr.idx < BITSET_WORD_BITS
+	  && (dfa->used_bkref_map
+	      & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx)))
+	{
+	  err = match_ctx_add_subtop (mctx, node, str_idx);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+    }
+  return REG_NOERROR;
+}
+
+#if 0
+/* Return the next state to which the current state STATE will transit by
+   accepting the current input byte.  */
+
+static re_dfastate_t *
+transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
+		  re_dfastate_t *state)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  re_node_set next_nodes;
+  re_dfastate_t *next_state;
+  int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);
+  unsigned int context;
+
+  *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
+  if (BE (*err != REG_NOERROR, 0))
+    return NULL;
+  for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
+    {
+      int cur_node = state->nodes.elems[node_cnt];
+      if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx))
+	{
+	  *err = re_node_set_merge (&next_nodes,
+				    dfa->eclosures + dfa->nexts[cur_node]);
+	  if (BE (*err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return NULL;
+	    }
+	}
+    }
+  context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags);
+  next_state = re_acquire_state_context (err, dfa, &next_nodes, context);
+  /* We don't need to check errors here, since the return value of
+     this function is next_state and ERR is already set.  */
+
+  re_node_set_free (&next_nodes);
+  re_string_skip_bytes (&mctx->input, 1);
+  return next_state;
+}
+#endif
+
+#ifdef RE_ENABLE_I18N
+static reg_errcode_t
+internal_function
+transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int i;
+
+  for (i = 0; i < pstate->nodes.nelem; ++i)
+    {
+      re_node_set dest_nodes, *new_nodes;
+      int cur_node_idx = pstate->nodes.elems[i];
+      int naccepted, dest_idx;
+      unsigned int context;
+      re_dfastate_t *dest_state;
+
+      if (!dfa->nodes[cur_node_idx].accept_mb)
+        continue;
+
+      if (dfa->nodes[cur_node_idx].constraint)
+	{
+	  context = re_string_context_at (&mctx->input,
+					  re_string_cur_idx (&mctx->input),
+					  mctx->eflags);
+	  if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,
+					   context))
+	    continue;
+	}
+
+      /* How many bytes the node can accept?  */
+      naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,
+					   re_string_cur_idx (&mctx->input));
+      if (naccepted == 0)
+	continue;
+
+      /* The node can accepts `naccepted' bytes.  */
+      dest_idx = re_string_cur_idx (&mctx->input) + naccepted;
+      mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
+			       : mctx->max_mb_elem_len);
+      err = clean_state_log_if_needed (mctx, dest_idx);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+#ifdef DEBUG
+      assert (dfa->nexts[cur_node_idx] != -1);
+#endif
+      new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];
+
+      dest_state = mctx->state_log[dest_idx];
+      if (dest_state == NULL)
+	dest_nodes = *new_nodes;
+      else
+	{
+	  err = re_node_set_init_union (&dest_nodes,
+					dest_state->entrance_nodes, new_nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+      context = re_string_context_at (&mctx->input, dest_idx - 1,
+				      mctx->eflags);
+      mctx->state_log[dest_idx]
+	= re_acquire_state_context (&err, dfa, &dest_nodes, context);
+      if (dest_state != NULL)
+	re_node_set_free (&dest_nodes);
+      if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0))
+	return err;
+    }
+  return REG_NOERROR;
+}
+#endif /* RE_ENABLE_I18N */
+
+static reg_errcode_t
+internal_function
+transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int i;
+  int cur_str_idx = re_string_cur_idx (&mctx->input);
+
+  for (i = 0; i < nodes->nelem; ++i)
+    {
+      int dest_str_idx, prev_nelem, bkc_idx;
+      int node_idx = nodes->elems[i];
+      unsigned int context;
+      const re_token_t *node = dfa->nodes + node_idx;
+      re_node_set *new_dest_nodes;
+
+      /* Check whether `node' is a backreference or not.  */
+      if (node->type != OP_BACK_REF)
+	continue;
+
+      if (node->constraint)
+	{
+	  context = re_string_context_at (&mctx->input, cur_str_idx,
+					  mctx->eflags);
+	  if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
+	    continue;
+	}
+
+      /* `node' is a backreference.
+	 Check the substring which the substring matched.  */
+      bkc_idx = mctx->nbkref_ents;
+      err = get_subexp (mctx, node_idx, cur_str_idx);
+      if (BE (err != REG_NOERROR, 0))
+	goto free_return;
+
+      /* And add the epsilon closures (which is `new_dest_nodes') of
+	 the backreference to appropriate state_log.  */
+#ifdef DEBUG
+      assert (dfa->nexts[node_idx] != -1);
+#endif
+      for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
+	{
+	  int subexp_len;
+	  re_dfastate_t *dest_state;
+	  struct re_backref_cache_entry *bkref_ent;
+	  bkref_ent = mctx->bkref_ents + bkc_idx;
+	  if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)
+	    continue;
+	  subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;
+	  new_dest_nodes = (subexp_len == 0
+			    ? dfa->eclosures + dfa->edests[node_idx].elems[0]
+			    : dfa->eclosures + dfa->nexts[node_idx]);
+	  dest_str_idx = (cur_str_idx + bkref_ent->subexp_to
+			  - bkref_ent->subexp_from);
+	  context = re_string_context_at (&mctx->input, dest_str_idx - 1,
+					  mctx->eflags);
+	  dest_state = mctx->state_log[dest_str_idx];
+	  prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
+			: mctx->state_log[cur_str_idx]->nodes.nelem);
+	  /* Add `new_dest_node' to state_log.  */
+	  if (dest_state == NULL)
+	    {
+	      mctx->state_log[dest_str_idx]
+		= re_acquire_state_context (&err, dfa, new_dest_nodes,
+					    context);
+	      if (BE (mctx->state_log[dest_str_idx] == NULL
+		      && err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	  else
+	    {
+	      re_node_set dest_nodes;
+	      err = re_node_set_init_union (&dest_nodes,
+					    dest_state->entrance_nodes,
+					    new_dest_nodes);
+	      if (BE (err != REG_NOERROR, 0))
+		{
+		  re_node_set_free (&dest_nodes);
+		  goto free_return;
+		}
+	      mctx->state_log[dest_str_idx]
+		= re_acquire_state_context (&err, dfa, &dest_nodes, context);
+	      re_node_set_free (&dest_nodes);
+	      if (BE (mctx->state_log[dest_str_idx] == NULL
+		      && err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	  /* We need to check recursively if the backreference can epsilon
+	     transit.  */
+	  if (subexp_len == 0
+	      && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)
+	    {
+	      err = check_subexp_matching_top (mctx, new_dest_nodes,
+					       cur_str_idx);
+	      if (BE (err != REG_NOERROR, 0))
+		goto free_return;
+	      err = transit_state_bkref (mctx, new_dest_nodes);
+	      if (BE (err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	}
+    }
+  err = REG_NOERROR;
+ free_return:
+  return err;
+}
+
+/* Enumerate all the candidates which the backreference BKREF_NODE can match
+   at BKREF_STR_IDX, and register them by match_ctx_add_entry().
+   Note that we might collect inappropriate candidates here.
+   However, the cost of checking them strictly here is too high, then we
+   delay these checking for prune_impossible_nodes().  */
+
+static reg_errcode_t
+internal_function
+get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int subexp_num, sub_top_idx;
+  const char *buf = (const char *) re_string_get_buffer (&mctx->input);
+  /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX.  */
+  int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
+  if (cache_idx != -1)
+    {
+      const struct re_backref_cache_entry *entry
+	= mctx->bkref_ents + cache_idx;
+      do
+        if (entry->node == bkref_node)
+	  return REG_NOERROR; /* We already checked it.  */
+      while (entry++->more);
+    }
+
+  subexp_num = dfa->nodes[bkref_node].opr.idx;
+
+  /* For each sub expression  */
+  for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx)
+    {
+      reg_errcode_t err;
+      re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];
+      re_sub_match_last_t *sub_last;
+      int sub_last_idx, sl_str, bkref_str_off;
+
+      if (dfa->nodes[sub_top->node].opr.idx != subexp_num)
+	continue; /* It isn't related.  */
+
+      sl_str = sub_top->str_idx;
+      bkref_str_off = bkref_str_idx;
+      /* At first, check the last node of sub expressions we already
+	 evaluated.  */
+      for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)
+	{
+	  int sl_str_diff;
+	  sub_last = sub_top->lasts[sub_last_idx];
+	  sl_str_diff = sub_last->str_idx - sl_str;
+	  /* The matched string by the sub expression match with the substring
+	     at the back reference?  */
+	  if (sl_str_diff > 0)
+	    {
+	      if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0))
+		{
+		  /* Not enough chars for a successful match.  */
+		  if (bkref_str_off + sl_str_diff > mctx->input.len)
+		    break;
+
+		  err = clean_state_log_if_needed (mctx,
+						   bkref_str_off
+						   + sl_str_diff);
+		  if (BE (err != REG_NOERROR, 0))
+		    return err;
+		  buf = (const char *) re_string_get_buffer (&mctx->input);
+		}
+	      if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0)
+		/* We don't need to search this sub expression any more.  */
+		break;
+	    }
+	  bkref_str_off += sl_str_diff;
+	  sl_str += sl_str_diff;
+	  err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
+				bkref_str_idx);
+
+	  /* Reload buf, since the preceding call might have reallocated
+	     the buffer.  */
+	  buf = (const char *) re_string_get_buffer (&mctx->input);
+
+	  if (err == REG_NOMATCH)
+	    continue;
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+
+      if (sub_last_idx < sub_top->nlasts)
+	continue;
+      if (sub_last_idx > 0)
+	++sl_str;
+      /* Then, search for the other last nodes of the sub expression.  */
+      for (; sl_str <= bkref_str_idx; ++sl_str)
+	{
+	  int cls_node, sl_str_off;
+	  const re_node_set *nodes;
+	  sl_str_off = sl_str - sub_top->str_idx;
+	  /* The matched string by the sub expression match with the substring
+	     at the back reference?  */
+	  if (sl_str_off > 0)
+	    {
+	      if (BE (bkref_str_off >= mctx->input.valid_len, 0))
+		{
+		  /* If we are at the end of the input, we cannot match.  */
+		  if (bkref_str_off >= mctx->input.len)
+		    break;
+
+		  err = extend_buffers (mctx);
+		  if (BE (err != REG_NOERROR, 0))
+		    return err;
+
+		  buf = (const char *) re_string_get_buffer (&mctx->input);
+		}
+	      if (buf [bkref_str_off++] != buf[sl_str - 1])
+		break; /* We don't need to search this sub expression
+			  any more.  */
+	    }
+	  if (mctx->state_log[sl_str] == NULL)
+	    continue;
+	  /* Does this state have a ')' of the sub expression?  */
+	  nodes = &mctx->state_log[sl_str]->nodes;
+	  cls_node = find_subexp_node (dfa, nodes, subexp_num,
+				       OP_CLOSE_SUBEXP);
+	  if (cls_node == -1)
+	    continue; /* No.  */
+	  if (sub_top->path == NULL)
+	    {
+	      sub_top->path = calloc (sizeof (state_array_t),
+				      sl_str - sub_top->str_idx + 1);
+	      if (sub_top->path == NULL)
+		return REG_ESPACE;
+	    }
+	  /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node
+	     in the current context?  */
+	  err = check_arrival (mctx, sub_top->path, sub_top->node,
+			       sub_top->str_idx, cls_node, sl_str,
+			       OP_CLOSE_SUBEXP);
+	  if (err == REG_NOMATCH)
+	      continue;
+	  if (BE (err != REG_NOERROR, 0))
+	      return err;
+	  sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str);
+	  if (BE (sub_last == NULL, 0))
+	    return REG_ESPACE;
+	  err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
+				bkref_str_idx);
+	  if (err == REG_NOMATCH)
+	    continue;
+	}
+    }
+  return REG_NOERROR;
+}
+
+/* Helper functions for get_subexp().  */
+
+/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR.
+   If it can arrive, register the sub expression expressed with SUB_TOP
+   and SUB_LAST.  */
+
+static reg_errcode_t
+internal_function
+get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,
+		re_sub_match_last_t *sub_last, int bkref_node, int bkref_str)
+{
+  reg_errcode_t err;
+  int to_idx;
+  /* Can the subexpression arrive the back reference?  */
+  err = check_arrival (mctx, &sub_last->path, sub_last->node,
+		       sub_last->str_idx, bkref_node, bkref_str,
+		       OP_OPEN_SUBEXP);
+  if (err != REG_NOERROR)
+    return err;
+  err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx,
+			     sub_last->str_idx);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+  to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx;
+  return clean_state_log_if_needed (mctx, to_idx);
+}
+
+/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX.
+   Search '(' if FL_OPEN, or search ')' otherwise.
+   TODO: This function isn't efficient...
+	 Because there might be more than one nodes whose types are
+	 OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
+	 nodes.
+	 E.g. RE: (a){2}  */
+
+static int
+internal_function
+find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
+		  int subexp_idx, int type)
+{
+  int cls_idx;
+  for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)
+    {
+      int cls_node = nodes->elems[cls_idx];
+      const re_token_t *node = dfa->nodes + cls_node;
+      if (node->type == type
+	  && node->opr.idx == subexp_idx)
+	return cls_node;
+    }
+  return -1;
+}
+
+/* Check whether the node TOP_NODE at TOP_STR can arrive to the node
+   LAST_NODE at LAST_STR.  We record the path onto PATH since it will be
+   heavily reused.
+   Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise.  */
+
+static reg_errcode_t
+internal_function
+check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
+	       int top_str, int last_node, int last_str, int type)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err = REG_NOERROR;
+  int subexp_num, backup_cur_idx, str_idx, null_cnt;
+  re_dfastate_t *cur_state = NULL;
+  re_node_set *cur_nodes, next_nodes;
+  re_dfastate_t **backup_state_log;
+  unsigned int context;
+
+  subexp_num = dfa->nodes[top_node].opr.idx;
+  /* Extend the buffer if we need.  */
+  if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0))
+    {
+      re_dfastate_t **new_array;
+      int old_alloc = path->alloc;
+      path->alloc += last_str + mctx->max_mb_elem_len + 1;
+      new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);
+      if (BE (new_array == NULL, 0))
+	{
+	  path->alloc = old_alloc;
+	  return REG_ESPACE;
+	}
+      path->array = new_array;
+      memset (new_array + old_alloc, '\0',
+	      sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
+    }
+
+  str_idx = path->next_idx ?: top_str;
+
+  /* Temporary modify MCTX.  */
+  backup_state_log = mctx->state_log;
+  backup_cur_idx = mctx->input.cur_idx;
+  mctx->state_log = path->array;
+  mctx->input.cur_idx = str_idx;
+
+  /* Setup initial node set.  */
+  context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
+  if (str_idx == top_str)
+    {
+      err = re_node_set_init_1 (&next_nodes, top_node);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+      err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
+      if (BE (err != REG_NOERROR, 0))
+	{
+	  re_node_set_free (&next_nodes);
+	  return err;
+	}
+    }
+  else
+    {
+      cur_state = mctx->state_log[str_idx];
+      if (cur_state && cur_state->has_backref)
+	{
+	  err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+      else
+	re_node_set_init_empty (&next_nodes);
+    }
+  if (str_idx == top_str || (cur_state && cur_state->has_backref))
+    {
+      if (next_nodes.nelem)
+	{
+	  err = expand_bkref_cache (mctx, &next_nodes, str_idx,
+				    subexp_num, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	}
+      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
+      if (BE (cur_state == NULL && err != REG_NOERROR, 0))
+	{
+	  re_node_set_free (&next_nodes);
+	  return err;
+	}
+      mctx->state_log[str_idx] = cur_state;
+    }
+
+  for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)
+    {
+      re_node_set_empty (&next_nodes);
+      if (mctx->state_log[str_idx + 1])
+	{
+	  err = re_node_set_merge (&next_nodes,
+				   &mctx->state_log[str_idx + 1]->nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	}
+      if (cur_state)
+	{
+	  err = check_arrival_add_next_nodes (mctx, str_idx,
+					      &cur_state->non_eps_nodes,
+					      &next_nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	}
+      ++str_idx;
+      if (next_nodes.nelem)
+	{
+	  err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	  err = expand_bkref_cache (mctx, &next_nodes, str_idx,
+				    subexp_num, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	}
+      context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
+      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
+      if (BE (cur_state == NULL && err != REG_NOERROR, 0))
+	{
+	  re_node_set_free (&next_nodes);
+	  return err;
+	}
+      mctx->state_log[str_idx] = cur_state;
+      null_cnt = cur_state == NULL ? null_cnt + 1 : 0;
+    }
+  re_node_set_free (&next_nodes);
+  cur_nodes = (mctx->state_log[last_str] == NULL ? NULL
+	       : &mctx->state_log[last_str]->nodes);
+  path->next_idx = str_idx;
+
+  /* Fix MCTX.  */
+  mctx->state_log = backup_state_log;
+  mctx->input.cur_idx = backup_cur_idx;
+
+  /* Then check the current node set has the node LAST_NODE.  */
+  if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node))
+    return REG_NOERROR;
+
+  return REG_NOMATCH;
+}
+
+/* Helper functions for check_arrival.  */
+
+/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them
+   to NEXT_NODES.
+   TODO: This function is similar to the functions transit_state*(),
+	 however this function has many additional works.
+	 Can't we unify them?  */
+
+static reg_errcode_t
+internal_function
+check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
+			      re_node_set *cur_nodes, re_node_set *next_nodes)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int result;
+  int cur_idx;
+#ifdef RE_ENABLE_I18N
+  reg_errcode_t err = REG_NOERROR;
+#endif
+  re_node_set union_set;
+  re_node_set_init_empty (&union_set);
+  for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
+    {
+      int naccepted = 0;
+      int cur_node = cur_nodes->elems[cur_idx];
+#ifdef DEBUG
+      re_token_type_t type = dfa->nodes[cur_node].type;
+      assert (!IS_EPSILON_NODE (type));
+#endif
+#ifdef RE_ENABLE_I18N
+      /* If the node may accept `multi byte'.  */
+      if (dfa->nodes[cur_node].accept_mb)
+	{
+	  naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,
+					       str_idx);
+	  if (naccepted > 1)
+	    {
+	      re_dfastate_t *dest_state;
+	      int next_node = dfa->nexts[cur_node];
+	      int next_idx = str_idx + naccepted;
+	      dest_state = mctx->state_log[next_idx];
+	      re_node_set_empty (&union_set);
+	      if (dest_state)
+		{
+		  err = re_node_set_merge (&union_set, &dest_state->nodes);
+		  if (BE (err != REG_NOERROR, 0))
+		    {
+		      re_node_set_free (&union_set);
+		      return err;
+		    }
+		}
+	      result = re_node_set_insert (&union_set, next_node);
+	      if (BE (result < 0, 0))
+		{
+		  re_node_set_free (&union_set);
+		  return REG_ESPACE;
+		}
+	      mctx->state_log[next_idx] = re_acquire_state (&err, dfa,
+							    &union_set);
+	      if (BE (mctx->state_log[next_idx] == NULL
+		      && err != REG_NOERROR, 0))
+		{
+		  re_node_set_free (&union_set);
+		  return err;
+		}
+	    }
+	}
+#endif /* RE_ENABLE_I18N */
+      if (naccepted
+	  || check_node_accept (mctx, dfa->nodes + cur_node, str_idx))
+	{
+	  result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
+	  if (BE (result < 0, 0))
+	    {
+	      re_node_set_free (&union_set);
+	      return REG_ESPACE;
+	    }
+	}
+    }
+  re_node_set_free (&union_set);
+  return REG_NOERROR;
+}
+
+/* For all the nodes in CUR_NODES, add the epsilon closures of them to
+   CUR_NODES, however exclude the nodes which are:
+    - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN.
+    - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN.
+*/
+
+static reg_errcode_t
+internal_function
+check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
+			  int ex_subexp, int type)
+{
+  reg_errcode_t err;
+  int idx, outside_node;
+  re_node_set new_nodes;
+#ifdef DEBUG
+  assert (cur_nodes->nelem);
+#endif
+  err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+  /* Create a new node set NEW_NODES with the nodes which are epsilon
+     closures of the node in CUR_NODES.  */
+
+  for (idx = 0; idx < cur_nodes->nelem; ++idx)
+    {
+      int cur_node = cur_nodes->elems[idx];
+      const re_node_set *eclosure = dfa->eclosures + cur_node;
+      outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type);
+      if (outside_node == -1)
+	{
+	  /* There are no problematic nodes, just merge them.  */
+	  err = re_node_set_merge (&new_nodes, eclosure);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&new_nodes);
+	      return err;
+	    }
+	}
+      else
+	{
+	  /* There are problematic nodes, re-calculate incrementally.  */
+	  err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,
+					      ex_subexp, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&new_nodes);
+	      return err;
+	    }
+	}
+    }
+  re_node_set_free (cur_nodes);
+  *cur_nodes = new_nodes;
+  return REG_NOERROR;
+}
+
+/* Helper function for check_arrival_expand_ecl.
+   Check incrementally the epsilon closure of TARGET, and if it isn't
+   problematic append it to DST_NODES.  */
+
+static reg_errcode_t
+internal_function
+check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
+			      int target, int ex_subexp, int type)
+{
+  int cur_node;
+  for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
+    {
+      int err;
+
+      if (dfa->nodes[cur_node].type == type
+	  && dfa->nodes[cur_node].opr.idx == ex_subexp)
+	{
+	  if (type == OP_CLOSE_SUBEXP)
+	    {
+	      err = re_node_set_insert (dst_nodes, cur_node);
+	      if (BE (err == -1, 0))
+		return REG_ESPACE;
+	    }
+	  break;
+	}
+      err = re_node_set_insert (dst_nodes, cur_node);
+      if (BE (err == -1, 0))
+	return REG_ESPACE;
+      if (dfa->edests[cur_node].nelem == 0)
+	break;
+      if (dfa->edests[cur_node].nelem == 2)
+	{
+	  err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
+					      dfa->edests[cur_node].elems[1],
+					      ex_subexp, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+      cur_node = dfa->edests[cur_node].elems[0];
+    }
+  return REG_NOERROR;
+}
+
+
+/* For all the back references in the current state, calculate the
+   destination of the back references by the appropriate entry
+   in MCTX->BKREF_ENTS.  */
+
+static reg_errcode_t
+internal_function
+expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
+		    int cur_str, int subexp_num, int type)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
+  struct re_backref_cache_entry *ent;
+
+  if (cache_idx_start == -1)
+    return REG_NOERROR;
+
+ restart:
+  ent = mctx->bkref_ents + cache_idx_start;
+  do
+    {
+      int to_idx, next_node;
+
+      /* Is this entry ENT is appropriate?  */
+      if (!re_node_set_contains (cur_nodes, ent->node))
+	continue; /* No.  */
+
+      to_idx = cur_str + ent->subexp_to - ent->subexp_from;
+      /* Calculate the destination of the back reference, and append it
+	 to MCTX->STATE_LOG.  */
+      if (to_idx == cur_str)
+	{
+	  /* The backreference did epsilon transit, we must re-check all the
+	     node in the current state.  */
+	  re_node_set new_dests;
+	  reg_errcode_t err2, err3;
+	  next_node = dfa->edests[ent->node].elems[0];
+	  if (re_node_set_contains (cur_nodes, next_node))
+	    continue;
+	  err = re_node_set_init_1 (&new_dests, next_node);
+	  err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type);
+	  err3 = re_node_set_merge (cur_nodes, &new_dests);
+	  re_node_set_free (&new_dests);
+	  if (BE (err != REG_NOERROR || err2 != REG_NOERROR
+		  || err3 != REG_NOERROR, 0))
+	    {
+	      err = (err != REG_NOERROR ? err
+		     : (err2 != REG_NOERROR ? err2 : err3));
+	      return err;
+	    }
+	  /* TODO: It is still inefficient...  */
+	  goto restart;
+	}
+      else
+	{
+	  re_node_set union_set;
+	  next_node = dfa->nexts[ent->node];
+	  if (mctx->state_log[to_idx])
+	    {
+	      int ret;
+	      if (re_node_set_contains (&mctx->state_log[to_idx]->nodes,
+					next_node))
+		continue;
+	      err = re_node_set_init_copy (&union_set,
+					   &mctx->state_log[to_idx]->nodes);
+	      ret = re_node_set_insert (&union_set, next_node);
+	      if (BE (err != REG_NOERROR || ret < 0, 0))
+		{
+		  re_node_set_free (&union_set);
+		  err = err != REG_NOERROR ? err : REG_ESPACE;
+		  return err;
+		}
+	    }
+	  else
+	    {
+	      err = re_node_set_init_1 (&union_set, next_node);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	    }
+	  mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set);
+	  re_node_set_free (&union_set);
+	  if (BE (mctx->state_log[to_idx] == NULL
+		  && err != REG_NOERROR, 0))
+	    return err;
+	}
+    }
+  while (ent++->more);
+  return REG_NOERROR;
+}
+
+/* Build transition table for the state.
+   Return 1 if succeeded, otherwise return NULL.  */
+
+static int
+internal_function
+build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
+{
+  reg_errcode_t err;
+  int i, j, ch, need_word_trtable = 0;
+  bitset_word_t elem, mask;
+  bool dests_node_malloced = false;
+  bool dest_states_malloced = false;
+  int ndests; /* Number of the destination states from `state'.  */
+  re_dfastate_t **trtable;
+  re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
+  re_node_set follows, *dests_node;
+  bitset_t *dests_ch;
+  bitset_t acceptable;
+
+  struct dests_alloc
+  {
+    re_node_set dests_node[SBC_MAX];
+    bitset_t dests_ch[SBC_MAX];
+  } *dests_alloc;
+
+  /* We build DFA states which corresponds to the destination nodes
+     from `state'.  `dests_node[i]' represents the nodes which i-th
+     destination state contains, and `dests_ch[i]' represents the
+     characters which i-th destination state accepts.  */
+  if (__libc_use_alloca (sizeof (struct dests_alloc)))
+    dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));
+  else
+    {
+      dests_alloc = re_malloc (struct dests_alloc, 1);
+      if (BE (dests_alloc == NULL, 0))
+	return 0;
+      dests_node_malloced = true;
+    }
+  dests_node = dests_alloc->dests_node;
+  dests_ch = dests_alloc->dests_ch;
+
+  /* Initialize transiton table.  */
+  state->word_trtable = state->trtable = NULL;
+
+  /* At first, group all nodes belonging to `state' into several
+     destinations.  */
+  ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
+  if (BE (ndests <= 0, 0))
+    {
+      if (dests_node_malloced)
+	free (dests_alloc);
+      /* Return 0 in case of an error, 1 otherwise.  */
+      if (ndests == 0)
+	{
+	  state->trtable = (re_dfastate_t **)
+	    calloc (sizeof (re_dfastate_t *), SBC_MAX);
+	  return 1;
+	}
+      return 0;
+    }
+
+  err = re_node_set_alloc (&follows, ndests + 1);
+  if (BE (err != REG_NOERROR, 0))
+    goto out_free;
+
+  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX
+			 + ndests * 3 * sizeof (re_dfastate_t *)))
+    dest_states = (re_dfastate_t **)
+      alloca (ndests * 3 * sizeof (re_dfastate_t *));
+  else
+    {
+      dest_states = (re_dfastate_t **)
+	malloc (ndests * 3 * sizeof (re_dfastate_t *));
+      if (BE (dest_states == NULL, 0))
+	{
+out_free:
+	  if (dest_states_malloced)
+	    free (dest_states);
+	  re_node_set_free (&follows);
+	  for (i = 0; i < ndests; ++i)
+	    re_node_set_free (dests_node + i);
+	  if (dests_node_malloced)
+	    free (dests_alloc);
+	  return 0;
+	}
+      dest_states_malloced = true;
+    }
+  dest_states_word = dest_states + ndests;
+  dest_states_nl = dest_states_word + ndests;
+  bitset_empty (acceptable);
+
+  /* Then build the states for all destinations.  */
+  for (i = 0; i < ndests; ++i)
+    {
+      int next_node;
+      re_node_set_empty (&follows);
+      /* Merge the follows of this destination states.  */
+      for (j = 0; j < dests_node[i].nelem; ++j)
+	{
+	  next_node = dfa->nexts[dests_node[i].elems[j]];
+	  if (next_node != -1)
+	    {
+	      err = re_node_set_merge (&follows, dfa->eclosures + next_node);
+	      if (BE (err != REG_NOERROR, 0))
+		goto out_free;
+	    }
+	}
+      dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);
+      if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0))
+	goto out_free;
+      /* If the new state has context constraint,
+	 build appropriate states for these contexts.  */
+      if (dest_states[i]->has_constraint)
+	{
+	  dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,
+							  CONTEXT_WORD);
+	  if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
+	    goto out_free;
+
+	  if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
+	    need_word_trtable = 1;
+
+	  dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
+							CONTEXT_NEWLINE);
+	  if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))
+	    goto out_free;
+ 	}
+      else
+	{
+	  dest_states_word[i] = dest_states[i];
+	  dest_states_nl[i] = dest_states[i];
+	}
+      bitset_merge (acceptable, dests_ch[i]);
+    }
+
+  if (!BE (need_word_trtable, 0))
+    {
+      /* We don't care about whether the following character is a word
+	 character, or we are in a single-byte character set so we can
+	 discern by looking at the character code: allocate a
+	 256-entry transition table.  */
+      trtable = state->trtable = calloc (sizeof (re_dfastate_t *), SBC_MAX);
+      if (BE (trtable == NULL, 0))
+	goto out_free;
+
+      /* For all characters ch...:  */
+      for (i = 0; i < BITSET_WORDS; ++i)
+	for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
+	     elem;
+	     mask <<= 1, elem >>= 1, ++ch)
+	  if (BE (elem & 1, 0))
+	    {
+	      /* There must be exactly one destination which accepts
+		 character ch.  See group_nodes_into_DFAstates.  */
+	      for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
+		;
+
+	      /* j-th destination accepts the word character ch.  */
+	      if (dfa->word_char[i] & mask)
+		trtable[ch] = dest_states_word[j];
+	      else
+		trtable[ch] = dest_states[j];
+	    }
+    }
+  else
+    {
+      /* We care about whether the following character is a word
+	 character, and we are in a multi-byte character set: discern
+	 by looking at the character code: build two 256-entry
+	 transition tables, one starting at trtable[0] and one
+	 starting at trtable[SBC_MAX].  */
+      trtable = state->word_trtable = calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
+      if (BE (trtable == NULL, 0))
+	goto out_free;
+
+      /* For all characters ch...:  */
+      for (i = 0; i < BITSET_WORDS; ++i)
+	for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
+	     elem;
+	     mask <<= 1, elem >>= 1, ++ch)
+	  if (BE (elem & 1, 0))
+	    {
+	      /* There must be exactly one destination which accepts
+		 character ch.  See group_nodes_into_DFAstates.  */
+	      for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
+		;
+
+	      /* j-th destination accepts the word character ch.  */
+	      trtable[ch] = dest_states[j];
+	      trtable[ch + SBC_MAX] = dest_states_word[j];
+	    }
+    }
+
+  /* new line */
+  if (bitset_contain (acceptable, NEWLINE_CHAR))
+    {
+      /* The current state accepts newline character.  */
+      for (j = 0; j < ndests; ++j)
+	if (bitset_contain (dests_ch[j], NEWLINE_CHAR))
+	  {
+	    /* k-th destination accepts newline character.  */
+	    trtable[NEWLINE_CHAR] = dest_states_nl[j];
+	    if (need_word_trtable)
+	      trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j];
+	    /* There must be only one destination which accepts
+	       newline.  See group_nodes_into_DFAstates.  */
+	    break;
+	  }
+    }
+
+  if (dest_states_malloced)
+    free (dest_states);
+
+  re_node_set_free (&follows);
+  for (i = 0; i < ndests; ++i)
+    re_node_set_free (dests_node + i);
+
+  if (dests_node_malloced)
+    free (dests_alloc);
+
+  return 1;
+}
+
+/* Group all nodes belonging to STATE into several destinations.
+   Then for all destinations, set the nodes belonging to the destination
+   to DESTS_NODE[i] and set the characters accepted by the destination
+   to DEST_CH[i].  This function return the number of destinations.  */
+
+static int
+internal_function
+group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
+			    re_node_set *dests_node, bitset_t *dests_ch)
+{
+  reg_errcode_t err;
+  int result;
+  int i, j, k;
+  int ndests; /* Number of the destinations from `state'.  */
+  bitset_t accepts; /* Characters a node can accept.  */
+  const re_node_set *cur_nodes = &state->nodes;
+  bitset_empty (accepts);
+  ndests = 0;
+
+  /* For all the nodes belonging to `state',  */
+  for (i = 0; i < cur_nodes->nelem; ++i)
+    {
+      re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];
+      re_token_type_t type = node->type;
+      unsigned int constraint = node->constraint;
+
+      /* Enumerate all single byte character this node can accept.  */
+      if (type == CHARACTER)
+	bitset_set (accepts, node->opr.c);
+      else if (type == SIMPLE_BRACKET)
+	{
+	  bitset_merge (accepts, node->opr.sbcset);
+	}
+      else if (type == OP_PERIOD)
+	{
+#ifdef RE_ENABLE_I18N
+	  if (dfa->mb_cur_max > 1)
+	    bitset_merge (accepts, dfa->sb_char);
+	  else
+#endif
+	    bitset_set_all (accepts);
+	  if (!(dfa->syntax & RE_DOT_NEWLINE))
+	    bitset_clear (accepts, '\n');
+	  if (dfa->syntax & RE_DOT_NOT_NULL)
+	    bitset_clear (accepts, '\0');
+	}
+#ifdef RE_ENABLE_I18N
+      else if (type == OP_UTF8_PERIOD)
+        {
+	  memset (accepts, '\xff', sizeof (bitset_t) / 2);
+	  if (!(dfa->syntax & RE_DOT_NEWLINE))
+	    bitset_clear (accepts, '\n');
+	  if (dfa->syntax & RE_DOT_NOT_NULL)
+	    bitset_clear (accepts, '\0');
+        }
+#endif
+      else
+	continue;
+
+      /* Check the `accepts' and sift the characters which are not
+	 match it the context.  */
+      if (constraint)
+	{
+	  if (constraint & NEXT_NEWLINE_CONSTRAINT)
+	    {
+	      bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR);
+	      bitset_empty (accepts);
+	      if (accepts_newline)
+		bitset_set (accepts, NEWLINE_CHAR);
+	      else
+		continue;
+	    }
+	  if (constraint & NEXT_ENDBUF_CONSTRAINT)
+	    {
+	      bitset_empty (accepts);
+	      continue;
+	    }
+
+	  if (constraint & NEXT_WORD_CONSTRAINT)
+	    {
+	      bitset_word_t any_set = 0;
+	      if (type == CHARACTER && !node->word_char)
+		{
+		  bitset_empty (accepts);
+		  continue;
+		}
+#ifdef RE_ENABLE_I18N
+	      if (dfa->mb_cur_max > 1)
+		for (j = 0; j < BITSET_WORDS; ++j)
+		  any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
+	      else
+#endif
+		for (j = 0; j < BITSET_WORDS; ++j)
+		  any_set |= (accepts[j] &= dfa->word_char[j]);
+	      if (!any_set)
+		continue;
+	    }
+	  if (constraint & NEXT_NOTWORD_CONSTRAINT)
+	    {
+	      bitset_word_t any_set = 0;
+	      if (type == CHARACTER && node->word_char)
+		{
+		  bitset_empty (accepts);
+		  continue;
+		}
+#ifdef RE_ENABLE_I18N
+	      if (dfa->mb_cur_max > 1)
+		for (j = 0; j < BITSET_WORDS; ++j)
+		  any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
+	      else
+#endif
+		for (j = 0; j < BITSET_WORDS; ++j)
+		  any_set |= (accepts[j] &= ~dfa->word_char[j]);
+	      if (!any_set)
+		continue;
+	    }
+	}
+
+      /* Then divide `accepts' into DFA states, or create a new
+	 state.  Above, we make sure that accepts is not empty.  */
+      for (j = 0; j < ndests; ++j)
+	{
+	  bitset_t intersec; /* Intersection sets, see below.  */
+	  bitset_t remains;
+	  /* Flags, see below.  */
+	  bitset_word_t has_intersec, not_subset, not_consumed;
+
+	  /* Optimization, skip if this state doesn't accept the character.  */
+	  if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))
+	    continue;
+
+	  /* Enumerate the intersection set of this state and `accepts'.  */
+	  has_intersec = 0;
+	  for (k = 0; k < BITSET_WORDS; ++k)
+	    has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];
+	  /* And skip if the intersection set is empty.  */
+	  if (!has_intersec)
+	    continue;
+
+	  /* Then check if this state is a subset of `accepts'.  */
+	  not_subset = not_consumed = 0;
+	  for (k = 0; k < BITSET_WORDS; ++k)
+	    {
+	      not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k];
+	      not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];
+	    }
+
+	  /* If this state isn't a subset of `accepts', create a
+	     new group state, which has the `remains'. */
+	  if (not_subset)
+	    {
+	      bitset_copy (dests_ch[ndests], remains);
+	      bitset_copy (dests_ch[j], intersec);
+	      err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]);
+	      if (BE (err != REG_NOERROR, 0))
+		goto error_return;
+	      ++ndests;
+	    }
+
+	  /* Put the position in the current group. */
+	  result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
+	  if (BE (result < 0, 0))
+	    goto error_return;
+
+	  /* If all characters are consumed, go to next node. */
+	  if (!not_consumed)
+	    break;
+	}
+      /* Some characters remain, create a new group. */
+      if (j == ndests)
+	{
+	  bitset_copy (dests_ch[ndests], accepts);
+	  err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]);
+	  if (BE (err != REG_NOERROR, 0))
+	    goto error_return;
+	  ++ndests;
+	  bitset_empty (accepts);
+	}
+    }
+  return ndests;
+ error_return:
+  for (j = 0; j < ndests; ++j)
+    re_node_set_free (dests_node + j);
+  return -1;
+}
+
+#ifdef RE_ENABLE_I18N
+/* Check how many bytes the node `dfa->nodes[node_idx]' accepts.
+   Return the number of the bytes the node accepts.
+   STR_IDX is the current index of the input string.
+
+   This function handles the nodes which can accept one character, or
+   one collating element like '.', '[a-z]', opposite to the other nodes
+   can only accept one byte.  */
+
+static int
+internal_function
+check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
+			 const re_string_t *input, int str_idx)
+{
+  const re_token_t *node = dfa->nodes + node_idx;
+  int char_len, elem_len;
+  int i;
+
+  if (BE (node->type == OP_UTF8_PERIOD, 0))
+    {
+      unsigned char c = re_string_byte_at (input, str_idx), d;
+      if (BE (c < 0xc2, 1))
+	return 0;
+
+      if (str_idx + 2 > input->len)
+	return 0;
+
+      d = re_string_byte_at (input, str_idx + 1);
+      if (c < 0xe0)
+	return (d < 0x80 || d > 0xbf) ? 0 : 2;
+      else if (c < 0xf0)
+	{
+	  char_len = 3;
+	  if (c == 0xe0 && d < 0xa0)
+	    return 0;
+	}
+      else if (c < 0xf8)
+	{
+	  char_len = 4;
+	  if (c == 0xf0 && d < 0x90)
+	    return 0;
+	}
+      else if (c < 0xfc)
+	{
+	  char_len = 5;
+	  if (c == 0xf8 && d < 0x88)
+	    return 0;
+	}
+      else if (c < 0xfe)
+	{
+	  char_len = 6;
+	  if (c == 0xfc && d < 0x84)
+	    return 0;
+	}
+      else
+	return 0;
+
+      if (str_idx + char_len > input->len)
+	return 0;
+
+      for (i = 1; i < char_len; ++i)
+	{
+	  d = re_string_byte_at (input, str_idx + i);
+	  if (d < 0x80 || d > 0xbf)
+	    return 0;
+	}
+      return char_len;
+    }
+
+  char_len = re_string_char_size_at (input, str_idx);
+  if (node->type == OP_PERIOD)
+    {
+      if (char_len <= 1)
+        return 0;
+      /* FIXME: I don't think this if is needed, as both '\n'
+	 and '\0' are char_len == 1.  */
+      /* '.' accepts any one character except the following two cases.  */
+      if ((!(dfa->syntax & RE_DOT_NEWLINE) &&
+	   re_string_byte_at (input, str_idx) == '\n') ||
+	  ((dfa->syntax & RE_DOT_NOT_NULL) &&
+	   re_string_byte_at (input, str_idx) == '\0'))
+	return 0;
+      return char_len;
+    }
+
+  elem_len = re_string_elem_size_at (input, str_idx);
+  if ((elem_len <= 1 && char_len <= 1) || char_len == 0)
+    return 0;
+
+  if (node->type == COMPLEX_BRACKET)
+    {
+      const re_charset_t *cset = node->opr.mbcset;
+# if 0
+      const unsigned char *pin
+	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
+      int j;
+      uint32_t nrules;
+# endif
+      int match_len = 0;
+      wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
+		    ? re_string_wchar_at (input, str_idx) : 0);
+
+      /* match with multibyte character?  */
+      for (i = 0; i < cset->nmbchars; ++i)
+	if (wc == cset->mbchars[i])
+	  {
+	    match_len = char_len;
+	    goto check_node_accept_bytes_match;
+	  }
+      /* match with character_class?  */
+      for (i = 0; i < cset->nchar_classes; ++i)
+	{
+	  wctype_t wt = cset->char_classes[i];
+	  if (__iswctype (wc, wt))
+	    {
+	      match_len = char_len;
+	      goto check_node_accept_bytes_match;
+	    }
+	}
+
+# if 0
+      nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+      if (nrules != 0)
+	{
+	  unsigned int in_collseq = 0;
+	  const int32_t *table, *indirect;
+	  const unsigned char *weights, *extra;
+	  const char *collseqwc;
+	  int32_t idx;
+	  /* This #include defines a local function!  */
+#  include <locale/weight.h>
+
+	  /* match with collating_symbol?  */
+	  if (cset->ncoll_syms)
+	    extra = (const unsigned char *)
+	      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+	  for (i = 0; i < cset->ncoll_syms; ++i)
+	    {
+	      const unsigned char *coll_sym = extra + cset->coll_syms[i];
+	      /* Compare the length of input collating element and
+		 the length of current collating element.  */
+	      if (*coll_sym != elem_len)
+		continue;
+	      /* Compare each bytes.  */
+	      for (j = 0; j < *coll_sym; j++)
+		if (pin[j] != coll_sym[1 + j])
+		  break;
+	      if (j == *coll_sym)
+		{
+		  /* Match if every bytes is equal.  */
+		  match_len = j;
+		  goto check_node_accept_bytes_match;
+		}
+	    }
+
+	  if (cset->nranges)
+	    {
+	      if (elem_len <= char_len)
+		{
+		  collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+		  in_collseq = __collseq_table_lookup (collseqwc, wc);
+		}
+	      else
+		in_collseq = find_collation_sequence_value (pin, elem_len);
+	    }
+	  /* match with range expression?  */
+	  for (i = 0; i < cset->nranges; ++i)
+	    if (cset->range_starts[i] <= in_collseq
+		&& in_collseq <= cset->range_ends[i])
+	      {
+		match_len = elem_len;
+		goto check_node_accept_bytes_match;
+	      }
+
+	  /* match with equivalence_class?  */
+	  if (cset->nequiv_classes)
+	    {
+	      const unsigned char *cp = pin;
+	      table = (const int32_t *)
+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+	      weights = (const unsigned char *)
+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+	      extra = (const unsigned char *)
+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+	      indirect = (const int32_t *)
+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+	      idx = findidx (&cp);
+	      if (idx > 0)
+		for (i = 0; i < cset->nequiv_classes; ++i)
+		  {
+		    int32_t equiv_class_idx = cset->equiv_classes[i];
+		    size_t weight_len = weights[idx];
+		    if (weight_len == weights[equiv_class_idx])
+		      {
+			int cnt = 0;
+			while (cnt <= weight_len
+			       && (weights[equiv_class_idx + 1 + cnt]
+				   == weights[idx + 1 + cnt]))
+			  ++cnt;
+			if (cnt > weight_len)
+			  {
+			    match_len = elem_len;
+			    goto check_node_accept_bytes_match;
+			  }
+		      }
+		  }
+	    }
+	}
+      else
+# endif
+	{
+	  /* match with range expression?  */
+	  wchar_t cmp_buf[6];
+
+	  memset (cmp_buf, 0, sizeof(cmp_buf));
+	  cmp_buf[2] = wc;
+	  for (i = 0; i < cset->nranges; ++i)
+	    {
+	      cmp_buf[0] = cset->range_starts[i];
+	      cmp_buf[4] = cset->range_ends[i];
+	      if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
+		  && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
+		{
+		  match_len = char_len;
+		  goto check_node_accept_bytes_match;
+		}
+	    }
+	}
+
+ check_node_accept_bytes_match:
+      if (!cset->non_match)
+	return match_len;
+      if (match_len > 0)
+	return 0;
+      return (elem_len > char_len) ? elem_len : char_len;
+    }
+  return 0;
+}
+
+# if 0
+static unsigned int
+internal_function
+find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
+{
+  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules == 0)
+    {
+      if (mbs_len == 1)
+	{
+	  /* No valid character.  Match it as a single byte character.  */
+	  const unsigned char *collseq = (const unsigned char *)
+	    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+	  return collseq[mbs[0]];
+	}
+      return UINT_MAX;
+    }
+  else
+    {
+      int32_t idx;
+      const unsigned char *extra = (const unsigned char *)
+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+      int32_t extrasize = (const unsigned char *)
+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra;
+
+      for (idx = 0; idx < extrasize;)
+	{
+	  int mbs_cnt, found = 0;
+	  int32_t elem_mbs_len;
+	  /* Skip the name of collating element name.  */
+	  idx = idx + extra[idx] + 1;
+	  elem_mbs_len = extra[idx++];
+	  if (mbs_len == elem_mbs_len)
+	    {
+	      for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt)
+		if (extra[idx + mbs_cnt] != mbs[mbs_cnt])
+		  break;
+	      if (mbs_cnt == elem_mbs_len)
+		/* Found the entry.  */
+		found = 1;
+	    }
+	  /* Skip the byte sequence of the collating element.  */
+	  idx += elem_mbs_len;
+	  /* Adjust for the alignment.  */
+	  idx = (idx + 3) & ~3;
+	  /* Skip the collation sequence value.  */
+	  idx += sizeof (uint32_t);
+	  /* Skip the wide char sequence of the collating element.  */
+	  idx = idx + sizeof (uint32_t) * (extra[idx] + 1);
+	  /* If we found the entry, return the sequence value.  */
+	  if (found)
+	    return *(uint32_t *) (extra + idx);
+	  /* Skip the collation sequence value.  */
+	  idx += sizeof (uint32_t);
+	}
+      return UINT_MAX;
+    }
+}
+# endif
+#endif /* RE_ENABLE_I18N */
+
+/* Check whether the node accepts the byte which is IDX-th
+   byte of the INPUT.  */
+
+static int
+internal_function
+check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
+		   int idx)
+{
+  unsigned char ch;
+  ch = re_string_byte_at (&mctx->input, idx);
+  switch (node->type)
+    {
+    case CHARACTER:
+      if (node->opr.c != ch)
+        return 0;
+      break;
+
+    case SIMPLE_BRACKET:
+      if (!bitset_contain (node->opr.sbcset, ch))
+        return 0;
+      break;
+
+#ifdef RE_ENABLE_I18N
+    case OP_UTF8_PERIOD:
+      if (ch >= 0x80)
+        return 0;
+      /* FALLTHROUGH */
+#endif
+    case OP_PERIOD:
+      if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE))
+	  || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL)))
+	return 0;
+      break;
+
+    default:
+      return 0;
+    }
+
+  if (node->constraint)
+    {
+      /* The node has constraints.  Check whether the current context
+	 satisfies the constraints.  */
+      unsigned int context = re_string_context_at (&mctx->input, idx,
+						   mctx->eflags);
+      if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
+	return 0;
+    }
+
+  return 1;
+}
+
+/* Extend the buffers, if the buffers have run out.  */
+
+static reg_errcode_t
+internal_function
+extend_buffers (re_match_context_t *mctx)
+{
+  reg_errcode_t ret;
+  re_string_t *pstr = &mctx->input;
+
+  /* Double the lengthes of the buffers.  */
+  ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+
+  if (mctx->state_log != NULL)
+    {
+      /* And double the length of state_log.  */
+      /* XXX We have no indication of the size of this buffer.  If this
+	 allocation fail we have no indication that the state_log array
+	 does not have the right size.  */
+      re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *,
+					      pstr->bufs_len + 1);
+      if (BE (new_array == NULL, 0))
+	return REG_ESPACE;
+      mctx->state_log = new_array;
+    }
+
+  /* Then reconstruct the buffers.  */
+  if (pstr->icase)
+    {
+#ifdef RE_ENABLE_I18N
+      if (pstr->mb_cur_max > 1)
+	{
+	  ret = build_wcs_upper_buffer (pstr);
+	  if (BE (ret != REG_NOERROR, 0))
+	    return ret;
+	}
+      else
+#endif /* RE_ENABLE_I18N  */
+	build_upper_buffer (pstr);
+    }
+  else
+    {
+#ifdef RE_ENABLE_I18N
+      if (pstr->mb_cur_max > 1)
+	build_wcs_buffer (pstr);
+      else
+#endif /* RE_ENABLE_I18N  */
+	{
+	  if (pstr->trans != NULL)
+	    re_string_translate_buffer (pstr);
+	}
+    }
+  return REG_NOERROR;
+}
+
+
+/* Functions for matching context.  */
+
+/* Initialize MCTX.  */
+
+static reg_errcode_t
+internal_function
+match_ctx_init (re_match_context_t *mctx, int eflags, int n)
+{
+  mctx->eflags = eflags;
+  mctx->match_last = -1;
+  if (n > 0)
+    {
+      mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
+      mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);
+      if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0))
+	return REG_ESPACE;
+    }
+  /* Already zero-ed by the caller.
+     else
+       mctx->bkref_ents = NULL;
+     mctx->nbkref_ents = 0;
+     mctx->nsub_tops = 0;  */
+  mctx->abkref_ents = n;
+  mctx->max_mb_elem_len = 1;
+  mctx->asub_tops = n;
+  return REG_NOERROR;
+}
+
+/* Clean the entries which depend on the current input in MCTX.
+   This function must be invoked when the matcher changes the start index
+   of the input, or changes the input string.  */
+
+static void
+internal_function
+match_ctx_clean (re_match_context_t *mctx)
+{
+  int st_idx;
+  for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx)
+    {
+      int sl_idx;
+      re_sub_match_top_t *top = mctx->sub_tops[st_idx];
+      for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx)
+	{
+	  re_sub_match_last_t *last = top->lasts[sl_idx];
+	  re_free (last->path.array);
+	  re_free (last);
+	}
+      re_free (top->lasts);
+      if (top->path)
+	{
+	  re_free (top->path->array);
+	  re_free (top->path);
+	}
+      free (top);
+    }
+
+  mctx->nsub_tops = 0;
+  mctx->nbkref_ents = 0;
+}
+
+/* Free all the memory associated with MCTX.  */
+
+static void
+internal_function
+match_ctx_free (re_match_context_t *mctx)
+{
+  /* First, free all the memory associated with MCTX->SUB_TOPS.  */
+  match_ctx_clean (mctx);
+  re_free (mctx->sub_tops);
+  re_free (mctx->bkref_ents);
+}
+
+/* Add a new backreference entry to MCTX.
+   Note that we assume that caller never call this function with duplicate
+   entry, and call with STR_IDX which isn't smaller than any existing entry.
+*/
+
+static reg_errcode_t
+internal_function
+match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from,
+		     int to)
+{
+  if (mctx->nbkref_ents >= mctx->abkref_ents)
+    {
+      struct re_backref_cache_entry* new_entry;
+      new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,
+			      mctx->abkref_ents * 2);
+      if (BE (new_entry == NULL, 0))
+	{
+	  re_free (mctx->bkref_ents);
+	  return REG_ESPACE;
+	}
+      mctx->bkref_ents = new_entry;
+      memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
+	      sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
+      mctx->abkref_ents *= 2;
+    }
+  if (mctx->nbkref_ents > 0
+      && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx)
+    mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1;
+
+  mctx->bkref_ents[mctx->nbkref_ents].node = node;
+  mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx;
+  mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from;
+  mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to;
+
+  /* This is a cache that saves negative results of check_dst_limits_calc_pos.
+     If bit N is clear, means that this entry won't epsilon-transition to
+     an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression.  If
+     it is set, check_dst_limits_calc_pos_1 will recurse and try to find one
+     such node.
+
+     A backreference does not epsilon-transition unless it is empty, so set
+     to all zeros if FROM != TO.  */
+  mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map
+    = (from == to ? ~0 : 0);
+
+  mctx->bkref_ents[mctx->nbkref_ents++].more = 0;
+  if (mctx->max_mb_elem_len < to - from)
+    mctx->max_mb_elem_len = to - from;
+  return REG_NOERROR;
+}
+
+/* Search for the first entry which has the same str_idx, or -1 if none is
+   found.  Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX.  */
+
+static int
+internal_function
+search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
+{
+  int left, right, mid, last;
+  last = right = mctx->nbkref_ents;
+  for (left = 0; left < right;)
+    {
+      mid = (left + right) / 2;
+      if (mctx->bkref_ents[mid].str_idx < str_idx)
+	left = mid + 1;
+      else
+	right = mid;
+    }
+  if (left < last && mctx->bkref_ents[left].str_idx == str_idx)
+    return left;
+  else
+    return -1;
+}
+
+/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches
+   at STR_IDX.  */
+
+static reg_errcode_t
+internal_function
+match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)
+{
+#ifdef DEBUG
+  assert (mctx->sub_tops != NULL);
+  assert (mctx->asub_tops > 0);
+#endif
+  if (BE (mctx->nsub_tops == mctx->asub_tops, 0))
+    {
+      int new_asub_tops = mctx->asub_tops * 2;
+      re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops,
+						   re_sub_match_top_t *,
+						   new_asub_tops);
+      if (BE (new_array == NULL, 0))
+	return REG_ESPACE;
+      mctx->sub_tops = new_array;
+      mctx->asub_tops = new_asub_tops;
+    }
+  mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t));
+  if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0))
+    return REG_ESPACE;
+  mctx->sub_tops[mctx->nsub_tops]->node = node;
+  mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx;
+  return REG_NOERROR;
+}
+
+/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches
+   at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP.  */
+
+static re_sub_match_last_t *
+internal_function
+match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx)
+{
+  re_sub_match_last_t *new_entry;
+  if (BE (subtop->nlasts == subtop->alasts, 0))
+    {
+      int new_alasts = 2 * subtop->alasts + 1;
+      re_sub_match_last_t **new_array = re_realloc (subtop->lasts,
+						    re_sub_match_last_t *,
+						    new_alasts);
+      if (BE (new_array == NULL, 0))
+	return NULL;
+      subtop->lasts = new_array;
+      subtop->alasts = new_alasts;
+    }
+  new_entry = calloc (1, sizeof (re_sub_match_last_t));
+  if (BE (new_entry != NULL, 1))
+    {
+      subtop->lasts[subtop->nlasts] = new_entry;
+      new_entry->node = node;
+      new_entry->str_idx = str_idx;
+      ++subtop->nlasts;
+    }
+  return new_entry;
+}
+
+static void
+internal_function
+sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
+	       re_dfastate_t **limited_sts, int last_node, int last_str_idx)
+{
+  sctx->sifted_states = sifted_sts;
+  sctx->limited_states = limited_sts;
+  sctx->last_node = last_node;
+  sctx->last_str_idx = last_str_idx;
+  re_node_set_init_empty (&sctx->limits);
+}
diff --git a/ap/build/uClibc/libc/misc/search/Makefile b/ap/build/uClibc/libc/misc/search/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/search/Makefile.in b/ap/build/uClibc/libc/misc/search/Makefile.in
new file mode 100644
index 0000000..35dacb4
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/Makefile.in
@@ -0,0 +1,35 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/search
+
+CSRC := hsearch.c
+
+# multi source _tsearch.c
+CSRC += tsearch.c tfind.c tdelete.c twalk.c tdestroy.c
+
+# multi source _lsearch.c
+CSRC += lfind.c lsearch.c
+
+# multi source insremque.c
+CSRC += insque.c remque.c
+
+# multi source _hsearch_r.c
+CSRC += hcreate_r.c hdestroy_r.c hsearch_r.c
+
+MISC_SEARCH_DIR := $(top_srcdir)libc/misc/search
+MISC_SEARCH_OUT := $(top_builddir)libc/misc/search
+
+MISC_SEARCH_SRC := $(patsubst %.c,$(MISC_SEARCH_DIR)/%.c,$(CSRC))
+MISC_SEARCH_OBJ := $(patsubst %.c,$(MISC_SEARCH_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_SEARCH_OBJ)
+
+objclean-y += CLEAN_libc/misc/search
+
+CLEAN_libc/misc/search:
+	$(do_rm) $(addprefix $(MISC_SEARCH_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/search/_hsearch_r.c b/ap/build/uClibc/libc/misc/search/_hsearch_r.c
new file mode 100644
index 0000000..bfe3efe
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/_hsearch_r.c
@@ -0,0 +1,226 @@
+/* Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1993.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+
+#include <search.h>
+
+
+/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
+   [Knuth]            The Art of Computer Programming, part 3 (6.4)  */
+
+
+/* The reentrant version has no static variables to maintain the state.
+   Instead the interface of all functions is extended to take an argument
+   which describes the current status.  */
+typedef struct _ENTRY
+{
+  unsigned int used;
+  ENTRY entry;
+}
+_ENTRY;
+
+
+#ifdef L_hcreate_r
+
+/* For the used double hash method the table size has to be a prime. To
+   correct the user given table size we need a prime test.  This trivial
+   algorithm is adequate because
+   a)  the code is (most probably) called a few times per program run and
+   b)  the number is small because the table must fit in the core  */
+static int isprime (unsigned int number)
+{
+  /* no even number will be passed */
+  unsigned int divisor = 3;
+
+  while (divisor * divisor < number && number % divisor != 0)
+    divisor += 2;
+
+  return number % divisor != 0;
+}
+
+
+/* Before using the hash table we must allocate memory for it.
+   Test for an existing table are done. We allocate one element
+   more as the found prime number says. This is done for more effective
+   indexing as explained in the comment for the hsearch function.
+   The contents of the table is zeroed, especially the field used
+   becomes zero.  */
+int hcreate_r (size_t nel, struct hsearch_data *htab)
+{
+  /* Test for correct arguments.  */
+  if (htab == NULL)
+    {
+      __set_errno (EINVAL);
+      return 0;
+    }
+
+  /* There is still another table active. Return with error. */
+  if (htab->table != NULL)
+    return 0;
+
+  /* Change nel to the first prime number not smaller as nel. */
+  nel |= 1;      /* make odd */
+  while (!isprime (nel))
+    nel += 2;
+
+  htab->size = nel;
+  htab->filled = 0;
+
+  /* allocate memory and zero out */
+  htab->table = (_ENTRY *) calloc (htab->size + 1, sizeof (_ENTRY));
+  if (htab->table == NULL)
+    return 0;
+
+  /* everything went alright */
+  return 1;
+}
+libc_hidden_def(hcreate_r)
+#endif
+
+#ifdef L_hdestroy_r
+/* After using the hash table it has to be destroyed. The used memory can
+   be freed and the local static variable can be marked as not used.  */
+void hdestroy_r (struct hsearch_data *htab)
+{
+  /* Test for correct arguments.  */
+  if (htab == NULL)
+    {
+      __set_errno (EINVAL);
+      return;
+    }
+
+  /* free used memory */
+  free (htab->table);
+
+  /* the sign for an existing table is an value != NULL in htable */
+  htab->table = NULL;
+}
+libc_hidden_def(hdestroy_r)
+#endif
+
+#ifdef L_hsearch_r
+/* This is the search function. It uses double hashing with open addressing.
+   The argument item.key has to be a pointer to an zero terminated, most
+   probably strings of chars. The function for generating a number of the
+   strings is simple but fast. It can be replaced by a more complex function
+   like ajw (see [Aho,Sethi,Ullman]) if the needs are shown.
+
+   We use an trick to speed up the lookup. The table is created by hcreate
+   with one more element available. This enables us to use the index zero
+   special. This index will never be used because we store the first hash
+   index in the field used where zero means not used. Every other value
+   means used. The used field can be used as a first fast comparison for
+   equality of the stored and the parameter value. This helps to prevent
+   unnecessary expensive calls of strcmp.  */
+
+
+int hsearch_r (ENTRY item, ACTION action, ENTRY **retval,
+	       struct hsearch_data *htab)
+{
+  unsigned int hval;
+  unsigned int count;
+  unsigned int len = strlen (item.key);
+  unsigned int idx;
+
+  /* Compute an value for the given string. Perhaps use a better method. */
+  hval = len;
+  count = len;
+  while (count-- > 0)
+    {
+      hval <<= 4;
+      hval += item.key[count];
+    }
+
+  /* First hash function: simply take the modul but prevent zero. */
+  hval %= htab->size;
+  if (hval == 0)
+    ++hval;
+
+  /* The first index tried. */
+  idx = hval;
+
+  if (htab->table[idx].used)
+    {
+      /* Further action might be required according to the action value. */
+      unsigned hval2;
+
+      if (htab->table[idx].used == hval
+	  && strcmp (item.key, htab->table[idx].entry.key) == 0)
+	{
+	  *retval = &htab->table[idx].entry;
+	  return 1;
+	}
+
+      /* Second hash function, as suggested in [Knuth] */
+      hval2 = 1 + hval % (htab->size - 2);
+
+      do
+	{
+	  /* Because SIZE is prime this guarantees to step through all
+             available indeces.  */
+          if (idx <= hval2)
+	    idx = htab->size + idx - hval2;
+	  else
+	    idx -= hval2;
+
+	  /* If we visited all entries leave the loop unsuccessfully.  */
+	  if (idx == hval)
+	    break;
+
+            /* If entry is found use it. */
+          if (htab->table[idx].used == hval
+	      && strcmp (item.key, htab->table[idx].entry.key) == 0)
+	    {
+	      *retval = &htab->table[idx].entry;
+	      return 1;
+	    }
+	}
+      while (htab->table[idx].used);
+    }
+
+  /* An empty bucket has been found. */
+  if (action == ENTER)
+    {
+      /* If table is full and another entry should be entered return
+	 with error.  */
+      if (htab->filled == htab->size)
+	{
+	  __set_errno (ENOMEM);
+	  *retval = NULL;
+	  return 0;
+	}
+
+      htab->table[idx].used  = hval;
+      htab->table[idx].entry = item;
+
+      ++htab->filled;
+
+      *retval = &htab->table[idx].entry;
+      return 1;
+    }
+
+  __set_errno (ESRCH);
+  *retval = NULL;
+  return 0;
+}
+libc_hidden_def(hsearch_r)
+#endif
diff --git a/ap/build/uClibc/libc/misc/search/_lsearch.c b/ap/build/uClibc/libc/misc/search/_lsearch.c
new file mode 100644
index 0000000..0cf496e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/_lsearch.c
@@ -0,0 +1,49 @@
+/*
+ * This file lifted in toto from 'Dlibs' on the atari ST  (RdeBath)
+ *
+ *
+ *    Dale Schumacher                         399 Beacon Ave.
+ *    (alias: Dalnefre')                      St. Paul, MN  55104
+ *    dal@syntel.UUCP                         United States of America
+ *  "It's not reality that's important, but how you perceive things."
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <search.h>
+
+
+#ifdef L_lfind
+
+void *lfind(const void *key, const void *base, size_t *nmemb,
+	size_t size, int (*compar)(const void *, const void *))
+{
+	register int n = *nmemb;
+
+	while (n--) {
+		if ((*compar) (key, base) == 0)
+			return ((void*)base);
+		base += size;
+	}
+	return (NULL);
+}
+libc_hidden_def(lfind)
+
+#endif
+
+#ifdef L_lsearch
+
+
+void *lsearch(const void *key, void *base, size_t *nmemb,
+	size_t size, int (*compar)(const void *, const void *))
+{
+	register char *p;
+
+	if ((p = lfind(key, base, nmemb, size, compar)) == NULL) {
+		p = memcpy((base + (size * (*nmemb))), key, size);
+		++(*nmemb);
+	}
+	return (p);
+}
+
+#endif
diff --git a/ap/build/uClibc/libc/misc/search/_tsearch.c b/ap/build/uClibc/libc/misc/search/_tsearch.c
new file mode 100644
index 0000000..20b04af
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/_tsearch.c
@@ -0,0 +1,220 @@
+/* Copyright (C) 1994 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+/*LINTLIBRARY*/
+
+#include <search.h>
+#include <stdlib.h>
+
+/* This routine is not very bad. It makes many assumptions about
+ * the compiler. It assumpts that the first field in node must be
+ * the "key" field, which points to the datum. It is a very trick
+ * stuff. H.J.
+ */
+
+typedef struct node_t
+{
+    void	*key;
+    struct node_t *left, *right;
+} node;
+
+#ifdef L_tsearch
+/* find or insert datum into search tree.
+char 	*key;			 key to be located
+register node	**rootp;	 address of tree root
+int	(*compar)();		 ordering function
+*/
+
+void *tsearch(__const void *key, void **vrootp, __compar_fn_t compar)
+{
+    register node *q;
+    register node **rootp = (node **) vrootp;
+
+    if (rootp == (struct node_t **)0)
+	return ((struct node_t *)0);
+    while (*rootp != (struct node_t *)0)	/* Knuth's T1: */
+    {
+	int r;
+
+	if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
+	    return (*rootp);		/* we found it! */
+	rootp = (r < 0) ?
+	    &(*rootp)->left :		/* T3: follow left branch */
+	    &(*rootp)->right;		/* T4: follow right branch */
+    }
+    q = (node *) malloc(sizeof(node));	/* T5: key not found */
+    if (q != (struct node_t *)0)	/* make new node */
+    {
+	*rootp = q;			/* link new node to old */
+	q->key = (void *)key;			/* initialize new node */
+	q->left = q->right = (struct node_t *)0;
+    }
+    return (q);
+}
+libc_hidden_def(tsearch)
+#endif
+
+#ifdef L_tfind
+void *tfind(__const void *key, void * __const *vrootp, __compar_fn_t compar)
+{
+    register node **rootp = (node **) vrootp;
+
+    if (rootp == (struct node_t **)0)
+	return ((struct node_t *)0);
+    while (*rootp != (struct node_t *)0)	/* Knuth's T1: */
+    {
+	int r;
+
+	if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
+	    return (*rootp);		/* we found it! */
+	rootp = (r < 0) ?
+	    &(*rootp)->left :		/* T3: follow left branch */
+	    &(*rootp)->right;		/* T4: follow right branch */
+    }
+    return NULL;
+}
+libc_hidden_def(tfind)
+#endif
+
+#ifdef L_tdelete
+/* delete node with given key
+char	*key;			key to be deleted
+register node	**rootp;	address of the root of tree
+int	(*compar)();		comparison function
+*/
+void *tdelete(__const void *key, void ** vrootp, __compar_fn_t compar)
+{
+    node *p;
+    register node *q;
+    register node *r;
+    int cmp;
+    register node **rootp = (node **) vrootp;
+
+    if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0)
+	return ((struct node_t *)0);
+    while ((cmp = (*compar)(key, (*rootp)->key)) != 0)
+    {
+	p = *rootp;
+	rootp = (cmp < 0) ?
+	    &(*rootp)->left :		/* follow left branch */
+	    &(*rootp)->right;		/* follow right branch */
+	if (*rootp == (struct node_t *)0)
+	    return ((struct node_t *)0);	/* key not found */
+    }
+    r = (*rootp)->right;			/* D1: */
+    if ((q = (*rootp)->left) == (struct node_t *)0)	/* Left (struct node_t *)0? */
+	q = r;
+    else if (r != (struct node_t *)0)		/* Right link is null? */
+    {
+	if (r->left == (struct node_t *)0)	/* D2: Find successor */
+	{
+	    r->left = q;
+	    q = r;
+	}
+	else
+	{			/* D3: Find (struct node_t *)0 link */
+	    for (q = r->left; q->left != (struct node_t *)0; q = r->left)
+		r = q;
+	    r->left = q->right;
+	    q->left = (*rootp)->left;
+	    q->right = (*rootp)->right;
+	}
+    }
+    free((struct node_t *) *rootp);	/* D4: Free node */
+    *rootp = q;				/* link parent to new node */
+    return(p);
+}
+#endif
+
+#ifdef L_twalk
+/* Walk the nodes of a tree
+register node	*root;		Root of the tree to be walked
+register void	(*action)();	Function to be called at each node
+register int	level;
+*/
+static void trecurse(__const void *vroot, __action_fn_t action, int level)
+{
+    register node *root = (node *) vroot;
+
+    if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
+	(*action)(root, leaf, level);
+    else
+    {
+	(*action)(root, preorder, level);
+	if (root->left != (struct node_t *)0)
+	    trecurse(root->left, action, level + 1);
+	(*action)(root, postorder, level);
+	if (root->right != (struct node_t *)0)
+	    trecurse(root->right, action, level + 1);
+	(*action)(root, endorder, level);
+    }
+}
+
+/* void twalk(root, action)		Walk the nodes of a tree
+node	*root;			Root of the tree to be walked
+void	(*action)();		Function to be called at each node
+PTR
+*/
+void twalk(__const void *vroot, __action_fn_t action)
+{
+    register __const node *root = (node *) vroot;
+
+    if (root != (node *)0 && action != (__action_fn_t) 0)
+	trecurse(root, action, 0);
+}
+#endif
+
+#ifdef __USE_GNU
+#ifdef L_tdestroy
+/* The standardized functions miss an important functionality: the
+   tree cannot be removed easily.  We provide a function to do this.  */
+static void
+internal_function
+tdestroy_recurse (node *root, __free_fn_t freefct)
+{
+    if (root->left != NULL)
+	tdestroy_recurse (root->left, freefct);
+    if (root->right != NULL)
+	tdestroy_recurse (root->right, freefct);
+    (*freefct) ((void *) root->key);
+    /* Free the node itself.  */
+    free (root);
+}
+
+void tdestroy (void *vroot, __free_fn_t freefct)
+{
+    node *root = (node *) vroot;
+    if (root != NULL) {
+	tdestroy_recurse (root, freefct);
+    }
+}
+libc_hidden_def(tdestroy)
+#endif
+#endif
+
+/* tsearch.c ends here */
diff --git a/ap/build/uClibc/libc/misc/search/hcreate_r.c b/ap/build/uClibc/libc/misc/search/hcreate_r.c
new file mode 100644
index 0000000..b62991e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/hcreate_r.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_hcreate_r
+#include "_hsearch_r.c"
diff --git a/ap/build/uClibc/libc/misc/search/hdestroy_r.c b/ap/build/uClibc/libc/misc/search/hdestroy_r.c
new file mode 100644
index 0000000..98e1ddb
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/hdestroy_r.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_hdestroy_r
+#include "_hsearch_r.c"
diff --git a/ap/build/uClibc/libc/misc/search/hsearch.c b/ap/build/uClibc/libc/misc/search/hsearch.c
new file mode 100644
index 0000000..d011997
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/hsearch.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <search.h>
+
+
+/* The non-reentrant version use a global space for storing the table.  */
+static struct hsearch_data htab;
+
+
+/* Define the non-reentrant function using the reentrant counterparts.  */
+ENTRY *hsearch (ENTRY item, ACTION action)
+{
+  ENTRY *result;
+
+  (void) hsearch_r (item, action, &result, &htab);
+
+  return result;
+}
+
+
+int hcreate (size_t nel)
+{
+  return hcreate_r (nel, &htab);
+}
+
+
+/* void __hdestroy (void) */
+void hdestroy (void)
+{
+  hdestroy_r (&htab);
+}
+
+/* Make sure the table is freed if we want to free everything before
+   exiting.  */
+/* text_set_element (__libc_subfreeres, __hdestroy); */
diff --git a/ap/build/uClibc/libc/misc/search/hsearch_r.c b/ap/build/uClibc/libc/misc/search/hsearch_r.c
new file mode 100644
index 0000000..48bdf2d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/hsearch_r.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_hsearch_r
+#include "_hsearch_r.c"
diff --git a/ap/build/uClibc/libc/misc/search/insque.c b/ap/build/uClibc/libc/misc/search/insque.c
new file mode 100644
index 0000000..fc5bf80
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/insque.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_insque
+#include "insremque.c"
diff --git a/ap/build/uClibc/libc/misc/search/insremque.c b/ap/build/uClibc/libc/misc/search/insremque.c
new file mode 100644
index 0000000..32edf7a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/insremque.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1992, 1995, 1996 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <features.h>
+#include <stddef.h>
+#include <search.h>
+
+#ifdef L_insque
+
+/* Insert ELEM into a doubly-linked list, after PREV.  */
+
+void
+insque (void *elem, void *prev)
+{
+  struct qelem *next = ((struct qelem *) prev)->q_forw;
+  ((struct qelem *) prev)->q_forw = (struct qelem *) elem;
+  if (next != NULL)
+    next->q_back = (struct qelem *) elem;
+  ((struct qelem *) elem)->q_forw = next;
+  ((struct qelem *) elem)->q_back = (struct qelem *) prev;
+}
+
+#endif
+
+#ifdef L_remque
+/* Unlink ELEM from the doubly-linked list that it is in.  */
+
+void
+remque (void *elem)
+{
+  struct qelem *next = ((struct qelem *) elem)->q_forw;
+  struct qelem *prev = ((struct qelem *) elem)->q_back;
+  if (next != NULL)
+    next->q_back = prev;
+  if (prev != NULL)
+    prev->q_forw = (struct qelem *) next;
+}
+
+#endif
diff --git a/ap/build/uClibc/libc/misc/search/lfind.c b/ap/build/uClibc/libc/misc/search/lfind.c
new file mode 100644
index 0000000..66111c5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/lfind.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_lfind
+#include "_lsearch.c"
diff --git a/ap/build/uClibc/libc/misc/search/lsearch.c b/ap/build/uClibc/libc/misc/search/lsearch.c
new file mode 100644
index 0000000..1e63297
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/lsearch.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_lsearch
+#include "_lsearch.c"
diff --git a/ap/build/uClibc/libc/misc/search/remque.c b/ap/build/uClibc/libc/misc/search/remque.c
new file mode 100644
index 0000000..bab6985
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/remque.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_remque
+#include "insremque.c"
diff --git a/ap/build/uClibc/libc/misc/search/tdelete.c b/ap/build/uClibc/libc/misc/search/tdelete.c
new file mode 100644
index 0000000..33d9fe8
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/tdelete.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_tdelete
+#include "_tsearch.c"
diff --git a/ap/build/uClibc/libc/misc/search/tdestroy.c b/ap/build/uClibc/libc/misc/search/tdestroy.c
new file mode 100644
index 0000000..3e397ea
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/tdestroy.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_tdestroy
+#include "_tsearch.c"
diff --git a/ap/build/uClibc/libc/misc/search/tfind.c b/ap/build/uClibc/libc/misc/search/tfind.c
new file mode 100644
index 0000000..e5a3161
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/tfind.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_tfind
+#include "_tsearch.c"
diff --git a/ap/build/uClibc/libc/misc/search/tsearch.c b/ap/build/uClibc/libc/misc/search/tsearch.c
new file mode 100644
index 0000000..8984fc1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/tsearch.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_tsearch
+#include "_tsearch.c"
diff --git a/ap/build/uClibc/libc/misc/search/twalk.c b/ap/build/uClibc/libc/misc/search/twalk.c
new file mode 100644
index 0000000..f36d341
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/search/twalk.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_twalk
+#include "_tsearch.c"
diff --git a/ap/build/uClibc/libc/misc/statfs/Makefile b/ap/build/uClibc/libc/misc/statfs/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/statfs/Makefile.in b/ap/build/uClibc/libc/misc/statfs/Makefile.in
new file mode 100644
index 0000000..aa92d1f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/Makefile.in
@@ -0,0 +1,31 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/statfs
+
+CSRC := statvfs.c fstatvfs.c
+ifeq ($(UCLIBC_HAS_LFS),y)
+ifeq ($(UCLIBC_LINUX_SPECIFIC),y)
+CSRC += fstatfs64.c statfs64.c
+endif
+CSRC += statvfs64.c fstatvfs64.c
+endif
+
+MISC_STATFS_DIR := $(top_srcdir)libc/misc/statfs
+MISC_STATFS_OUT := $(top_builddir)libc/misc/statfs
+
+MISC_STATFS_SRC := $(patsubst %.c,$(MISC_STATFS_DIR)/%.c,$(CSRC))
+MISC_STATFS_OBJ := $(patsubst %.c,$(MISC_STATFS_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_STATFS_OBJ)
+
+libc-nomulti-$(UCLIBC_HAS_LFS) += $(MISC_STATFS_OUT)/statvfs64.o $(MISC_STATFS_OUT)/fstatvfs64.o
+
+objclean-y += CLEAN_libc/misc/statfs
+
+CLEAN_libc/misc/statfs:
+	$(do_rm) $(addprefix $(MISC_STATFS_OUT)/*., o os oS)
diff --git a/ap/build/uClibc/libc/misc/statfs/fstatfs64.c b/ap/build/uClibc/libc/misc/statfs/fstatfs64.c
new file mode 100644
index 0000000..27bb8d6
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/fstatfs64.c
@@ -0,0 +1,51 @@
+/* Return information about the filesystem on which FD resides.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <_lfs_64.h>
+
+#include <errno.h>
+#include <string.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+#include <stddef.h>
+
+extern __typeof(fstatfs) __libc_fstatfs;
+
+/* Return information about the filesystem on which FD resides.  */
+int fstatfs64 (int fd, struct statfs64 *buf)
+{
+    struct statfs buf32;
+
+    if (__libc_fstatfs (fd, &buf32) < 0)
+	return -1;
+
+    buf->f_type = buf32.f_type;
+    buf->f_bsize = buf32.f_bsize;
+    buf->f_blocks = buf32.f_blocks;
+    buf->f_bfree = buf32.f_bfree;
+    buf->f_bavail = buf32.f_bavail;
+    buf->f_files = buf32.f_files;
+    buf->f_ffree = buf32.f_ffree;
+    buf->f_fsid = buf32.f_fsid;
+    buf->f_namelen = buf32.f_namelen;
+    memcpy (buf->f_spare, buf32.f_spare, sizeof (buf32.f_spare));
+
+    return 0;
+}
+libc_hidden_def(fstatfs64)
diff --git a/ap/build/uClibc/libc/misc/statfs/fstatvfs.c b/ap/build/uClibc/libc/misc/statfs/fstatvfs.c
new file mode 100644
index 0000000..63fce0f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/fstatvfs.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <features.h>
+#include <errno.h>
+#include <mntent.h>
+#include <paths.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+
+
+#ifndef __USE_FILE_OFFSET64
+extern int fstatfs (int __fildes, struct statfs *__buf)
+     __THROW __nonnull ((2));
+#else
+# ifdef __REDIRECT_NTH
+extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf),
+			   fstatfs64) __nonnull ((2));
+# else
+#  define fstatfs fstatfs64
+# endif
+#endif
+
+extern __typeof(fstatfs) __libc_fstatfs;
+
+int fstatvfs (int fd, struct statvfs *buf)
+{
+    struct statfs fsbuf;
+    struct stat st;
+
+    /* Get as much information as possible from the system.  */
+    if (__libc_fstatfs (fd, &fsbuf) < 0)
+	return -1;
+
+#define STAT(st) fstat (fd, st)
+#include "internal_statvfs.c"
+
+    /* We signal success if the statfs call succeeded.  */
+    return 0;
+}
+libc_hidden_def(fstatvfs)
diff --git a/ap/build/uClibc/libc/misc/statfs/fstatvfs64.c b/ap/build/uClibc/libc/misc/statfs/fstatvfs64.c
new file mode 100644
index 0000000..f57e9d9
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/fstatvfs64.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <_lfs_64.h>
+
+#include <errno.h>
+#include <mntent.h>
+#include <paths.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+
+
+#undef stat
+#define stat stat64
+
+int fstatvfs64 (int fd, struct statvfs64 *buf)
+{
+    struct statfs64 fsbuf;
+    struct stat64 st;
+#if !defined __UCLIBC_LINUX_SPECIFIC__
+    int ret;
+    struct statvfs buf32;
+
+    ret = fstatvfs (fd, &buf32);
+    if (ret == 0) {
+      fsbuf.f_bsize = buf32.f_bsize;
+      fsbuf.f_frsize = buf32.f_frsize;
+      fsbuf.f_blocks = buf32.f_blocks;
+      fsbuf.f_bfree = buf32.f_bfree;
+      fsbuf.f_bavail = buf32.f_bavail;
+      fsbuf.f_files = buf32.f_files;
+      fsbuf.f_ffree = buf32.f_ffree;
+      if (sizeof (fsbuf.f_fsid) == sizeof(buf32.f_fsid))
+	memcpy (&fsbuf.f_fsid, &buf32.f_fsid, sizeof(fsbuf.f_fsid));
+      /* and if not, then you could approximate or whatever.. */
+      fsbuf.f_namelen = buf32.f_namemax;
+    } else
+      return ret;
+#else
+    /* Get as much information as possible from the system.  */
+    if (fstatfs64 (fd, &fsbuf) < 0)
+	return -1;
+#endif
+#define STAT(st) fstat64 (fd, st)
+#include "internal_statvfs.c"
+
+    /* We signal success if the statfs call succeeded.  */
+    return 0;
+}
diff --git a/ap/build/uClibc/libc/misc/statfs/internal_statvfs.c b/ap/build/uClibc/libc/misc/statfs/internal_statvfs.c
new file mode 100644
index 0000000..6075e9c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/internal_statvfs.c
@@ -0,0 +1,111 @@
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+  /* Now fill in the fields we have information for.  */
+  buf->f_bsize = fsbuf.f_bsize;
+  /* Linux does not support f_frsize, so set it to the full block size.  */
+  buf->f_frsize = fsbuf.f_bsize;
+  buf->f_blocks = fsbuf.f_blocks;
+  buf->f_bfree = fsbuf.f_bfree;
+  buf->f_bavail = fsbuf.f_bavail;
+  buf->f_files = fsbuf.f_files;
+  buf->f_ffree = fsbuf.f_ffree;
+  if (sizeof (buf->f_fsid) == sizeof (fsbuf.f_fsid))
+    buf->f_fsid = (fsbuf.f_fsid.__val[0]
+		   | ((unsigned long int) fsbuf.f_fsid.__val[1]
+		      << (8 * (sizeof (buf->f_fsid)
+			       - sizeof (fsbuf.f_fsid.__val[0])))));
+  else
+    /* We cannot help here.  The statvfs element is not large enough to
+       contain both words of the statfs f_fsid field.  */
+    buf->f_fsid = fsbuf.f_fsid.__val[0];
+#ifdef _STATVFSBUF_F_UNUSED
+  buf->__f_unused = 0;
+#endif
+  buf->f_namemax = fsbuf.f_namelen;
+  memset (buf->__f_spare, '\0', 6 * sizeof (int));
+
+  /* What remains to do is to fill the fields f_favail and f_flag.  */
+
+  /* XXX I have no idea how to compute f_favail.  Any idea???  */
+  buf->f_favail = buf->f_ffree;
+
+  /* Determining the flags is tricky.  We have to read /proc/mounts or
+     the /etc/mtab file and search for the entry which matches the given
+     file.  The way we can test for matching filesystem is using the
+     device number.  */
+  buf->f_flag = 0;
+  if (STAT (&st) >= 0)
+    {
+      int save_errno = errno;
+      struct mntent mntbuf;
+      FILE *mtab;
+
+      mtab = setmntent ("/proc/mounts", "r");
+      if (mtab == NULL)
+	mtab = setmntent (_PATH_MOUNTED, "r");
+
+      if (mtab != NULL)
+	{
+	  char tmpbuf[1024];
+
+	  while (getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf)))
+	    {
+	      struct stat fsst;
+
+	      /* Find out about the device the current entry is for.  */
+	      if (stat (mntbuf.mnt_dir, &fsst) >= 0
+		  && st.st_dev == fsst.st_dev)
+		{
+		  /* Bingo, we found the entry for the device FD is on.
+		     Now interpret the option string.  */
+		  char *cp = mntbuf.mnt_opts;
+		  char *opt;
+
+		  while ((opt = strsep (&cp, ",")) != NULL)
+		    if (strcmp (opt, "ro") == 0)
+		      buf->f_flag |= ST_RDONLY;
+		    else if (strcmp (opt, "nosuid") == 0)
+		      buf->f_flag |= ST_NOSUID;
+#ifdef __USE_GNU
+		    else if (strcmp (opt, "noexec") == 0)
+		      buf->f_flag |= ST_NOEXEC;
+		    else if (strcmp (opt, "nodev") == 0)
+		      buf->f_flag |= ST_NODEV;
+		    else if (strcmp (opt, "sync") == 0)
+		      buf->f_flag |= ST_SYNCHRONOUS;
+		    else if (strcmp (opt, "mand") == 0)
+		      buf->f_flag |= ST_MANDLOCK;
+		    else if (strcmp (opt, "noatime") == 0)
+		      buf->f_flag |= ST_NOATIME;
+		    else if (strcmp (opt, "nodiratime") == 0)
+		      buf->f_flag |= ST_NODIRATIME;
+#endif
+
+		  /* We can stop looking for more entries.  */
+		  break;
+		}
+	    }
+
+	  /* Close the file.  */
+	  endmntent (mtab);
+	}
+
+      __set_errno (save_errno);
+    }
diff --git a/ap/build/uClibc/libc/misc/statfs/statfs64.c b/ap/build/uClibc/libc/misc/statfs/statfs64.c
new file mode 100644
index 0000000..0cc8595
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/statfs64.c
@@ -0,0 +1,49 @@
+/* Return information about the filesystem on which FILE resides.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <_lfs_64.h>
+
+#include <string.h>
+#include <stddef.h>
+#include <sys/statfs.h>
+
+extern __typeof(statfs) __libc_statfs;
+
+/* Return information about the filesystem on which FILE resides.  */
+int statfs64 (const char *file, struct statfs64 *buf)
+{
+    struct statfs buf32;
+
+    if (__libc_statfs (file, &buf32) < 0)
+	return -1;
+
+    buf->f_type = buf32.f_type;
+    buf->f_bsize = buf32.f_bsize;
+    buf->f_blocks = buf32.f_blocks;
+    buf->f_bfree = buf32.f_bfree;
+    buf->f_bavail = buf32.f_bavail;
+    buf->f_files = buf32.f_files;
+    buf->f_ffree = buf32.f_ffree;
+    buf->f_fsid = buf32.f_fsid;
+    buf->f_namelen = buf32.f_namelen;
+    memcpy (buf->f_spare, buf32.f_spare, sizeof (buf32.f_spare));
+
+    return 0;
+}
+libc_hidden_def(statfs64)
diff --git a/ap/build/uClibc/libc/misc/statfs/statvfs.c b/ap/build/uClibc/libc/misc/statfs/statvfs.c
new file mode 100644
index 0000000..5ac38ed
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/statvfs.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <features.h>
+#include <errno.h>
+#include <mntent.h>
+#include <paths.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+
+
+extern __typeof(statfs) __libc_statfs;
+
+int statvfs (const char *file, struct statvfs *buf)
+{
+    struct statfs fsbuf;
+    struct stat st;
+
+    /* Get as much information as possible from the system.  */
+    if (__libc_statfs (file, &fsbuf) < 0)
+	return -1;
+
+#define STAT(st) stat (file, st)
+#include "internal_statvfs.c"
+
+    /* We signal success if the statfs call succeeded.  */
+    return 0;
+}
+libc_hidden_def(statvfs)
diff --git a/ap/build/uClibc/libc/misc/statfs/statvfs64.c b/ap/build/uClibc/libc/misc/statfs/statvfs64.c
new file mode 100644
index 0000000..9923e66
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/statfs/statvfs64.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <_lfs_64.h>
+
+#include <errno.h>
+#include <mntent.h>
+#include <paths.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+
+
+#undef stat
+#define stat stat64
+
+int statvfs64 (const char *file, struct statvfs64 *buf)
+{
+    struct statfs64 fsbuf;
+    struct stat64 st;
+#if !defined __UCLIBC_LINUX_SPECIFIC__
+    int ret;
+    struct statvfs buf32;
+
+    ret = statvfs (file, &buf32);
+    if (ret == 0) {
+      fsbuf.f_bsize = buf32.f_bsize;
+      fsbuf.f_frsize = buf32.f_frsize;
+      fsbuf.f_blocks = buf32.f_blocks;
+      fsbuf.f_bfree = buf32.f_bfree;
+      fsbuf.f_bavail = buf32.f_bavail;
+      fsbuf.f_files = buf32.f_files;
+      fsbuf.f_ffree = buf32.f_ffree;
+      if (sizeof (fsbuf.f_fsid) == sizeof(buf32.f_fsid))
+	memcpy (&fsbuf.f_fsid, &buf32.f_fsid, sizeof(fsbuf.f_fsid));
+      /* and if not, then you could approximate or whatever.. */
+      fsbuf.f_namelen = buf32.f_namemax;
+    } else
+      return ret;
+#else
+    /* Get as much information as possible from the system.  */
+    if (statfs64 (file, &fsbuf) < 0)
+	return -1;
+#endif
+#define STAT(st) stat (file, st)
+#include "internal_statvfs.c"
+
+    /* We signal success if the statfs call succeeded.  */
+    return 0;
+}
diff --git a/ap/build/uClibc/libc/misc/syslog/Makefile b/ap/build/uClibc/libc/misc/syslog/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/syslog/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/syslog/Makefile.in b/ap/build/uClibc/libc/misc/syslog/Makefile.in
new file mode 100644
index 0000000..5cc4f52
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/syslog/Makefile.in
@@ -0,0 +1,25 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/syslog
+
+CSRC := syslog.c
+
+MISC_SYSLOG_DIR := $(top_srcdir)libc/misc/syslog
+MISC_SYSLOG_OUT := $(top_builddir)libc/misc/syslog
+
+MISC_SYSLOG_SRC := $(patsubst %.c,$(MISC_SYSLOG_DIR)/%.c,$(CSRC))
+MISC_SYSLOG_OBJ := $(patsubst %.c,$(MISC_SYSLOG_OUT)/%.o,$(CSRC))
+
+ifeq ($(UCLIBC_HAS_SYSLOG),y)
+libc-y += $(MISC_SYSLOG_OBJ)
+endif
+
+objclean-y += CLEAN_libc/misc/syslog
+
+CLEAN_libc/misc/syslog:
+	$(do_rm) $(addprefix $(MISC_SYSLOG_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/syslog/syslog.c b/ap/build/uClibc/libc/misc/syslog/syslog.c
new file mode 100644
index 0000000..f1b848f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/syslog/syslog.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *	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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 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.
+ */
+
+/*
+ * SYSLOG -- print message on log file
+ *
+ * This routine looks a lot like printf, except that it outputs to the
+ * log file instead of the standard output.  Also:
+ *	adds a timestamp,
+ *	prints the module name in front of the message,
+ *	has some other formatting types (or will sometime),
+ *	adds a newline on the end of the message.
+ *
+ * The output of this routine is intended to be read by syslogd(8).
+ *
+ * Author: Eric Allman
+ * Modified to use UNIX domain IPC by Ralph Campbell
+ * Patched March 12, 1996 by A. Ian Vogelesang <vogelesang@hdshq.com>
+ *  - to correct the handling of message & format string truncation,
+ *  - to visibly tag truncated records to facilitate
+ *    investigation of such Bad Things with grep, and,
+ *  - to correct the handling of case where "write"
+ *    returns after writing only part of the message.
+ * Rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz> on May 14, 1997
+ *  - better buffer overrun checks.
+ *  - special handling of "%m" removed as we use GNU sprintf which handles
+ *    it automatically.
+ *  - Major code cleanup.
+ */
+
+#define __FORCE_GLIBC
+#include <features.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/signal.h>
+#include <sys/syslog.h>
+
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <netdb.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <paths.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+
+#include <bits/uClibc_mutex.h>
+
+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+
+/* !glibc_compat: glibc uses argv[0] by default
+ * (default: if there was no openlog or if openlog passed NULL),
+ * not string "syslog"
+ */
+static const char *LogTag = "syslog";   /* string to tag the entry with */
+static int       LogFile = -1;          /* fd for log */
+static smalluint connected;             /* have done connect */
+/* all bits in option argument for openlog fit in 8 bits */
+static smalluint LogStat = 0;           /* status bits, set by openlog */
+/* default facility code if openlog is not called */
+/* (this fits in 8 bits even without >> 3 shift, but playing extra safe) */
+static smalluint LogFacility = LOG_USER >> 3;
+/* bits mask of priorities to be logged (eight prios - 8 bits is enough) */
+static smalluint LogMask = 0xff;
+/* AF_UNIX address of local logger (we use struct sockaddr
+ * instead of struct sockaddr_un since "/dev/log" is small enough) */
+static const struct sockaddr SyslogAddr = {
+	.sa_family = AF_UNIX, /* sa_family_t (usually a short) */
+	.sa_data = _PATH_LOG  /* char [14] */
+};
+
+static void
+closelog_intern(int sig)
+{
+	/* mylock must be held by the caller */
+	if (LogFile != -1) {
+		(void) close(LogFile);
+	}
+	LogFile = -1;
+	connected = 0;
+	if (sig == 0) { /* called from closelog()? - reset to defaults */
+		LogStat = 0;
+		LogTag = "syslog";
+		LogFacility = LOG_USER >> 3;
+		LogMask = 0xff;
+	}
+}
+
+static void
+openlog_intern(const char *ident, int logstat, int logfac)
+{
+	int fd;
+	int logType = SOCK_DGRAM;
+
+	if (ident != NULL)
+		LogTag = ident;
+	LogStat = logstat;
+	/* (we were checking also for logfac != 0, but it breaks
+	 * openlog(xx, LOG_KERN) since LOG_KERN == 0) */
+	if ((logfac & ~LOG_FACMASK) == 0) /* if we don't have invalid bits */
+		LogFacility = (unsigned)logfac >> 3;
+
+	fd = LogFile;
+	if (fd == -1) {
+ retry:
+		if (logstat & LOG_NDELAY) {
+			LogFile = fd = socket(AF_UNIX, logType, 0);
+			if (fd == -1) {
+				return;
+			}
+			fcntl(fd, F_SETFD, FD_CLOEXEC);
+			/* We don't want to block if e.g. syslogd is SIGSTOPed */
+			fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL));
+		}
+	}
+
+	if (fd != -1 && !connected) {
+		if (connect(fd, &SyslogAddr, sizeof(SyslogAddr)) != -1) {
+			connected = 1;
+		} else {
+			if (fd != -1) {
+				close(fd);
+				LogFile = fd = -1;
+			}
+			if (logType == SOCK_DGRAM) {
+				logType = SOCK_STREAM;
+				goto retry;
+			}
+		}
+	}
+}
+
+/*
+ * OPENLOG -- open system log
+ */
+void
+openlog(const char *ident, int logstat, int logfac)
+{
+	__UCLIBC_MUTEX_LOCK(mylock);
+	openlog_intern(ident, logstat, logfac);
+	__UCLIBC_MUTEX_UNLOCK(mylock);
+}
+libc_hidden_def(openlog)
+
+/*
+ * syslog, vsyslog --
+ *     print message on log file; output is intended for syslogd(8).
+ */
+void
+vsyslog(int pri, const char *fmt, va_list ap)
+{
+	register char *p;
+	char *last_chr, *head_end, *end, *stdp;
+	time_t now;
+	int fd, saved_errno;
+	int rc;
+	char tbuf[1024]; /* syslogd is unable to handle longer messages */
+
+	/* Just throw out this message if pri has bad bits. */
+	if ((pri & ~(LOG_PRIMASK|LOG_FACMASK)) != 0)
+		return;
+
+	saved_errno = errno;
+
+	__UCLIBC_MUTEX_LOCK(mylock);
+
+	/* See if we should just throw out this message according to LogMask. */
+	if ((LogMask & LOG_MASK(LOG_PRI(pri))) == 0)
+		goto getout;
+	if (LogFile < 0 || !connected)
+		openlog_intern(NULL, LogStat | LOG_NDELAY, (int)LogFacility << 3);
+
+	/* Set default facility if none specified. */
+	if ((pri & LOG_FACMASK) == 0)
+		pri |= ((int)LogFacility << 3);
+
+	/* Build the message. We know the starting part of the message can take
+	 * no longer than 64 characters plus length of the LogTag. So it's
+	 * safe to test only LogTag and use normal sprintf everywhere else.
+	 */
+	(void)time(&now);
+	stdp = p = tbuf + sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4);
+	/*if (LogTag) - always true */ {
+		if (strlen(LogTag) < sizeof(tbuf) - 64)
+			p += sprintf(p, "%s", LogTag);
+		else
+			p += sprintf(p, "<BUFFER OVERRUN ATTEMPT>");
+	}
+	if (LogStat & LOG_PID)
+		p += sprintf(p, "[%d]", getpid());
+	/*if (LogTag) - always true */ {
+		*p++ = ':';
+		*p++ = ' ';
+	}
+	head_end = p;
+
+	/* We format the rest of the message. If the buffer becomes full, we mark
+	 * the message as truncated. Note that we require at least 2 free bytes
+	 * in the buffer as we might want to add "\r\n" there.
+	 */
+
+	end = tbuf + sizeof(tbuf) - 1;
+	__set_errno(saved_errno);
+	p += vsnprintf(p, end - p, fmt, ap);
+	if (p >= end || p < head_end) {	/* Returned -1 in case of error... */
+		static const char truncate_msg[12] = "[truncated] "; /* no NUL! */
+		memmove(head_end + sizeof(truncate_msg), head_end,
+				end - head_end - sizeof(truncate_msg));
+		memcpy(head_end, truncate_msg, sizeof(truncate_msg));
+		if (p < head_end) {
+			while (p < end && *p) {
+				p++;
+			}
+		}
+		else {
+			p = end - 1;
+		}
+
+	}
+	last_chr = p;
+
+	/* Output to stderr if requested. */
+	if (LogStat & LOG_PERROR) {
+		*last_chr = '\n';
+		(void)write(STDERR_FILENO, stdp, last_chr - stdp + 1);
+	}
+
+	/* Output the message to the local logger using NUL as a message delimiter. */
+	p = tbuf;
+	*last_chr = '\0';
+	if (LogFile >= 0) {
+		do {
+			/* can't just use write, it can result in SIGPIPE */
+			rc = send(LogFile, p, last_chr + 1 - p, MSG_NOSIGNAL);
+			if (rc < 0) {
+				/* I don't think looping forever on EAGAIN is a good idea.
+				 * Imagine that syslogd is SIGSTOPed... */
+				if (/* (errno != EAGAIN) && */ (errno != EINTR)) {
+					closelog_intern(1); /* 1: do not reset LogXXX globals to default */
+					goto write_err;
+				}
+				rc = 0;
+			}
+			p += rc;
+		} while (p <= last_chr);
+		goto getout;
+	}
+
+ write_err:
+	/*
+	 * Output the message to the console; don't worry about blocking,
+	 * if console blocks everything will.  Make sure the error reported
+	 * is the one from the syslogd failure.
+	 */
+	/* should mode be O_WRONLY | O_NOCTTY? -- Uli */
+	/* yes, but in Linux "/dev/console" never becomes ctty anyway -- vda */
+	if ((LogStat & LOG_CONS) &&
+	    (fd = open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY)) >= 0) {
+		p = strchr(tbuf, '>') + 1;
+		last_chr[0] = '\r';
+		last_chr[1] = '\n';
+		(void)write(fd, p, last_chr - p + 2);
+		(void)close(fd);
+	}
+
+ getout:
+	__UCLIBC_MUTEX_UNLOCK(mylock);
+}
+libc_hidden_def(vsyslog)
+
+void
+syslog(int pri, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsyslog(pri, fmt, ap);
+	va_end(ap);
+}
+libc_hidden_def(syslog)
+
+/*
+ * CLOSELOG -- close the system log
+ */
+void
+closelog(void)
+{
+	__UCLIBC_MUTEX_LOCK(mylock);
+	closelog_intern(0); /* 0: reset LogXXX globals to default */
+	__UCLIBC_MUTEX_UNLOCK(mylock);
+}
+libc_hidden_def(closelog)
+
+/* setlogmask -- set the log mask level */
+int setlogmask(int pmask)
+{
+	int omask;
+
+	omask = LogMask;
+	if (pmask != 0) {
+		__UCLIBC_MUTEX_LOCK(mylock);
+		LogMask = pmask;
+		__UCLIBC_MUTEX_UNLOCK(mylock);
+	}
+	return omask;
+}
diff --git a/ap/build/uClibc/libc/misc/sysvipc/.indent.pro b/ap/build/uClibc/libc/misc/sysvipc/.indent.pro
new file mode 100644
index 0000000..492ecf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/ap/build/uClibc/libc/misc/sysvipc/Makefile b/ap/build/uClibc/libc/misc/sysvipc/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/sysvipc/Makefile.in b/ap/build/uClibc/libc/misc/sysvipc/Makefile.in
new file mode 100644
index 0000000..115cfc6
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/Makefile.in
@@ -0,0 +1,32 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/sysvipc
+
+CSRC := ftok.c __syscall_ipc.c
+
+# multi source sem.c
+CSRC += semget.c semctl.c semop.c semtimedop.c
+
+# multi source shm.c
+CSRC += shmat.c shmctl.c shmdt.c shmget.c
+
+# multi source msgq.c
+CSRC += msgctl.c msgget.c msgrcv.c msgsnd.c
+
+MISC_SYSVIPC_DIR := $(top_srcdir)libc/misc/sysvipc
+MISC_SYSVIPC_OUT := $(top_builddir)libc/misc/sysvipc
+
+MISC_SYSVIPC_SRC := $(patsubst %.c,$(MISC_SYSVIPC_DIR)/%.c,$(CSRC))
+MISC_SYSVIPC_OBJ := $(patsubst %.c,$(MISC_SYSVIPC_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_SYSVIPC_OBJ)
+
+objclean-y += CLEAN_libc/misc/sysvipc
+
+CLEAN_libc/misc/sysvipc:
+	$(do_rm) $(addprefix $(MISC_SYSVIPC_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/sysvipc/__syscall_ipc.c b/ap/build/uClibc/libc/misc/sysvipc/__syscall_ipc.c
new file mode 100644
index 0000000..304a42c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/__syscall_ipc.c
@@ -0,0 +1,17 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * __syscall_ipc() for uClibc
+ *
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <sys/syscall.h>
+
+#ifdef __NR_ipc
+#define __NR___syscall_ipc __NR_ipc
+#include "ipc.h"
+_syscall6(int, __syscall_ipc, unsigned int, call, long, first, long, second, long,
+		  third, void *, ptr, void *, fifth)
+#endif
diff --git a/ap/build/uClibc/libc/misc/sysvipc/ftok.c b/ap/build/uClibc/libc/misc/sysvipc/ftok.c
new file mode 100644
index 0000000..cec2438
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/ftok.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <sys/ipc.h>
+#include <sys/stat.h>
+#ifdef __UCLIBC_HAS_LFS__
+# include <_lfs_64.h>
+#else
+# define stat64 stat
+#endif
+
+key_t ftok (const char *pathname, int proj_id)
+{
+  struct stat64 st;
+  key_t key;
+
+  if (stat64(pathname, &st) < 0)
+    return (key_t) -1;
+
+  key = ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16)
+	 | ((proj_id & 0xff) << 24));
+
+  return key;
+}
diff --git a/ap/build/uClibc/libc/misc/sysvipc/ipc.h b/ap/build/uClibc/libc/misc/sysvipc/ipc.h
new file mode 100644
index 0000000..339d136
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/ipc.h
@@ -0,0 +1,35 @@
+#ifndef IPC_H
+#define IPC_H
+#include <syscall.h>
+#include <bits/wordsize.h>
+
+#if __WORDSIZE == 32 || defined __alpha__ || defined __mips__
+# define __IPC_64	0x100
+#else
+# define __IPC_64	0x0
+#endif
+
+#ifdef __NR_ipc
+
+/* The actual system call: all functions are multiplexed by this.  */
+extern int __syscall_ipc (unsigned int __call, long __first, long __second,
+					  long __third, void *__ptr, void *__fifth) attribute_hidden;
+
+
+/* The codes for the functions to use the multiplexer `__syscall_ipc'.  */
+#define IPCOP_semop	 1
+#define IPCOP_semget	 2
+#define IPCOP_semctl	 3
+#define IPCOP_semtimedop 4
+#define IPCOP_msgsnd	11
+#define IPCOP_msgrcv	12
+#define IPCOP_msgget	13
+#define IPCOP_msgctl	14
+#define IPCOP_shmat	21
+#define IPCOP_shmdt	22
+#define IPCOP_shmget	23
+#define IPCOP_shmctl	24
+
+#endif
+
+#endif							/* IPC_H */
diff --git a/ap/build/uClibc/libc/misc/sysvipc/msgctl.c b/ap/build/uClibc/libc/misc/sysvipc/msgctl.c
new file mode 100644
index 0000000..480a54c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/msgctl.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_msgctl
+#include "msgq.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/msgget.c b/ap/build/uClibc/libc/misc/sysvipc/msgget.c
new file mode 100644
index 0000000..f7e54d5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/msgget.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_msgget
+#include "msgq.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/msgq.c b/ap/build/uClibc/libc/misc/sysvipc/msgq.c
new file mode 100644
index 0000000..185cd26
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/msgq.c
@@ -0,0 +1,112 @@
+#include <errno.h>
+#include <sys/msg.h>
+#include "ipc.h"
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include "sysdep-cancel.h"
+#else
+#define SINGLE_THREAD_P 1
+#endif
+
+
+#ifdef L_msgctl
+
+#ifdef __NR_msgctl
+#define __NR___libc_msgctl __NR_msgctl
+static __inline__ _syscall3(int, __libc_msgctl, int, msqid, int, cmd, struct msqid_ds *, buf)
+#endif
+/* Message queue control operation.  */
+int msgctl(int msqid, int cmd, struct msqid_ds *buf)
+{
+#ifdef __NR_msgctl
+	return __libc_msgctl(msqid, cmd | __IPC_64, buf);
+#else
+    return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0);
+#endif
+}
+#endif
+
+
+#ifdef L_msgget
+#ifdef __NR_msgget
+_syscall2(int, msgget, key_t, key, int, msgflg)
+#else
+/* Get messages queue.  */
+int msgget (key_t key, int msgflg)
+{
+    return __syscall_ipc(IPCOP_msgget ,key ,msgflg ,0 ,0, 0);
+}
+#endif
+#endif
+
+
+struct new_msg_buf{
+    struct msgbuf * oldmsg;
+    long int r_msgtyp;       /* the fifth arg of __syscall_ipc */
+};
+/* Receive message from message queue.  */
+
+
+#ifdef L_msgrcv
+#ifdef __NR_msgrcv
+#define __NR___syscall_msgrcv __NR_msgrcv
+static inline _syscall5(ssize_t, __syscall_msgrcv, int, msqid, void *, msgp,
+			size_t, msgsz, long int, msgtyp, int, msgflg)
+#endif
+static inline ssize_t do_msgrcv (int msqid, void *msgp, size_t msgsz,
+			    long int msgtyp, int msgflg)
+{
+#ifdef __NR_msgrcv
+    return __syscall_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
+#else
+    struct new_msg_buf temp;
+
+    temp.r_msgtyp = msgtyp;
+    temp.oldmsg = msgp;
+    return __syscall_ipc(IPCOP_msgrcv ,msqid ,msgsz ,msgflg ,&temp, 0);
+#endif
+}
+ssize_t msgrcv (int msqid, void *msgp, size_t msgsz,
+	    long int msgtyp, int msgflg)
+{
+    if (SINGLE_THREAD_P)
+	return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+    int oldtype = LIBC_CANCEL_ASYNC ();
+    int result = do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
+    LIBC_CANCEL_RESET (oldtype);
+    return result;
+#endif
+}
+#endif
+
+
+
+#ifdef L_msgsnd
+#ifdef __NR_msgsnd
+#define __NR___syscall_msgsnd __NR_msgsnd
+static inline _syscall4(int, __syscall_msgsnd, int, msqid, const void *, msgp,
+			size_t, msgsz, int, msgflg)
+#endif
+/* Send message to message queue.  */
+static inline int do_msgsnd (int msqid, const void *msgp, size_t msgsz,
+			    int msgflg)
+{
+#ifdef __NR_msgsnd
+    return __syscall_msgsnd(msqid, msgp, msgsz, msgflg);
+#else
+    return __syscall_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg, (void *)msgp, 0);
+#endif
+}
+int msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
+{
+    if (SINGLE_THREAD_P)
+	return do_msgsnd(msqid, msgp, msgsz, msgflg);
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+    int oldtype = LIBC_CANCEL_ASYNC ();
+    int result = do_msgsnd(msqid, msgp, msgsz, msgflg);
+    LIBC_CANCEL_RESET (oldtype);
+    return result;
+#endif
+}
+#endif
+
diff --git a/ap/build/uClibc/libc/misc/sysvipc/msgrcv.c b/ap/build/uClibc/libc/misc/sysvipc/msgrcv.c
new file mode 100644
index 0000000..a85e52a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/msgrcv.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_msgrcv
+#include "msgq.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/msgsnd.c b/ap/build/uClibc/libc/misc/sysvipc/msgsnd.c
new file mode 100644
index 0000000..9f09d1f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/msgsnd.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_msgsnd
+#include "msgq.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/sem.c b/ap/build/uClibc/libc/misc/sysvipc/sem.c
new file mode 100644
index 0000000..cca4cdf
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/sem.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <sys/sem.h>
+#include <stddef.h>
+#include <stdlib.h> /* for NULL */
+
+#include "ipc.h"
+
+
+#ifdef L_semctl
+/* Return identifier for array of NSEMS semaphores associated with
+   KEY.  */
+#include <stdarg.h>
+/* arg for semctl system calls. */
+union semun {
+    int val;			/* value for SETVAL */
+    struct semid_ds *buf;		/* buffer for IPC_STAT & IPC_SET */
+    unsigned short *array;		/* array for GETALL & SETALL */
+    struct seminfo *__buf;		/* buffer for IPC_INFO */
+    void *__pad;
+};
+
+
+#ifdef __NR_semctl
+#define __NR___semctl __NR_semctl
+static __inline__ _syscall4(int, __semctl, int, semid, int, semnum, int, cmd, void *, arg)
+#endif
+
+int semctl(int semid, int semnum, int cmd, ...)
+{
+    union semun arg;
+    va_list ap;
+
+    /* Get the argument.  */
+    va_start (ap, cmd);
+    arg = va_arg (ap, union semun);
+    va_end (ap);
+#ifdef __NR_semctl
+    return __semctl(semid, semnum, cmd | __IPC_64, arg.__pad);
+#else
+    return __syscall_ipc(IPCOP_semctl, semid, semnum, cmd|__IPC_64, &arg, NULL);
+#endif
+}
+#endif
+
+#ifdef L_semget
+#ifdef __NR_semget
+_syscall3(int, semget, key_t, key, int, nsems, int, semflg)
+
+#else
+/* Return identifier for array of NSEMS semaphores associated
+ * with KEY.  */
+int semget (key_t key, int nsems, int semflg)
+{
+    return __syscall_ipc(IPCOP_semget, key, nsems, semflg, NULL, 0);
+}
+#endif
+#endif
+
+#ifdef L_semop
+
+#ifdef __NR_semop
+_syscall3(int, semop, int, semid, struct sembuf *, sops, size_t, nsops)
+
+#else
+/* Perform user-defined atomical operation of array of semaphores.  */
+int semop (int semid, struct sembuf *sops, size_t nsops)
+{
+    return __syscall_ipc(IPCOP_semop, semid, (int) nsops, 0, sops, NULL);
+}
+#endif
+#endif
+
+#ifdef L_semtimedop
+
+#ifdef __NR_semtimedop
+_syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout)
+
+#else
+
+int semtimedop(int semid, struct sembuf *sops, size_t nsops,
+	       const struct timespec *timeout)
+{
+    return __syscall_ipc(IPCOP_semtimedop, semid, nsops, 0, sops, (void *) timeout);
+}
+#endif
+#endif
diff --git a/ap/build/uClibc/libc/misc/sysvipc/semctl.c b/ap/build/uClibc/libc/misc/sysvipc/semctl.c
new file mode 100644
index 0000000..df62a76
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/semctl.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_semctl
+#include "sem.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/semget.c b/ap/build/uClibc/libc/misc/sysvipc/semget.c
new file mode 100644
index 0000000..94d0b5d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/semget.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_semget
+#include "sem.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/semop.c b/ap/build/uClibc/libc/misc/sysvipc/semop.c
new file mode 100644
index 0000000..0c67f62
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/semop.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_semop
+#include "sem.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/semtimedop.c b/ap/build/uClibc/libc/misc/sysvipc/semtimedop.c
new file mode 100644
index 0000000..ecd0438
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/semtimedop.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_semtimedop
+#include "sem.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/shm.c b/ap/build/uClibc/libc/misc/sysvipc/shm.c
new file mode 100644
index 0000000..27e871f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/shm.c
@@ -0,0 +1,95 @@
+/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* SHMLBA uses it on most of the archs (not mips) */
+#define __getpagesize getpagesize
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/shm.h>
+#include <syscall.h>
+#include "ipc.h"
+
+#ifdef L_shmat
+/* Attach the shared memory segment associated with SHMID to the data
+   segment of the calling process.  SHMADDR and SHMFLG determine how
+   and where the segment is attached.  */
+#if defined(__NR_osf_shmat)
+# define __NR_shmat  __NR_osf_shmat
+#endif
+#ifdef __NR_shmat
+_syscall3(void *, shmat, int, shmid, const void *,shmaddr, int, shmflg)
+#else
+/* psm: don't remove this, else mips will fail */
+#include <unistd.h>
+
+void * shmat (int shmid, const void *shmaddr, int shmflg)
+{
+    int retval;
+    unsigned long raddr;
+
+    retval = __syscall_ipc(IPCOP_shmat, shmid, shmflg, (int) &raddr, (void *) shmaddr, 0);
+    return ((unsigned long int) retval > -(unsigned long int) SHMLBA
+	    ? (void *) retval : (void *) raddr);
+}
+#endif
+#endif
+
+#ifdef L_shmctl
+/* Provide operations to control over shared memory segments.  */
+#ifdef __NR_shmctl
+#define __NR___libc_shmctl __NR_shmctl
+static __inline__ _syscall3(int, __libc_shmctl, int, shmid, int, cmd, struct shmid_ds *, buf)
+#endif
+int shmctl(int shmid, int cmd, struct shmid_ds *buf)
+{
+#ifdef __NR_shmctl
+	return __libc_shmctl(shmid, cmd | __IPC_64, buf);
+#else
+    return __syscall_ipc(IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf, 0);
+#endif
+}
+#endif
+
+
+#ifdef L_shmdt
+/* Detach shared memory segment starting at address specified by SHMADDR
+   from the caller's data segment.  */
+#ifdef __NR_shmdt
+_syscall1(int, shmdt, const void *, shmaddr)
+#else
+int shmdt (const void *shmaddr)
+{
+    return __syscall_ipc(IPCOP_shmdt, 0, 0, 0, (void *) shmaddr, 0);
+}
+#endif
+#endif
+
+#ifdef L_shmget
+/* Return an identifier for an shared memory segment of at least size SIZE
+   which is associated with KEY.  */
+#ifdef __NR_shmget
+_syscall3(int, shmget, key_t, key, size_t, size, int, shmflg)
+#else
+int shmget (key_t key, size_t size, int shmflg)
+{
+    return __syscall_ipc(IPCOP_shmget, key, size, shmflg, NULL, 0);
+}
+#endif
+#endif
diff --git a/ap/build/uClibc/libc/misc/sysvipc/shmat.c b/ap/build/uClibc/libc/misc/sysvipc/shmat.c
new file mode 100644
index 0000000..d6cd22a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/shmat.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_shmat
+#include "shm.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/shmctl.c b/ap/build/uClibc/libc/misc/sysvipc/shmctl.c
new file mode 100644
index 0000000..90fab5a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/shmctl.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_shmctl
+#include "shm.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/shmdt.c b/ap/build/uClibc/libc/misc/sysvipc/shmdt.c
new file mode 100644
index 0000000..0783341
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/shmdt.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_shmdt
+#include "shm.c"
diff --git a/ap/build/uClibc/libc/misc/sysvipc/shmget.c b/ap/build/uClibc/libc/misc/sysvipc/shmget.c
new file mode 100644
index 0000000..4778e36
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/sysvipc/shmget.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_shmget
+#include "shm.c"
diff --git a/ap/build/uClibc/libc/misc/time/.indent.pro b/ap/build/uClibc/libc/misc/time/.indent.pro
new file mode 100644
index 0000000..492ecf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/ap/build/uClibc/libc/misc/time/Makefile b/ap/build/uClibc/libc/misc/time/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/time/Makefile.in b/ap/build/uClibc/libc/misc/time/Makefile.in
new file mode 100644
index 0000000..78f01ad
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/Makefile.in
@@ -0,0 +1,43 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/time
+
+CSRC := adjtime.c
+ifeq ($(UCLIBC_SUSV3_LEGACY),y)
+CSRC += ftime.c
+endif
+# multi source time.c
+CSRC +=	asctime.c asctime_r.c clock.c ctime.c ctime_r.c gmtime.c gmtime_r.c \
+	localtime.c localtime_r.c mktime.c strftime.c strptime.c tzset.c \
+	_time_t2tm.c __time_tm.c _time_mktime.c dysize.c timegm.c \
+	_time_mktime_tzi.c _time_localtime_tzi.c
+ifeq ($(UCLIBC_HAS_FLOATS),y)
+CSRC += difftime.c
+endif
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+CSRC += strftime_l.c strptime_l.c
+endif
+ifeq ($(UCLIBC_HAS_WCHAR),y)
+CSRC += wcsftime.c
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+CSRC += wcsftime_l.c
+endif
+endif
+
+MISC_TIME_DIR := $(top_srcdir)libc/misc/time
+MISC_TIME_OUT := $(top_builddir)libc/misc/time
+
+MISC_TIME_SRC := $(patsubst %.c,$(MISC_TIME_DIR)/%.c,$(CSRC))
+MISC_TIME_OBJ := $(patsubst %.c,$(MISC_TIME_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_TIME_OBJ)
+
+objclean-y += CLEAN_libc/misc/time
+
+CLEAN_libc/misc/time:
+	$(do_rm) $(addprefix $(MISC_TIME_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/time/__time_tm.c b/ap/build/uClibc/libc/misc/time/__time_tm.c
new file mode 100644
index 0000000..59b7d8a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/__time_tm.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L___time_tm
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/_time_localtime_tzi.c b/ap/build/uClibc/libc/misc/time/_time_localtime_tzi.c
new file mode 100644
index 0000000..32728a4
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/_time_localtime_tzi.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L__time_localtime_tzi
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/_time_mktime.c b/ap/build/uClibc/libc/misc/time/_time_mktime.c
new file mode 100644
index 0000000..1fd9200
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/_time_mktime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L__time_mktime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/_time_mktime_tzi.c b/ap/build/uClibc/libc/misc/time/_time_mktime_tzi.c
new file mode 100644
index 0000000..543893e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/_time_mktime_tzi.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L__time_mktime_tzi
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/_time_t2tm.c b/ap/build/uClibc/libc/misc/time/_time_t2tm.c
new file mode 100644
index 0000000..903651f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/_time_t2tm.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L__time_t2tm
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/adjtime.c b/ap/build/uClibc/libc/misc/time/adjtime.c
new file mode 100644
index 0000000..1e80871
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/adjtime.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <limits.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <errno.h>
+
+
+#define MAX_SEC	(LONG_MAX / 1000000L - 2)
+#define MIN_SEC	(LONG_MIN / 1000000L + 2)
+
+#ifndef MOD_OFFSET
+#define modes mode
+#endif
+
+int
+adjtime(const struct timeval * itv, struct timeval * otv)
+{
+  struct timex tntx;
+
+  if (itv)
+  {
+    struct timeval tmp;
+
+    /* We will do some check here. */
+    tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L;
+    tmp.tv_usec = itv->tv_usec % 1000000L;
+    if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC)
+    {
+	__set_errno(EINVAL);
+	return -1;
+    }
+    tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L;
+    tntx.modes = ADJ_OFFSET_SINGLESHOT;
+  }
+  else
+  {
+    tntx.modes = 0;
+  }
+  if (adjtimex(&tntx) < 0) return -1;
+  if (otv) {
+    if (tntx.offset < 0)
+      {
+	otv->tv_usec = -(-tntx.offset % 1000000);
+	otv->tv_sec  = -(-tntx.offset / 1000000);
+      }
+    else
+      {
+	otv->tv_usec = tntx.offset % 1000000;
+	otv->tv_sec  = tntx.offset / 1000000;
+      }
+  }
+  return 0;
+}
diff --git a/ap/build/uClibc/libc/misc/time/asctime.c b/ap/build/uClibc/libc/misc/time/asctime.c
new file mode 100644
index 0000000..d80c017
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/asctime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_asctime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/asctime_r.c b/ap/build/uClibc/libc/misc/time/asctime_r.c
new file mode 100644
index 0000000..aec38b1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/asctime_r.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_asctime_r
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/clock.c b/ap/build/uClibc/libc/misc/time/clock.c
new file mode 100644
index 0000000..9cc4254
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/clock.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_clock
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/ctime.c b/ap/build/uClibc/libc/misc/time/ctime.c
new file mode 100644
index 0000000..4bd09a8
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/ctime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_ctime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/ctime_r.c b/ap/build/uClibc/libc/misc/time/ctime_r.c
new file mode 100644
index 0000000..c03f5c9
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/ctime_r.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_ctime_r
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/difftime.c b/ap/build/uClibc/libc/misc/time/difftime.c
new file mode 100644
index 0000000..4bcec2c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/difftime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_difftime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/dysize.c b/ap/build/uClibc/libc/misc/time/dysize.c
new file mode 100644
index 0000000..b1bf84b
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/dysize.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_dysize
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/ftime.c b/ap/build/uClibc/libc/misc/time/ftime.c
new file mode 100644
index 0000000..ff78d41
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/ftime.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1994, 1997 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/timeb.h>
+#include <sys/time.h>
+
+
+int ftime(struct timeb *timebuf)
+{
+	struct timeval tv;
+	struct timezone tz;
+
+	/* In Linux, gettimeofday fails only on bad parameter.
+	 * We know that here parameters aren't bad.
+	 */
+	gettimeofday (&tv, &tz);
+
+	timebuf->time = tv.tv_sec;
+	timebuf->millitm = (tv.tv_usec + 999) / 1000;
+	timebuf->timezone = tz.tz_minuteswest;
+	timebuf->dstflag = tz.tz_dsttime;
+	return 0;
+}
diff --git a/ap/build/uClibc/libc/misc/time/gmtime.c b/ap/build/uClibc/libc/misc/time/gmtime.c
new file mode 100644
index 0000000..24a512c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/gmtime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_gmtime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/gmtime_r.c b/ap/build/uClibc/libc/misc/time/gmtime_r.c
new file mode 100644
index 0000000..8677dd2
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/gmtime_r.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_gmtime_r
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/localtime.c b/ap/build/uClibc/libc/misc/time/localtime.c
new file mode 100644
index 0000000..e4bffbd
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/localtime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_localtime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/localtime_r.c b/ap/build/uClibc/libc/misc/time/localtime_r.c
new file mode 100644
index 0000000..5351834
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/localtime_r.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_localtime_r
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/mktime.c b/ap/build/uClibc/libc/misc/time/mktime.c
new file mode 100644
index 0000000..2b2c8e4
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/mktime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_mktime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/strftime.c b/ap/build/uClibc/libc/misc/time/strftime.c
new file mode 100644
index 0000000..2eb827d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/strftime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_strftime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/strftime_l.c b/ap/build/uClibc/libc/misc/time/strftime_l.c
new file mode 100644
index 0000000..e1d34ad
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/strftime_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_strftime_l
+#define __UCLIBC_DO_XLOCALE
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/strptime.c b/ap/build/uClibc/libc/misc/time/strptime.c
new file mode 100644
index 0000000..771633f
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/strptime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_strptime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/strptime_l.c b/ap/build/uClibc/libc/misc/time/strptime_l.c
new file mode 100644
index 0000000..16ee7e1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/strptime_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_strptime_l
+#define __UCLIBC_DO_XLOCALE
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/time.c b/ap/build/uClibc/libc/misc/time/time.c
new file mode 100644
index 0000000..8e2ebf1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/time.c
@@ -0,0 +1,2485 @@
+/* Copyright (C) 2002-2004   Manuel Novoa III    <mjn3@codepoet.org>
+ *
+ * GNU Library General Public License (LGPL) version 2 or later.
+ *
+ * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
+ */
+
+/* June 15, 2002     Initial Notes:
+ *
+ * Note: It is assumed throught that time_t is either long or unsigned long.
+ *       Similarly, clock_t is assumed to be long int.
+ *
+ * Warning: Assumptions are made about the layout of struct tm!  It is
+ *    assumed that the initial fields of struct tm are (in order):
+ *    tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday
+ *
+ * Reached the inital goal of supporting the ANSI/ISO C99 time functions
+ * as well as SUSv3's strptime.  All timezone info is obtained from the
+ * TZ env variable.
+ *
+ * Differences from glibc worth noting:
+ *
+ * Leap seconds are not considered here.
+ *
+ * glibc stores additional timezone info the struct tm, whereas we don't.
+ *
+ * Alternate digits and era handling are not currently implemented.
+ * The modifiers are accepted, and tested for validity with the following
+ * specifier, but are ignored otherwise.
+ *
+ * strftime does not implement glibc extension modifiers or widths for
+ *     conversion specifiers.  However it does implement the glibc
+ *     extension specifiers %l, %k, and %s.  It also recognizes %P, but
+ *     treats it as a synonym for %p; i.e. doesn't convert to lower case.
+ *
+ * strptime implements the glibc extension specifiers.  However, it follows
+ *     SUSv3 in requiring at least one non-alphanumeric char between
+ *     conversion specifiers.  Also, strptime only sets struct tm fields
+ *     for which format specifiers appear and does not try to infer other
+ *     fields (such as wday) as glibc's version does.
+ *
+ * TODO - Since glibc's %l and %k can space-pad their output in strftime,
+ *     it might be reasonable to eat whitespace first for those specifiers.
+ *     This could be done by pushing " %I" and " %H" respectively so that
+ *     leading whitespace is consumed.  This is really only an issue if %l
+ *     or %k occurs at the start of the format string.
+ *
+ * TODO - Implement getdate? tzfile? struct tm extensions?
+ *
+ * TODO - Rework _time_mktime to remove the dependency on long long.
+ */
+
+/* Oct 28, 2002
+ *
+ * Fixed allowed char check for std and dst TZ fields.
+ *
+ * Added several options concerned with timezone support.  The names will
+ * probably change once Erik gets the new config system in place.
+ *
+ * Defining __TIME_TZ_FILE causes tzset() to attempt to read the TZ value
+ * from the file /etc/TZ if the TZ env variable isn't set.  The file contents
+ * must be the intended value of TZ, followed by a newline.  No other chars,
+ * spacing, etc is allowed.  As an example, an easy way for me to init
+ * /etc/TZ appropriately would be:    echo CST6CDT > /etc/TZ
+ *
+ * Defining __TIME_TZ_FILE_ONCE will cause all further accesses of /etc/TZ
+ * to be skipped once a legal value has been read.
+ *
+ * Defining __TIME_TZ_OPT_SPEED will cause a tzset() to keep a copy of the
+ * last TZ setting string and do a "fast out" if the current string is the
+ * same.
+ *
+ * Nov 21, 2002   Fix an error return case in _time_mktime.
+ *
+ * Nov 26, 2002   Fix bug in setting daylight and timezone when no (valid) TZ.
+ *   Bug reported by Arne Bernin <arne@alamut.de> in regards to freeswan.
+ *
+ * July 27, 2003  Adjust the struct tm extension field support.
+ *   Change __tm_zone back to a ptr and add the __tm_tzname[] buffer for
+ *   __tm_zone to point to.  This gets around complaints from g++.
+ *  Who knows... it might even fix the PPC timezone init problem.
+ *
+ * July 29, 2003  Fix a bug in mktime behavior when tm_isdst was -1.
+ *   Bug reported by "Sid Wade" <sid@vivato.net> in regards to busybox.
+ *
+ *   NOTE: uClibc mktime behavior is different than glibc's when
+ *   the struct tm has tm_isdst == -1 and also had fields outside of
+ *   the normal ranges.
+ *
+ *   Apparently, glibc examines (at least) tm_sec and guesses the app's
+ *   intention of assuming increasing or decreasing time when entering an
+ *   ambiguous time period at the dst<->st boundaries.
+ *
+ *   The uClibc behavior is to always normalize the struct tm and then
+ *   try to determing the dst setting.
+ *
+ *   As long as tm_isdst != -1 or the time specifiec by struct tm is
+ *   unambiguous (not falling in the dst<->st transition region) both
+ *   uClibc and glibc should produce the same result for mktime.
+ *
+ * Oct 31, 2003 Kill the seperate __tm_zone and __tm_tzname[] and which
+ *   doesn't work if you want the memcpy the struct.  Sigh... I didn't
+ *   think about that.  So now, when the extensions are enabled, we
+ *   malloc space when necessary and keep the timezone names in a linked
+ *   list.
+ *
+ *   Fix a dst-related bug which resulted in use of uninitialized data.
+ *
+ * Nov 15, 2003 I forgot to update the thread locking in the last dst fix.
+ *
+ * Dec 14, 2003 Fix some dst issues in _time_mktime().
+ *   Normalize the tm_isdst value to -1, 0, or 1.
+ *   If no dst for this timezone, then reset tm_isdst to 0.
+ *
+ * May 7, 2004
+ *   Change clock() to allow wrapping.
+ *   Add timegm() function.
+ *   Make lookup_tzname() static (as it should have been).
+ *   Have strftime() get timezone information from the passed struct
+ *     for the %z and %Z conversions when using struct tm extensions.
+ *
+ * Jul 24, 2004
+ *   Fix 2 bugs in strftime related to glibc struct tm extensions.
+ *   1) Need to negate tm_gmtoff field value when used. (bug 336).
+ *   2) Deal with NULL ptr case for tm_zone field, which was causing
+ *      segfaults in both the NIST/PCTS tests and the Python 2.4.1
+ *      self-test suite.
+ *      NOTE: We set uninitialized timezone names to "???", and this
+ *            differs (intentionally) from glibc's behavior.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <bits/uClibc_uintmaxtostr.h>
+#include <bits/uClibc_mutex.h>
+
+#ifdef __UCLIBC_HAS_WCHAR__
+#include <wchar.h>
+#endif
+#ifdef __UCLIBC_HAS_XLOCALE__
+#include <xlocale.h>
+#endif
+
+
+#ifndef __isleap
+#define __isleap(y) ( !((y) % 4) && ( ((y) % 100) || !((y) % 400) ) )
+#endif
+
+#ifndef TZNAME_MAX
+#define TZNAME_MAX _POSIX_TZNAME_MAX
+#endif
+
+#if defined (L_tzset) || defined (L_localtime_r) || defined(L_strftime) || \
+    defined(L__time_mktime) || defined(L__time_mktime_tzi) || \
+    ((defined(L_strftime) || defined(L_strftime_l)) && \
+    defined(__UCLIBC_HAS_XLOCALE__))
+
+void _time_tzset(int use_old_rules) attribute_hidden;
+
+#ifndef L__time_mktime
+
+ /* Jan 1, 2007 Z - tm = 0,0,0,1,0,107,1,0,0 */
+
+static const time_t new_rule_starts = 1167609600;
+
+#endif
+#endif
+
+/**********************************************************************/
+/* The era code is currently unfinished. */
+/*  #define ENABLE_ERA_CODE */
+
+#define TZ_BUFLEN		(2*TZNAME_MAX + 56)
+
+#ifdef __UCLIBC_HAS_TZ_FILE__
+
+#include <sys/stat.h>
+#include "paths.h"
+/* ":<tzname>+hh:mm:ss<tzname>+hh:mm:ss,Mmm.w.d/hh:mm:ss,Mmm.w.d/hh:mm:ss" + nul */
+/* 1 + 2*(1+TZNAME_MAX+1 + 9 + 7 + 9) + 1 = 2*TZNAME_MAX + 56 */
+
+#else  /* __UCLIBC_HAS_TZ_FILE__ */
+
+/* Probably no longer needed. */
+#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__
+
+#endif /* __UCLIBC_HAS_TZ_FILE__ */
+
+/**********************************************************************/
+
+extern struct tm __time_tm attribute_hidden;
+
+typedef struct {
+	long gmt_offset;
+	long dst_offset;
+	short day;					/* for J or normal */
+	short week;
+	short month;
+	short rule_type;			/* J, M, \0 */
+	char tzname[TZNAME_MAX+1];
+} rule_struct;
+
+__UCLIBC_MUTEX_EXTERN(_time_tzlock);
+
+extern rule_struct _time_tzinfo[2] attribute_hidden;
+
+extern struct tm *_time_t2tm(const time_t *__restrict timer,
+					int offset, struct tm *__restrict result) attribute_hidden;
+
+extern time_t _time_mktime(struct tm *timeptr, int store_on_success) attribute_hidden;
+
+extern struct tm *__time_localtime_tzi(const time_t *__restrict timer,
+					struct tm *__restrict result,
+					rule_struct *tzi) attribute_hidden;
+
+extern time_t _time_mktime_tzi(struct tm *timeptr, int store_on_success,
+					rule_struct *tzi) attribute_hidden;
+
+/**********************************************************************/
+#ifdef L_asctime
+
+static char __time_str[26];
+
+char *asctime(const struct tm *ptm)
+{
+	return asctime_r(ptm, __time_str);
+}
+libc_hidden_def(asctime)
+
+#endif
+/**********************************************************************/
+#ifdef L_asctime_r
+
+/* Strictly speaking, this implementation isn't correct.  ANSI/ISO specifies
+ * that the implementation of asctime() be equivalent to
+ *
+ *   char *asctime(const struct tm *timeptr)
+ *   {
+ *       static char wday_name[7][3] = {
+ *           "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ *       };
+ *       static char mon_name[12][3] = {
+ *           "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ *           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ *       };
+ *       static char result[26];
+ *
+ *       sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
+ *           wday_name[timeptr->tm_wday],
+ *           mon_name[timeptr->tm_mon],
+ *           timeptr->tm_mday, timeptr->tm_hour,
+ *           timeptr->tm_min, timeptr->tm_sec,
+ *           1900 + timeptr->tm_year);
+ *       return result;
+ *   }
+ *
+ * but the above is either inherently unsafe, or carries with it the implicit
+ * assumption that all fields of timeptr fall within their usual ranges, and
+ * that the tm_year value falls in the range [-2899,8099] to avoid overflowing
+ * the static buffer.
+ *
+ * If we take the implicit assumption as given, then the implementation below
+ * is still incorrect for tm_year values < -900, as there will be either
+ * 0-padding and/or a missing negative sign for the year conversion .  But given
+ * the usual use of asctime(), I think it isn't unreasonable to restrict correct
+ * operation to the domain of years between 1000 and 9999.
+ */
+
+/* This is generally a good thing, but if you're _sure_ any data passed will be
+ * in range, you can #undef this. */
+#define SAFE_ASCTIME_R		1
+
+static const unsigned char at_data[] = {
+	'S', 'u', 'n', 'M', 'o', 'n', 'T', 'u', 'e', 'W', 'e', 'd',
+	'T', 'h', 'u', 'F', 'r', 'i', 'S', 'a', 't',
+
+	'J', 'a', 'n', 'F', 'e', 'b', 'M', 'a', 'r', 'A', 'p', 'r',
+	'M', 'a', 'y', 'J', 'u', 'n', 'J', 'u', 'l', 'A', 'u', 'g',
+	'S', 'e', 'p', 'O', 'c', 't', 'N', 'o', 'v', 'D', 'e', 'c',
+
+#ifdef SAFE_ASCTIME_R
+	'?', '?', '?',
+#endif
+	' ', '?', '?', '?',
+	' ', '0',
+	offsetof(struct tm, tm_mday),
+	' ', '0',
+	offsetof(struct tm, tm_hour),
+	':', '0',
+	offsetof(struct tm, tm_min),
+	':', '0',
+	offsetof(struct tm, tm_sec),
+	' ', '?', '?', '?', '?', '\n', 0
+};
+
+char *asctime_r(register const struct tm *__restrict ptm,
+				register char *__restrict buffer)
+{
+	int tmp;
+
+	assert(ptm);
+	assert(buffer);
+
+#ifdef SAFE_ASCTIME_R
+	memcpy(buffer, at_data + 3*(7 + 12), sizeof(at_data) - 3*(7 + 12));
+
+	if (((unsigned int)(ptm->tm_wday)) <= 6) {
+		memcpy(buffer, at_data + 3 * ptm->tm_wday, 3);
+	}
+
+	if (((unsigned int)(ptm->tm_mon)) <= 11) {
+		memcpy(buffer + 4, at_data + 3*7 + 3 * ptm->tm_mon, 3);
+	}
+#else
+	assert(((unsigned int)(ptm->tm_wday)) <= 6);
+	assert(((unsigned int)(ptm->tm_mon)) <= 11);
+
+	memcpy(buffer, at_data + 3*(7 + 12) - 3, sizeof(at_data) + 3 - 3*(7 + 12));
+
+	memcpy(buffer, at_data + 3 * ptm->tm_wday, 3);
+	memcpy(buffer + 4, at_data + 3*7 + 3 * ptm->tm_mon, 3);
+#endif
+
+#ifdef SAFE_ASCTIME_R
+	buffer += 19;
+	tmp = ptm->tm_year + 1900;
+	if (((unsigned int) tmp) < 10000) {
+		buffer += 4;
+		do {
+			*buffer = '0' + (tmp % 10);
+			tmp /= 10;
+		} while (*--buffer == '?');
+	}
+/*	Not sure if we should even bother ...
+	} else {
+		__set_errno(EOVERFLOW);
+		return NULL;
+	}
+*/
+#else  /* SAFE_ASCTIME_R */
+	buffer += 23;
+	tmp = ptm->tm_year + 1900;
+	assert( ((unsigned int) tmp) < 10000 );
+/*	Not sure if we should even bother ...
+	if ( ((unsigned int) tmp) >= 10000 ) {
+		__set_errno(EOVERFLOW);
+		return NULL;
+	}
+*/
+	do {
+		*buffer = '0' + (tmp % 10);
+		tmp /= 10;
+	} while (*--buffer == '?');
+#endif /* SAFE_ASCTIME_R */
+
+	do {
+		--buffer;
+		tmp = *((int *)(((const char *) ptm) + (int) *buffer));
+#ifdef SAFE_ASCTIME_R
+		if (((unsigned int) tmp) >= 100) { /* Just check 2 digit non-neg. */
+			buffer[-1] = *buffer = '?';
+		} else
+#else
+		assert(((unsigned int) tmp) < 100); /* Just check 2 digit non-neg. */
+#endif
+		{
+			*buffer = '0' + (tmp % 10);
+#ifdef __BCC__
+			buffer[-1] = '0' + (tmp/10);
+#else
+			buffer[-1] += (tmp/10);
+#endif
+		}
+	} while ((buffer -= 2)[-2] == '0');
+
+	if (*++buffer == '0') {		/* Space-pad day of month. */
+		*buffer = ' ';
+	}
+
+	return buffer - 8;
+}
+libc_hidden_def(asctime_r)
+
+#endif
+/**********************************************************************/
+#ifdef L_clock
+
+#include <sys/times.h>
+
+#ifndef __BCC__
+#if CLOCKS_PER_SEC != 1000000L
+#error unexpected value for CLOCKS_PER_SEC!
+#endif
+#endif
+
+#ifdef __UCLIBC_CLK_TCK_CONST
+# if __UCLIBC_CLK_TCK_CONST > CLOCKS_PER_SEC
+#  error __UCLIBC_CLK_TCK_CONST > CLOCKS_PER_SEC!
+# elif __UCLIBC_CLK_TCK_CONST < 1
+#  error __UCLIBC_CLK_TCK_CONST < 1!
+# endif
+#endif
+
+/* Note: SUSv3 notes
+ *
+ *   On XSI-conformant systems, CLOCKS_PER_SEC is defined to be one million.
+ *
+ *   The value returned by clock() may wrap around on some implementations.
+ *   For example, on a machine with 32-bit values for clock_t, it wraps
+ *   after 2147 seconds.
+ *
+ * This implies that we should bitwise and with LONG_MAX.
+ */
+
+clock_t clock(void)
+{
+	struct tms xtms;
+	unsigned long t;
+
+	times(&xtms);
+
+	t = ((unsigned long) xtms.tms_utime) + xtms.tms_stime;
+
+#ifndef __UCLIBC_CLK_TCK_CONST
+
+# error __UCLIBC_CLK_TCK_CONST not defined!
+
+#elif ((CLOCKS_PER_SEC % __UCLIBC_CLK_TCK_CONST) == 0)
+
+	/* CLOCKS_PER_SEC == k * __UCLIBC_CLK_TCK_CONST for some integer k >= 1. */
+	return ((t * (CLOCKS_PER_SEC/__UCLIBC_CLK_TCK_CONST)) & LONG_MAX);
+
+#else
+
+	/* Unlike the previous case, the scaling factor is not an integer.
+	 * So when tms_utime, tms_stime, or their sum wraps, some of the
+	 * "visible" bits in the return value are affected.  Nothing we
+	 * can really do about this though other than handle tms_utime and
+	 * tms_stime seperately and then sum.  But since that doesn't really
+	 * buy us much, we don't bother. */
+
+	return ((((t / __UCLIBC_CLK_TCK_CONST) * CLOCKS_PER_SEC)
+			 + ((((t % __UCLIBC_CLK_TCK_CONST) * CLOCKS_PER_SEC)
+				 / __UCLIBC_CLK_TCK_CONST))
+			 ) & LONG_MAX);
+
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_ctime
+
+char *ctime(const time_t *t)
+{
+	/* ANSI/ISO/SUSv3 say that ctime is equivalent to the following:
+	 * return asctime(localtime(t));
+	 * I don't think "equivalent" means "it uses the same internal buffer",
+	 * it means "gives the same resultant string".
+	 *
+	 * I doubt anyone ever uses weird code like:
+	 * struct tm *ptm = localtime(t1); ...; ctime(t2); use(ptm);
+	 * which relies on the assumption that ctime's and localtime's
+	 * internal static struct tm is the same.
+	 *
+	 * Using localtime_r instead of localtime avoids linking in
+	 * localtime's static buffer:
+	 */
+	struct tm xtm;
+	memset(&xtm, 0, sizeof(xtm));
+
+	return asctime(localtime_r(t, &xtm));
+}
+libc_hidden_def(ctime)
+#endif
+/**********************************************************************/
+#ifdef L_ctime_r
+
+char *ctime_r(const time_t *t, char *buf)
+{
+	struct tm xtm;
+
+	return asctime_r(localtime_r(t, &xtm), buf);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_difftime
+
+#include <float.h>
+
+#if FLT_RADIX != 2
+#error difftime implementation assumptions violated for you arch!
+#endif
+
+double difftime(time_t time1, time_t time0)
+{
+#if (LONG_MAX >> DBL_MANT_DIG) == 0
+
+	/* time_t fits in the mantissa of a double. */
+	return (double)time1 - (double)time0;
+
+#elif ((LONG_MAX >> DBL_MANT_DIG) >> DBL_MANT_DIG) == 0
+
+	/* time_t can overflow the mantissa of a double. */
+	time_t t1, t0, d;
+
+	d = ((time_t) 1) << DBL_MANT_DIG;
+	t1 = time1 / d;
+	time1 -= (t1 * d);
+	t0 = time0 / d;
+	time0 -= (t0*d);
+
+	/* Since FLT_RADIX==2 and d is a power of 2, the only possible
+	 * rounding error in the expression below would occur from the
+	 * addition. */
+	return (((double) t1) - t0) * d + (((double) time1) - time0);
+
+#else
+#error difftime needs special implementation on your arch.
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_gmtime
+
+struct tm *gmtime(const time_t *timer)
+{
+	register struct tm *ptm = &__time_tm;
+
+	_time_t2tm(timer, 0, ptm); /* Can return NULL... */
+
+	return ptm;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_gmtime_r
+
+struct tm *gmtime_r(const time_t *__restrict timer,
+					struct tm *__restrict result)
+{
+	return _time_t2tm(timer, 0, result);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_localtime
+
+struct tm *localtime(const time_t *timer)
+{
+	register struct tm *ptm = &__time_tm;
+
+	/* In this implementation, tzset() is called by localtime_r().  */
+
+	localtime_r(timer, ptm);	/* Can return NULL... */
+
+	return ptm;
+}
+libc_hidden_def(localtime)
+
+#endif
+/**********************************************************************/
+#ifdef L_localtime_r
+
+struct tm *localtime_r(register const time_t *__restrict timer,
+					   register struct tm *__restrict result)
+{
+	__UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+	_time_tzset(*timer < new_rule_starts);
+
+	__time_localtime_tzi(timer, result, _time_tzinfo);
+
+	__UCLIBC_MUTEX_UNLOCK(_time_tzlock);
+
+	return result;
+}
+libc_hidden_def(localtime_r)
+
+#endif
+/**********************************************************************/
+#ifdef L__time_localtime_tzi
+
+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+
+struct ll_tzname_item;
+
+typedef struct ll_tzname_item {
+	struct ll_tzname_item *next;
+	char tzname[1];
+} ll_tzname_item_t;
+
+/* Structures form a list "UTC" -> "???" -> "tzname1" -> "tzname2"... */
+struct {
+	struct ll_tzname_item *next;
+	char tzname[4];
+} ll_tzname_UNKNOWN = { NULL, "???" };
+const struct {
+	struct ll_tzname_item *next;
+	char tzname[4];
+} ll_tzname_UTC = { (void*)&ll_tzname_UNKNOWN, "UTC" };
+
+static const char *lookup_tzname(const char *key)
+{
+	int len;
+	ll_tzname_item_t *p = (void*) &ll_tzname_UTC;
+
+	do {
+		if (strcmp(p->tzname, key) == 0)
+			return p->tzname;
+		p = p->next;
+	} while (p != NULL);
+
+	/* Hmm... a new name. */
+	len = strnlen(key, TZNAME_MAX+1);
+	if (len < TZNAME_MAX+1) { /* Verify legal length */
+		p = malloc(sizeof(ll_tzname_item_t) + len);
+		if (p != NULL) {
+			/* Insert as 3rd item in the list. */
+			p->next = ll_tzname_UNKNOWN.next;
+			ll_tzname_UNKNOWN.next = p;
+			return strcpy(p->tzname, key);
+		}
+	}
+
+	/* Either invalid or couldn't alloc. */
+	return ll_tzname_UNKNOWN.tzname;
+}
+
+#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */
+
+static const unsigned char day_cor[] = { /* non-leap */
+	31, 31, 34, 34, 35, 35, 36, 36, 36, 37, 37, 38, 38
+/*	 0,  0,  3,  3,  4,  4,  5,  5,  5,  6,  6,  7,  7 */
+/*	    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 */
+};
+
+/* Note: timezone locking is done by localtime_r. */
+
+static int tm_isdst(register const struct tm *__restrict ptm,
+					register rule_struct *r)
+{
+	long sec;
+	int i, isdst, isleap, day, day0, monlen, mday;
+	int oday = oday; /* ok to be uninitialized, shutting up compiler warning */
+
+	isdst = 0;
+	if (r[1].tzname[0] != 0) {
+		/* First, get the current seconds offset from the start of the year.
+		 * Fields of ptm are assumed to be in their normal ranges. */
+		sec = ptm->tm_sec
+			+ 60 * (ptm->tm_min
+					+ 60 * (long)(ptm->tm_hour
+								  + 24 * ptm->tm_yday));
+		/* Do some prep work. */
+		i = (ptm->tm_year % 400) + 1900; /* Make sure we don't overflow. */
+		isleap = __isleap(i);
+		--i;
+		day0 = (1
+				+ i				/* Normal years increment 1 wday. */
+				+ (i/4)
+				- (i/100)
+				+ (i/400) ) % 7;
+		i = 0;
+		do {
+			day = r->day;		/* Common for 'J' and # case. */
+			if (r->rule_type == 'J') {
+				if (!isleap || (day < (31+29))) {
+					--day;
+				}
+			} else if (r->rule_type == 'M') {
+				/* Find 0-based day number for 1st of the month. */
+				day = 31*r->month - day_cor[r->month -1];
+				if (isleap && (day >= 59)) {
+					++day;
+				}
+				monlen = 31 + day_cor[r->month -1] - day_cor[r->month];
+				if (isleap && (r->month == 2)) {
+					++monlen;
+				}
+				/* Wweekday (0 is Sunday) of 1st of the month
+				 * is (day0 + day) % 7. */
+				if ((mday = r->day - ((day0 + day) % 7)) >= 0) {
+					mday -= 7;	/* Back up into prev month since r->week>0. */
+				}
+				if ((mday += 7 * r->week) >= monlen) {
+					mday -= 7;
+				}
+				/* So, 0-based day number is... */
+				day += mday;
+			}
+
+			if (i != 0) {
+				/* Adjust sec since dst->std change time is in dst. */
+				sec += (r[-1].gmt_offset - r->gmt_offset);
+				if (oday > day) {
+					++isdst;	/* Year starts in dst. */
+				}
+			}
+			oday = day;
+
+			/* Now convert day to seconds and add offset and compare. */
+			if (sec >= (day * 86400L) + r->dst_offset) {
+				++isdst;
+			}
+			++r;
+		} while (++i < 2);
+	}
+
+	return (isdst & 1);
+}
+
+struct tm attribute_hidden *__time_localtime_tzi(register const time_t *__restrict timer,
+								register struct tm *__restrict result,
+								rule_struct *tzi)
+{
+	time_t x[1];
+	long offset;
+	int days, dst;
+
+	dst = 0;
+	do {
+		days = -7;
+		offset = 604800L - tzi[dst].gmt_offset;
+		if (*timer > (LONG_MAX - 604800L)) {
+			days = -days;
+			offset = -offset;
+		}
+		*x = *timer + offset;
+
+		_time_t2tm(x, days, result);
+		result->tm_isdst = dst;
+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+# ifdef __USE_BSD
+		result->tm_gmtoff = - tzi[dst].gmt_offset;
+		result->tm_zone = lookup_tzname(tzi[dst].tzname);
+# else
+		result->__tm_gmtoff = - tzi[dst].gmt_offset;
+		result->__tm_zone = lookup_tzname(tzi[dst].tzname);
+# endif
+#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */
+	} while ((++dst < 2)
+			 && ((result->tm_isdst = tm_isdst(result, tzi)) != 0));
+
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_mktime
+
+time_t mktime(struct tm *timeptr)
+{
+	return  _time_mktime(timeptr, 1);
+}
+
+/* Another name for `mktime'.  */
+/* time_t timelocal(struct tm *tp) */
+strong_alias(mktime,timelocal)
+
+#endif
+/**********************************************************************/
+#ifdef L_timegm
+/* Like `mktime' but timeptr represents Universal Time, not local time. */
+
+time_t timegm(struct tm *timeptr)
+{
+	rule_struct gmt_tzinfo[2];
+
+	memset(gmt_tzinfo, 0, sizeof(gmt_tzinfo));
+	strcpy(gmt_tzinfo[0].tzname, "GMT"); /* Match glibc behavior here. */
+
+	return  _time_mktime_tzi(timeptr, 1, gmt_tzinfo);
+}
+
+#endif
+/**********************************************************************/
+#if defined(L_strftime) || defined(L_strftime_l)
+
+#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
+
+size_t strftime(char *__restrict s, size_t maxsize,
+				const char *__restrict format,
+				const struct tm *__restrict timeptr)
+{
+	return strftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE);
+}
+
+#else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+#define NO_E_MOD		0x80
+#define NO_O_MOD		0x40
+
+#define ILLEGAL_SPEC	0x3f
+
+#define INT_SPEC		0x00	/* must be 0x00!! */
+#define STRING_SPEC		0x10	/* must be 0x10!! */
+#define CALC_SPEC		0x20
+#define STACKED_SPEC	0x30
+
+#define MASK_SPEC		0x30
+
+/* Compatibility:
+ *
+ * No alternate digit (%O?) handling.  Always uses 0-9.
+ * Alternate locale format (%E?) handling is broken for nontrivial ERAs.
+ * glibc's %P is currently faked by %p.  This means it doesn't do lower case.
+ * glibc's %k, %l, and %s are handled.
+ * glibc apparently allows (and ignores) extraneous 'E' and 'O' modifiers,
+ *   while they are flagged as illegal conversions here.
+ */
+
+/* Warning: Assumes ASCII values! (as do lots of other things in the lib...) */
+static const unsigned char spec[] = {
+	/* A */		0x03 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* B */		0x04 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* C */		0x0a |     INT_SPEC            | NO_O_MOD,
+	/* D */		0x02 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* E */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* F */		0x03 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* G */		0x03 |    CALC_SPEC | NO_E_MOD | NO_O_MOD,
+	/* H */		0x0b |     INT_SPEC | NO_E_MOD,
+	/* I */		0x0c |     INT_SPEC | NO_E_MOD,
+	/* J */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* K */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* L */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* M */		0x0d |     INT_SPEC | NO_E_MOD,
+	/* N */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* O */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* P */		0x05 |  STRING_SPEC | NO_E_MOD | NO_O_MOD, /* glibc ; use %p */
+	/* Q */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* R */		0x04 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* S */		0x0e |     INT_SPEC | NO_E_MOD,
+	/* T */		0x05 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* U */		0x04 |    CALC_SPEC | NO_E_MOD,
+	/* V */		0x05 |    CALC_SPEC | NO_E_MOD,
+	/* W */		0x06 |    CALC_SPEC | NO_E_MOD,
+	/* X */		0x0a | STACKED_SPEC            | NO_O_MOD,
+	/* Y */		0x0f |     INT_SPEC            | NO_O_MOD,
+	/* Z */		0x01 |    CALC_SPEC | NO_E_MOD | NO_O_MOD,
+	'?',						/* 26 */
+	'?',						/* 27 */
+	'?',						/* 28 */
+	'?',						/* 29 */
+	0,							/* 30 */
+	0,							/* 31 */
+	/* a */		0x00 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* b */		0x01 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* c */		0x08 | STACKED_SPEC            | NO_O_MOD,
+	/* d */		0x00 |     INT_SPEC | NO_E_MOD,
+	/* e */		0x01 |     INT_SPEC | NO_E_MOD,
+	/* f */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* g */		0x02 |    CALC_SPEC | NO_E_MOD | NO_O_MOD,
+	/* h */		0x01 |  STRING_SPEC | NO_E_MOD | NO_O_MOD, /* same as b */
+	/* i */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* j */		0x08 |     INT_SPEC | NO_E_MOD | NO_O_MOD,
+	/* k */		0x03 |     INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* l */		0x04 |     INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* m */		0x05 |     INT_SPEC | NO_E_MOD,
+	/* n */		0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* o */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* p */		0x02 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* q */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* r */		0x0b | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* s */		0x07 |    CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* t */		0x01 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* u */		0x07 |     INT_SPEC | NO_E_MOD,
+	/* v */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* w */		0x02 |     INT_SPEC | NO_E_MOD,
+	/* x */		0x09 | STACKED_SPEC            | NO_O_MOD,
+	/* y */		0x09 |     INT_SPEC,
+	/* z */		0x00 |    CALC_SPEC | NO_E_MOD | NO_O_MOD,
+
+
+	/* WARNING!!! These are dependent on the layout of struct tm!!! */
+#define FIELD_MAX (26+6+26)
+	60 /* 61? */, 59, 23, 31, 11, 0 /* 9999 */, 6, 0 /* 365 */,
+
+#define TP_OFFSETS (FIELD_MAX+8)
+	3, /* d */
+	3, /* e */
+	6, /* w */
+	2, /* k */
+	2, /* l */
+	4, /* m */
+	0, /* CURRENTLY UNUSED */
+	/* NOTE: u,j,y order must be preserved as 6,7,5 seq is used in the code! */
+#define CALC_OFFSETS (TP_OFFSETS + 7)
+	6, /* u */
+	7, /* j */
+	5, /* y */
+	5, /* C */
+	2, /* H */
+	2, /* I */
+	1, /* M */
+	0, /* S */
+	5, /* Y */
+	6, /* a */
+	4, /* b, h */
+	2, /* p */
+	6, /* A */
+	4, /* B */
+	2, /* P */
+
+#define TP_CODES (TP_OFFSETS + 16 + 6)
+	2 | 16, /* d */
+	2, /* e */
+	0 | 16, /* w */
+	2, /* k */
+	2 | 32 | 0, /* l */
+	2 | 16 | 1, /* m */
+	0, /* CURRENTLY UNUSED */
+	0 | 16 | 8 , /* u */
+	4 | 16 | 1, /* j */
+	2 | 128 | 32 | 16 , /* y */
+	2 | 128 | 64 | 32 | 16 , /* C */
+	2 | 16, /* H */
+	2 | 32 | 16 | 0, /* I */
+	2 | 16, /* M */
+	2 | 16, /* S */
+	6 | 16, /* Y */
+	2, /* a */
+	2, /* b, h */
+	2 | 64, /* p */
+	2, /* A */
+	2, /* B */
+	2 | 64, /* P */
+
+#define STRINGS_NL_ITEM_START (TP_CODES + 16 + 6)
+	_NL_ITEM_INDEX(ABDAY_1),	/* a */
+	_NL_ITEM_INDEX(ABMON_1),	/* b, h */
+	_NL_ITEM_INDEX(AM_STR),		/* p */
+	_NL_ITEM_INDEX(DAY_1),		/* A */
+	_NL_ITEM_INDEX(MON_1),		/* B */
+	_NL_ITEM_INDEX(AM_STR),		/* P -- wrong! need lower case */
+
+#define STACKED_STRINGS_START (STRINGS_NL_ITEM_START+6)
+	6, 7, 8, 16, 24, 29,		/* 6 - offsets from offset-count to strings */
+	'\n', 0,					/* 2 */
+	'\t', 0,					/* 2 */
+	'%', 'm', '/', '%', 'd', '/', '%', 'y', 0, /* 9 - %D */
+	'%', 'Y', '-', '%', 'm', '-', '%', 'd', 0, /* 9 - %F (glibc extension) */
+	'%', 'H', ':', '%', 'M', 0,	/* 6 - %R*/
+	'%', 'H', ':', '%', 'M', ':', '%', 'S', 0, /* 9 - %T */
+
+#define STACKED_STRINGS_NL_ITEM_START (STACKED_STRINGS_START + 43)
+	_NL_ITEM_INDEX(D_T_FMT),	/* c */
+	_NL_ITEM_INDEX(D_FMT),		/* x */
+	_NL_ITEM_INDEX(T_FMT),		/* X */
+	_NL_ITEM_INDEX(T_FMT_AMPM), /* r */
+#ifdef ENABLE_ERA_CODE
+	_NL_ITEM_INDEX(ERA_D_T_FMT), /* Ec */
+	_NL_ITEM_INDEX(ERA_D_FMT),	/* Ex */
+	_NL_ITEM_INDEX(ERA_T_FMT),	/* EX */
+#endif
+};
+
+static int load_field(int k, const struct tm *__restrict timeptr)
+{
+	int r;
+	int r_max;
+
+	r = ((int *) timeptr)[k];
+
+	r_max = spec[FIELD_MAX + k];
+
+	if (k == 7) {
+		r_max = 365;
+	} else if (k == 5) {
+		r += 1900;
+		r_max = 9999;
+	}
+
+	if ((((unsigned int) r) > r_max) || ((k == 3) && !r)) {
+		r = -1;
+	}
+
+	return r;
+}
+
+#define MAX_PUSH 4
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Check multibyte format string validity.
+#endif
+
+size_t __XL_NPP(strftime)(char *__restrict s, size_t maxsize,
+					  const char *__restrict format,
+					  const struct tm *__restrict timeptr   __LOCALE_PARAM )
+{
+	long tzo;
+	register const char *p;
+	register const char *o;
+#ifndef __UCLIBC_HAS_TM_EXTENSIONS__
+	const rule_struct *rsp;
+#endif
+	const char *stack[MAX_PUSH];
+	size_t count;
+	size_t o_count;
+	int field_val = 0, i = 0, j, lvl;
+	int x[3];			/* wday, yday, year */
+	int isofm, days;
+	char buf[__UIM_BUFLEN_LONG];
+	unsigned char mod;
+	unsigned char code;
+
+	/* We'll, let's get this out of the way. */
+	_time_tzset(_time_mktime((struct tm *) timeptr, 0) < new_rule_starts);
+
+	lvl = 0;
+	p = format;
+	count = maxsize;
+
+LOOP:
+	if (!count) {
+		return 0;
+	}
+	if (!*p) {
+		if (lvl == 0) {
+			*s = 0;				/* nul-terminate */
+			return maxsize - count;
+		}
+		p = stack[--lvl];
+		goto LOOP;
+	}
+
+	o_count = 1;
+	if ((*(o = p) == '%') && (*++p != '%')) {
+		o_count = 2;
+		mod = ILLEGAL_SPEC;
+		if ((*p == 'O') || (*p == 'E')) { /* modifier */
+			mod |= ((*p == 'O') ? NO_O_MOD : NO_E_MOD);
+			++o_count;
+			++p;
+		}
+		if ((((unsigned char)(((*p) | 0x20) - 'a')) >= 26)
+			|| (((code = spec[(int)(*p - 'A')]) & mod) >= ILLEGAL_SPEC)
+			) {
+			if (!*p) {
+				--p;
+				--o_count;
+			}
+			goto OUTPUT;
+		}
+		code &= ILLEGAL_SPEC;	/* modifiers are preserved in mod var. */
+
+		if ((code & MASK_SPEC) == STACKED_SPEC) {
+			if (lvl == MAX_PUSH) {
+				goto OUTPUT;	/* Stack full so treat as illegal spec. */
+			}
+			stack[lvl++] = ++p;
+			if ((code &= 0xf) < 8) {
+				p = ((const char *) spec) + STACKED_STRINGS_START + code;
+				p += *((unsigned char *)p);
+				goto LOOP;
+			}
+			p = ((const char *) spec) + STACKED_STRINGS_NL_ITEM_START
+				+ (code & 7);
+#ifdef ENABLE_ERA_CODE
+			if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */
+				&& (*(o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME,
+							(int)(((unsigned char *)p)[4]))
+							__LOCALE_ARG
+							)))
+				) {
+				p = o;
+				goto LOOP;
+			}
+#endif
+			p = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME,
+							(int)(*((unsigned char *)p)))
+							__LOCALE_ARG
+							);
+			goto LOOP;
+		}
+
+		o = ((const char *) spec) + 26;	/* set to "????" */
+		if ((code & MASK_SPEC) == CALC_SPEC) {
+
+			if (*p == 's') {
+				time_t t;
+
+				/* Use a cast to silence the warning since *timeptr won't
+				 * be changed. */
+				if ((t = _time_mktime((struct tm *) timeptr, 0))
+					== ((time_t) -1)
+					) {
+					o_count = 1;
+					goto OUTPUT;
+				}
+#ifdef TIME_T_IS_UNSIGNED
+				o = _uintmaxtostr(buf + sizeof(buf) - 1,
+								  (uintmax_t) t,
+								  10, __UIM_DECIMAL);
+#else
+				o = _uintmaxtostr(buf + sizeof(buf) - 1,
+								  (uintmax_t) t,
+								  -10, __UIM_DECIMAL);
+#endif
+				o_count = sizeof(buf);
+				goto OUTPUT;
+			} else if (((*p) | 0x20) == 'z') { /* 'z' or 'Z' */
+
+				if (timeptr->tm_isdst < 0) {
+					/* SUSv3 specifies this behavior for 'z', but we'll also
+					 * treat it as "no timezone info" for 'Z' too. */
+					o_count = 0;
+					goto OUTPUT;
+				}
+
+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+
+# ifdef __USE_BSD
+#  define RSP_TZNAME		timeptr->tm_zone
+#  define RSP_GMT_OFFSET	(-timeptr->tm_gmtoff)
+# else
+#  define RSP_TZNAME		timeptr->__tm_zone
+#  define RSP_GMT_OFFSET	(-timeptr->__tm_gmtoff)
+# endif
+
+#else
+
+#define RSP_TZNAME		rsp->tzname
+#define RSP_GMT_OFFSET	rsp->gmt_offset
+
+				__UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+				rsp = _time_tzinfo;
+				if (timeptr->tm_isdst > 0) {
+					++rsp;
+				}
+#endif
+
+				if (*p == 'Z') {
+					o = RSP_TZNAME;
+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+					/* Sigh... blasted glibc extensions.  Of course we can't
+					 * count on the pointer being valid.  Best we can do is
+					 * handle NULL, which looks to be all that glibc does.
+					 * At least that catches the memset() with 0 case.
+					 * NOTE: We handle this case differently than glibc!
+					 * It uses system timezone name (based on tm_isdst) in this
+					 * case... although it always seems to use the embedded
+					 * tm_gmtoff value.  What we'll do instead is treat the
+					 * timezone name as unknown/invalid and return "???". */
+					if (!o) {
+						o = "???";
+					}
+#endif
+					assert(o != NULL);
+#if 0
+					if (!o) {	/* PARANOIA */
+						o = spec+30; /* empty string */
+					}
+#endif
+					o_count = SIZE_MAX;
+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+					goto OUTPUT;
+#endif
+				} else {		/* z */
+					*s = '+';
+					if ((tzo = -RSP_GMT_OFFSET) < 0) {
+						tzo = -tzo;
+						*s = '-';
+					}
+					++s;
+					--count;
+
+					i = tzo / 60;
+					field_val = ((i / 60) * 100) + (i % 60);
+
+					i = 16 + 6;	/* 0-fill, width = 4 */
+				}
+#ifndef __UCLIBC_HAS_TM_EXTENSIONS__
+				__UCLIBC_MUTEX_UNLOCK(_time_tzlock);
+				if (*p == 'Z') {
+					goto OUTPUT;
+				}
+#endif
+			} else {
+				/* TODO: don't need year for U, W */
+				for (i=0 ; i < 3 ; i++) {
+					if ((x[i] = load_field(spec[CALC_OFFSETS+i],timeptr)) < 0) {
+						goto OUTPUT;
+					}
+				}
+
+				i = 16 + 2;		/* 0-fill, width = 2 */
+
+				if ((*p == 'U') || (*p == 'W')) {
+					field_val = ((x[1] - x[0]) + 7);
+					if (*p == 'W') {
+						++field_val;
+					}
+					field_val /= 7;
+					if ((*p == 'W') && !x[0]) {
+						--field_val;
+					}
+				} else {	/* ((*p == 'g') || (*p == 'G') || (*p == 'V')) */
+ISO_LOOP:
+					isofm = (((x[1] - x[0]) + 11) % 7) - 3;	/* [-3,3] */
+
+					if (x[1] < isofm) {	/* belongs to previous year */
+						--x[2];
+						x[1] += 365 + __isleap(x[2]);
+						goto ISO_LOOP;
+					}
+
+					field_val = ((x[1] - isofm) / 7) + 1; /* week # */
+					days = 365 + __isleap(x[2]);
+					isofm = ((isofm + 7*53 + 3 - days)) % 7 + days - 3; /* next year */
+					if (x[1] >= isofm) { /* next year */
+						x[1] -= days;
+						++x[2];
+						goto ISO_LOOP;
+					}
+
+					if (*p != 'V') { /* need year */
+						field_val = x[2]; /* TODO: what if x[2] now 10000 ?? */
+						if (*p == 'g') {
+							field_val %= 100;
+						} else {
+							i = 16 + 6;	/* 0-fill, width = 4 */
+						}
+					}
+				}
+			}
+		} else {
+			i = TP_OFFSETS + (code & 0x1f);
+			if ((field_val = load_field(spec[i], timeptr)) < 0) {
+				goto OUTPUT;
+			}
+
+			i = spec[i+(TP_CODES - TP_OFFSETS)];
+
+			j = (i & 128) ? 100: 12;
+			if (i & 64) {
+				field_val /= j;;
+			}
+			if (i & 32) {
+				field_val %= j;
+				if (((i & 128) + field_val) == 0) { /* mod 12? == 0 */
+					field_val = j; /* set to 12 */
+				}
+			}
+			field_val += (i & 1);
+			if ((i & 8) && !field_val) {
+				field_val += 7;
+			}
+		}
+
+		if ((code & MASK_SPEC) == STRING_SPEC) {
+			o_count = SIZE_MAX;
+			field_val += spec[STRINGS_NL_ITEM_START + (code & 0xf)];
+			o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, field_val)  __LOCALE_ARG);
+		} else {
+			o_count = ((i >> 1) & 3) + 1;
+			o = buf + o_count;
+			do {
+				*(char *)(--o) = '0' + (field_val % 10);
+				field_val /= 10;
+			} while (o > buf);
+			if (*buf == '0') {
+				*buf = ' ' + (i & 16);
+			}
+		}
+	}
+
+OUTPUT:
+	++p;
+	while (o_count && count && *o) {
+		*s++ = *o++;
+		--o_count;
+		--count;
+	}
+	goto LOOP;
+}
+# ifdef L_strftime_l
+libc_hidden_def(strftime_l)
+# endif
+
+#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+#endif
+/**********************************************************************/
+#if defined(L_strptime) || defined(L_strptime_l)
+
+#define ISDIGIT(C) __isdigit_char((C))
+
+#ifdef __UCLIBC_DO_XLOCALE
+#define ISSPACE(C) isspace_l((C), locale_arg)
+#else
+#define ISSPACE(C) isspace((C))
+#endif
+
+#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
+
+char *strptime(const char *__restrict buf, const char *__restrict format,
+			   struct tm *__restrict tm)
+{
+	return strptime_l(buf, format, tm, __UCLIBC_CURLOCALE);
+}
+
+#else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+/* TODO:
+ * 1) %l and %k are space-padded, so "%l" by itself fails while " %l" succeeds.
+ *    Both work for glibc.  So, should we always strip spaces?
+ * 2) %Z
+ */
+
+/* Notes:
+ * There are several differences between this strptime and glibc's strptime.
+ * 1) glibc strips leading space before numeric conversions.
+ * 2) glibc will read fields without whitespace in between.  SUSv3 states
+ *    that you must have whitespace between conversion operators.  Besides,
+ *    how do you know how long a number should be if there are leading 0s?
+ * 3) glibc attempts to compute some the struct tm fields based on the
+ *    data retrieved; tm_wday in particular.  I don't as I consider it
+ *     another glibc attempt at mind-reading...
+ */
+
+#define NO_E_MOD		0x80
+#define NO_O_MOD		0x40
+
+#define ILLEGAL_SPEC	0x3f
+
+#define INT_SPEC		0x00	/* must be 0x00!! */
+#define STRING_SPEC		0x10	/* must be 0x10!! */
+#define CALC_SPEC		0x20
+#define STACKED_SPEC	0x30
+
+#define MASK_SPEC		0x30
+
+/* Warning: Assumes ASCII values! (as do lots of other things in the lib...) */
+static const unsigned char spec[] = {
+	/* A */		0x02 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* B */		0x01 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* C */		0x08 |     INT_SPEC            | NO_O_MOD,
+	/* D */		0x01 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* E */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* F */		0x02 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* G */		0x0f |     INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* H */		0x06 |     INT_SPEC | NO_E_MOD,
+	/* I */		0x07 |     INT_SPEC | NO_E_MOD,
+	/* J */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* K */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* L */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* M */		0x04 |     INT_SPEC | NO_E_MOD,
+	/* N */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* O */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* P */		0x00 |  STRING_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* Q */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* R */		0x03 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* S */		0x05 |     INT_SPEC | NO_E_MOD,
+	/* T */		0x04 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* U */		0x0c |     INT_SPEC | NO_E_MOD,
+	/* V */		0x0d |     INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* W */		0x0c |     INT_SPEC | NO_E_MOD,
+	/* X */		0x0a | STACKED_SPEC            | NO_O_MOD,
+	/* Y */		0x0a |     INT_SPEC            | NO_O_MOD,
+	/* Z */		0x02 |    CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+
+	/* WARNING! This assumes orderings:
+	 *    AM,PM
+	 *    ABDAY_1-ABDAY-7,DAY_1-DAY_7
+	 *    ABMON_1-ABMON_12,MON_1-MON12
+	 * Also, there are exactly 6 bytes between 'Z' and 'a'.
+	 */
+#define STRINGS_NL_ITEM_START (26)
+	_NL_ITEM_INDEX(AM_STR),		/* p (P) */
+	_NL_ITEM_INDEX(ABMON_1),	/* B, b */
+	_NL_ITEM_INDEX(ABDAY_1),	/* A, a */
+	2,
+	24,
+	14,
+
+	/* a */		0x02 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* b */		0x01 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* c */		0x08 | STACKED_SPEC            | NO_O_MOD,
+	/* d */		0x00 |     INT_SPEC | NO_E_MOD,
+	/* e */		0x00 |     INT_SPEC | NO_E_MOD,
+	/* f */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* g */		0x0e |     INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* h */		0x01 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* i */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* j */		0x01 |     INT_SPEC | NO_E_MOD | NO_O_MOD,
+	/* k */		0x06 |     INT_SPEC | NO_E_MOD,            /* glibc */
+	/* l */		0x07 |     INT_SPEC | NO_E_MOD,            /* glibc */
+	/* m */		0x02 |     INT_SPEC | NO_E_MOD,
+	/* n */		0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* o */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* p */		0x00 |  STRING_SPEC | NO_E_MOD | NO_O_MOD,
+	/* q */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* r */		0x0b | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* s */		0x00 |    CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* t */		0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD,
+	/* u */		0x0b |     INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+	/* v */		       ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD,
+	/* w */		0x03 |     INT_SPEC | NO_E_MOD,
+	/* x */		0x09 | STACKED_SPEC            | NO_O_MOD,
+	/* y */		0x09 |     INT_SPEC,
+	/* z */		0x01 |    CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */
+
+#define INT_FIELD_START (26+6+26)
+	/* (field #) << 3  + lower bound (0|1) + correction 0:none, 2:-1, 4:-1900
+	 * followed by upper bound prior to correction with 1=>366 and 2=>9999. */
+	/* d, e */	(3 << 3) + 1 + 0, 31,
+	/* j */		(7 << 3) + 1 + 2, /* 366 */ 1,
+	/* m */		(4 << 3) + 1 + 2, 12,
+	/* w */		(6 << 3) + 0 + 0, 6,
+	/* M */		(1 << 3) + 0 + 0, 59,
+	/* S */		0        + 0 + 0, 60,
+	/* H (k) */	(2 << 3) + 0 + 0, 23,
+	/* I (l) */	(9 << 3) + 1 + 0, 12, /* goes with 8 -- am/pm */
+	/* C */		(10<< 3) + 0 + 0, 99,
+	/* y */		(11<< 3) + 0 + 0, 99,
+	/* Y */		(5 << 3) + 0 + 4, /* 9999 */ 2,
+	/* u */		(6 << 3) + 1 + 0, 7,
+	/* The following are processed and range-checked, but ignored otherwise. */
+	/* U, W */	(12<< 3) + 0 + 0, 53,
+	/* V */		(12<< 3) + 1 + 0, 53,
+	/* g */		(12<< 3) + 0 + 0, 99,
+	/* G */		(12<< 3) + 0 /*+ 4*/, /* 9999 */ 2, /* Note: -1 or 10000? */
+
+#define STACKED_STRINGS_START (INT_FIELD_START+32)
+	5, 6, 14, 22, 27,			/* 5 - offsets from offset-count to strings */
+	' ', 0,						/* 2 - %n or %t */
+	'%', 'm', '/', '%', 'd', '/', '%', 'y', 0, /* 9 - %D */
+	'%', 'Y', '-', '%', 'm', '-', '%', 'd', 0, /* 9 - %F (glibc extension) */
+	'%', 'H', ':', '%', 'M', 0,	/* 6 - %R*/
+	'%', 'H', ':', '%', 'M', ':', '%', 'S', 0, /* 9 - %T */
+
+#define STACKED_STRINGS_NL_ITEM_START (STACKED_STRINGS_START + 40)
+	_NL_ITEM_INDEX(D_T_FMT),	/* c */
+	_NL_ITEM_INDEX(D_FMT),		/* x */
+	_NL_ITEM_INDEX(T_FMT),		/* X */
+	_NL_ITEM_INDEX(T_FMT_AMPM), /* r */
+#ifdef ENABLE_ERA_CODE
+	_NL_ITEM_INDEX(ERA_D_T_FMT), /* Ec */
+	_NL_ITEM_INDEX(ERA_D_FMT),	/* Ex */
+	_NL_ITEM_INDEX(ERA_T_FMT),	/* EX */
+#endif
+};
+
+#define MAX_PUSH 4
+
+char *__XL_NPP(strptime)(const char *__restrict buf, const char *__restrict format,
+					 struct tm *__restrict tm   __LOCALE_PARAM)
+{
+	register const char *p;
+	char *o;
+	const char *stack[MAX_PUSH];
+	int i, j, lvl;
+	int fields[13];
+	unsigned char mod;
+	unsigned char code;
+
+	i = 0;
+	do {
+		fields[i] = INT_MIN;
+	} while (++i < 13);
+
+	lvl = 0;
+	p = format;
+
+LOOP:
+	if (!*p) {
+		if (lvl == 0) {			/* Done. */
+			if (fields[6] == 7) { /* Cleanup for %u here since just once. */
+				fields[6] = 0;	/* Don't use mod in case unset. */
+			}
+
+			i = 0;
+			do {				/* Store the values into tm. */
+				if (fields[i] != INT_MIN) {
+					((int *) tm)[i] = fields[i];
+				}
+			} while (++i < 8);
+
+			return (char *) buf; /* Success. */
+		}
+		p = stack[--lvl];
+		goto LOOP;
+	}
+
+	if ((*p == '%') && (*++p != '%')) {
+		mod = ILLEGAL_SPEC;
+		if ((*p == 'O') || (*p == 'E')) { /* Modifier? */
+			mod |= ((*p == 'O') ? NO_O_MOD : NO_E_MOD);
+			++p;
+		}
+
+		if (!*p
+			|| (((unsigned char)(((*p) | 0x20) - 'a')) >= 26)
+			|| (((code = spec[(int)(*p - 'A')]) & mod) >= ILLEGAL_SPEC)
+			) {
+			return NULL;		/* Illegal spec. */
+		}
+
+		if ((code & MASK_SPEC) == STACKED_SPEC) {
+			if (lvl == MAX_PUSH) {
+				return NULL;	/* Stack full so treat as illegal spec. */
+			}
+			stack[lvl++] = ++p;
+			if ((code &= 0xf) < 8) {
+				p = ((const char *) spec) + STACKED_STRINGS_START + code;
+				p += *((unsigned char *)p);
+				goto LOOP;
+			}
+
+			p = ((const char *) spec) + STACKED_STRINGS_NL_ITEM_START
+				+ (code & 7);
+#ifdef ENABLE_ERA_CODE
+			if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */
+				&& (*(o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME,
+							(int)(((unsigned char *)p)[4]))
+							__LOCALE_ARG
+							)))
+				) {
+				p = o;
+				goto LOOP;
+			}
+#endif
+			p = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME,
+							(int)(*((unsigned char *)p)))
+							__LOCALE_ARG
+							);
+			goto LOOP;
+		}
+
+		++p;
+
+		if ((code & MASK_SPEC) == STRING_SPEC) {
+			code &= 0xf;
+			j = spec[STRINGS_NL_ITEM_START + 3 + code];
+			i = _NL_ITEM(LC_TIME, spec[STRINGS_NL_ITEM_START + code]);
+			/* Go backwards to check full names before abreviations. */
+			do {
+				--j;
+				o = __XL_NPP(nl_langinfo)(i+j   __LOCALE_ARG);
+				if (!__XL_NPP(strncasecmp)(buf, o, strlen(o)   __LOCALE_ARG) && *o) {
+					do {		/* Found a match. */
+						++buf;
+					} while (*++o);
+					if (!code) { /* am/pm */
+						fields[8] = j * 12;
+						if (fields[9] >= 0) { /* We have a previous %I or %l. */
+							fields[2] = fields[9] + fields[8];
+						}
+					} else {	/* day (4) or month (6) */
+						fields[2 + (code << 1)]
+							= j % (spec[STRINGS_NL_ITEM_START + 3 + code] >> 1);
+					}
+					goto LOOP;
+				}
+			} while (j);
+			return NULL;		/* Failed to match. */
+		}
+
+		if ((code & MASK_SPEC) == CALC_SPEC) {
+			if ((code &= 0xf) < 1) { /* s or z*/
+				time_t t;
+
+				o = (char *) buf;
+				i = errno;
+				__set_errno(0);
+				if (!ISSPACE(*buf)) { /* Signal an error if whitespace. */
+#ifdef TIME_T_IS_UNSIGNED
+					t = __XL_NPP(strtoul)(buf, &o, 10   __LOCALE_ARG);
+#else
+					t = __XL_NPP(strtol)(buf, &o, 10   __LOCALE_ARG);
+#endif
+				}
+				if ((o == buf) || errno) { /* Not a number or overflow. */
+					return NULL;
+				}
+				__set_errno(i);	/* Restore errno. */
+				buf = o;
+
+				if (!code) {	/* s */
+					localtime_r(&t, tm); /* TODO: check for failure? */
+					i = 0;
+					do {		/* Now copy values from tm to fields. */
+						 fields[i] = ((int *) tm)[i];
+					} while (++i < 8);
+				}
+			}
+			/* TODO: glibc treats %Z as a nop.  For now, do the same. */
+			goto LOOP;
+		}
+
+		assert((code & MASK_SPEC) == INT_SPEC);
+		{
+			register const unsigned char *x;
+			code &= 0xf;
+			x = spec + INT_FIELD_START + (code << 1);
+			if ((j = x[1]) < 3) { /* upper bound (inclusive) */
+				j = ((j==1) ? 366 : 9999);
+			}
+			i = -1;
+			while (ISDIGIT(*buf)) {
+				if (i < 0) {
+					i = 0;
+				}
+				if ((i = 10*i + (*buf - '0')) > j) { /* Overflow. */
+					return NULL;
+				}
+				++buf;
+			}
+			if (i < (*x & 1)) {	/* This catches no-digit case too. */
+				return NULL;
+			}
+			if (*x & 2) {
+				--i;
+			}
+			if (*x & 4) {
+				i -= 1900;
+			}
+
+			if (*x == (9 << 3) + 1 + 0) { /* %I or %l */
+				if (i == 12) {
+					i = 0;
+				}
+				if (fields[8] >= 0) { /* We have a previous %p or %P. */
+					fields[2] = i + fields[8];
+				}
+			}
+
+			fields[(*x) >> 3] = i;
+
+			if (((unsigned char)(*x - (10 << 3) + 0 + 0)) <= 8) { /* %C or %y */
+				if ((j = fields[10]) < 0) {	/* No %C, so i must be %y data. */
+					if (i <= 68) { /* Map [0-68] to 2000+i */
+						i += 100;
+					}
+				} else {		/* Have %C data, but what about %y? */
+					if ((i = fields[11]) < 0) {	/* No %y data. */
+						i = 0;	/* Treat %y val as 0 following glibc's example. */
+					}
+					i += 100*(j - 19);
+				}
+				fields[5] = i;
+			}
+		}
+		goto LOOP;
+	} else if (ISSPACE(*p)) {
+		++p;
+		while (ISSPACE(*buf)) {
+			++buf;
+		}
+		goto LOOP;
+	} else if (*buf++ == *p++) {
+		goto LOOP;
+	}
+	return NULL;
+}
+# ifdef L_strptime_l
+libc_hidden_def(strptime_l)
+# endif
+
+#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+#endif
+/**********************************************************************/
+#ifdef L_time
+
+#ifndef __BCC__
+#error The uClibc version of time is in sysdeps/linux/common.
+#endif
+
+time_t time(register time_t *tloc)
+{
+	struct timeval tv;
+	register struct timeval *p = &tv;
+
+	gettimeofday(p, NULL);		/* This should never fail... */
+
+	if (tloc) {
+		*tloc = p->tv_sec;
+	}
+
+	return p->tv_sec;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_tzset
+
+static const char vals[] = {
+	'T', 'Z', 0,				/* 3 */
+	'U', 'T', 'C', 0,			/* 4 */
+	25, 60, 60, 1,				/* 4 */
+	'.', 1,						/* M */
+	5, '.', 1,
+	6,  0,  0,					/* Note: overloaded for non-M non-J case... */
+	0, 1, 0,					/* J */
+	',', 'M',      '4', '.', '1', '.', '0',
+	',', 'M', '1', '0', '.', '5', '.', '0', 0,
+	',', 'M',      '3', '.', '2', '.', '0',
+	',', 'M', '1', '1', '.', '1', '.', '0', 0
+};
+
+#define TZ    vals
+#define UTC   (vals + 3)
+#define RANGE (vals + 7)
+#define RULE  (vals + 11 - 1)
+#define DEFAULT_RULES (vals + 22)
+#define DEFAULT_2007_RULES (vals + 38)
+
+/* Initialize to UTC. */
+int daylight = 0;
+long timezone = 0;
+char *tzname[2] = { (char *) UTC, (char *) (UTC-1) };
+
+__UCLIBC_MUTEX_INIT(_time_tzlock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+rule_struct _time_tzinfo[2];
+
+static const char *getoffset(register const char *e, long *pn)
+{
+	register const char *s = RANGE-1;
+	long n;
+	int f;
+
+	n = 0;
+	f = -1;
+	do {
+		++s;
+		if (__isdigit_char(*e)) {
+			f = *e++ - '0';
+		}
+		if (__isdigit_char(*e)) {
+			f = 10 * f + (*e++ - '0');
+		}
+		if (((unsigned int)f) >= *s) {
+			return NULL;
+		}
+		n = (*s) * n + f;
+		f = 0;
+		if (*e == ':') {
+			++e;
+			--f;
+		}
+	} while (*s > 1);
+
+	*pn = n;
+	return e;
+}
+
+static const char *getnumber(register const char *e, int *pn)
+{
+#ifdef __BCC__
+	/* bcc can optimize the counter if it thinks it is a pointer... */
+	register const char *n = (const char *) 3;
+	int f;
+
+	f = 0;
+	while (n && __isdigit_char(*e)) {
+		f = 10 * f + (*e++ - '0');
+		--n;
+	}
+
+	*pn = f;
+	return (n == (const char *) 3) ? NULL : e;
+#else  /* __BCC__ */
+	int n, f;
+
+	n = 3;
+	f = 0;
+	while (n && __isdigit_char(*e)) {
+		f = 10 * f + (*e++ - '0');
+		--n;
+	}
+
+	*pn = f;
+	return (n == 3) ? NULL : e;
+#endif /* __BCC__ */
+}
+
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Should we preserve errno from open/read/close errors re TZ file?
+#endif
+
+#ifdef __UCLIBC_HAS_TZ_FILE__
+
+#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__
+static smallint TZ_file_read;		/* Let BSS initialization set this to 0. */
+#endif
+
+static char *read_TZ_file(char *buf)
+{
+	int r;
+	int fd;
+	char *p = NULL;
+
+	fd = open(__UCLIBC_TZ_FILE_PATH__, O_RDONLY);
+	if (fd >= 0) {
+#if 0
+		/* TZ are small *files*. On files, short reads
+		 * only occur on EOF (unlike, say, pipes).
+		 * The code below is pedanticallly more correct,
+		 * but this way we always read at least twice:
+		 * 1st read is short, 2nd one is zero bytes.
+		 */
+		size_t todo = TZ_BUFLEN;
+		p = buf;
+		do {
+			r = read(fd, p, todo);
+			if (r < 0)
+				goto ERROR;
+			if (r == 0)
+				break;
+			p += r;
+			todo -= r;
+		} while (todo);
+#else
+		/* Shorter, and does one fewer read syscall */
+		r = read(fd, buf, TZ_BUFLEN);
+		if (r < 0)
+			goto ERROR;
+		p = buf + r;
+#endif
+		if ((p > buf) && (p[-1] == '\n')) { /* Must end with newline */
+			p[-1] = 0;
+			p = buf;
+#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__
+			TZ_file_read = 1;
+#endif
+		} else {
+ERROR:
+			p = NULL;
+		}
+		close(fd);
+	}
+#ifdef __UCLIBC_FALLBACK_TO_ETC_LOCALTIME__
+	else {
+		fd = open("/etc/localtime", O_RDONLY);
+		if (fd >= 0) {
+			r = read(fd, buf, TZ_BUFLEN);
+			if (r != TZ_BUFLEN
+			 || strncmp(buf, "TZif", 4) != 0
+			 || (unsigned char)buf[4] < 2
+			 || lseek(fd, -TZ_BUFLEN, SEEK_END) < 0
+			) {
+				goto ERROR;
+			}
+			/* tzfile.h from tzcode database says about TZif2+ files:
+			**
+			** If tzh_version is '2' or greater, the above is followed by a second instance
+			** of tzhead and a second instance of the data in which each coded transition
+			** time uses 8 rather than 4 chars,
+			** then a POSIX-TZ-environment-variable-style string for use in handling
+			** instants after the last transition time stored in the file
+			** (with nothing between the newlines if there is no POSIX representation for
+			** such instants).
+			*/
+			r = read(fd, buf, TZ_BUFLEN);
+			if (r <= 0 || buf[--r] != '\n')
+				goto ERROR;
+			buf[r] = 0;
+			while (r != 0) {
+				if (buf[--r] == '\n') {
+					p = buf + r + 1;
+#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__
+					TZ_file_read = 1;
+#endif
+					break;
+				}
+			} /* else ('\n' not found): p remains NULL */
+			close(fd);
+		}
+	}
+#endif /* __UCLIBC_FALLBACK_TO_ETC_LOCALTIME__ */
+	return p;
+}
+
+#endif /* __UCLIBC_HAS_TZ_FILE__ */
+
+void tzset(void)
+{
+	_time_tzset((time(NULL)) < new_rule_starts);
+}
+
+void _time_tzset(int use_old_rules)
+{
+	register const char *e;
+	register char *s;
+	long off = 0;
+	short *p;
+	rule_struct new_rules[2];
+	int n, count, f;
+	char c;
+#ifdef __UCLIBC_HAS_TZ_FILE__
+	char buf[TZ_BUFLEN];
+#endif
+#ifdef __UCLIBC_HAS_TZ_CACHING__
+	static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */
+#endif
+
+	/* Put this inside the lock to prevent the possibility of two different
+	 * timezones being used in a threaded app. */
+	__UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+	e = getenv(TZ);				/* TZ env var always takes precedence. */
+
+#if defined(__UCLIBC_HAS_TZ_FILE__) && !defined(__UCLIBC_HAS_TZ_FILE_READ_MANY__)
+	if (e) {
+		/* Never use TZfile if TZ env var is set. */
+		TZ_file_read = 0;
+	}
+	if (TZ_file_read) {
+		/* We already parsed TZfile before, skip everything. */
+		goto FAST_DONE;
+	}
+#endif
+
+	/* Warning!!!  Since uClibc doesn't do lib locking, the following is
+	 * potentially unsafe in a multi-threaded program since it is remotely
+	 * possible that another thread could call setenv() for TZ and overwrite
+	 * the string being parsed.  So, don't do that... */
+
+#ifdef __UCLIBC_HAS_TZ_FILE__
+	if (!e)
+		e = read_TZ_file(buf);
+#endif
+	if (!e		/* TZ env var not set and no TZfile (or bad TZfile) */
+	 || !*e		/* or set to empty string. */
+	) {
+		goto ILLEGAL;
+	}
+
+	if (*e == ':') {			/* Ignore leading ':'. */
+		++e;
+	}
+
+#ifdef __UCLIBC_HAS_TZ_CACHING__
+	if (strcmp(e, oldval) == 0) {
+		/* Same string as last time... nothing to do. */
+		goto FAST_DONE;
+	}
+	/* Make a copy of the TZ env string.  It won't be nul-terminated if
+	 * it is too long, but it that case it will be illegal and will be reset
+	 * to the empty string anyway. */
+	strncpy(oldval, e, TZ_BUFLEN);
+#endif
+
+	count = 0;
+	new_rules[1].tzname[0] = 0;
+LOOP:
+	/* Get std or dst name. */
+	c = 0;
+	if (*e == '<') {
+		++e;
+		c = '>';
+	}
+
+	s = new_rules[count].tzname;
+	n = 0;
+	while (*e
+	    && isascii(*e)		/* SUSv3 requires char in portable char set. */
+	    && (isalpha(*e)
+		|| (c && (isalnum(*e) || (*e == '+') || (*e == '-')))
+	       )
+	) {
+		*s++ = *e++;
+		if (++n > TZNAME_MAX) {
+			goto ILLEGAL;
+		}
+	}
+	*s = 0;
+
+	if ((n < 3)					/* Check for minimum length. */
+	 || (c && (*e++ != c))	/* Match any quoting '<'. */
+	) {
+		goto ILLEGAL;
+	}
+
+	/* Get offset */
+	s = (char *) e;
+	if ((*e != '-') && (*e != '+')) {
+		if (count && !__isdigit_char(*e)) {
+			off -= 3600;		/* Default to 1 hour ahead of std. */
+			goto SKIP_OFFSET;
+		}
+		--e;
+	}
+
+	++e;
+	e = getoffset(e, &off);
+	if (!e) {
+		goto ILLEGAL;
+	}
+
+	if (*s == '-') {
+		off = -off;				/* Save off in case needed for dst default. */
+	}
+SKIP_OFFSET:
+	new_rules[count].gmt_offset = off;
+
+	if (!count) {
+		new_rules[1].gmt_offset = off; /* Shouldn't be needed... */
+		if (*e) {
+			++count;
+			goto LOOP;
+		}
+	} else {					/* OK, we have dst, so get some rules. */
+		count = 0;
+		if (!*e) {				/* No rules so default to US rules. */
+			e = use_old_rules ? DEFAULT_RULES : DEFAULT_2007_RULES;
+#ifdef DEBUG_TZSET
+			if (e == DEFAULT_RULES)
+				printf("tzset: Using old rules.\n");
+			else if (e == DEFAULT_2007_RULES)
+				printf("tzset: Using new rules\n");
+			else
+				printf("tzset: Using undefined rules\n");
+#endif
+		}
+
+		do {
+			if (*e++ != ',') {
+				goto ILLEGAL;
+			}
+
+			n = 365;
+			s = (char *) RULE;
+			c = *e++;
+			if (c == 'M') {
+				n = 12;
+			} else if (c == 'J') {
+				s += 8;
+			} else {
+				--e;
+				c = 0;
+				s += 6;
+			}
+
+			p = &new_rules[count].rule_type;
+			*p = c;
+			if (c != 'M') {
+				p -= 2;
+			}
+
+			do {
+				++s;
+				e = getnumber(e, &f);
+				if (!e
+				 || ((unsigned int)(f - s[1]) > n)
+				 || (*s && (*e++ != *s))
+				) {
+					goto ILLEGAL;
+				}
+				*--p = f;
+				s += 2;
+				n = *s;
+			} while (n > 0);
+
+			off = 2 * 60 * 60;	/* Default to 2:00:00 */
+			if (*e == '/') {
+				++e;
+				e = getoffset(e, &off);
+				if (!e) {
+					goto ILLEGAL;
+				}
+			}
+			new_rules[count].dst_offset = off;
+		} while (++count < 2);
+
+		if (*e) {
+ILLEGAL:
+#ifdef __UCLIBC_HAS_TZ_CACHING__
+			oldval[0] = 0; /* oldval = "" */
+#endif
+			memset(_time_tzinfo, 0, sizeof(_time_tzinfo));
+			strcpy(_time_tzinfo[0].tzname, UTC);
+			goto DONE;
+		}
+	}
+
+	memcpy(_time_tzinfo, new_rules, sizeof(new_rules));
+DONE:
+	tzname[0] = _time_tzinfo[0].tzname;
+	tzname[1] = _time_tzinfo[1].tzname;
+	daylight = !!_time_tzinfo[1].tzname[0];
+	timezone = _time_tzinfo[0].gmt_offset;
+
+#if defined(__UCLIBC_HAS_TZ_FILE__) || defined(__UCLIBC_HAS_TZ_CACHING__)
+FAST_DONE:
+#endif
+	__UCLIBC_MUTEX_UNLOCK(_time_tzlock);
+}
+libc_hidden_def(tzset)
+#endif
+/**********************************************************************/
+/*  #ifdef L_utime */
+
+/* utime is a syscall in both linux and elks. */
+/*  int utime(const char *path, const struct utimbuf *times) */
+
+/*  #endif */
+/**********************************************************************/
+/* Non-SUSv3 */
+/**********************************************************************/
+#ifdef L_utimes
+
+#ifndef __BCC__
+#error The uClibc version of utimes is in sysdeps/linux/common.
+#endif
+
+#include <utime.h>
+
+int utimes(const char *filename, register const struct timeval *tvp)
+{
+	register struct utimbuf *p = NULL;
+	struct utimbuf utb;
+
+	if (tvp) {
+		p = &utb;
+		p->actime = tvp[0].tv_sec;
+		p->modtime = tvp[1].tv_sec;
+	}
+	return utime(filename, p);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L__time_t2tm
+
+static const uint16_t _vals[] = {
+	60, 60, 24, 7 /* special */, 36524, 1461, 365, 0
+};
+
+static const unsigned char days[] = {
+	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, /* non-leap */
+	    29,
+};
+
+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+static const char utc_string[] = "UTC";
+#endif
+
+/* Notes:
+ * If time_t is 32 bits, then no overflow is possible.
+ * It time_t is > 32 bits, this needs to be adjusted to deal with overflow.
+ */
+
+/* Note: offset is the correction in _days_ to *timer! */
+
+struct tm attribute_hidden *_time_t2tm(const time_t *__restrict timer,
+					  int offset, struct tm *__restrict result)
+{
+	register int *p;
+	time_t t1, t, v;
+	int wday = wday; /* ok to be uninitialized, shutting up warning */
+
+	{
+		register const uint16_t *vp;
+		t = *timer;
+		p = (int *) result;
+		p[7] = 0;
+		vp = _vals;
+		do {
+			if ((v = *vp) == 7) {
+				/* Overflow checking, assuming time_t is long int... */
+#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L)
+#if (INT_MAX == 2147483647L) && (LONG_MAX == 9223372036854775807L)
+				/* Valid range for t is [-784223472856L, 784223421720L].
+				 * Outside of this range, the tm_year field will overflow. */
+				if (((unsigned long)(t + offset- -784223472856L))
+					> (784223421720L - -784223472856L)
+					) {
+					return NULL;
+				}
+#else
+#error overflow conditions unknown
+#endif
+#endif
+
+				/* We have days since the epoch, so caluclate the weekday. */
+#if defined(__BCC__) && TIME_T_IS_UNSIGNED
+				wday = (t + 4) % (*vp);	/* t is unsigned */
+#else
+				wday = ((int)((t % (*vp)) + 11)) % ((int)(*vp)); /* help bcc */
+#endif
+				/* Set divisor to days in 400 years.  Be kind to bcc... */
+				v = ((time_t)(vp[1])) << 2;
+				++v;
+				/* Change to days since 1/1/1601 so that for 32 bit time_t
+				 * values, we'll have t >= 0.  This should be changed for
+				 * archs with larger time_t types.
+				 * Also, correct for offset since a multiple of 7. */
+
+				/* TODO: Does this still work on archs with time_t > 32 bits? */
+				t += (135140L - 366) + offset; /* 146097 - (365*30 + 7) -366 */
+			}
+#if defined(__BCC__) && TIME_T_IS_UNSIGNED
+			t -= ((t1 = t / v) * v);
+#else
+			if ((t -= ((t1 = t / v) * v)) < 0) {
+				t += v;
+				--t1;
+			}
+#endif
+
+			if ((*vp == 7) && (t == v-1)) {
+				--t;			/* Correct for 400th year leap case */
+				++p[4];			/* Stash the extra day... */
+			}
+
+#if defined(__BCC__) && 0
+			*p = t1;
+			if (v <= 60) {
+				*p = t;
+				t = t1;
+			}
+			++p;
+#else
+			if (v <= 60) {
+				*p++ = t;
+				t = t1;
+			} else {
+				*p++ = t1;
+			}
+#endif
+		} while (*++vp);
+	}
+
+	if (p[-1] == 4) {
+		--p[-1];
+		t = 365;
+	}
+
+	*p += ((int) t);			/* result[7] .. tm_yday */
+
+	p -= 2;						/* at result[5] */
+
+#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L)
+	/* Protect against overflow.  TODO: Unecessary if int arith wraps? */
+	*p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + (p[1] - 299); /* tm_year */
+#else
+	*p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + p[1] - 299; /* tm_year */
+#endif
+
+	p[1] = wday;				/* result[6] .. tm_wday */
+
+	{
+		register const unsigned char *d = days;
+
+		wday = 1900 + *p;
+		if (__isleap(wday)) {
+			d += 11;
+		}
+
+		wday = p[2] + 1;		/* result[7] .. tm_yday */
+		*--p = 0;				/* at result[4] .. tm_mon */
+		while (wday > *d) {
+			wday -= *d;
+			if (*d == 29) {
+				d -= 11;		/* Backup to non-leap Feb. */
+			}
+			++d;
+			++*p;				/* Increment tm_mon. */
+		}
+		p[-1] = wday;			/* result[3] .. tm_mday */
+	}
+	/* TODO -- should this be 0? */
+	p[4] = 0;					/* result[8] .. tm_isdst */
+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+# ifdef __USE_BSD
+	result->tm_gmtoff = 0;
+	result->tm_zone = utc_string;
+# else
+	result->__tm_gmtoff = 0;
+	result->__tm_zone = utc_string;
+# endif
+#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */
+
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L___time_tm
+
+struct tm __time_tm;	/* Global shared by gmtime() and localtime(). */
+
+#endif
+/**********************************************************************/
+#ifdef L__time_mktime
+
+time_t attribute_hidden _time_mktime(struct tm *timeptr, int store_on_success)
+{
+	time_t t;
+
+	__UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+	tzset();
+
+	t = _time_mktime_tzi(timeptr, store_on_success, _time_tzinfo);
+
+	__UCLIBC_MUTEX_UNLOCK(_time_tzlock);
+
+	return t;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L__time_mktime_tzi
+
+static const unsigned char __vals[] = {
+	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, /* non-leap */
+	    29,
+};
+
+time_t attribute_hidden _time_mktime_tzi(struct tm *timeptr, int store_on_success,
+						rule_struct *tzi)
+{
+#ifdef __BCC__
+	long days, secs;
+#else
+	long long secs;
+#endif
+	time_t t;
+	struct tm x;
+	/* 0:sec  1:min  2:hour  3:mday  4:mon  5:year  6:wday  7:yday  8:isdst */
+	register int *p = (int *) &x;
+	register const unsigned char *s;
+	int d, default_dst;
+
+	memcpy(p, timeptr, sizeof(struct tm));
+
+	if (!tzi[1].tzname[0]) { /* No dst in this timezone, */
+		p[8] = 0;				/* so set tm_isdst to 0. */
+	}
+
+	default_dst = 0;
+	if (p[8]) {					/* Either dst or unknown? */
+		default_dst = 1;		/* Assume advancing (even if unknown). */
+		p[8] = ((p[8] > 0) ? 1 : -1); /* Normalize so abs() <= 1. */
+	}
+
+	d = 400;
+	p[5] = (p[5] - ((p[6] = p[5]/d) * d)) + (p[7] = p[4]/12);
+	if ((p[4] -= 12 * p[7]) < 0) {
+		p[4] += 12;
+		--p[5];
+	}
+
+	s = __vals;
+	d = (p[5] += 1900);			/* Correct year.  Now between 1900 and 2300. */
+	if (__isleap(d)) {
+		s += 11;
+	}
+
+	p[7] = 0;
+	d = p[4];
+	while (d) {
+		p[7] += *s;
+		if (*s == 29) {
+			s -= 11;			/* Backup to non-leap Feb. */
+		}
+		++s;
+		--d;
+	}
+
+	_time_tzset (x.tm_year < 2007);	/* tm_year was expanded above */
+
+#ifdef __BCC__
+	d = p[5] - 1;
+	days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]);
+	secs = p[0] + 60*( p[1] + 60*((long)(p[2])) )
+		+ tzi[default_dst].gmt_offset;
+DST_CORRECT:
+	if (secs < 0) {
+		secs += 120009600L;
+		days -= 1389;
+	}
+	if ( ((unsigned long)(days + secs/86400L)) > 49710L) {
+		t = ((time_t)(-1));
+		goto DONE;
+	}
+	secs += (days * 86400L);
+#else
+	d = p[5] - 1;
+	d = -719163L + d*365 + (d/4) - (d/100) + (d/400);
+	secs = p[0]
+		+ tzi[default_dst].gmt_offset
+		+ 60*( p[1]
+			   + 60*(p[2]
+					 + 24*(((146073L * ((long long)(p[6])) + d)
+							+ p[3]) + p[7])));
+
+DST_CORRECT:
+	if (((unsigned long long)(secs - LONG_MIN))
+		> (((unsigned long long)LONG_MAX) - LONG_MIN)
+		) {
+		t = ((time_t)(-1));
+		goto DONE;
+	}
+#endif
+
+	d = ((struct tm *)p)->tm_isdst;
+	t = secs;
+
+	__time_localtime_tzi(&t, (struct tm *)p, tzi);
+
+	if (t == ((time_t)(-1))) {	/* Remember, time_t can be unsigned. */
+		goto DONE;
+	}
+
+	if ((d < 0) && (((struct tm *)p)->tm_isdst != default_dst)) {
+#ifdef __BCC__
+		secs -= (days * 86400L);
+#endif
+		secs += (tzi[1-default_dst].gmt_offset
+				 - tzi[default_dst].gmt_offset);
+		goto DST_CORRECT;
+	}
+
+
+	if (store_on_success) {
+		memcpy(timeptr, p, sizeof(struct tm));
+	}
+
+
+DONE:
+	return t;
+}
+
+#endif
+/**********************************************************************/
+#if defined(L_wcsftime) || defined(L_wcsftime_l)
+
+#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
+
+size_t wcsftime(wchar_t *__restrict s, size_t maxsize,
+				const wchar_t *__restrict format,
+				const struct tm *__restrict timeptr)
+{
+	return wcsftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE);
+}
+
+#else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+size_t __XL_NPP(wcsftime)(wchar_t *__restrict s, size_t maxsize,
+					  const wchar_t *__restrict format,
+					  const struct tm *__restrict timeptr   __LOCALE_PARAM )
+{
+#warning wcsftime always fails
+	return 0;					/* always fail */
+}
+#ifdef L_wcsftime_l
+libc_hidden_def(wcsftime_l)
+#endif
+
+#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+#endif
+/**********************************************************************/
+#ifdef L_dysize
+/* Return the number of days in YEAR.  */
+
+int dysize(int year)
+{
+	return __isleap(year) ? 366 : 365;
+}
+
+#endif
+/**********************************************************************/
diff --git a/ap/build/uClibc/libc/misc/time/timegm.c b/ap/build/uClibc/libc/misc/time/timegm.c
new file mode 100644
index 0000000..ae2fc7d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/timegm.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_timegm
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/tzset.c b/ap/build/uClibc/libc/misc/time/tzset.c
new file mode 100644
index 0000000..e5607a5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/tzset.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_tzset
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/wcsftime.c b/ap/build/uClibc/libc/misc/time/wcsftime.c
new file mode 100644
index 0000000..e4b25c0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/wcsftime.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wcsftime
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/time/wcsftime_l.c b/ap/build/uClibc/libc/misc/time/wcsftime_l.c
new file mode 100644
index 0000000..68c2954
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/time/wcsftime_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wcsftime_l
+#define __UCLIBC_DO_XLOCALE
+#include "time.c"
diff --git a/ap/build/uClibc/libc/misc/ttyent/Makefile b/ap/build/uClibc/libc/misc/ttyent/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ttyent/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/ttyent/Makefile.in b/ap/build/uClibc/libc/misc/ttyent/Makefile.in
new file mode 100644
index 0000000..bfa80be
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ttyent/Makefile.in
@@ -0,0 +1,23 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/ttyent
+
+CSRC := getttyent.c
+
+MISC_TTYENT_DIR := $(top_srcdir)libc/misc/ttyent
+MISC_TTYENT_OUT := $(top_builddir)libc/misc/ttyent
+
+MISC_TTYENT_SRC := $(patsubst %.c,$(MISC_TTYENT_DIR)/%.c,$(CSRC))
+MISC_TTYENT_OBJ := $(patsubst %.c,$(MISC_TTYENT_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_TTYENT_OBJ)
+
+objclean-y += CLEAN_libc/misc/ttyent
+
+CLEAN_libc/misc/ttyent:
+	$(do_rm) $(addprefix $(MISC_TTYENT_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/ttyent/getttyent.c b/ap/build/uClibc/libc/misc/ttyent/getttyent.c
new file mode 100644
index 0000000..474f7f0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/ttyent/getttyent.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	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.
+ */
+
+#include <features.h>
+#include <ttyent.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef __UCLIBC_HAS_THREADS__
+# include <pthread.h>
+#endif
+
+static char zapchar;
+static FILE *tf;
+static struct ttyent tty;
+
+
+/* Skip over the current field, removing quotes, and return
+ * a pointer to the next field.
+ */
+#define	QUOTED	1
+static char * skip(register char *p)
+{
+    register char *t;
+    register int c, q;
+
+    for (q = 0, t = p; (c = *p) != '\0'; p++) {
+	if (c == '"') {
+	    q ^= QUOTED;	/* obscure, but nice */
+	    continue;
+	}
+	if (q == QUOTED && *p == '\\' && *(p+1) == '"')
+	    p++;
+	*t++ = *p;
+	if (q == QUOTED)
+	    continue;
+	if (c == '#') {
+	    zapchar = c;
+	    *p = 0;
+	    break;
+	}
+	if (c == '\t' || c == ' ' || c == '\n') {
+	    zapchar = c;
+	    *p++ = 0;
+	    while ((c = *p) == '\t' || c == ' ' || c == '\n')
+		p++;
+	    break;
+	}
+    }
+    *--t = '\0';
+    return (p);
+}
+
+static char * value(register char *p)
+{
+
+    return ((p = strchr(p, '=')) ? ++p : NULL);
+}
+
+int setttyent(void)
+{
+
+    if (tf) {
+	rewind(tf);
+	return (1);
+    } else if ((tf = fopen(_PATH_TTYS, "r"))) {
+	/* We do the locking ourselves.  */
+#ifdef __UCLIBC_HAS_THREADS__
+	__fsetlocking (tf, FSETLOCKING_BYCALLER);
+#endif
+	return (1);
+    }
+    return (0);
+}
+libc_hidden_def(setttyent)
+
+struct ttyent * getttyent(void)
+{
+    register int c;
+    register char *p;
+    static char *line = NULL;
+    struct ttyent *retval = NULL;
+
+    if (!tf && !setttyent())
+	return (NULL);
+
+    if (!line) {
+            line = malloc(BUFSIZ);
+		if (!line)
+		    abort();
+    }
+
+	__STDIO_ALWAYS_THREADLOCK(tf);
+
+    for (;;) {
+	if (!fgets_unlocked(p = line, BUFSIZ, tf)) {
+	    goto DONE;
+	}
+	/* skip lines that are too big */
+	if (!strchr(p, '\n')) {
+	    while ((c = getc_unlocked(tf)) != '\n' && c != EOF)
+		;
+	    continue;
+	}
+	while (isspace(*p))
+	    ++p;
+	if (*p && *p != '#')
+	    break;
+    }
+
+    zapchar = 0;
+    tty.ty_name = p;
+    p = skip(p);
+    if (!*(tty.ty_getty = p))
+	tty.ty_getty = tty.ty_type = NULL;
+    else {
+	p = skip(p);
+	if (!*(tty.ty_type = p))
+	    tty.ty_type = NULL;
+	else
+	    p = skip(p);
+    }
+    tty.ty_status = 0;
+    tty.ty_window = NULL;
+
+#define	scmp(e)	!strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1])
+#define	vcmp(e)	!strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
+    for (; *p; p = skip(p)) {
+	if (scmp(_TTYS_OFF))
+	    tty.ty_status &= ~TTY_ON;
+	else if (scmp(_TTYS_ON))
+	    tty.ty_status |= TTY_ON;
+	else if (scmp(_TTYS_SECURE))
+	    tty.ty_status |= TTY_SECURE;
+	else if (vcmp(_TTYS_WINDOW))
+	    tty.ty_window = value(p);
+	else
+	    break;
+    }
+
+    if (zapchar == '#' || *p == '#')
+	while ((c = *++p) == ' ' || c == '\t')
+	    ;
+    tty.ty_comment = p;
+    if (*p == 0)
+	tty.ty_comment = 0;
+    if ((p = strchr(p, '\n')))
+	*p = '\0';
+    retval = &tty;
+
+ DONE:
+    __STDIO_ALWAYS_THREADUNLOCK(tf);
+    return retval;
+}
+libc_hidden_def(getttyent)
+
+int endttyent(void)
+{
+    int rval;
+
+    if (tf) {
+	rval = !(fclose(tf) == EOF);
+	tf = NULL;
+	return (rval);
+    }
+    return (1);
+}
+libc_hidden_def(endttyent)
+
+struct ttyent * getttynam(const char *_tty)
+{
+    register struct ttyent *t;
+
+    setttyent();
+    while ((t = getttyent()))
+	if (!strcmp(_tty, t->ty_name))
+	    break;
+    endttyent();
+    return (t);
+}
diff --git a/ap/build/uClibc/libc/misc/utmp/Makefile b/ap/build/uClibc/libc/misc/utmp/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/utmp/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/utmp/Makefile.in b/ap/build/uClibc/libc/misc/utmp/Makefile.in
new file mode 100644
index 0000000..49ae5a5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/utmp/Makefile.in
@@ -0,0 +1,27 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/utmp
+
+CSRC := utent.c wtent.c
+
+ifeq ($(UCLIBC_HAS_UTMPX),y)
+CSRC += utxent.c
+endif
+
+MISC_UTMP_DIR := $(top_srcdir)libc/misc/utmp
+MISC_UTMP_OUT := $(top_builddir)libc/misc/utmp
+
+MISC_UTMP_SRC := $(patsubst %.c,$(MISC_UTMP_DIR)/%.c,$(CSRC))
+MISC_UTMP_OBJ := $(patsubst %.c,$(MISC_UTMP_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_UTMP_OBJ)
+
+objclean-y += CLEAN_libc/misc/utmp
+
+CLEAN_libc/misc/utmp:
+	$(do_rm) $(addprefix $(MISC_UTMP_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/utmp/utent.c b/ap/build/uClibc/libc/misc/utmp/utent.c
new file mode 100644
index 0000000..f97cad3
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/utmp/utent.c
@@ -0,0 +1,208 @@
+/* utent.c <ndf@linux.mit.edu> */
+/* Let it be known that this is very possibly the worst standard ever.  HP-UX
+   does one thing, someone else does another, linux another... If anyone
+   actually has the standard, please send it to me.
+
+   Note that because of the way this stupid stupid standard works, you
+   have to call endutent() to close the file even if you've not called
+   setutent -- getutid and family use the same file descriptor.
+
+   Modified by Erik Andersen for uClibc...
+*/
+
+#include <features.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <errno.h>
+#include <string.h>
+#include <utmp.h>
+#include <not-cancel.h>
+
+#include <bits/uClibc_mutex.h>
+__UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER);
+
+
+/* Do not create extra unlocked functions if no locking is needed */
+#if defined __UCLIBC_HAS_THREADS__
+# define static_if_threaded static
+#else
+# define static_if_threaded /* nothing */
+# define __setutent setutent
+# define __getutent getutent
+# define __getutid getutid
+#endif
+
+
+/* Some global crap */
+static int static_fd = -1;
+static struct utmp static_utmp;
+static const char default_file_name[] = _PATH_UTMP;
+static const char *static_ut_name = default_file_name;
+
+
+/* This function must be called with the LOCK held */
+static_if_threaded void __setutent(void)
+{
+    if (static_fd < 0) {
+	static_fd = open_not_cancel_2(static_ut_name, O_RDWR | O_CLOEXEC);
+	if (static_fd < 0) {
+	    static_fd = open_not_cancel_2(static_ut_name, O_RDONLY | O_CLOEXEC);
+	    if (static_fd < 0) {
+		return; /* static_fd remains < 0 */
+	    }
+	}
+#ifndef __ASSUME_O_CLOEXEC
+	/* Make sure the file will be closed on exec()  */
+	fcntl_not_cancel(static_fd, F_SETFD, FD_CLOEXEC);
+#endif
+	return;
+    }
+    lseek(static_fd, 0, SEEK_SET);
+}
+#if defined __UCLIBC_HAS_THREADS__
+void setutent(void)
+{
+    __UCLIBC_MUTEX_LOCK(utmplock);
+    __setutent();
+    __UCLIBC_MUTEX_UNLOCK(utmplock);
+}
+#endif
+libc_hidden_def(setutent)
+
+/* This function must be called with the LOCK held */
+static_if_threaded struct utmp *__getutent(void)
+{
+    if (static_fd < 0) {
+	__setutent();
+	if (static_fd < 0) {
+	    return NULL;
+	}
+    }
+
+    if (read_not_cancel(static_fd, &static_utmp, sizeof(static_utmp)) == sizeof(static_utmp)) {
+	return &static_utmp;
+    }
+
+    return NULL;
+}
+#if defined __UCLIBC_HAS_THREADS__
+struct utmp *getutent(void)
+{
+    struct utmp *ret;
+
+    __UCLIBC_MUTEX_LOCK(utmplock);
+    ret = __getutent();
+    __UCLIBC_MUTEX_UNLOCK(utmplock);
+    return ret;
+}
+#endif
+libc_hidden_def(getutent)
+
+void endutent(void)
+{
+    __UCLIBC_MUTEX_LOCK(utmplock);
+    if (static_fd >= 0)
+	close_not_cancel_no_status(static_fd);
+    static_fd = -1;
+    __UCLIBC_MUTEX_UNLOCK(utmplock);
+}
+libc_hidden_def(endutent)
+
+/* This function must be called with the LOCK held */
+static_if_threaded struct utmp *__getutid(const struct utmp *utmp_entry)
+{
+    struct utmp *lutmp;
+    unsigned type;
+
+    /* We use the fact that constants we are interested in are: */
+    /* RUN_LVL=1, ... OLD_TIME=4; INIT_PROCESS=5, ... USER_PROCESS=8 */
+    type = utmp_entry->ut_type - 1;
+    type /= 4;
+
+    while ((lutmp = __getutent()) != NULL) {
+	if (type == 0 && lutmp->ut_type == utmp_entry->ut_type)	{
+	    /* one of RUN_LVL, BOOT_TIME, NEW_TIME, OLD_TIME */
+	    return lutmp;
+	}
+	if (type == 1 && strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id)) == 0) {
+	    /* INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, DEAD_PROCESS */
+	    return lutmp;
+	}
+    }
+
+    return NULL;
+}
+#if defined __UCLIBC_HAS_THREADS__
+struct utmp *getutid(const struct utmp *utmp_entry)
+{
+    struct utmp *ret;
+
+    __UCLIBC_MUTEX_LOCK(utmplock);
+    ret = __getutid(utmp_entry);
+    __UCLIBC_MUTEX_UNLOCK(utmplock);
+    return ret;
+}
+#endif
+libc_hidden_def(getutid)
+
+struct utmp *getutline(const struct utmp *utmp_entry)
+{
+    struct utmp *lutmp;
+
+    __UCLIBC_MUTEX_LOCK(utmplock);
+    while ((lutmp = __getutent()) != NULL) {
+	if (lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) {
+	    if (strncmp(lutmp->ut_line, utmp_entry->ut_line, sizeof(lutmp->ut_line)) == 0) {
+		break;
+	    }
+	}
+    }
+    __UCLIBC_MUTEX_UNLOCK(utmplock);
+    return lutmp;
+}
+libc_hidden_def(getutline)
+
+struct utmp *pututline(const struct utmp *utmp_entry)
+{
+    __UCLIBC_MUTEX_LOCK(utmplock);
+    /* Ignore the return value.  That way, if they've already positioned
+       the file pointer where they want it, everything will work out. */
+    lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
+
+    if (__getutid(utmp_entry) != NULL)
+	lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
+    else
+	lseek(static_fd, (off_t) 0, SEEK_END);
+    if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
+	utmp_entry = NULL;
+
+    __UCLIBC_MUTEX_UNLOCK(utmplock);
+    return (struct utmp *)utmp_entry;
+}
+libc_hidden_def(pututline)
+
+int utmpname(const char *new_ut_name)
+{
+    __UCLIBC_MUTEX_LOCK(utmplock);
+    if (new_ut_name != NULL) {
+	if (static_ut_name != default_file_name)
+	    free((char *)static_ut_name);
+	static_ut_name = strdup(new_ut_name);
+	if (static_ut_name == NULL) {
+	    /* We should probably whine about out-of-memory
+	     * errors here...  Instead just reset to the default */
+	    static_ut_name = default_file_name;
+	}
+    }
+
+    if (static_fd >= 0) {
+	close_not_cancel_no_status(static_fd);
+	static_fd = -1;
+    }
+    __UCLIBC_MUTEX_UNLOCK(utmplock);
+    return 0; /* or maybe return -(static_ut_name != new_ut_name)? */
+}
+libc_hidden_def(utmpname)
diff --git a/ap/build/uClibc/libc/misc/utmp/utxent.c b/ap/build/uClibc/libc/misc/utmp/utxent.c
new file mode 100644
index 0000000..a0e80a6
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/utmp/utxent.c
@@ -0,0 +1,107 @@
+/*
+ * utexent.c : Support for accessing user accounting database.
+ * Copyright (C) 2010 STMicroelectronics Ltd.
+ *
+ * Author: Salvatore Cro <salvatore.cro@st.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ */
+
+#include <features.h>
+#include <string.h>
+#include <utmpx.h>
+#include <utmp.h>
+
+void setutxent(void)
+{
+	setutent ();
+}
+
+void endutxent(void)
+{
+	endutent ();
+}
+
+struct utmpx *getutxent(void)
+{
+	return (struct utmpx *) getutent ();
+}
+
+struct utmpx *getutxid(const struct utmpx *utmp_entry)
+{
+	return (struct utmpx *) getutid ((const struct utmp *) utmp_entry);
+}
+
+struct utmpx *getutxline(const struct utmpx *utmp_entry)
+{
+	return (struct utmpx *) getutline ((const struct utmp *) utmp_entry);
+}
+
+struct utmpx *pututxline (const struct utmpx *utmp_entry)
+{
+	return (struct utmpx *) pututline ((const struct utmp *) utmp_entry);
+}
+
+int utmpxname (const char *new_ut_name)
+{
+	return utmpname (new_ut_name);
+}
+
+void updwtmpx (const char *wtmpx_file, const struct utmpx *utmpx)
+{
+	updwtmp (wtmpx_file, (const struct utmp *) utmpx);
+}
+
+/* Copy the information in UTMPX to UTMP. */
+void getutmp (const struct utmpx *utmpx, struct utmp *utmp)
+{
+#if _HAVE_UT_TYPE - 0
+	utmp->ut_type = utmpx->ut_type;
+#endif
+#if _HAVE_UT_PID - 0
+	utmp->ut_pid = utmpx->ut_pid;
+#endif
+	memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line));
+	memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user));
+#if _HAVE_UT_ID - 0
+	memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id));
+#endif
+#if _HAVE_UT_HOST - 0
+	memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host));
+#endif
+#if _HAVE_UT_TV - 0
+	utmp->ut_tv.tv_sec = utmpx->ut_tv.tv_sec;
+	utmp->ut_tv.tv_usec = utmpx->ut_tv.tv_usec;
+#else
+	utmp->ut_time = utmpx->ut_time;
+#endif
+}
+
+/* Copy the information in UTMP to UTMPX. */
+void getutmpx (const struct utmp *utmp, struct utmpx *utmpx)
+{
+	memset (utmpx, 0, sizeof (struct utmpx));
+
+#if _HAVE_UT_TYPE - 0
+	utmpx->ut_type = utmp->ut_type;
+#endif
+#if _HAVE_UT_PID - 0
+	utmpx->ut_pid = utmp->ut_pid;
+#endif
+	memcpy (utmpx->ut_line, utmp->ut_line, sizeof (utmp->ut_line));
+	memcpy (utmpx->ut_user, utmp->ut_user, sizeof (utmp->ut_user));
+#if _HAVE_UT_ID - 0
+	memcpy (utmpx->ut_id, utmp->ut_id, sizeof (utmp->ut_id));
+#endif
+#if _HAVE_UT_HOST - 0
+	memcpy (utmpx->ut_host, utmp->ut_host, sizeof (utmp->ut_host));
+#endif
+#if _HAVE_UT_TV - 0
+	utmpx->ut_tv.tv_sec = utmp->ut_tv.tv_sec;
+	utmpx->ut_tv.tv_usec = utmp->ut_tv.tv_usec;
+#else
+	utmpx->ut_time = utmp->ut_time;
+#endif
+}
+
diff --git a/ap/build/uClibc/libc/misc/utmp/wtent.c b/ap/build/uClibc/libc/misc/utmp/wtent.c
new file mode 100644
index 0000000..c97f89c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/utmp/wtent.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* wtmp support rubbish (i.e. complete crap) */
+
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <not-cancel.h>
+
+#if 0
+/* This is enabled in uClibc/libutil/logwtmp.c */
+void logwtmp (const char *line, const char *name, const char *host)
+{
+    struct utmp lutmp;
+    memset(&lutmp, 0, sizeof(lutmp));
+
+    lutmp.ut_type = (name && *name) ? USER_PROCESS : DEAD_PROCESS;
+    lutmp.ut_pid = getpid();
+    strncpy(lutmp.ut_line, line, sizeof(lutmp.ut_line)-1);
+    strncpy(lutmp.ut_name, name, sizeof(lutmp.ut_name)-1);
+    strncpy(lutmp.ut_host, host, sizeof(lutmp.ut_host)-1);
+    gettimeofday(&(lutmp.ut_tv), NULL);
+
+    updwtmp(_PATH_WTMP, &lutmp);
+}
+#endif
+
+void updwtmp(const char *wtmp_file, const struct utmp *lutmp)
+{
+    int fd;
+
+    fd = open_not_cancel(wtmp_file, O_APPEND | O_WRONLY, 0);
+    if (fd >= 0) {
+	if (lockf(fd, F_LOCK, 0) == 0) {
+	    write_not_cancel(fd, lutmp, sizeof(struct utmp));
+	    lockf(fd, F_ULOCK, 0);
+	    close_not_cancel_no_status(fd);
+	}
+    }
+}
+libc_hidden_def(updwtmp)
diff --git a/ap/build/uClibc/libc/misc/wchar/Makefile b/ap/build/uClibc/libc/misc/wchar/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/wchar/Makefile.in b/ap/build/uClibc/libc/misc/wchar/Makefile.in
new file mode 100644
index 0000000..be95a18
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/Makefile.in
@@ -0,0 +1,41 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+# The stdio and time related wide functions are now built in the normal
+# directories.
+#
+# stdio:
+#	fwide fgetwc getwchar fgetws fputwc putwchar fputws ungetwc
+#	getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias)
+#	putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias)
+# time:
+# wcsftime
+#
+
+subdirs += libc/misc/wchar
+
+# multi source wchar.c
+CSRC :=	btowc.c wctob.c mbsinit.c mbrlen.c mbrtowc.c wcrtomb.c mbsrtowcs.c \
+	wcsrtombs.c _wchar_utf8sntowcs.c _wchar_wcsntoutf8s.c \
+	mbsnrtowcs.c wcsnrtombs.c wcwidth.c wcswidth.c
+
+ifeq ($(UCLIBC_HAS_LOCALE),y)
+CSRC += iconv.c
+endif
+
+MISC_WCHAR_DIR := $(top_srcdir)libc/misc/wchar
+MISC_WCHAR_OUT := $(top_builddir)libc/misc/wchar
+
+MISC_WCHAR_SRC := $(patsubst %.c,$(MISC_WCHAR_DIR)/%.c,$(CSRC))
+MISC_WCHAR_OBJ := $(patsubst %.c,$(MISC_WCHAR_OUT)/%.o,$(CSRC))
+
+libc-$(UCLIBC_HAS_WCHAR) += $(MISC_WCHAR_OBJ)
+
+objclean-y += CLEAN_libc/misc/wchar
+
+CLEAN_libc/misc/wchar:
+	$(do_rm) $(addprefix $(MISC_WCHAR_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/wchar/_wchar_utf8sntowcs.c b/ap/build/uClibc/libc/misc/wchar/_wchar_utf8sntowcs.c
new file mode 100644
index 0000000..a01990e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/_wchar_utf8sntowcs.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L__wchar_utf8sntowcs
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/_wchar_wcsntoutf8s.c b/ap/build/uClibc/libc/misc/wchar/_wchar_wcsntoutf8s.c
new file mode 100644
index 0000000..a63aa91
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/_wchar_wcsntoutf8s.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L__wchar_wcsntoutf8s
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/btowc.c b/ap/build/uClibc/libc/misc/wchar/btowc.c
new file mode 100644
index 0000000..d5e60ce
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/btowc.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_btowc
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/iconv.c b/ap/build/uClibc/libc/misc/wchar/iconv.c
new file mode 100644
index 0000000..e6e8ea8
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/iconv.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iconv
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/mbrlen.c b/ap/build/uClibc/libc/misc/wchar/mbrlen.c
new file mode 100644
index 0000000..01bd31e
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/mbrlen.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_mbrlen
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/mbrtowc.c b/ap/build/uClibc/libc/misc/wchar/mbrtowc.c
new file mode 100644
index 0000000..76ce28a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/mbrtowc.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_mbrtowc
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/mbsinit.c b/ap/build/uClibc/libc/misc/wchar/mbsinit.c
new file mode 100644
index 0000000..23aaac5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/mbsinit.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_mbsinit
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/mbsnrtowcs.c b/ap/build/uClibc/libc/misc/wchar/mbsnrtowcs.c
new file mode 100644
index 0000000..9b407c1
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/mbsnrtowcs.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_mbsnrtowcs
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/mbsrtowcs.c b/ap/build/uClibc/libc/misc/wchar/mbsrtowcs.c
new file mode 100644
index 0000000..dd47a91
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/mbsrtowcs.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_mbsrtowcs
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/wchar.c b/ap/build/uClibc/libc/misc/wchar/wchar.c
new file mode 100644
index 0000000..412c557
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/wchar.c
@@ -0,0 +1,1565 @@
+
+/*  Copyright (C) 2002, 2003, 2004     Manuel Novoa III
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!
+ *
+ *  Besides uClibc, I'm using this code in my libc for elks, which is
+ *  a 16-bit environment with a fairly limited compiler.  It would make
+ *  things much easier for me if this file isn't modified unnecessarily.
+ *  In particular, please put any new or replacement functions somewhere
+ *  else, and modify the makefile to use your version instead.
+ *  Thanks.  Manuel
+ *
+ *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */
+
+
+/* May 23, 2002     Initial Notes:
+ *
+ * I'm still tweaking this stuff, but it passes the tests I've thrown
+ * at it, and Erik needs it for the gcc port.  The glibc extension
+ * __wcsnrtombs() hasn't been tested, as I didn't find a test for it
+ * in the glibc source.  I also need to fix the behavior of
+ * _wchar_utf8sntowcs() if the max number of wchars to convert is 0.
+ *
+ * UTF-8 -> wchar -> UTF-8 conversion tests on Markus Kuhn's UTF-8-demo.txt
+ * file on my platform (x86) show about 5-10% faster conversion speed than
+ * glibc with mbsrtowcs()/wcsrtombs() and almost twice as fast as glibc with
+ * individual mbrtowc()/wcrtomb() calls.
+ *
+ * If 'DECODER' is defined, then _wchar_utf8sntowcs() will be compiled
+ * as a fail-safe UTF-8 decoder appropriate for a terminal, etc.  which
+ * needs to deal gracefully with whatever is sent to it.  In that mode,
+ * it passes Markus Kuhn's UTF-8-test.txt stress test.  I plan to add
+ * an arg to force that behavior, so the interface will be changing.
+ *
+ * I need to fix the error checking for 16-bit wide chars.  This isn't
+ * an issue for uClibc, but may be for ELKS.  I'm currently not sure
+ * if I'll use 16-bit, 32-bit, or configureable wchars in ELKS.
+ *
+ * July 1, 2002
+ *
+ * Fixed _wchar_utf8sntowcs() for the max number of wchars == 0 case.
+ * Fixed nul-char bug in btowc(), and another in __mbsnrtowcs() for 8-bit
+ *    locales.
+ * Enabled building of a C/POSIX-locale-only version, so full locale support
+ *    no longer needs to be enabled.
+ *
+ * Nov 4, 2002
+ *
+ * Fixed a bug in _wchar_wcsntoutf8s().  Don't store wcs position if dst is NULL.
+ * Also, introduce an awful hack into _wchar_wcsntoutf8s() and wcsrtombs() in
+ *   order to support %ls in printf.  See comments below for details.
+ * Change behaviour of wc<->mb functions when in the C locale.  Now they do
+ *   a 1-1 map for the range 0x80-UCHAR_MAX.  This is for backwards compatibility
+ *   and consistency with the stds requirements that a printf format string by
+ *   a valid multibyte string beginning and ending in it's initial shift state.
+ *
+ * Nov 5, 2002
+ *
+ * Forgot to change btowc and wctob when I changed the wc<->mb functions yesterday.
+ *
+ * Nov 7, 2002
+ *
+ * Add wcwidth and wcswidth, based on Markus Kuhn's wcwidth of 2002-05-08.
+ *   Added some size/speed optimizations and integrated it into my locale
+ *   framework.  Minimally tested at the moment, but the stub C-locale
+ *   version (which most people would probably be using) should be fine.
+ *
+ * Nov 21, 2002
+ *
+ * Revert the wc<->mb changes from earlier this month involving the C-locale.
+ * Add a couple of ugly hacks to support *wprintf.
+ * Add a mini iconv() and iconv implementation (requires locale support).
+ *
+ * Aug 1, 2003
+ * Bug fix for mbrtowc.
+ *
+ * Aug 18, 2003
+ * Bug fix: _wchar_utf8sntowcs and _wchar_wcsntoutf8s now set errno if EILSEQ.
+ *
+ * Feb 11, 2004
+ * Bug fix: Fix size check for remaining output space in iconv().
+ *
+ * Manuel
+ */
+#ifdef _LIBC
+#include <errno.h>
+#include <stddef.h>
+#include <limits.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <locale.h>
+#include <wchar.h>
+#include <bits/uClibc_uwchar.h>
+
+/**********************************************************************/
+#ifdef __UCLIBC_HAS_LOCALE__
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_iswspace
+/* generates one warning */
+#warning TODO: Fix Cc2wc* and Cwc2c* defines!
+#endif
+#endif /* __UCLIBC_MJN3_ONLY__ */
+
+#define ENCODING		(__UCLIBC_CURLOCALE->encoding)
+
+#define Cc2wc_IDX_SHIFT		__LOCALE_DATA_Cc2wc_IDX_SHIFT
+#define Cc2wc_ROW_LEN		__LOCALE_DATA_Cc2wc_ROW_LEN
+#define Cwc2c_DOMAIN_MAX	__LOCALE_DATA_Cwc2c_DOMAIN_MAX
+#define Cwc2c_TI_SHIFT		__LOCALE_DATA_Cwc2c_TI_SHIFT
+#define Cwc2c_TT_SHIFT		__LOCALE_DATA_Cwc2c_TT_SHIFT
+#define Cwc2c_TI_LEN		__LOCALE_DATA_Cwc2c_TI_LEN
+
+#ifndef __CTYPE_HAS_UTF_8_LOCALES
+#warning __CTYPE_HAS_UTF_8_LOCALES not set!
+#endif
+
+#else  /* __UCLIBC_HAS_LOCALE__ */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_btowc
+/* emit only once */
+#warning fix preprocessor logic testing locale settings
+#endif
+#endif
+
+#define ENCODING (__ctype_encoding_7_bit)
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+#error __CTYPE_HAS_8_BIT_LOCALES is defined!
+#endif
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+#error __CTYPE_HAS_UTF_8_LOCALES is defined!
+#endif
+#undef L__wchar_utf8sntowcs
+#undef L__wchar_wcsntoutf8s
+
+#endif /* __UCLIBC_HAS_LOCALE__ */
+/**********************************************************************/
+
+#if WCHAR_MAX > 0xffffUL
+#define UTF_8_MAX_LEN 6
+#else
+#define UTF_8_MAX_LEN 3
+#endif
+
+#define KUHN 1
+
+/* Implementation-specific work functions. */
+
+extern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
+					const char **__restrict src, size_t n,
+					mbstate_t *ps, int allow_continuation) attribute_hidden;
+
+extern size_t _wchar_wcsntoutf8s(char *__restrict s, size_t n,
+					const wchar_t **__restrict src, size_t wn) attribute_hidden;
+#endif
+/**********************************************************************/
+#ifdef L_btowc
+
+
+wint_t btowc(int c)
+{
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+
+	wchar_t wc;
+	unsigned char buf[1];
+	mbstate_t mbstate;
+
+	if (c != EOF) {
+		*buf = (unsigned char) c;
+		mbstate.__mask = 0;		/* Initialize the mbstate. */
+		if (mbrtowc(&wc, (char*) buf, 1, &mbstate) <= 1) {
+			return wc;
+		}
+	}
+	return WEOF;
+
+#else  /* !__CTYPE_HAS_8_BIT_LOCALES */
+
+#ifdef __UCLIBC_HAS_LOCALE__
+	assert((ENCODING == __ctype_encoding_7_bit)
+		   || (ENCODING == __ctype_encoding_utf8));
+#endif
+
+	/* If we don't have 8-bit locale support, then this is trivial since
+	 * anything outside of 0-0x7f is illegal in C/POSIX and UTF-8 locales. */
+	return (((unsigned int)c) < 0x80) ? c : WEOF;
+
+#endif /* !__CTYPE_HAS_8_BIT_LOCALES */
+}
+libc_hidden_def(btowc)
+
+#endif
+/**********************************************************************/
+#ifdef L_wctob
+
+/* Note: We completely ignore ps in all currently supported conversions. */
+
+
+int wctob(wint_t c)
+{
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+
+	unsigned char buf[MB_LEN_MAX];
+
+	return (wcrtomb((char*) buf, c, NULL) == 1) ? *buf : EOF;
+
+#else  /*  __CTYPE_HAS_8_BIT_LOCALES */
+
+#ifdef __UCLIBC_HAS_LOCALE__
+	assert((ENCODING == __ctype_encoding_7_bit)
+		   || (ENCODING == __ctype_encoding_utf8));
+#endif /* __UCLIBC_HAS_LOCALE__ */
+
+	/* If we don't have 8-bit locale support, then this is trivial since
+	 * anything outside of 0-0x7f is illegal in C/POSIX and UTF-8 locales. */
+
+	/* TODO: need unsigned version of wint_t... */
+/*  	return (((unsigned int)c) < 0x80) ? c : WEOF; */
+	return ((c >= 0) && (c < 0x80)) ? c : EOF;
+
+#endif /*  __CTYPE_HAS_8_BIT_LOCALES */
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_mbsinit
+
+int mbsinit(const mbstate_t *ps)
+{
+	return !ps || !ps->__mask;
+}
+libc_hidden_def(mbsinit)
+
+#endif
+/**********************************************************************/
+#ifdef L_mbrlen
+
+
+size_t mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps)
+{
+	static mbstate_t mbstate;	/* Rely on bss 0-init. */
+
+	return mbrtowc(NULL, s, n, (ps != NULL) ? ps : &mbstate);
+}
+libc_hidden_def(mbrlen)
+
+#endif
+/**********************************************************************/
+#ifdef L_mbrtowc
+
+
+size_t mbrtowc(wchar_t *__restrict pwc, const char *__restrict s,
+			   size_t n, mbstate_t *__restrict ps)
+{
+	static mbstate_t mbstate;	/* Rely on bss 0-init. */
+	wchar_t wcbuf[1];
+	const char *p;
+	size_t r;
+	char empty_string[1];		/* Avoid static to be fPIC friendly. */
+
+	if (!ps) {
+		ps = &mbstate;
+	}
+
+	if (!s) {
+		pwc = (wchar_t *) s;	/* NULL */
+		empty_string[0] = 0;	/* Init the empty string when necessary. */
+		s = empty_string;
+		n = 1;
+	} else if (*s == '\0') {
+		if (pwc)
+			*pwc = '\0';
+	/* According to the ISO C 89 standard this is the expected behaviour.  */
+		return 0;
+	} else if (!n) {
+		/* TODO: change error code? */
+#if 0
+		return (ps->__mask && (ps->__wc == 0xffffU))
+			? ((size_t) -1) : ((size_t) -2);
+#else
+		return 0;
+#endif
+	}
+
+	p = s;
+
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+	/* Need to do this here since mbsrtowcs doesn't allow incompletes. */
+	if (ENCODING == __ctype_encoding_utf8) {
+		if (!pwc) {
+			pwc = wcbuf;
+		}
+		r = _wchar_utf8sntowcs(pwc, 1, &p, n, ps, 1);
+		return (r == 1) ? (p-s) : r; /* Need to return 0 if nul char. */
+	}
+#endif
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: This adds a trailing nul!
+#endif /* __UCLIBC_MJN3_ONLY__ */
+
+	r = mbsnrtowcs(wcbuf, &p, SIZE_MAX, 1, ps);
+
+	if (((ssize_t) r) >= 0) {
+		if (pwc) {
+			*pwc = *wcbuf;
+		}
+	}
+	return (size_t) r;
+}
+libc_hidden_def(mbrtowc)
+
+#endif
+/**********************************************************************/
+#ifdef L_wcrtomb
+
+
+/* Note: We completely ignore ps in all currently supported conversions. */
+/* TODO: Check for valid state anyway? */
+
+size_t wcrtomb(register char *__restrict s, wchar_t wc,
+			   mbstate_t *__restrict ps)
+{
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Should wcsnrtombs nul-terminate unconditionally?  Check glibc.
+#endif /* __UCLIBC_MJN3_ONLY__ */
+	wchar_t wcbuf[1];
+	const wchar_t *pwc;
+	size_t r;
+	char buf[MB_LEN_MAX];
+
+	if (!s) {
+		s = buf;
+		wc = 0;
+	}
+
+	pwc = wcbuf;
+	wcbuf[0] = wc;
+
+	r = wcsnrtombs(s, &pwc, 1, MB_LEN_MAX, ps);
+	return (r != 0) ? r : 1;
+}
+libc_hidden_def(wcrtomb)
+
+#endif
+/**********************************************************************/
+#ifdef L_mbsrtowcs
+
+
+size_t mbsrtowcs(wchar_t *__restrict dst, const char **__restrict src,
+				 size_t len, mbstate_t *__restrict ps)
+{
+	static mbstate_t mbstate;	/* Rely on bss 0-init. */
+
+	return mbsnrtowcs(dst, src, SIZE_MAX, len,
+						((ps != NULL) ? ps : &mbstate));
+}
+libc_hidden_def(mbsrtowcs)
+
+#endif
+/**********************************************************************/
+#ifdef L_wcsrtombs
+
+/* Note: We completely ignore ps in all currently supported conversions.
+
+ * TODO: Check for valid state anyway? */
+
+
+size_t wcsrtombs(char *__restrict dst, const wchar_t **__restrict src,
+				 size_t len, mbstate_t *__restrict ps)
+{
+	return wcsnrtombs(dst, src, SIZE_MAX, len, ps);
+}
+libc_hidden_def(wcsrtombs)
+
+#endif
+/**********************************************************************/
+#ifdef L__wchar_utf8sntowcs
+
+/* Define DECODER to generate a UTF-8 decoder which passes Markus Kuhn's
+ * UTF-8-test.txt strss test.
+ */
+/*  #define DECODER */
+
+#ifdef DECODER
+#ifndef KUHN
+#define KUHN
+#endif
+#endif
+
+size_t attribute_hidden _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
+						  const char **__restrict src, size_t n,
+						  mbstate_t *ps, int allow_continuation)
+{
+	register const char *s;
+	__uwchar_t mask;
+	__uwchar_t wc;
+	wchar_t wcbuf[1];
+	size_t count;
+	int incr;
+
+	s = *src;
+
+	assert(s != NULL);
+	assert(ps != NULL);
+
+	incr = 1;
+	/* NOTE: The following is an AWFUL HACK!  In order to support %s in
+	 * wprintf, we need to be able to compute the number of wchars needed
+	 * for the mbs conversion, not to exceed the precision specified.
+	 * But if dst is NULL, the return value is the length assuming a
+	 * sufficiently sized buffer.  So, we allow passing of (wchar_t *) ps
+	 * as pwc in order to flag that we really want the length, subject
+	 * to the restricted buffer size and no partial conversions.
+	 * See mbsnrtowcs() as well. */
+	if (!pwc || (pwc == ((wchar_t *)ps))) {
+		if (!pwc) {
+			wn = SIZE_MAX;
+		}
+		pwc = wcbuf;
+		incr = 0;
+	}
+
+	/* This is really here only to support the glibc extension function
+	 * __mbsnrtowcs which apparently returns 0 if wn == 0 without any
+	 * check on the validity of the mbstate. */
+	if (!(count = wn)) {
+		return 0;
+	}
+
+	if ((mask = (__uwchar_t) ps->__mask) != 0) { /* A continuation... */
+#ifdef DECODER
+		wc = (__uwchar_t) ps->__wc;
+		if (n) {
+			goto CONTINUE;
+		}
+		goto DONE;
+#else
+		if ((wc = (__uwchar_t) ps->__wc) != 0xffffU) {
+			/* TODO: change error code here and below? */
+			if (n) {
+				goto CONTINUE;
+			}
+			goto DONE;
+		}
+		__set_errno(EILSEQ);
+		return (size_t) -1;		/* We're in an error state. */
+#endif
+	}
+
+	do {
+		if (!n) {
+			goto DONE;
+		}
+		--n;
+		if ((wc = ((unsigned char) *s++)) >= 0x80) { /* Not ASCII... */
+			mask = 0x40;
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Fix range for 16 bit wchar_t case.
+#endif
+			if (( ((unsigned char)(s[-1] - 0xc0)) < (0xfe - 0xc0) ) &&
+			(((unsigned char)s[-1] != 0xc0 ) && ((unsigned char)s[-1] != 0xc1 ))) {
+				goto START;
+			}
+		BAD:
+#ifdef DECODER
+			wc = 0xfffdU;
+			goto COMPLETE;
+#else
+			ps->__mask = mask;
+			ps->__wc = 0xffffU;
+			__set_errno(EILSEQ);
+			return (size_t) -1;	/* Illegal start byte! */
+#endif
+
+		CONTINUE:
+			while (n) {
+				--n;
+				if ((*s & 0xc0) != 0x80) {
+					goto BAD;
+				}
+				mask <<= 5;
+				wc <<= 6;
+				wc += (*s & 0x3f);	/* keep seperate for bcc (smaller code) */
+				++s;
+			START:
+				wc &= ~(mask << 1);
+
+				if ((wc & mask) == 0) {	/* Character completed. */
+					if ((mask >>= 5) == 0x40) {
+						mask += mask;
+					}
+					/* Check for invalid sequences (longer than necessary)
+					 * and invalid chars.  */
+					if ( (wc < mask) /* Sequence not minimal length. */
+#ifdef KUHN
+#if UTF_8_MAX_LEN == 3
+#error broken since mask can overflow!!
+						 /* For plane 0, these are the only defined values.*/
+						 || (wc > 0xfffdU)
+#else
+						 /* Note that we don't need to worry about exceeding */
+						 /* 31 bits as that is the most that UTF-8 provides. */
+						 || ( ((__uwchar_t)(wc - 0xfffeU)) < 2)
+#endif
+						 || ( ((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U) )
+#endif /* KUHN */
+						 ) {
+						goto BAD;
+					}
+					goto COMPLETE;
+				}
+			}
+			/* Character potentially valid but incomplete. */
+			if (!allow_continuation) {
+				if (count != wn) {
+					return 0;
+				}
+				/* NOTE: The following can fail if you allow and then disallow
+				 * continuation!!! */
+#if UTF_8_MAX_LEN == 3
+#error broken since mask can overflow!!
+#endif
+				/* Need to back up... */
+				do {
+					--s;
+				} while ((mask >>= 5) >= 0x40);
+				goto DONE;
+			}
+			ps->__mask = (wchar_t) mask;
+			ps->__wc = (wchar_t) wc;
+			*src = s;
+			return (size_t) -2;
+		}
+	COMPLETE:
+		*pwc = wc;
+		pwc += incr;
+	}
+#ifdef DECODER
+	while (--count);
+#else
+	while (wc && --count);
+
+	if (!wc) {
+		s = NULL;
+	}
+#endif
+
+ DONE:
+	/* ps->__wc is irrelavent here. */
+	ps->__mask = 0;
+	if (pwc != wcbuf) {
+		*src = s;
+	}
+
+	return wn - count;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L__wchar_wcsntoutf8s
+
+size_t attribute_hidden _wchar_wcsntoutf8s(char *__restrict s, size_t n,
+						  const wchar_t **__restrict src, size_t wn)
+{
+	register char *p;
+	size_t len, t;
+	__uwchar_t wc;
+	const __uwchar_t *swc;
+	int store;
+	char buf[MB_LEN_MAX];
+	char m;
+
+	store = 1;
+	/* NOTE: The following is an AWFUL HACK!  In order to support %ls in
+	 * printf, we need to be able to compute the number of bytes needed
+	 * for the mbs conversion, not to exceed the precision specified.
+	 * But if dst is NULL, the return value is the length assuming a
+	 * sufficiently sized buffer.  So, we allow passing of (char *) src
+	 * as dst in order to flag that we really want the length, subject
+	 * to the restricted buffer size and no partial conversions.
+	 * See wcsnrtombs() as well. */
+	if (!s || (s == ((char *) src))) {
+		if (!s) {
+			n = SIZE_MAX;
+		}
+		s = buf;
+		store = 0;
+	}
+
+	t = n;
+	swc = (const __uwchar_t *) *src;
+
+	assert(swc != NULL);
+
+	while (wn && t) {
+		wc = *swc;
+
+		*s = wc;
+		len = 1;
+
+		if (wc >= 0x80) {
+#ifdef KUHN
+			if (
+#if UTF_8_MAX_LEN == 3
+				/* For plane 0, these are the only defined values.*/
+				/* Note that we don't need to worry about exceeding */
+				/* 31 bits as that is the most that UTF-8 provides. */
+				(wc > 0xfffdU)
+#else
+				/* UTF_8_MAX_LEN == 6 */
+				(wc > 0x7fffffffUL)
+				|| ( ((__uwchar_t)(wc - 0xfffeU)) < 2)
+#endif
+				|| ( ((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U) )
+				) {
+				__set_errno(EILSEQ);
+				return (size_t) -1;
+			}
+#else  /* KUHN */
+#if UTF_8_MAX_LEN != 3
+			if (wc > 0x7fffffffUL) { /* Value too large. */
+				__set_errno(EILSEQ);
+				return (size_t) -1;
+			}
+#endif
+#endif /* KUHN */
+
+			wc >>= 1;
+			p = s;
+			do {
+				++p;
+			} while (wc >>= 5);
+			wc = *swc;
+			if ((len = p - s) > t) { /* Not enough space. */
+				break;
+			}
+
+			m = 0x80;
+			while( p>s ) {
+				m = (m >> 1) | 0x80;
+				*--p = (wc & 0x3f) | 0x80;
+				wc >>= 6;
+			}
+			*s |= (m << 1);
+		} else if (wc == 0) {	/* End of string. */
+			swc = NULL;
+			break;
+		}
+
+		++swc;
+		--wn;
+		t -= len;
+		if (store) {
+			s += len;
+		}
+	}
+
+	if (store) {
+		*src = (const wchar_t *) swc;
+	}
+
+	return n - t;
+}
+
+
+#endif
+/**********************************************************************/
+#ifdef L_mbsnrtowcs
+
+/* WARNING: We treat len as SIZE_MAX when dst is NULL! */
+
+size_t mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src,
+					size_t NMC, size_t len, mbstate_t *__restrict ps)
+{
+	static mbstate_t mbstate;	/* Rely on bss 0-init. */
+	wchar_t wcbuf[1];
+	const char *s;
+	size_t count;
+	int incr;
+
+	if (!ps) {
+		ps = &mbstate;
+	}
+
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+	if (ENCODING == __ctype_encoding_utf8) {
+		size_t r;
+		return ((r = _wchar_utf8sntowcs(dst, len, src, NMC, ps, 1))
+				!= (size_t) -2) ? r : 0;
+	}
+#endif
+	incr = 1;
+	/* NOTE: The following is an AWFUL HACK!  In order to support %s in
+	 * wprintf, we need to be able to compute the number of wchars needed
+	 * for the mbs conversion, not to exceed the precision specified.
+	 * But if dst is NULL, the return value is the length assuming a
+	 * sufficiently sized buffer.  So, we allow passing of ((wchar_t *)ps)
+	 * as dst in order to flag that we really want the length, subject
+	 * to the restricted buffer size and no partial conversions.
+	 * See _wchar_utf8sntowcs() as well. */
+	if (!dst || (dst == ((wchar_t *)ps))) {
+		if (!dst) {
+			len = SIZE_MAX;
+		}
+		dst = wcbuf;
+		incr = 0;
+	}
+
+	/* Since all the following encodings are single-byte encodings... */
+	if (len > NMC) {
+		len = NMC;
+	}
+
+	count = len;
+	s = *src;
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+	if (ENCODING == __ctype_encoding_8_bit) {
+		wchar_t wc;
+		while (count) {
+			if ((wc = ((unsigned char)(*s))) >= 0x80) {	/* Non-ASCII... */
+				wc -= 0x80;
+				wc = __UCLIBC_CURLOCALE->tbl8c2wc[
+						  (__UCLIBC_CURLOCALE->idx8c2wc[wc >> Cc2wc_IDX_SHIFT]
+						   << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))];
+				if (!wc) {
+					goto BAD;
+				}
+			}
+			if (!(*dst = wc)) {
+				s = NULL;
+				break;
+			}
+			dst += incr;
+			++s;
+			--count;
+		}
+		if (dst != wcbuf) {
+			*src = s;
+		}
+		return len - count;
+	}
+#endif
+
+#ifdef __UCLIBC_HAS_LOCALE__
+	assert(ENCODING == __ctype_encoding_7_bit);
+#endif
+
+	while (count) {
+		if ((*dst = (unsigned char) *s) == 0) {
+			s = NULL;
+			break;
+		}
+		if (*dst >= 0x80) {
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+		BAD:
+#endif
+			__set_errno(EILSEQ);
+			return (size_t) -1;
+		}
+		++s;
+		dst += incr;
+		--count;
+	}
+	if (dst != wcbuf) {
+		*src = s;
+	}
+	return len - count;
+}
+libc_hidden_def(mbsnrtowcs)
+
+#endif
+/**********************************************************************/
+#ifdef L_wcsnrtombs
+
+/* WARNING: We treat len as SIZE_MAX when dst is NULL! */
+
+/* Note: We completely ignore ps in all currently supported conversions.
+ * TODO: Check for valid state anyway? */
+
+size_t wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src,
+					size_t NWC, size_t len, mbstate_t *__restrict ps)
+{
+	const __uwchar_t *s;
+	size_t count;
+	int incr;
+	char buf[MB_LEN_MAX];
+
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+	if (ENCODING == __ctype_encoding_utf8) {
+		return _wchar_wcsntoutf8s(dst, len, src, NWC);
+	}
+#endif /* __CTYPE_HAS_UTF_8_LOCALES */
+
+	incr = 1;
+	/* NOTE: The following is an AWFUL HACK!  In order to support %ls in
+	 * printf, we need to be able to compute the number of bytes needed
+	 * for the mbs conversion, not to exceed the precision specified.
+	 * But if dst is NULL, the return value is the length assuming a
+	 * sufficiently sized buffer.  So, we allow passing of (char *) src
+	 * as dst in order to flag that we really want the length, subject
+	 * to the restricted buffer size and no partial conversions.
+	 * See _wchar_wcsntoutf8s() as well. */
+	if (!dst || (dst == ((char *) src))) {
+		if (!dst) {
+			len = SIZE_MAX;
+		}
+		dst = buf;
+		incr = 0;
+	}
+
+	/* Since all the following encodings are single-byte encodings... */
+	if (len > NWC) {
+		len = NWC;
+	}
+
+	count = len;
+	s = (const __uwchar_t *) *src;
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+	if (ENCODING == __ctype_encoding_8_bit) {
+		__uwchar_t wc;
+		__uwchar_t u;
+		while (count) {
+			if ((wc = *s) <= 0x7f) {
+				if (!(*dst = (unsigned char) wc)) {
+					s = NULL;
+					break;
+				}
+			} else {
+				u = 0;
+				if (wc <= Cwc2c_DOMAIN_MAX) {
+					u = __UCLIBC_CURLOCALE->idx8wc2c[wc >> (Cwc2c_TI_SHIFT
+														+ Cwc2c_TT_SHIFT)];
+					u = __UCLIBC_CURLOCALE->tbl8wc2c[(u << Cwc2c_TI_SHIFT)
+									+ ((wc >> Cwc2c_TT_SHIFT)
+									   & ((1 << Cwc2c_TI_SHIFT)-1))];
+					u = __UCLIBC_CURLOCALE->tbl8wc2c[Cwc2c_TI_LEN
+									+ (u << Cwc2c_TT_SHIFT)
+									+ (wc & ((1 << Cwc2c_TT_SHIFT)-1))];
+				}
+
+#ifdef __WCHAR_REPLACEMENT_CHAR
+				*dst = (unsigned char) ( u ? u : __WCHAR_REPLACEMENT_CHAR );
+#else  /* __WCHAR_REPLACEMENT_CHAR */
+				if (!u) {
+					goto BAD;
+				}
+				*dst = (unsigned char) u;
+#endif /* __WCHAR_REPLACEMENT_CHAR */
+			}
+			++s;
+			dst += incr;
+			--count;
+		}
+		if (dst != buf) {
+			*src = (const wchar_t *) s;
+		}
+		return len - count;
+	}
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+
+#ifdef __UCLIBC_HAS_LOCALE__
+	assert(ENCODING == __ctype_encoding_7_bit);
+#endif
+
+	while (count) {
+		if (*s >= 0x80) {
+#if defined(__CTYPE_HAS_8_BIT_LOCALES) && !defined(__WCHAR_REPLACEMENT_CHAR)
+		BAD:
+#endif
+			__set_errno(EILSEQ);
+			return (size_t) -1;
+		}
+		if ((*dst = (unsigned char) *s) == 0) {
+			s = NULL;
+			break;
+		}
+		++s;
+		dst += incr;
+		--count;
+	}
+	if (dst != buf) {
+		*src = (const wchar_t *) s;
+	}
+	return len - count;
+}
+libc_hidden_def(wcsnrtombs)
+
+#endif
+/**********************************************************************/
+#ifdef L_wcswidth
+
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: If we start doing translit, wcwidth and wcswidth will need updating.
+#warning TODO: Update wcwidth to match latest by Kuhn.
+#endif
+
+#if defined(__UCLIBC_HAS_LOCALE__) && \
+( defined(__CTYPE_HAS_8_BIT_LOCALES) || defined(__CTYPE_HAS_UTF_8_LOCALES) )
+
+static const unsigned char new_idx[] = {
+	0,    5,    5,    6,   10,   15,   28,   39,
+	48,   48,   71,   94,  113,  128,  139,  154,
+	175,  186,  188,  188,  188,  188,  188,  188,
+	203,  208,  208,  208,  208,  208,  208,  208,
+	208,  219,  219,  219,  222,  222,  222,  222,
+	222,  222,  222,  222,  222,  222,  222,  224,
+	224,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  231,  231,  231,
+	231,  231,  231,  231,  231,  233,  233,  233,
+	233,  233,  233,  233,  234,  234,  234,  234,
+	234,  234,  234,  234,  234,  234,  234,  234,
+	234,  234,  234,  234,  234,  234,  234,  234,
+	234,  234,  234,  234,  234,  234,  234,  234,
+	234,  234,  234,  234,  234,  234,  234,  234,
+	234,  234,  234,  234,  234,  234,  234,  234,
+	236,  236,  236,  236,  236,  236,  236,  236,
+	236,  236,  236,  236,  236,  236,  236,  236,
+	236,  236,  236,  236,  236,  236,  236,  236,
+	236,  236,  236,  236,  236,  236,  236,  236,
+	236,  237,  237,  238,  241,  241,  242,  249,
+	255,
+};
+
+static const unsigned char new_tbl[] = {
+	0x00, 0x01, 0x20, 0x7f, 0xa0, 0x00, 0x00, 0x50,
+	0x60, 0x70, 0x00, 0x83, 0x87, 0x88, 0x8a, 0x00,
+	0x91, 0xa2, 0xa3, 0xba, 0xbb, 0xbe, 0xbf, 0xc0,
+	0xc1, 0xc3, 0xc4, 0xc5, 0x00, 0x4b, 0x56, 0x70,
+	0x71, 0xd6, 0xe5, 0xe7, 0xe9, 0xea, 0xee, 0x00,
+	0x0f, 0x10, 0x11, 0x12, 0x30, 0x4b, 0xa6, 0xb1,
+	0x00, 0x01, 0x03, 0x3c, 0x3d, 0x41, 0x49, 0x4d,
+	0x4e, 0x51, 0x55, 0x62, 0x64, 0x81, 0x82, 0xbc,
+	0xbd, 0xc1, 0xc5, 0xcd, 0xce, 0xe2, 0xe4, 0x00,
+	0x02, 0x03, 0x3c, 0x3d, 0x41, 0x43, 0x47, 0x49,
+	0x4b, 0x4e, 0x70, 0x72, 0x81, 0x83, 0xbc, 0xbd,
+	0xc1, 0xc6, 0xc7, 0xc9, 0xcd, 0xce, 0x00, 0x01,
+	0x02, 0x3c, 0x3d, 0x3f, 0x40, 0x41, 0x44, 0x4d,
+	0x4e, 0x56, 0x57, 0x82, 0x83, 0xc0, 0xc1, 0xcd,
+	0xce, 0x00, 0x3e, 0x41, 0x46, 0x49, 0x4a, 0x4e,
+	0x55, 0x57, 0xbf, 0xc0, 0xc6, 0xc7, 0xcc, 0xce,
+	0x00, 0x41, 0x44, 0x4d, 0x4e, 0xca, 0xcb, 0xd2,
+	0xd5, 0xd6, 0xd7, 0x00, 0x31, 0x32, 0x34, 0x3b,
+	0x47, 0x4f, 0xb1, 0xb2, 0xb4, 0xba, 0xbb, 0xbd,
+	0xc8, 0xce, 0x00, 0x18, 0x1a, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3a, 0x71, 0x7f, 0x80, 0x85, 0x86,
+	0x88, 0x90, 0x98, 0x99, 0xbd, 0xc6, 0xc7, 0x00,
+	0x2d, 0x31, 0x32, 0x33, 0x36, 0x38, 0x39, 0x3a,
+	0x58, 0x5a, 0x00, 0x60, 0x00, 0x12, 0x15, 0x32,
+	0x35, 0x52, 0x54, 0x72, 0x74, 0xb7, 0xbe, 0xc6,
+	0xc7, 0xc9, 0xd4, 0x00, 0x0b, 0x0f, 0xa9, 0xaa,
+	0x00, 0x0b, 0x10, 0x2a, 0x2f, 0x60, 0x64, 0x6a,
+	0x70, 0xd0, 0xeb, 0x00, 0x29, 0x2b, 0x00, 0x80,
+	0x00, 0x2a, 0x30, 0x3f, 0x40, 0x99, 0x9b, 0x00,
+	0xd0, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x1e,
+	0x1f, 0x00, 0x00, 0x10, 0x20, 0x24, 0x30, 0x70,
+	0xff, 0x00, 0x61, 0xe0, 0xe7, 0xf9, 0xfc,
+};
+
+static const signed char new_wtbl[] = {
+	0,   -1,    1,   -1,    1,    1,    0,    1,
+	0,    1,    1,    0,    1,    0,    1,    1,
+	0,    1,    0,    1,    0,    1,    0,    1,
+	0,    1,    0,    1,    1,    0,    1,    0,
+	1,    0,    1,    0,    1,    0,    1,    1,
+	0,    1,    0,    1,    0,    1,    0,    1,
+	1,    0,    1,    0,    1,    0,    1,    0,
+	1,    0,    1,    0,    1,    0,    1,    0,
+	1,    0,    1,    0,    1,    0,    1,    1,
+	0,    1,    0,    1,    0,    1,    0,    1,
+	0,    1,    0,    1,    0,    1,    0,    1,
+	0,    1,    0,    1,    0,    1,    1,    0,
+	1,    0,    1,    0,    1,    0,    1,    0,
+	1,    0,    1,    0,    1,    0,    1,    0,
+	1,    1,    0,    1,    0,    1,    0,    1,
+	0,    1,    0,    1,    0,    1,    0,    1,
+	1,    0,    1,    0,    1,    0,    1,    0,
+	1,    0,    1,    1,    0,    1,    0,    1,
+	0,    1,    0,    1,    0,    1,    0,    1,
+	0,    1,    1,    0,    1,    0,    1,    0,
+	1,    0,    1,    0,    1,    0,    1,    0,
+	1,    0,    1,    0,    1,    0,    1,    1,
+	0,    1,    0,    1,    0,    1,    0,    1,
+	0,    1,    2,    0,    1,    0,    1,    0,
+	1,    0,    1,    0,    1,    0,    1,    0,
+	1,    0,    1,    1,    0,    1,    0,    1,
+	1,    0,    1,    0,    1,    0,    1,    0,
+	1,    0,    1,    1,    2,    1,    1,    2,
+	2,    0,    2,    1,    2,    0,    2,    2,
+	1,    1,    2,    1,    1,    2,    1,    0,
+	1,    1,    0,    1,    0,    1,    2,    1,
+	0,    2,    1,    2,    1,    0,    1,
+};
+
+
+int wcswidth(const wchar_t *pwcs, size_t n)
+{
+	int h, l, m, count;
+	wchar_t wc;
+	unsigned char b;
+
+	if (ENCODING == __ctype_encoding_7_bit) {
+		size_t i;
+
+		for (i = 0 ; (i < n) && pwcs[i] ; i++) {
+			if (pwcs[i] != (pwcs[i] & 0x7f)) {
+				return -1;
+			}
+		}
+	}
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+	else if (ENCODING == __ctype_encoding_8_bit) {
+		mbstate_t mbstate;
+
+		mbstate.__mask = 0;			/* Initialize the mbstate. */
+		if (wcsnrtombs(NULL, &pwcs, n, SIZE_MAX, &mbstate) == ((size_t) - 1)) {
+			return -1;
+		}
+	}
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+#if defined(__CTYPE_HAS_UTF_8_LOCALES) && defined(KUHN)
+	/* For stricter handling of allowed unicode values... see comments above. */
+	else if (ENCODING == __ctype_encoding_utf8) {
+		size_t i;
+
+		for (i = 0 ; (i < n) && pwcs[i] ; i++) {
+			if ( (((__uwchar_t)((pwcs[i]) - 0xfffeU)) < 2)
+				 || (((__uwchar_t)((pwcs[i]) - 0xd800U)) < (0xe000U - 0xd800U))
+				) {
+				return -1;
+			}
+		}
+	}
+#endif /* __CTYPE_HAS_UTF_8_LOCALES */
+
+	for (count = 0 ; n && (wc = *pwcs++) ; n--) {
+		if (wc <= 0xff) {
+			/* If we're here, wc != 0. */
+			if ((wc < 32) || ((wc >= 0x7f) && (wc < 0xa0))) {
+				return -1;
+			}
+			++count;
+			continue;
+		}
+		if (((unsigned int) wc) <= 0xffff) {
+			b = wc & 0xff;
+			h = (wc >> 8);
+			l = new_idx[h];
+			h = new_idx[h+1];
+			while ((m = (l+h) >> 1) != l) {
+				if (b >= new_tbl[m]) {
+					l = m;
+				} else {		/* wc < tbl[m] */
+					h = m;
+				}
+			}
+			count += new_wtbl[l]; /* none should be -1. */
+			continue;
+		}
+
+		/* Redo this to minimize average number of compares?*/
+		if (wc >= 0x1d167) {
+			if (wc <= 0x1d1ad) {
+				if ((wc <= 0x1d169
+					 || (wc >= 0x1d173
+						 && (wc <= 0x1d182
+							 || (wc >= 0x1d185
+								 && (wc <= 0x1d18b
+									 || (wc >= 0x1d1aa))))))
+					) {
+					continue;
+				}
+			} else if (((wc >= 0xe0020) && (wc <= 0xe007f)) || (wc == 0xe0001)) {
+				continue;
+			} else if ((wc >= 0x20000) && (wc <= 0x2ffff)) {
+				++count;		/* need 2.. add one here */
+			}
+#if (WCHAR_MAX > 0x7fffffffL)
+			else if (wc > 0x7fffffffL) {
+				return -1;
+			}
+#endif /* (WCHAR_MAX > 0x7fffffffL) */
+		}
+
+		++count;
+	}
+
+	return count;
+}
+
+#else  /*  __UCLIBC_HAS_LOCALE__ */
+
+int wcswidth(const wchar_t *pwcs, size_t n)
+{
+	int count;
+	wchar_t wc;
+	size_t i;
+
+	for (i = 0 ; (i < n) && pwcs[i] ; i++) {
+		if (pwcs[i] != (pwcs[i] & 0x7f)) {
+			return -1;
+		}
+	}
+
+	for (count = 0 ; n && (wc = *pwcs++) ; n--) {
+		if (wc <= 0xff) {
+			/* If we're here, wc != 0. */
+			if ((wc < 32) || ((wc >= 0x7f) && (wc < 0xa0))) {
+				return -1;
+			}
+			++count;
+			continue;
+		} else {
+			return -1;
+		}
+	}
+
+	return count;
+}
+
+#endif /*  __UCLIBC_HAS_LOCALE__ */
+
+libc_hidden_def(wcswidth)
+
+#endif
+/**********************************************************************/
+#ifdef L_wcwidth
+
+
+int wcwidth(wchar_t wc)
+{
+	return wcswidth(&wc, 1);
+}
+
+#endif
+/**********************************************************************/
+
+
+typedef struct {
+	mbstate_t tostate;
+	mbstate_t fromstate;
+	int tocodeset;
+	int fromcodeset;
+	int frombom;
+	int tobom;
+	int fromcodeset0;
+	int frombom0;
+	int tobom0;
+	int skip_invalid_input;		/* To support iconv -c option. */
+} _UC_iconv_t;
+
+/* For the multibyte
+ * bit 0 means swap endian
+ * bit 1 means 2 byte
+ * bit 2 means 4 byte
+ *
+ */
+
+#if defined L_iconv && defined _LIBC
+/* Used externally only by iconv utility */
+extern const unsigned char __iconv_codesets[];
+libc_hidden_proto(__iconv_codesets)
+#endif
+
+#if defined L_iconv || defined L_iconv_main
+const unsigned char __iconv_codesets[] =
+	"\x0a\xe0""WCHAR_T\x00"		/* superset of UCS-4 but platform-endian */
+#if __BYTE_ORDER == __BIG_ENDIAN
+	"\x08\xec""UCS-4\x00"		/* always BE */
+	"\x0a\xec""UCS-4BE\x00"
+	"\x0a\xed""UCS-4LE\x00"
+	"\x09\xe4""UTF-32\x00"		/* platform endian with BOM */
+	"\x0b\xe4""UTF-32BE\x00"
+	"\x0b\xe5""UTF-32LE\x00"
+	"\x08\xe2""UCS-2\x00"		/* always BE */
+	"\x0a\xe2""UCS-2BE\x00"
+	"\x0a\xe3""UCS-2LE\x00"
+	"\x09\xea""UTF-16\x00"		/* platform endian with BOM */
+	"\x0b\xea""UTF-16BE\x00"
+	"\x0b\xeb""UTF-16LE\x00"
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+	"\x08\xed""UCS-4\x00"		/* always BE */
+	"\x0a\xed""UCS-4BE\x00"
+	"\x0a\xec""UCS-4LE\x00"
+	"\x09\xf4""UTF-32\x00"		/* platform endian with BOM */
+	"\x0b\xe5""UTF-32BE\x00"
+	"\x0b\xe4""UTF-32LE\x00"
+	"\x08\xe3""UCS-2\x00"		/* always BE */
+	"\x0a\xe3""UCS-2BE\x00"
+	"\x0a\xe2""UCS-2LE\x00"
+	"\x09\xfa""UTF-16\x00"		/* platform endian with BOM */
+	"\x0b\xeb""UTF-16BE\x00"
+	"\x0b\xea""UTF-16LE\x00"
+#endif
+	"\x08\x02""UTF-8\x00"
+	"\x0b\x01""US-ASCII\x00"
+	"\x07\x01""ASCII";			/* Must be last! (special case to save a nul) */
+#endif
+#if defined L_iconv && defined _LIBC
+libc_hidden_data_def(__iconv_codesets)
+#endif
+
+
+#ifdef L_iconv
+
+#include <iconv.h>
+#include <string.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#if (__BYTE_ORDER != __BIG_ENDIAN) && (__BYTE_ORDER != __LITTLE_ENDIAN)
+#error unsupported endianness for iconv
+#endif
+
+#ifndef __CTYPE_HAS_8_BIT_LOCALES
+#error currently iconv requires 8 bit locales
+#endif
+#ifndef __CTYPE_HAS_UTF_8_LOCALES
+#error currently iconv requires UTF-8 locales
+#endif
+
+
+enum {
+	IC_WCHAR_T = 0xe0,
+	IC_MULTIBYTE = 0xe0,
+#if __BYTE_ORDER == __BIG_ENDIAN
+	IC_UCS_4 =	0xec,
+	IC_UTF_32 = 0xe4,
+	IC_UCS_2 =	0xe2,
+	IC_UTF_16 = 0xea,
+#else
+	IC_UCS_4 =	0xed,
+	IC_UTF_32 = 0xe5,
+	IC_UCS_2 =	0xe3,
+	IC_UTF_16 = 0xeb,
+#endif
+	IC_UTF_8 = 2,
+	IC_ASCII = 1
+};
+
+
+static int find_codeset(const char *name)
+{
+	const unsigned char *s;
+	int codeset;
+
+	for (s = __iconv_codesets; *s; s += *s) {
+		if (!strcasecmp((char*) (s + 2), name)) {
+			return s[1];
+		}
+	}
+
+	/* The following is ripped from find_locale in locale.c. */
+
+	/* TODO: maybe CODESET_LIST + *s ??? */
+	/* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */
+	codeset = 2;
+	s = (const unsigned char *) __LOCALE_DATA_CODESET_LIST;
+	do {
+		++codeset;		/* Increment codeset first. */
+		if (!strcasecmp(__LOCALE_DATA_CODESET_LIST+*s, name)) {
+			return codeset;
+		}
+	} while (*++s);
+
+	return 0;			/* No matching codeset! */
+}
+
+iconv_t weak_function iconv_open(const char *tocode, const char *fromcode)
+{
+	register _UC_iconv_t *px;
+	int tocodeset, fromcodeset;
+
+	if (((tocodeset = find_codeset(tocode)) != 0)
+		&& ((fromcodeset = find_codeset(fromcode)) != 0)) {
+		if ((px = malloc(sizeof(_UC_iconv_t))) != NULL) {
+			px->tocodeset = tocodeset;
+			px->tobom0 = px->tobom = (tocodeset >= 0xe0) ? (tocodeset & 0x10) >> 4 : 0;
+			px->fromcodeset0 = px->fromcodeset = fromcodeset;
+			px->frombom0 = px->frombom = (fromcodeset >= 0xe0) ? (fromcodeset & 0x10) >> 4 : 0;
+			px->skip_invalid_input = px->tostate.__mask
+				= px->fromstate.__mask = 0;
+			return (iconv_t) px;
+		}
+	} else {
+		__set_errno(EINVAL);
+	}
+	return (iconv_t)(-1);
+}
+
+int weak_function iconv_close(iconv_t cd)
+{
+	free(cd);
+
+	return 0;
+}
+
+size_t weak_function iconv(iconv_t cd, char **__restrict inbuf,
+						   size_t *__restrict inbytesleft,
+						   char **__restrict outbuf,
+						   size_t *__restrict outbytesleft)
+{
+	_UC_iconv_t *px = (_UC_iconv_t *) cd;
+	size_t nrcount, r;
+	wchar_t wc, wc2;
+	int inci, inco;
+
+	assert(px != (_UC_iconv_t *)(-1));
+	assert(sizeof(wchar_t) == 4);
+
+	if (!inbuf || !*inbuf) {	/* Need to reinitialze conversion state. */
+		/* Note: For shift-state encodings we possibly need to output the
+		 * shift sequence to return to initial state! */
+		if ((px->fromcodeset & 0xf0) == 0xe0) {
+		}
+		px->tostate.__mask = px->fromstate.__mask = 0;
+		px->fromcodeset = px->fromcodeset0;
+		px->tobom = px->tobom0;
+		px->frombom = px->frombom0;
+		return 0;
+	}
+
+	nrcount = 0;
+	while (*inbytesleft) {
+		if (!*outbytesleft) {
+		TOO_BIG:
+			__set_errno(E2BIG);
+			return (size_t) -1;
+		}
+
+		inci = inco = 1;
+		if (px->fromcodeset >= IC_MULTIBYTE) {
+			inci = (px->fromcodeset == IC_WCHAR_T) ? 4: (px->fromcodeset & 6);
+			if (*inbytesleft < inci) goto INVALID;
+			wc = (((unsigned int)((unsigned char)((*inbuf)[0]))) << 8)
+				+ ((unsigned char)((*inbuf)[1]));
+			if (inci == 4) {
+				wc = (((unsigned int)((unsigned char)((*inbuf)[2]))) << 8)
+					+ ((unsigned char)((*inbuf)[3])) + (wc << 16);
+				if (!(px->fromcodeset & 1)) wc = bswap_32(wc);
+			} else {
+				if (!(px->fromcodeset & 1)) wc = bswap_16(wc);
+				if (((px->fromcodeset & IC_UTF_16) == IC_UTF_16)
+					 && (((__uwchar_t)(wc - 0xd800U)) < (0xdc00U - 0xd800U))
+					) {			/* surrogate */
+					wc =- 0xd800U;
+					if (*inbytesleft < 4) goto INVALID;
+					wc2 = (((unsigned int)((unsigned char)((*inbuf)[2]))) << 8)
+						+ ((unsigned char)((*inbuf)[3]));
+					if (!(px->fromcodeset & 1)) wc = bswap_16(wc2);
+					if (((__uwchar_t)(wc2 -= 0xdc00U)) < (0xe0000U - 0xdc00U)) {
+						goto ILLEGAL;
+					}
+					inci = 4;	/* Change inci here in case skipping illegals. */
+					wc = 0x10000UL + (wc << 10) + wc2;
+				}
+			}
+
+			if (px->frombom) {
+				px->frombom = 0;
+				if ((wc == 0xfeffU)
+					|| (wc == ((inci == 4)
+							   ? (((wchar_t) 0xfffe0000UL))
+							   : ((wchar_t)(0xfffeUL))))
+					) {
+					if (wc != 0xfeffU) {
+						px->fromcodeset ^= 1; /* toggle endianness */
+						wc = 0xfeffU;
+					}
+					if (!px->frombom) {
+						goto BOM_SKIP_OUTPUT;
+					}
+					goto GOT_BOM;
+				}
+			}
+
+			if (px->fromcodeset != IC_WCHAR_T) {
+				if (((__uwchar_t) wc) > (((px->fromcodeset & IC_UCS_4) == IC_UCS_4)
+										 ? 0x7fffffffUL : 0x10ffffUL)
+#ifdef KUHN
+					|| (((__uwchar_t)(wc - 0xfffeU)) < 2)
+					|| (((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U))
+#endif
+					) {
+					goto ILLEGAL;
+				}
+			}
+		} else if (px->fromcodeset == IC_UTF_8) {
+			const char *p = *inbuf;
+			r = _wchar_utf8sntowcs(&wc, 1, &p, *inbytesleft, &px->fromstate, 0);
+			if (((ssize_t) r) <= 0) { /* either EILSEQ or incomplete or nul */
+				if (((ssize_t) r) < 0) { /* either EILSEQ or incomplete or nul */
+					assert((r == (size_t)(-1)) || (r == (size_t)(-2)));
+					if (r == (size_t)(-2)) {
+					INVALID:
+						__set_errno(EINVAL);
+					} else {
+						px->fromstate.__mask = 0;
+						inci = 1;
+					ILLEGAL:
+						if (px->skip_invalid_input) {
+							px->skip_invalid_input = 2;	/* flag for iconv utility */
+							goto BOM_SKIP_OUTPUT;
+						}
+						__set_errno(EILSEQ);
+					}
+					return (size_t)(-1);
+				}
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: optimize this.
+#endif
+				if (p != NULL) { /* incomplete char case */
+					goto INVALID;
+				}
+				p = *inbuf + 1;	/* nul */
+			}
+			inci = p - *inbuf;
+		} else if ((wc = ((unsigned char)(**inbuf))) >= 0x80) {	/* Non-ASCII... */
+			if (px->fromcodeset == IC_ASCII) { /* US-ASCII codeset */
+				goto ILLEGAL;
+			} else {			/* some other 8-bit ascii-extension codeset */
+				const __codeset_8_bit_t *c8b
+					= __locale_mmap->codeset_8_bit + px->fromcodeset - 3;
+				wc -= 0x80;
+				wc = __UCLIBC_CURLOCALE->tbl8c2wc[
+							 (c8b->idx8c2wc[wc >> Cc2wc_IDX_SHIFT]
+							  << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))];
+				if (!wc) {
+					goto ILLEGAL;
+				}
+			}
+		}
+
+
+		if (px->tobom) {
+			inci = 0;
+			wc = 0xfeffU;
+	GOT_BOM:
+			px->tobom = 0;
+		}
+
+		if (px->tocodeset >= IC_MULTIBYTE) {
+			inco = (px->tocodeset == IC_WCHAR_T) ? 4: (px->tocodeset & 6);
+			if (*outbytesleft < inco) goto TOO_BIG;
+			if (px->tocodeset != IC_WCHAR_T) {
+				if (((__uwchar_t) wc) > (((px->tocodeset & IC_UCS_4) == IC_UCS_4)
+										 ? 0x7fffffffUL : 0x10ffffUL)
+#ifdef KUHN
+					|| (((__uwchar_t)(wc - 0xfffeU)) < 2)
+					|| (((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U))
+#endif
+					) {
+				REPLACE_32:
+					wc = 0xfffd;
+					++nrcount;
+				}
+			}
+			if (inco == 4) {
+				if (px->tocodeset & 1) wc = bswap_32(wc);
+			} else {
+				if (((__uwchar_t)wc ) > 0xffffU) {
+					if ((px->tocodeset & IC_UTF_16) != IC_UTF_16) {
+						goto REPLACE_32;
+					}
+					if (*outbytesleft < (inco = 4)) goto TOO_BIG;
+					wc2 = 0xdc00U + (wc & 0x3ff);
+					wc = 0xd800U + ((wc >> 10) & 0x3ff);
+					if (px->tocodeset & 1) {
+						wc = bswap_16(wc);
+						wc2 = bswap_16(wc2);
+					}
+					wc += (wc2 << 16);
+				} else if (px->tocodeset & 1) wc = bswap_16(wc);
+			}
+			(*outbuf)[0] = (char)((unsigned char)(wc));
+			(*outbuf)[1] = (char)((unsigned char)(wc >> 8));
+			if (inco == 4) {
+				(*outbuf)[2] = (char)((unsigned char)(wc >> 16));
+				(*outbuf)[3] = (char)((unsigned char)(wc >> 24));
+			}
+		} else if (px->tocodeset == IC_UTF_8) {
+			const wchar_t *pw = &wc;
+			do {
+				r = _wchar_wcsntoutf8s(*outbuf, *outbytesleft, &pw, 1);
+				if (r != (size_t)(-1)) {
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: What happens for a nul?
+#endif
+					if (r == 0) {
+						if (wc != 0) {
+							goto TOO_BIG;
+						}
+						++r;
+					}
+					break;
+				}
+				wc = 0xfffdU;
+				++nrcount;
+			} while (1);
+			inco = r;
+		} else if (((__uwchar_t)(wc)) < 0x80) {
+		CHAR_GOOD:
+				**outbuf = wc;
+		} else {
+			if ((px->tocodeset != 0x01) && (wc <= Cwc2c_DOMAIN_MAX)) {
+				const __codeset_8_bit_t *c8b
+					= __locale_mmap->codeset_8_bit + px->tocodeset - 3;
+				__uwchar_t u;
+				u = c8b->idx8wc2c[wc >> (Cwc2c_TI_SHIFT + Cwc2c_TT_SHIFT)];
+				u = __UCLIBC_CURLOCALE->tbl8wc2c[(u << Cwc2c_TI_SHIFT)
+						 + ((wc >> Cwc2c_TT_SHIFT)
+							& ((1 << Cwc2c_TI_SHIFT)-1))];
+				wc = __UCLIBC_CURLOCALE->tbl8wc2c[Cwc2c_TI_LEN
+						 + (u << Cwc2c_TT_SHIFT)
+						 + (wc & ((1 << Cwc2c_TT_SHIFT)-1))];
+				if (wc) {
+					goto CHAR_GOOD;
+				}
+			}
+			**outbuf = '?';
+			++nrcount;
+		}
+
+		*outbuf += inco;
+		*outbytesleft -= inco;
+	BOM_SKIP_OUTPUT:
+		*inbuf += inci;
+		*inbytesleft -= inci;
+	}
+	return nrcount;
+}
+#endif
diff --git a/ap/build/uClibc/libc/misc/wchar/wcrtomb.c b/ap/build/uClibc/libc/misc/wchar/wcrtomb.c
new file mode 100644
index 0000000..91eb306
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/wcrtomb.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wcrtomb
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/wcsnrtombs.c b/ap/build/uClibc/libc/misc/wchar/wcsnrtombs.c
new file mode 100644
index 0000000..af9d6c3
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/wcsnrtombs.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wcsnrtombs
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/wcsrtombs.c b/ap/build/uClibc/libc/misc/wchar/wcsrtombs.c
new file mode 100644
index 0000000..e5b6c0b
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/wcsrtombs.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wcsrtombs
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/wcswidth.c b/ap/build/uClibc/libc/misc/wchar/wcswidth.c
new file mode 100644
index 0000000..3d955a2
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/wcswidth.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wcswidth
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/wctob.c b/ap/build/uClibc/libc/misc/wchar/wctob.c
new file mode 100644
index 0000000..88d31f5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/wctob.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wctob
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wchar/wcwidth.c b/ap/build/uClibc/libc/misc/wchar/wcwidth.c
new file mode 100644
index 0000000..6c4a344
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wchar/wcwidth.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2004-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wcwidth
+#include "wchar.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/Makefile b/ap/build/uClibc/libc/misc/wctype/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/wctype/Makefile.in b/ap/build/uClibc/libc/misc/wctype/Makefile.in
new file mode 100644
index 0000000..4eacc11
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/Makefile.in
@@ -0,0 +1,36 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/wctype
+
+# multi source _wctype.c
+COM_SRC := \
+	iswalnum.c iswalpha.c iswcntrl.c iswdigit.c iswgraph.c \
+	iswlower.c iswprint.c iswpunct.c iswspace.c iswupper.c \
+	iswxdigit.c iswblank.c wctrans.c towctrans.c \
+	wctype.c iswctype.c towlower.c towupper.c
+
+CSRC :=
+ifeq ($(UCLIBC_HAS_WCHAR),y)
+CSRC += $(COM_SRC)
+endif
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+CSRC += $(patsubst %.c,%_l.c,$(COM_SRC))
+endif
+
+MISC_WCTYPE_DIR := $(top_srcdir)libc/misc/wctype
+MISC_WCTYPE_OUT := $(top_builddir)libc/misc/wctype
+
+MISC_WCTYPE_SRC := $(patsubst %.c,$(MISC_WCTYPE_DIR)/%.c,$(CSRC))
+MISC_WCTYPE_OBJ := $(patsubst %.c,$(MISC_WCTYPE_OUT)/%.o,$(CSRC))
+
+libc-y += $(MISC_WCTYPE_OBJ)
+
+objclean-y += CLEAN_libc/misc/wctype
+
+CLEAN_libc/misc/wctype:
+	$(do_rm) $(addprefix $(MISC_WCTYPE_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/wctype/_wctype.c b/ap/build/uClibc/libc/misc/wctype/_wctype.c
new file mode 100644
index 0000000..89269f4
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/_wctype.c
@@ -0,0 +1,860 @@
+/*  Copyright (C) 2002, 2003     Manuel Novoa III
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!
+ *
+ *  Besides uClibc, I'm using this code in my libc for elks, which is
+ *  a 16-bit environment with a fairly limited compiler.  It would make
+ *  things much easier for me if this file isn't modified unnecessarily.
+ *  In particular, please put any new or replacement functions somewhere
+ *  else, and modify the makefile to use your version instead.
+ *  Thanks.  Manuel
+ *
+ *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */
+
+#define __NO_CTYPE
+
+#include <wctype.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <locale.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <bits/uClibc_uwchar.h>
+
+#if defined(__LOCALE_C_ONLY) && defined(__UCLIBC_DO_XLOCALE)
+# error xlocale functionality is not supported in stub locale mode.
+#endif
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+# include <xlocale.h>
+#endif
+
+/* We know wide char support is enabled.  We wouldn't be here otherwise. */
+
+/* Define this if you want to unify the towupper and towlower code in the
+ * towctrans function. */
+/* #define SMALL_UPLOW */
+
+
+/* Pull in __CTYPE_xxx constants */
+#include <bits/uClibc_charclass.h>
+
+
+/* The following is used to implement wctype(), but it is defined
+ * here because the ordering must agree with that of the enumeration
+ * below (ignoring unclassified). */
+#define __CTYPE_TYPESTRING \
+	"\6alnum\0\6alpha\0\6blank\0\6cntrl\0\6digit\0\6graph\0\6lower\0" \
+	"\6print\0\6punct\0\6space\0\6upper\0\7xdigit\0\0"
+
+
+/* The values for wctype_t. */
+enum {
+	_CTYPE_unclassified = 0,
+	_CTYPE_isalnum,
+	_CTYPE_isalpha,
+	_CTYPE_isblank,
+	_CTYPE_iscntrl,
+	_CTYPE_isdigit,
+	_CTYPE_isgraph,
+	_CTYPE_islower,
+	_CTYPE_isprint,
+	_CTYPE_ispunct,
+	_CTYPE_isspace,
+	_CTYPE_isupper,
+	_CTYPE_isxdigit				/* _MUST_ be last of the standard classes! */
+};
+
+/* The following is used to implement wctrans(). */
+
+#define __CTYPE_TRANSTRING	"\10tolower\0\10toupper\0\10totitle\0\0"
+
+enum {
+	_CTYPE_tolower = 1,
+	_CTYPE_toupper,
+	_CTYPE_totitle
+};
+
+/*--------------------------------------------------------------------*/
+
+#define _CTYPE_iswxdigit (_CTYPE_isxdigit)
+
+/*--------------------------------------------------------------------*/
+
+#ifdef __UCLIBC_MJN3_ONLY__
+# ifdef L_iswspace
+/* generates one warning */
+#  warning TODO: Fix WC* defines!
+# endif
+#endif
+
+#define ENCODING		(__UCLIBC_CURLOCALE->encoding)
+
+#define WCctype			(__UCLIBC_CURLOCALE->tblwctype)
+#define WCuplow			(__UCLIBC_CURLOCALE->tblwuplow)
+#define WCcmob			(__UCLIBC_CURLOCALE->tblwcomb)
+#define WCuplow_diff		(__UCLIBC_CURLOCALE->tblwuplow_diff)
+
+
+#define WC_TABLE_DOMAIN_MAX   __LOCALE_DATA_WC_TABLE_DOMAIN_MAX
+
+#define WCctype_II_LEN        __LOCALE_DATA_WCctype_II_LEN
+#define WCctype_TI_LEN        __LOCALE_DATA_WCctype_TI_LEN
+#define WCctype_UT_LEN        __LOCALE_DATA_WCctype_UT_LEN
+#define WCctype_II_SHIFT      __LOCALE_DATA_WCctype_II_SHIFT
+#define WCctype_TI_SHIFT      __LOCALE_DATA_WCctype_TI_SHIFT
+
+#define WCuplow_II_LEN        __LOCALE_DATA_WCuplow_II_LEN
+#define WCuplow_TI_LEN        __LOCALE_DATA_WCuplow_TI_LEN
+#define WCuplow_UT_LEN        __LOCALE_DATA_WCuplow_UT_LEN
+#define WCuplow_II_SHIFT      __LOCALE_DATA_WCuplow_II_SHIFT
+#define WCuplow_TI_SHIFT      __LOCALE_DATA_WCuplow_TI_SHIFT
+
+
+#define WCctype_TI_MASK		((1 << (WCctype_TI_SHIFT)) - 1)
+#define WCctype_II_MASK		((1 << (WCctype_II_SHIFT)) - 1)
+
+/**********************************************************************/
+
+#undef __PASTE2
+#undef __PASTE3
+#define __PASTE2(X,Y)		X ## Y
+#define __PASTE3(X,Y,Z)		X ## Y ## Z
+
+#ifdef __UCLIBC_DO_XLOCALE
+
+#define ISW_FUNC_BODY(NAME) \
+int __PASTE3(isw,NAME,_l) (wint_t wc, __locale_t l) \
+{ \
+	return iswctype_l(wc, __PASTE2(_CTYPE_is,NAME), l); \
+}
+
+#else  /* __UCLIBC_DO_XLOCALE */
+
+#define ISW_FUNC_BODY(NAME) \
+int __PASTE2(isw,NAME) (wint_t wc) \
+{ \
+	return iswctype(wc, __PASTE2(_CTYPE_is,NAME)); \
+}
+
+#endif /* __UCLIBC_DO_XLOCALE */
+/**********************************************************************/
+#if defined(L_iswalnum) || defined(L_iswalnum_l)
+
+ISW_FUNC_BODY(alnum);
+# ifdef L_iswalnum
+libc_hidden_def(iswalnum)
+# endif
+
+#endif
+/**********************************************************************/
+#if defined(L_iswalpha) || defined(L_iswalpha_l)
+
+ISW_FUNC_BODY(alpha);
+
+#endif
+/**********************************************************************/
+#if defined(L_iswblank) || defined(L_iswblank_l)
+
+ISW_FUNC_BODY(blank);
+
+#endif
+/**********************************************************************/
+#if defined(L_iswcntrl) || defined(L_iswcntrl_l)
+
+ISW_FUNC_BODY(cntrl);
+
+#endif
+/**********************************************************************/
+#if defined(L_iswdigit) || defined(L_iswdigit_l)
+
+ISW_FUNC_BODY(digit);
+
+#endif
+/**********************************************************************/
+#if defined(L_iswgraph) || defined(L_iswgraph_l)
+
+ISW_FUNC_BODY(graph);
+
+#endif
+/**********************************************************************/
+#if defined(L_iswlower) || defined(L_iswlower_l)
+
+ISW_FUNC_BODY(lower);
+# ifdef L_iswlower
+libc_hidden_def(iswlower)
+# endif
+
+#endif
+/**********************************************************************/
+#if defined(L_iswprint) || defined(L_iswprint_l)
+
+ISW_FUNC_BODY(print);
+
+#endif
+/**********************************************************************/
+#if defined(L_iswpunct) || defined(L_iswpunct_l)
+
+ISW_FUNC_BODY(punct);
+
+#endif
+/**********************************************************************/
+#if defined(L_iswspace) || defined(L_iswspace_l)
+
+ISW_FUNC_BODY(space);
+# ifdef L_iswspace
+libc_hidden_def(iswspace)
+# else
+libc_hidden_def(iswspace_l)
+# endif
+
+#endif
+/**********************************************************************/
+#if defined(L_iswupper) || defined(L_iswupper_l)
+
+ISW_FUNC_BODY(upper);
+# ifdef L_iswupper
+libc_hidden_def(iswupper)
+# endif
+
+#endif
+/**********************************************************************/
+#if defined(L_iswxdigit) || defined(L_iswxdigit_l)
+
+ISW_FUNC_BODY(xdigit);
+
+#endif
+/**********************************************************************/
+#if defined(L_towlower) || defined(L_towlower_l)
+
+# ifdef L_towlower
+#  define TOWLOWER(w) towlower(w)
+# else
+#  define TOWLOWER(w) towlower_l(w, __locale_t locale)
+#  undef __UCLIBC_CURLOCALE
+#  define __UCLIBC_CURLOCALE (locale)
+# endif
+
+# ifdef __UCLIBC_HAS_XLOCALE__
+#  define TOWCTRANS(w,d) towctrans_l(w,d, __UCLIBC_CURLOCALE)
+# else
+#  define TOWCTRANS(w,d) towctrans(w,d)
+# endif
+
+# define __C_towlower(wc) \
+	(((__uwchar_t)(wc) <= 0x7f) ? (__C_ctype_tolower)[(wc)] : (wc))
+
+# ifdef __LOCALE_C_ONLY
+
+wint_t towlower(wint_t wc)
+{
+#  ifdef __UCLIBC_HAS_CTYPE_TABLES__
+	return __C_towlower(wc);
+#  else
+	return (wc == (unsigned)wc)
+		? __C_tolower((unsigned)wc)
+		: 0;
+#  endif
+}
+
+# else  /* __LOCALE_C_ONLY */
+
+#  ifdef SMALL_UPLOW
+
+#   if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__)
+wint_t towlower(wint_t wc)
+{
+	return towctrans_l(wc, _CTYPE_tolower, __UCLIBC_CURLOCALE);
+}
+#   else  /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
+wint_t TOWLOWER(wint_t wc)
+{
+	return TOWCTRANS(wc, _CTYPE_tolower);
+}
+#   endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
+
+#  else  /* SMALL_UPLOW */
+
+#   if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__)
+
+wint_t towlower(wint_t wc)
+{
+	return towlower_l(wc, __UCLIBC_CURLOCALE);
+}
+
+#   else  /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
+
+wint_t TOWLOWER(wint_t wc)
+{
+	unsigned sc, n, i;
+	__uwchar_t u = wc;
+
+	if (ENCODING == __ctype_encoding_7_bit) {
+		/* We're in the C/POSIX locale, so ignore the tables. */
+		return __C_towlower(wc);
+	}
+
+	if (u <= WC_TABLE_DOMAIN_MAX) {
+		sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
+		u >>= WCuplow_TI_SHIFT;
+		n = u & ((1 << WCuplow_II_SHIFT) - 1);
+		u >>= WCuplow_II_SHIFT;
+
+		i = ((unsigned) WCuplow[u]) << WCuplow_II_SHIFT;
+		i = ((unsigned) WCuplow[WCuplow_II_LEN + i + n]) << WCuplow_TI_SHIFT;
+		i = ((unsigned) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN	+ i + sc]) << 1;
+		wc += WCuplow_diff[i + 1];
+	}
+	return wc;
+}
+
+#   endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
+
+#  endif /* SMALL_UPLOW */
+
+#  ifdef L_towlower_l
+libc_hidden_def(towlower_l)
+#  endif
+
+# endif /* __LOCALE_C_ONLY */
+
+# ifndef L_towlower_l
+libc_hidden_def(towlower)
+# endif
+
+#endif
+/**********************************************************************/
+#if defined(L_towupper) || defined(L_towupper_l)
+
+# ifdef L_towupper
+#  define TOWUPPER(w) towupper(w)
+# else
+#  define TOWUPPER(w) towupper_l(w, __locale_t locale)
+#  undef __UCLIBC_CURLOCALE
+#  define __UCLIBC_CURLOCALE (locale)
+# endif
+
+# ifdef __UCLIBC_HAS_XLOCALE__
+#  define TOWCTRANS(w,d) towctrans_l(w,d, __UCLIBC_CURLOCALE)
+# else
+#  define TOWCTRANS(w,d) towctrans(w,d)
+# endif
+
+# define __C_towupper(wc) \
+	(((__uwchar_t)(wc) <= 0x7f) ? (__C_ctype_toupper)[(wc)] : (wc))
+
+# ifdef __LOCALE_C_ONLY
+
+wint_t towupper(wint_t wc)
+{
+#  ifdef __UCLIBC_HAS_CTYPE_TABLES__
+	return __C_towupper(wc);
+#  else
+	return (wc == (unsigned)wc)
+		? __C_toupper((unsigned)wc)
+		: 0;
+#  endif
+}
+
+# else  /* __LOCALE_C_ONLY */
+
+#  ifdef SMALL_UPLOW
+
+#   if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__)
+wint_t towupper(wint_t wc)
+{
+	return towctrans_l(wc, _CTYPE_toupper, __UCLIBC_CURLOCALE);
+}
+#   else
+wint_t TOWUPPER(wint_t wc)
+{
+	return TOWCTRANS(wc, _CTYPE_toupper);
+}
+#   endif
+
+#  else  /* SMALL_UPLOW */
+
+#   if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__)
+wint_t towupper(wint_t wc)
+{
+	return towupper_l(wc, __UCLIBC_CURLOCALE);
+}
+#   else  /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
+wint_t TOWUPPER(wint_t wc)
+{
+	unsigned sc, n, i;
+	__uwchar_t u = wc;
+
+	if (ENCODING == __ctype_encoding_7_bit) {
+		/* We're in the C/POSIX locale, so ignore the tables. */
+		return __C_towupper(wc);
+	}
+
+	if (u <= WC_TABLE_DOMAIN_MAX) {
+		sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
+		u >>= WCuplow_TI_SHIFT;
+		n = u & ((1 << WCuplow_II_SHIFT) - 1);
+		u >>= WCuplow_II_SHIFT;
+
+		i = ((unsigned) WCuplow[u]) << WCuplow_II_SHIFT;
+		i = ((unsigned) WCuplow[WCuplow_II_LEN + i + n]) << WCuplow_TI_SHIFT;
+		i = ((unsigned) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN + i + sc]) << 1;
+		wc += WCuplow_diff[i];
+	}
+	return wc;
+}
+#   endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
+
+#  endif /* SMALL_UPLOW */
+
+#  ifdef L_towupper_l
+libc_hidden_def(towupper_l)
+#  endif
+
+# endif /* __LOCALE_C_ONLY */
+
+# ifndef L_towupper_l
+libc_hidden_def(towupper)
+# endif
+
+#endif
+/**********************************************************************/
+#ifdef L_wctype
+
+static const unsigned char typestring[] = __CTYPE_TYPESTRING;
+
+wctype_t wctype(const char *property)
+{
+	const unsigned char *p;
+	int i;
+
+	p = typestring;
+	i = 1;
+	do {
+		if (!strcmp(property, (const char *) ++p)) {
+			return i;
+		}
+		++i;
+		p += p[-1];
+	} while (*p);
+
+	/* TODO - Add locale-specific classifications. */
+	return 0;
+}
+libc_hidden_def(wctype)
+
+#endif
+/**********************************************************************/
+#ifdef L_wctype_l
+
+#ifdef __UCLIBC_MJN3_ONLY__
+# warning REMINDER: Currently wctype_l simply calls wctype.
+#endif
+
+wctype_t wctype_l (const char *property, __locale_t locale)
+{
+	return wctype(property);
+}
+
+#endif
+/**********************************************************************/
+#if defined(L_iswctype) || defined(L_iswctype_l)
+
+#define __C_iswdigit(c) \
+	((sizeof(c) == sizeof(char)) \
+	 ? ((unsigned char)((c) - '0') < 10) \
+	 : ((__uwchar_t)((c) - '0') < 10) \
+	)
+#define __C_iswxdigit(c) \
+	(__C_iswdigit(c) \
+	 || ((sizeof(c) == sizeof(char)) \
+		 ? ((unsigned char)(((c) | 0x20) - 'a') < 6) \
+		 : ((__uwchar_t)(((c) | 0x20) - 'a') < 6) \
+	    ) \
+	)
+
+#ifdef __UCLIBC_MJN3_ONLY__
+# ifdef L_iswctype
+#  warning CONSIDER: Change to bit shift?  would need to sync with wctype.h
+# endif
+#endif
+
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+# if !defined(__UCLIBC_HAS_XLOCALE__) || defined(L_iswctype_l)
+static const unsigned short int desc2flag[] = {
+	[_CTYPE_unclassified] = 0,
+	[_CTYPE_isalnum] = (unsigned short int) _ISwalnum,
+	[_CTYPE_isalpha] = (unsigned short int) _ISwalpha,
+	[_CTYPE_isblank] = (unsigned short int) _ISwblank,
+	[_CTYPE_iscntrl] = (unsigned short int) _ISwcntrl,
+	[_CTYPE_isdigit] = (unsigned short int) _ISwdigit,
+	[_CTYPE_isgraph] = (unsigned short int) _ISwgraph,
+	[_CTYPE_islower] = (unsigned short int) _ISwlower,
+	[_CTYPE_isprint] = (unsigned short int) _ISwprint,
+	[_CTYPE_ispunct] = (unsigned short int) _ISwpunct,
+	[_CTYPE_isspace] = (unsigned short int) _ISwspace,
+	[_CTYPE_isupper] = (unsigned short int) _ISwupper,
+	[_CTYPE_isxdigit] = (unsigned short int) _ISwxdigit,
+};
+# endif
+#endif
+
+#ifdef __LOCALE_C_ONLY
+
+#ifdef __UCLIBC_HAS_CTYPE_TABLES__
+
+int iswctype(wint_t wc, wctype_t desc)
+{
+	/* Note... wctype_t is unsigned. */
+
+	if ((__uwchar_t) wc <= 0x7f
+	 && desc < (sizeof(desc2flag) / sizeof(desc2flag[0]))
+	) {
+		return __isctype(wc, desc2flag[desc]);
+	}
+	return 0;
+}
+
+#else  /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+int iswctype(wint_t wc, wctype_t desc)
+{
+	/* This is lame, but it is here just to get it working for now. */
+
+	if (wc == (unsigned)wc) {
+		switch (desc) {
+			case _CTYPE_isupper:
+				return __C_isupper((unsigned)wc);
+			case _CTYPE_islower:
+				return __C_islower((unsigned)wc);
+			case _CTYPE_isalpha:
+				return __C_isalpha((unsigned)wc);
+			case _CTYPE_isdigit:
+				return __C_isdigit((unsigned)wc);
+			case _CTYPE_isxdigit:
+				return __C_isxdigit((unsigned)wc);
+			case _CTYPE_isspace:
+				return __C_isspace((unsigned)wc);
+			case _CTYPE_isprint:
+				return __C_isprint((unsigned)wc);
+			case _CTYPE_isgraph:
+				return __C_isgraph((unsigned)wc);
+			case _CTYPE_isblank:
+				return __C_isblank((unsigned)wc);
+			case _CTYPE_iscntrl:
+				return __C_iscntrl((unsigned)wc);
+			case _CTYPE_ispunct:
+				return __C_ispunct((unsigned)wc);
+			case _CTYPE_isalnum:
+				return __C_isalnum((unsigned)wc);
+			default:
+				break;
+		}
+	}
+	return 0;
+}
+
+#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
+
+#else  /* __LOCALE_C_ONLY */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+# ifdef L_iswctype
+#  warning CONSIDER: Handle combining class?
+# endif
+#endif
+
+#ifdef L_iswctype
+# define ISWCTYPE(w,d) iswctype(w,d)
+#else
+# define ISWCTYPE(w,d) iswctype_l(w,d, __locale_t locale)
+# undef __UCLIBC_CURLOCALE
+# define __UCLIBC_CURLOCALE (locale)
+#endif
+
+#if defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__)
+
+int iswctype(wint_t wc, wctype_t desc)
+{
+	return iswctype_l(wc, desc, __UCLIBC_CURLOCALE);
+}
+
+#else  /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */
+
+int ISWCTYPE(wint_t wc, wctype_t desc)
+{
+	unsigned sc, n, i0, i1;
+	unsigned char d = __CTYPE_unclassified;
+
+	if ((ENCODING != __ctype_encoding_7_bit) || ((__uwchar_t)wc <= 0x7f)) {
+		if (desc < _CTYPE_iswxdigit) {
+			if ((__uwchar_t)wc <= WC_TABLE_DOMAIN_MAX) {
+				/* From here on, we know wc > 0. */
+				sc = wc & WCctype_TI_MASK;
+				wc >>= WCctype_TI_SHIFT;
+				n = wc & WCctype_II_MASK;
+				wc >>= WCctype_II_SHIFT;
+
+				i0 = WCctype[wc];
+				i0 <<= WCctype_II_SHIFT;
+				i1 = WCctype[WCctype_II_LEN + i0 + n];
+				i1 <<= (WCctype_TI_SHIFT-1);
+				d = WCctype[WCctype_II_LEN + WCctype_TI_LEN + i1 + (sc >> 1)];
+
+				d = (sc & 1) ? (d >> 4) : (d & 0xf);
+			} else if ((__uwchar_t)(wc - 0xe0020UL) <= 0x5f
+				|| wc == 0xe0001UL
+				|| (((__uwchar_t)(wc - 0xf0000UL) < 0x20000UL) && ((wc & 0xffffU) <= 0xfffdU))
+			) {
+				d = __CTYPE_punct;
+			}
+
+#if 0
+			return ((unsigned char)(d - ctype_range[2*desc]) <= ctype_range[2*desc + 1])
+				&& ((desc != _CTYPE_iswblank) || (d & 1));
+#else
+			return __UCLIBC_CURLOCALE->code2flag[d] & desc2flag[desc];
+#endif
+		}
+
+#ifdef __UCLIBC_MJN3_ONLY__
+# warning TODO: xdigit really needs to be handled better.  Remember only for ascii!
+#endif
+		/* TODO - Add locale-specific classifications. */
+		return (desc == _CTYPE_iswxdigit) ? __C_iswxdigit(wc) : 0;
+	}
+	return 0;
+}
+
+#endif /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */
+
+#ifdef L_iswctype_l
+libc_hidden_def(iswctype_l)
+#endif
+
+#endif /* __LOCALE_C_ONLY */
+
+#ifdef L_iswctype
+libc_hidden_def(iswctype)
+#endif
+
+#endif
+/**********************************************************************/
+#if defined(L_towctrans) || defined(L_towctrans_l)
+
+#ifdef __LOCALE_C_ONLY
+
+/* Minimal support for C/POSIX locale. */
+
+wint_t towctrans(wint_t wc, wctrans_t desc)
+{
+	if ((unsigned)(desc - _CTYPE_tolower) <= (_CTYPE_toupper - _CTYPE_tolower)) {
+		/* Transliteration is either tolower or toupper. */
+#if 0
+/* I think it's wrong: _toupper(c) assumes that c is a *lowercase* *letter* -
+ * it is defined as ((c) ^ 0x20)! */
+		if ((__uwchar_t) wc <= 0x7f) {
+			return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc);
+		}
+#endif
+		__uwchar_t c = wc | 0x20; /* lowercase if it's a letter */
+		if (c >= 'a' && c <= 'z') {
+			if (desc == _CTYPE_toupper)
+				c &= ~0x20; /* uppercase */
+			return c;
+		}
+	} else {
+		__set_errno(EINVAL);	/* Invalid transliteration. */
+	}
+	return wc;
+}
+
+#else  /* __LOCALE_C_ONLY */
+
+#ifdef L_towctrans
+# define TOWCTRANS(w,d) towctrans(w,d)
+#else
+# define TOWCTRANS(w,d) towctrans_l(w,d, __locale_t locale)
+# undef __UCLIBC_CURLOCALE
+# define __UCLIBC_CURLOCALE (locale)
+#endif
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+# define TOWLOWER(w,l) towlower_l(w,l)
+# define TOWUPPER(w,l) towupper_l(w,l)
+#else
+# define TOWLOWER(w,l) towlower(w)
+# define TOWUPPER(w,l) towupper(w)
+#endif
+
+#if defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__)
+
+wint_t towctrans(wint_t wc, wctrans_t desc)
+{
+	return towctrans_l(wc, desc, __UCLIBC_CURLOCALE);
+}
+
+#else  /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */
+
+#ifdef SMALL_UPLOW
+
+wint_t TOWCTRANS(wint_t wc, wctrans_t desc)
+{
+	unsigned sc, n, i;
+	__uwchar_t u = wc;
+
+	/* TODO - clean up */
+	if (ENCODING == __ctype_encoding_7_bit) {
+		if ((__uwchar_t)wc > 0x7f
+		 || (unsigned)(desc - _CTYPE_tolower) > (_CTYPE_toupper - _CTYPE_tolower)
+		) {
+			/* We're in the C/POSIX locale, so ignore non-ASCII values
+			 * as well an any mappings other than toupper or tolower. */
+			return wc;
+		}
+	}
+
+	if ((unsigned)(desc - _CTYPE_tolower) <= (_CTYPE_totitle - _CTYPE_tolower)) {
+		if (u <= WC_TABLE_DOMAIN_MAX) {
+			sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
+			u >>= WCuplow_TI_SHIFT;
+			n = u & ((1 << WCuplow_II_SHIFT) - 1);
+			u >>= WCuplow_II_SHIFT;
+
+			i = ((unsigned) WCuplow[u]) << WCuplow_II_SHIFT;
+			i = ((unsigned) WCuplow[WCuplow_II_LEN + i + n]) << WCuplow_TI_SHIFT;
+			i = ((unsigned) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN + i + sc]) << 1;
+			if (desc == _CTYPE_tolower) {
+				++i;
+			}
+			wc += WCuplow_diff[i];
+			if (desc == _CTYPE_totitle) {
+#ifdef __UCLIBC_MJN3_ONLY__
+# warning TODO: Verify totitle special cases!
+#endif
+				/* WARNING! These special cases work for glibc 2.2.4.  Changes
+				 * may be needed if the glibc locale tables are updated. */
+				if ((__uwchar_t)(wc - 0x1c4) <= (0x1cc - 0x1c4)
+				 || wc == 0x1f1
+				) {
+					++wc;
+				}
+			}
+		}
+	} else {
+		/* TODO - Deal with other transliterations. */
+		__set_errno(EINVAL);
+	}
+
+	return wc;
+}
+
+#else  /* SMALL_UPLOW */
+
+wint_t TOWCTRANS(wint_t wc, wctrans_t desc)
+{
+	if (ENCODING == __ctype_encoding_7_bit) {
+		if ((__uwchar_t)wc > 0x7f
+		 || (unsigned)(desc - _CTYPE_tolower) > (_CTYPE_toupper - _CTYPE_tolower)
+		) {
+			/* We're in the C/POSIX locale, so ignore non-ASCII values
+			 * as well an any mappings other than toupper or tolower. */
+			return wc;
+		}
+	}
+
+	if (desc == _CTYPE_tolower) {
+		return TOWLOWER(wc, __UCLIBC_CURLOCALE);
+	}
+	if ((unsigned)(desc - _CTYPE_toupper) <= (_CTYPE_totitle - _CTYPE_toupper)) {
+		wc = TOWUPPER(wc, __UCLIBC_CURLOCALE);
+		if (desc == _CTYPE_totitle) {
+#ifdef __UCLIBC_MJN3_ONLY__
+# warning TODO: Verify totitle special cases!
+#endif
+			/* WARNING! These special cases work for glibc 2.2.4.  Changes
+			 * may be needed if the glibc locale tables are updated. */
+			if ((__uwchar_t)(wc - 0x1c4) <= (0x1cc - 0x1c4)
+			 || wc == 0x1f1
+			) {
+				++wc;
+			}
+		}
+	} else {
+		/* TODO - Deal with other transliterations. */
+		__set_errno(EINVAL);
+	}
+	return wc;
+}
+
+#endif /* SMALL_UPLOW */
+
+#endif /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */
+
+#ifdef L_towctrans_l
+libc_hidden_def(towctrans_l)
+#endif
+
+#endif /* __LOCALE_C_ONLY */
+
+#ifndef L_towctrans_l
+libc_hidden_def(towctrans)
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L_wctrans
+
+static const char transstring[] = __CTYPE_TRANSTRING;
+
+wctrans_t wctrans(const char *property)
+{
+	const unsigned char *p;
+	int i;
+
+	p = (const unsigned char *) transstring;
+	i = 1;
+	do {
+		if (!strcmp(property, (const char*) ++p)) {
+			return i;
+		}
+		++i;
+		p += p[-1];
+	} while (*p);
+
+	/* TODO - Add locale-specific translations. */
+	return 0;
+}
+libc_hidden_def(wctrans)
+
+#endif
+/**********************************************************************/
+#ifdef L_wctrans_l
+
+# ifdef __UCLIBC_MJN3_ONLY__
+#  warning REMINDER: Currently wctrans_l simply calls wctrans.
+# endif
+
+wctrans_t wctrans_l(const char *property, __locale_t locale)
+{
+	return wctrans(property);
+}
+
+#endif
+/**********************************************************************/
diff --git a/ap/build/uClibc/libc/misc/wctype/iswalnum.c b/ap/build/uClibc/libc/misc/wctype/iswalnum.c
new file mode 100644
index 0000000..a85a03d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswalnum.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswalnum
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswalnum_l.c b/ap/build/uClibc/libc/misc/wctype/iswalnum_l.c
new file mode 100644
index 0000000..6e3cd77
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswalnum_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswalnum_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswalpha.c b/ap/build/uClibc/libc/misc/wctype/iswalpha.c
new file mode 100644
index 0000000..6b829eb
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswalpha.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswalpha
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswalpha_l.c b/ap/build/uClibc/libc/misc/wctype/iswalpha_l.c
new file mode 100644
index 0000000..79b11cf
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswalpha_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswalpha_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswblank.c b/ap/build/uClibc/libc/misc/wctype/iswblank.c
new file mode 100644
index 0000000..67862d5
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswblank.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswblank
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswblank_l.c b/ap/build/uClibc/libc/misc/wctype/iswblank_l.c
new file mode 100644
index 0000000..4c5709c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswblank_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswblank_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswcntrl.c b/ap/build/uClibc/libc/misc/wctype/iswcntrl.c
new file mode 100644
index 0000000..50d72b4
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswcntrl.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswcntrl
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswcntrl_l.c b/ap/build/uClibc/libc/misc/wctype/iswcntrl_l.c
new file mode 100644
index 0000000..2fe64d7
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswcntrl_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswcntrl_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswctype.c b/ap/build/uClibc/libc/misc/wctype/iswctype.c
new file mode 100644
index 0000000..777d410
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswctype.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswctype
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswctype_l.c b/ap/build/uClibc/libc/misc/wctype/iswctype_l.c
new file mode 100644
index 0000000..71bce18
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswctype_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswctype_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswdigit.c b/ap/build/uClibc/libc/misc/wctype/iswdigit.c
new file mode 100644
index 0000000..b2aa5d0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswdigit.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswdigit
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswdigit_l.c b/ap/build/uClibc/libc/misc/wctype/iswdigit_l.c
new file mode 100644
index 0000000..4832c9c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswdigit_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswdigit_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswgraph.c b/ap/build/uClibc/libc/misc/wctype/iswgraph.c
new file mode 100644
index 0000000..8113054
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswgraph.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswgraph
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswgraph_l.c b/ap/build/uClibc/libc/misc/wctype/iswgraph_l.c
new file mode 100644
index 0000000..db68315
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswgraph_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswgraph_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswlower.c b/ap/build/uClibc/libc/misc/wctype/iswlower.c
new file mode 100644
index 0000000..016d8cc
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswlower.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswlower
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswlower_l.c b/ap/build/uClibc/libc/misc/wctype/iswlower_l.c
new file mode 100644
index 0000000..5b9f821
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswlower_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswlower_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswprint.c b/ap/build/uClibc/libc/misc/wctype/iswprint.c
new file mode 100644
index 0000000..8e47e88
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswprint.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswprint
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswprint_l.c b/ap/build/uClibc/libc/misc/wctype/iswprint_l.c
new file mode 100644
index 0000000..148414c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswprint_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswprint_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswpunct.c b/ap/build/uClibc/libc/misc/wctype/iswpunct.c
new file mode 100644
index 0000000..1175e1a
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswpunct.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswpunct
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswpunct_l.c b/ap/build/uClibc/libc/misc/wctype/iswpunct_l.c
new file mode 100644
index 0000000..a6d3616
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswpunct_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswpunct_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswspace.c b/ap/build/uClibc/libc/misc/wctype/iswspace.c
new file mode 100644
index 0000000..603f5cf
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswspace.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswspace
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswspace_l.c b/ap/build/uClibc/libc/misc/wctype/iswspace_l.c
new file mode 100644
index 0000000..e389f89
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswspace_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswspace_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswupper.c b/ap/build/uClibc/libc/misc/wctype/iswupper.c
new file mode 100644
index 0000000..4cfdebb
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswupper.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswupper
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswupper_l.c b/ap/build/uClibc/libc/misc/wctype/iswupper_l.c
new file mode 100644
index 0000000..359aef9
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswupper_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswupper_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswxdigit.c b/ap/build/uClibc/libc/misc/wctype/iswxdigit.c
new file mode 100644
index 0000000..568f253
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswxdigit.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswxdigit
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/iswxdigit_l.c b/ap/build/uClibc/libc/misc/wctype/iswxdigit_l.c
new file mode 100644
index 0000000..1d543ab
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/iswxdigit_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_iswxdigit_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/towctrans.c b/ap/build/uClibc/libc/misc/wctype/towctrans.c
new file mode 100644
index 0000000..9ad0468
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/towctrans.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_towctrans
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/towctrans_l.c b/ap/build/uClibc/libc/misc/wctype/towctrans_l.c
new file mode 100644
index 0000000..e179b50
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/towctrans_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_towctrans_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/towlower.c b/ap/build/uClibc/libc/misc/wctype/towlower.c
new file mode 100644
index 0000000..dffbff3
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/towlower.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_towlower
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/towlower_l.c b/ap/build/uClibc/libc/misc/wctype/towlower_l.c
new file mode 100644
index 0000000..f1aa7e6
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/towlower_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_towlower_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/towupper.c b/ap/build/uClibc/libc/misc/wctype/towupper.c
new file mode 100644
index 0000000..1dab8fe
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/towupper.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_towupper
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/towupper_l.c b/ap/build/uClibc/libc/misc/wctype/towupper_l.c
new file mode 100644
index 0000000..cf05d5c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/towupper_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_towupper_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/wctrans.c b/ap/build/uClibc/libc/misc/wctype/wctrans.c
new file mode 100644
index 0000000..f99d9cd
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/wctrans.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wctrans
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/wctrans_l.c b/ap/build/uClibc/libc/misc/wctype/wctrans_l.c
new file mode 100644
index 0000000..79854c2
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/wctrans_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wctrans_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/wctype.c b/ap/build/uClibc/libc/misc/wctype/wctype.c
new file mode 100644
index 0000000..0dc1e6d
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/wctype.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wctype
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wctype/wctype_l.c b/ap/build/uClibc/libc/misc/wctype/wctype_l.c
new file mode 100644
index 0000000..65f82e2
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wctype/wctype_l.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2002-2006 Manuel Novoa III <mjn3@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_wctype_l
+#define __UCLIBC_DO_XLOCALE
+#include "_wctype.c"
diff --git a/ap/build/uClibc/libc/misc/wordexp/Makefile b/ap/build/uClibc/libc/misc/wordexp/Makefile
new file mode 100644
index 0000000..4a8f4a0
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wordexp/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../
+top_builddir=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/libc/misc/wordexp/Makefile.in b/ap/build/uClibc/libc/misc/wordexp/Makefile.in
new file mode 100644
index 0000000..981db64
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wordexp/Makefile.in
@@ -0,0 +1,23 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/wordexp
+
+CSRC := wordexp.c
+
+MISC_WORDEXP_DIR := $(top_srcdir)libc/misc/wordexp
+MISC_WORDEXP_OUT := $(top_builddir)libc/misc/wordexp
+
+MISC_WORDEXP_SRC := $(patsubst %.c,$(MISC_WORDEXP_DIR)/%.c,$(CSRC))
+MISC_WORDEXP_OBJ := $(patsubst %.c,$(MISC_WORDEXP_OUT)/%.o,$(CSRC))
+
+libc-$(UCLIBC_HAS_WORDEXP) += $(MISC_WORDEXP_OBJ)
+
+objclean-y += CLEAN_libc/misc/wordexp
+
+CLEAN_libc/misc/wordexp:
+	$(do_rm) $(addprefix $(MISC_WORDEXP_OUT)/*., o os)
diff --git a/ap/build/uClibc/libc/misc/wordexp/wordexp.c b/ap/build/uClibc/libc/misc/wordexp/wordexp.c
new file mode 100644
index 0000000..700ea2c
--- /dev/null
+++ b/ap/build/uClibc/libc/misc/wordexp/wordexp.c
@@ -0,0 +1,2250 @@
+/* vi: set sw=4 ts=4: */
+/* POSIX.2 wordexp implementation.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <features.h>
+#include <bits/kernel-features.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include <assert.h>
+#include <fnmatch.h>
+#include <glob.h>
+#include <wordexp.h>
+
+#define __WORDEXP_FULL
+
+/*
+ * This is a recursive-descent-style word expansion routine.
+ */
+
+/* These variables are defined and initialized in the startup code.  */
+/*extern int __libc_argc;*/
+/*extern char **__libc_argv;*/
+
+/* FIXME!!!! */
+int attribute_hidden __libc_argc;
+char attribute_hidden **__libc_argv;
+
+/* Some forward declarations */
+static int parse_dollars(char **word, size_t * word_length,
+						 size_t * max_length, const char *words,
+						 size_t * offset, int flags, wordexp_t * pwordexp,
+						 const char *ifs, const char *ifs_white,
+						 int quoted);
+static int parse_backtick(char **word, size_t * word_length,
+						  size_t * max_length, const char *words,
+						  size_t * offset, int flags, wordexp_t * pwordexp,
+						  const char *ifs, const char *ifs_white);
+static int parse_dquote(char **word, size_t * word_length,
+						size_t * max_length, const char *words,
+						size_t * offset, int flags, wordexp_t * pwordexp,
+						const char *ifs, const char *ifs_white);
+
+
+
+/* The w_*() functions manipulate word lists. */
+#define W_CHUNK	(100)
+
+/* Result of w_newword will be ignored if it's the last word. */
+static __inline__ char *w_newword(size_t * actlen, size_t * maxlen)
+{
+	*actlen = *maxlen = 0;
+	return NULL;
+}
+
+/* Add a character to the buffer, allocating room for it if needed.  */
+static __inline__ char *w_addchar(char *buffer, size_t * actlen,
+							  size_t * maxlen, char ch)
+	 /* (lengths exclude trailing zero) */
+{
+
+	if (*actlen == *maxlen) {
+		char *old_buffer = buffer;
+		assert(buffer == NULL || *maxlen != 0);
+		*maxlen += W_CHUNK;
+		buffer = realloc(buffer, 1 + *maxlen);
+		if (buffer == NULL)
+			free(old_buffer);
+	}
+
+	if (buffer != NULL) {
+		buffer[*actlen] = ch;
+		buffer[++(*actlen)] = '\0';
+	}
+
+	return buffer;
+}
+#ifndef MAX
+#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
+#endif
+static char *w_addmem(char *buffer, size_t * actlen, size_t * maxlen,
+					  const char *str, size_t len)
+{
+	/* Add a string to the buffer, allocating room for it if needed.
+	 */
+	if (*actlen + len > *maxlen) {
+		char *old_buffer = buffer;
+		assert(buffer == NULL || *maxlen != 0);
+		*maxlen += MAX(2 * len, W_CHUNK);
+		buffer = realloc(old_buffer, 1 + *maxlen);
+		if (buffer == NULL)
+			free(old_buffer);
+	}
+
+	if (buffer != NULL) {
+		*((char *) mempcpy(&buffer[*actlen], str, len)) = '\0';
+		*actlen += len;
+	}
+	return buffer;
+}
+
+/* Add a string to the buffer, allocating room for it if needed.  */
+static char *w_addstr(char *buffer, size_t * actlen, size_t * maxlen,
+					  const char *str)
+	 /* (lengths exclude trailing zero) */
+{
+	size_t len;
+	assert(str != NULL);		/* w_addstr only called from this file */
+	len = strlen(str);
+
+	return w_addmem(buffer, actlen, maxlen, str, len);
+}
+
+/* Add a word to the wordlist */
+static int w_addword(wordexp_t * pwordexp, char *word)
+{
+	size_t num_p;
+	char **new_wordv;
+
+	/* Internally, NULL acts like "".  Convert NULLs to "" before
+	 * the caller sees them.
+	 */
+	if (word == NULL) {
+		word = strdup("");
+		if (word == NULL)
+			goto no_space;
+	}
+
+	num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs;
+	new_wordv = realloc(pwordexp->we_wordv, sizeof(char *) * num_p);
+	if (new_wordv != NULL) {
+		pwordexp->we_wordv = new_wordv;
+		pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc++] = word;
+		pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc] = NULL;
+		return 0;
+	}
+
+  no_space:
+	return WRDE_NOSPACE;
+}
+
+/* The parse_*() functions should leave *offset being the offset in 'words'
+ * to the last character processed.
+ */
+static int
+parse_backslash(char **word, size_t * word_length, size_t * max_length,
+				const char *words, size_t * offset)
+{
+	/* We are poised _at_ a backslash, not in quotes */
+
+	switch (words[1 + *offset]) {
+	case 0:
+		/* Backslash is last character of input words */
+		return WRDE_SYNTAX;
+
+	case '\n':
+		++(*offset);
+		break;
+
+	default:
+		*word = w_addchar(*word, word_length, max_length, words[1 + *offset]);
+		if (*word == NULL)
+			return WRDE_NOSPACE;
+
+		++(*offset);
+		break;
+	}
+
+	return 0;
+}
+
+static int
+parse_qtd_backslash(char **word, size_t * word_length, size_t * max_length,
+					const char *words, size_t * offset)
+{
+	/* We are poised _at_ a backslash, inside quotes */
+
+	switch (words[1 + *offset]) {
+	case 0:
+		/* Backslash is last character of input words */
+		return WRDE_SYNTAX;
+
+	case '\n':
+		++(*offset);
+		break;
+
+	case '$':
+	case '`':
+	case '"':
+	case '\\':
+		*word =
+			w_addchar(*word, word_length, max_length, words[1 + *offset]);
+		if (*word == NULL)
+			return WRDE_NOSPACE;
+
+		++(*offset);
+		break;
+
+	default:
+		*word = w_addchar(*word, word_length, max_length, words[*offset]);
+		if (*word != NULL)
+			*word =
+				w_addchar(*word, word_length, max_length,
+						  words[1 + *offset]);
+
+		if (*word == NULL)
+			return WRDE_NOSPACE;
+
+		++(*offset);
+		break;
+	}
+
+	return 0;
+}
+
+static int
+parse_tilde(char **word, size_t * word_length, size_t * max_length,
+			const char *words, size_t * offset, size_t wordc)
+{
+	/* We are poised _at_ a tilde */
+	size_t i;
+
+	if (*word_length != 0) {
+		if (!((*word)[*word_length - 1] == '=' && wordc == 0)) {
+			if (!((*word)[*word_length - 1] == ':'
+				  && strchr(*word, '=') && wordc == 0)) {
+				*word = w_addchar(*word, word_length, max_length, '~');
+				return *word ? 0 : WRDE_NOSPACE;
+			}
+		}
+	}
+
+	for (i = 1 + *offset; words[i]; i++) {
+		if (words[i] == ':' || words[i] == '/' || words[i] == ' ' ||
+			words[i] == '\t' || words[i] == 0)
+			break;
+
+		if (words[i] == '\\') {
+			*word = w_addchar(*word, word_length, max_length, '~');
+			return *word ? 0 : WRDE_NOSPACE;
+		}
+	}
+
+	if (i == 1 + *offset) {
+		/* Tilde appears on its own */
+		uid_t uid;
+		struct passwd pwd, *tpwd;
+		int buflen = 1000;
+		char *home;
+		char *buffer;
+		int result;
+
+		/* POSIX.2 says ~ expands to $HOME and if HOME is unset the
+		   results are unspecified.  We do a lookup on the uid if
+		   HOME is unset. */
+
+		home = getenv("HOME");
+		if (home != NULL) {
+			*word = w_addstr(*word, word_length, max_length, home);
+			if (*word == NULL)
+				return WRDE_NOSPACE;
+		} else {
+			uid = getuid();
+			buffer = alloca(buflen);
+
+			while ((result = getpwuid_r(uid, &pwd, buffer, buflen, &tpwd))
+					!= 0 && errno == ERANGE)
+			{
+				buflen += 1000;
+				buffer = alloca(buflen);
+			}
+
+			if (result == 0 && tpwd != NULL && pwd.pw_dir != NULL) {
+				*word = w_addstr(*word, word_length, max_length, pwd.pw_dir);
+				if (*word == NULL)
+					return WRDE_NOSPACE;
+			} else {
+				*word = w_addchar(*word, word_length, max_length, '~');
+				if (*word == NULL)
+					return WRDE_NOSPACE;
+			}
+		}
+	} else {
+		/* Look up user name in database to get home directory */
+		char *user = strndup(&words[1 + *offset], i - (1 + *offset));
+		struct passwd pwd, *tpwd;
+		int buflen = 1000;
+		char *buffer = alloca(buflen);
+		int result;
+
+		while ((result = getpwnam_r(user, &pwd, buffer, buflen, &tpwd)) != 0
+			   && errno == ERANGE) {
+			buflen += 1000;
+			buffer = alloca(buflen);
+		}
+
+		if (result == 0 && tpwd != NULL && pwd.pw_dir)
+			*word = w_addstr(*word, word_length, max_length, pwd.pw_dir);
+		else {
+			/* (invalid login name) */
+			*word = w_addchar(*word, word_length, max_length, '~');
+			if (*word != NULL)
+				*word = w_addstr(*word, word_length, max_length, user);
+		}
+
+		*offset = i - 1;
+	}
+	return *word ? 0 : WRDE_NOSPACE;
+}
+
+
+static int
+do_parse_glob(const char *glob_word, char **word, size_t * word_length,
+			  size_t * max_length, wordexp_t * pwordexp, const char *ifs
+			  /*, const char *ifs_white*/)
+{
+	int error;
+	int match;
+	glob_t globbuf;
+
+	error = glob(glob_word, GLOB_NOCHECK, NULL, &globbuf);
+
+	if (error != 0) {
+		/* We can only run into memory problems.  */
+		assert(error == GLOB_NOSPACE);
+		return WRDE_NOSPACE;
+	}
+
+	if (ifs && !*ifs) {
+		/* No field splitting allowed. */
+		assert(globbuf.gl_pathv[0] != NULL);
+		*word = w_addstr(*word, word_length, max_length, globbuf.gl_pathv[0]);
+		for (match = 1; match < globbuf.gl_pathc && *word != NULL; ++match) {
+			*word = w_addchar(*word, word_length, max_length, ' ');
+			if (*word != NULL)
+				*word = w_addstr(*word, word_length, max_length,
+								 globbuf.gl_pathv[match]);
+		}
+
+		globfree(&globbuf);
+		return *word ? 0 : WRDE_NOSPACE;
+	}
+
+	assert(ifs == NULL || *ifs != '\0');
+	if (*word != NULL) {
+		free(*word);
+		*word = w_newword(word_length, max_length);
+	}
+
+	for (match = 0; match < globbuf.gl_pathc; ++match) {
+		char *matching_word = strdup(globbuf.gl_pathv[match]);
+
+		if (matching_word == NULL || w_addword(pwordexp, matching_word)) {
+			globfree(&globbuf);
+			return WRDE_NOSPACE;
+		}
+	}
+
+	globfree(&globbuf);
+	return 0;
+}
+
+static int
+parse_glob(char **word, size_t * word_length, size_t * max_length,
+		   const char *words, size_t * offset, int flags,
+		   wordexp_t * pwordexp, const char *ifs, const char *ifs_white)
+{
+	/* We are poised just after a '*', a '[' or a '?'. */
+	int error = WRDE_NOSPACE;
+	int quoted = 0;				/* 1 if singly-quoted, 2 if doubly */
+	int i;
+	wordexp_t glob_list;		/* List of words to glob */
+
+	glob_list.we_wordc = 0;
+	glob_list.we_wordv = NULL;
+	glob_list.we_offs = 0;
+	for (; words[*offset] != '\0'; ++*offset) {
+		if ((ifs && strchr(ifs, words[*offset])) ||
+			(!ifs && strchr(" \t\n", words[*offset])))
+			/* Reached IFS */
+			break;
+
+		/* Sort out quoting */
+		if (words[*offset] == '\'') {
+			if (quoted == 0) {
+				quoted = 1;
+				continue;
+			} else if (quoted == 1) {
+				quoted = 0;
+				continue;
+			}
+		} else if (words[*offset] == '"') {
+			if (quoted == 0) {
+				quoted = 2;
+				continue;
+			} else if (quoted == 2) {
+				quoted = 0;
+				continue;
+			}
+		}
+
+		/* Sort out other special characters */
+		if (quoted != 1 && words[*offset] == '$') {
+			error = parse_dollars(word, word_length, max_length, words,
+								  offset, flags, &glob_list, ifs,
+								  ifs_white, quoted == 2);
+			if (error)
+				goto tidy_up;
+
+			continue;
+		} else if (words[*offset] == '\\') {
+			if (quoted)
+				error = parse_qtd_backslash(word, word_length, max_length,
+											words, offset);
+			else
+				error = parse_backslash(word, word_length, max_length,
+										words, offset);
+
+			if (error)
+				goto tidy_up;
+
+			continue;
+		}
+
+		*word = w_addchar(*word, word_length, max_length, words[*offset]);
+		if (*word == NULL)
+			goto tidy_up;
+	}
+
+	/* Don't forget to re-parse the character we stopped at. */
+	--*offset;
+
+	/* Glob the words */
+	error = w_addword(&glob_list, *word);
+	*word = w_newword(word_length, max_length);
+	for (i = 0; error == 0 && i < glob_list.we_wordc; i++)
+		error = do_parse_glob(glob_list.we_wordv[i], word, word_length,
+				max_length, pwordexp, ifs /*, ifs_white*/);
+
+	/* Now tidy up */
+  tidy_up:
+	wordfree(&glob_list);
+	return error;
+}
+
+static int
+parse_squote(char **word, size_t * word_length, size_t * max_length,
+			 const char *words, size_t * offset)
+{
+	/* We are poised just after a single quote */
+	for (; words[*offset]; ++(*offset)) {
+		if (words[*offset] != '\'') {
+			*word = w_addchar(*word, word_length, max_length, words[*offset]);
+			if (*word == NULL)
+				return WRDE_NOSPACE;
+		} else
+			return 0;
+	}
+
+	/* Unterminated string */
+	return WRDE_SYNTAX;
+}
+
+#ifdef __WORDEXP_FULL
+static int eval_expr(char *expr, long int *result);
+
+static char *_itoa(unsigned long long int value, char *buflim)
+{
+	sprintf(buflim, "%llu", value);
+	return buflim;
+}
+
+/* Functions to evaluate an arithmetic expression */
+static int eval_expr_val(char **expr, long int *result)
+{
+	int sgn = +1;
+	char *digit;
+
+	/* Skip white space */
+	for (digit = *expr; digit && *digit && isspace(*digit); ++digit);
+
+	switch (*digit) {
+	case '(':
+
+		/* Scan for closing paren */
+		for (++digit; **expr && **expr != ')'; ++(*expr));
+
+		/* Is there one? */
+		if (!**expr)
+			return WRDE_SYNTAX;
+
+		*(*expr)++ = 0;
+
+		if (eval_expr(digit, result))
+			return WRDE_SYNTAX;
+
+		return 0;
+
+	case '+':					/* Positive value */
+		++digit;
+		break;
+
+	case '-':					/* Negative value */
+		++digit;
+		sgn = -1;
+		break;
+
+	default:
+		if (!isdigit(*digit))
+			return WRDE_SYNTAX;
+	}
+
+	*result = 0;
+	for (; *digit && isdigit(*digit); ++digit)
+		*result = (*result * 10) + (*digit - '0');
+
+	*expr = digit;
+	*result *= sgn;
+	return 0;
+}
+
+static int eval_expr_multdiv(char **expr, long int *result)
+{
+	long int arg;
+
+	/* Read a Value */
+	if (eval_expr_val(expr, result) != 0)
+		return WRDE_SYNTAX;
+
+	while (**expr) {
+		/* Skip white space */
+		for (; *expr && **expr && isspace(**expr); ++(*expr));
+
+		if (**expr == '*') {
+			++(*expr);
+			if (eval_expr_val(expr, &arg) != 0)
+				return WRDE_SYNTAX;
+
+			*result *= arg;
+		} else if (**expr == '/') {
+			++(*expr);
+			if (eval_expr_val(expr, &arg) != 0)
+				return WRDE_SYNTAX;
+
+			*result /= arg;
+		} else
+			break;
+	}
+
+	return 0;
+}
+
+static int eval_expr(char *expr, long int *result)
+{
+	long int arg;
+
+	/* Read a Multdiv */
+	if (eval_expr_multdiv(&expr, result) != 0)
+		return WRDE_SYNTAX;
+
+	while (*expr) {
+		/* Skip white space */
+		for (; expr && *expr && isspace(*expr); ++expr);
+
+		if (*expr == '+') {
+			++expr;
+			if (eval_expr_multdiv(&expr, &arg) != 0)
+				return WRDE_SYNTAX;
+
+			*result += arg;
+		} else if (*expr == '-') {
+			++expr;
+			if (eval_expr_multdiv(&expr, &arg) != 0)
+				return WRDE_SYNTAX;
+
+			*result -= arg;
+		} else
+			break;
+	}
+
+	return 0;
+}
+
+static int
+parse_arith(char **word, size_t * word_length, size_t * max_length,
+			const char *words, size_t * offset, int flags, int bracket)
+{
+	/* We are poised just after "$((" or "$[" */
+	int error;
+	int paren_depth = 1;
+	size_t expr_length;
+	size_t expr_maxlen;
+	char *expr;
+
+	expr = w_newword(&expr_length, &expr_maxlen);
+	for (; words[*offset]; ++(*offset)) {
+		switch (words[*offset]) {
+		case '$':
+			error = parse_dollars(&expr, &expr_length, &expr_maxlen,
+								  words, offset, flags, NULL, NULL, NULL,
+								  1);
+			/* The ``1'' here is to tell parse_dollars not to
+			 * split the fields.
+			 */
+			if (error) {
+				free(expr);
+				return error;
+			}
+			break;
+
+		case '`':
+			(*offset)++;
+			error = parse_backtick(&expr, &expr_length, &expr_maxlen,
+								   words, offset, flags, NULL, NULL, NULL);
+			/* The first NULL here is to tell parse_backtick not to
+			 * split the fields.
+			 */
+			if (error) {
+				free(expr);
+				return error;
+			}
+			break;
+
+		case '\\':
+			error = parse_qtd_backslash(&expr, &expr_length, &expr_maxlen,
+										words, offset);
+			if (error) {
+				free(expr);
+				return error;
+			}
+			/* I think that a backslash within an
+			 * arithmetic expansion is bound to
+			 * cause an error sooner or later anyway though.
+			 */
+			break;
+
+		case ')':
+			if (--paren_depth == 0) {
+				char result[21];	/* 21 = ceil(log10(2^64)) + 1 */
+				long int numresult = 0;
+				long long int convertme;
+
+				if (bracket || words[1 + *offset] != ')') {
+					free(expr);
+					return WRDE_SYNTAX;
+				}
+
+				++(*offset);
+
+				/* Go - evaluate. */
+				if (*expr && eval_expr(expr, &numresult) != 0) {
+					free(expr);
+					return WRDE_SYNTAX;
+				}
+
+				if (numresult < 0) {
+					convertme = -numresult;
+					*word = w_addchar(*word, word_length, max_length, '-');
+					if (!*word) {
+						free(expr);
+						return WRDE_NOSPACE;
+					}
+				} else
+					convertme = numresult;
+
+				result[20] = '\0';
+				*word = w_addstr(*word, word_length, max_length,
+								 _itoa(convertme, &result[20]));
+				free(expr);
+				return *word ? 0 : WRDE_NOSPACE;
+			}
+			expr =
+				w_addchar(expr, &expr_length, &expr_maxlen,
+						  words[*offset]);
+			if (expr == NULL)
+				return WRDE_NOSPACE;
+
+			break;
+
+		case ']':
+			if (bracket && paren_depth == 1) {
+				char result[21];	/* 21 = ceil(log10(2^64)) + 1 */
+				long int numresult = 0;
+
+				/* Go - evaluate. */
+				if (*expr && eval_expr(expr, &numresult) != 0) {
+					free(expr);
+					return WRDE_SYNTAX;
+				}
+
+				result[20] = '\0';
+				*word = w_addstr(*word, word_length, max_length,
+								 _itoa(numresult, &result[20]));
+				free(expr);
+				return *word ? 0 : WRDE_NOSPACE;
+			}
+
+			free(expr);
+			return WRDE_SYNTAX;
+
+		case '\n':
+		case ';':
+		case '{':
+		case '}':
+			free(expr);
+			return WRDE_BADCHAR;
+
+		case '(':
+			++paren_depth;
+		default:
+			expr =
+				w_addchar(expr, &expr_length, &expr_maxlen,
+						  words[*offset]);
+			if (expr == NULL)
+				return WRDE_NOSPACE;
+		}
+	}
+
+	/* Premature end */
+	free(expr);
+	return WRDE_SYNTAX;
+}
+
+/* Function called by child process in exec_comm() */
+static void attribute_noreturn
+exec_comm_child(char *comm, int *fildes, int showerr, int noexec)
+{
+	int fd;
+	const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL };
+
+	/* Execute the command, or just check syntax? */
+	if (noexec)
+		args[1] = "-nc";
+
+	/* Redirect output.  */
+	fd = fildes[1];
+	if (likely(fd != STDOUT_FILENO)) {
+		dup2(fd, STDOUT_FILENO);
+		close(fd);
+	}
+#if defined O_CLOEXEC && defined __UCLIBC_LINUX_SPECIFIC__ && defined __ASSUME_PIPE2
+	else {
+		/* Reset the close-on-exec flag (if necessary).  */
+		fcntl (fd, F_SETFD, 0);
+	}
+#endif
+	/* Redirect stderr to /dev/null if we have to.  */
+	if (showerr == 0) {
+		close(STDERR_FILENO);
+		fd = open(_PATH_DEVNULL, O_WRONLY);
+		if (fd >= 0 && fd != STDERR_FILENO) {
+			dup2(fd, 2);
+			close(fd);
+		}
+	}
+
+	/* Make sure the subshell doesn't field-split on our behalf. */
+	unsetenv("IFS");
+
+	if (fildes[0] != 1)
+		close(fildes[0]);
+	execve(_PATH_BSHELL, (char *const *) args, __environ);
+
+	/* Bad.  What now?  */
+	abort();
+}
+
+/* Function to execute a command and retrieve the results */
+/* pwordexp contains NULL if field-splitting is forbidden */
+static int
+exec_comm(char *comm, char **word, size_t * word_length,
+		  size_t * max_length, int flags, wordexp_t * pwordexp,
+		  const char *ifs, const char *ifs_white)
+{
+	int fildes[2];
+	int bufsize = 128;
+	int buflen;
+	int i;
+	int status = 0;
+	size_t maxnewlines = 0;
+	char *buffer;
+	pid_t pid;
+
+	/* Don't fork() unless necessary */
+	if (!comm || !*comm)
+		return 0;
+#if defined O_CLOEXEC && defined __UCLIBC_LINUX_SPECIFIC__ && defined __ASSUME_PIPE2
+	if (pipe2(fildes, O_CLOEXEC) < 0)
+		/* Bad */
+		return WRDE_NOSPACE;
+#else
+	if (pipe(fildes) < 0)
+		/* Bad */
+		return WRDE_NOSPACE;
+#endif
+
+	if ((pid = fork()) < 0) {
+		/* Bad */
+		close(fildes[0]);
+		close(fildes[1]);
+		return WRDE_NOSPACE;
+	}
+
+	if (pid == 0)
+		exec_comm_child(comm, fildes, (flags & WRDE_SHOWERR), 0);
+
+	/* Parent */
+
+	close(fildes[1]);
+	buffer = alloca(bufsize);
+
+	if (!pwordexp)
+		/* Quoted - no field splitting */
+	{
+		while (1) {
+			if ((buflen = read(fildes[0], buffer, bufsize)) < 1) {
+				if (waitpid(pid, &status, WNOHANG) == 0)
+					continue;
+				if ((buflen = read(fildes[0], buffer, bufsize)) < 1)
+					break;
+			}
+
+			maxnewlines += buflen;
+
+			*word = w_addmem(*word, word_length, max_length, buffer, buflen);
+			if (*word == NULL)
+				goto no_space;
+		}
+	} else
+		/* Not quoted - split fields */
+	{
+		int copying = 0;
+
+		/* 'copying' is:
+		 *  0 when searching for first character in a field not IFS white space
+		 *  1 when copying the text of a field
+		 *  2 when searching for possible non-whitespace IFS
+		 *  3 when searching for non-newline after copying field
+		 */
+
+		while (1) {
+			if ((buflen = read(fildes[0], buffer, bufsize)) < 1) {
+				if (waitpid(pid, &status, WNOHANG) == 0)
+					continue;
+				if ((buflen = read(fildes[0], buffer, bufsize)) < 1)
+					break;
+			}
+
+			for (i = 0; i < buflen; ++i) {
+				if (strchr(ifs, buffer[i]) != NULL) {
+					/* Current character is IFS */
+					if (strchr(ifs_white, buffer[i]) == NULL) {
+						/* Current character is IFS but not whitespace */
+						if (copying == 2) {
+							/*            current character
+							 *                   |
+							 *                   V
+							 * eg: text<space><comma><space>moretext
+							 *
+							 * So, strip whitespace IFS (like at the start)
+							 */
+							copying = 0;
+							continue;
+						}
+
+						copying = 0;
+						/* fall through and delimit field.. */
+					} else {
+						if (buffer[i] == '\n') {
+							/* Current character is (IFS) newline */
+
+							/* If copying a field, this is the end of it,
+							   but maybe all that's left is trailing newlines.
+							   So start searching for a non-newline. */
+							if (copying == 1)
+								copying = 3;
+
+							continue;
+						} else {
+							/* Current character is IFS white space, but
+							   not a newline */
+
+							/* If not either copying a field or searching
+							   for non-newline after a field, ignore it */
+							if (copying != 1 && copying != 3)
+								continue;
+
+							/* End of field (search for non-ws IFS afterwards) */
+							copying = 2;
+						}
+					}
+
+					/* First IFS white space (non-newline), or IFS non-whitespace.
+					 * Delimit the field.  Nulls are converted by w_addword. */
+					if (w_addword(pwordexp, *word) == WRDE_NOSPACE)
+						goto no_space;
+
+					*word = w_newword(word_length, max_length);
+
+					maxnewlines = 0;
+					/* fall back round the loop.. */
+				} else {
+					/* Not IFS character */
+
+					if (copying == 3) {
+						/* Nothing but (IFS) newlines since the last field,
+						   so delimit it here before starting new word */
+						if (w_addword(pwordexp, *word) == WRDE_NOSPACE)
+							goto no_space;
+
+						*word = w_newword(word_length, max_length);
+					}
+
+					copying = 1;
+
+					if (buffer[i] == '\n')	/* happens if newline not in IFS */
+						maxnewlines++;
+					else
+						maxnewlines = 0;
+
+					*word = w_addchar(*word, word_length, max_length,
+									  buffer[i]);
+					if (*word == NULL)
+						goto no_space;
+				}
+			}
+		}
+	}
+
+	/* Chop off trailing newlines (required by POSIX.2)  */
+	/* Ensure we don't go back further than the beginning of the
+	   substitution (i.e. remove maxnewlines bytes at most) */
+	while (maxnewlines-- != 0 &&
+		   *word_length > 0 && (*word)[*word_length - 1] == '\n') {
+		(*word)[--*word_length] = '\0';
+
+		/* If the last word was entirely newlines, turn it into a new word
+		 * which can be ignored if there's nothing following it. */
+		if (*word_length == 0) {
+			free(*word);
+			*word = w_newword(word_length, max_length);
+			break;
+		}
+	}
+
+	close(fildes[0]);
+
+	/* Check for syntax error (re-execute but with "-n" flag) */
+	if (buflen < 1 && status != 0) {
+		if ((pid = fork()) < 0) {
+			/* Bad */
+			return WRDE_NOSPACE;
+		}
+
+		if (pid == 0) {
+			fildes[0] = fildes[1] = -1;
+			exec_comm_child(comm, fildes, 0, 1);
+		}
+
+		if (waitpid(pid, &status, 0) == pid && status != 0)
+			return WRDE_SYNTAX;
+	}
+
+	return 0;
+
+  no_space:
+	kill(pid, SIGKILL);
+	waitpid(pid, NULL, 0);
+	close(fildes[0]);
+	return WRDE_NOSPACE;
+}
+
+static int
+parse_comm(char **word, size_t * word_length, size_t * max_length,
+		   const char *words, size_t * offset, int flags,
+		   wordexp_t * pwordexp, const char *ifs, const char *ifs_white)
+{
+	/* We are poised just after "$(" */
+	int paren_depth = 1;
+	int error = 0;
+	int quoted = 0;				/* 1 for singly-quoted, 2 for doubly-quoted */
+	size_t comm_length;
+	size_t comm_maxlen;
+	char *comm = w_newword(&comm_length, &comm_maxlen);
+
+	for (; words[*offset]; ++(*offset)) {
+		switch (words[*offset]) {
+		case '\'':
+			if (quoted == 0)
+				quoted = 1;
+			else if (quoted == 1)
+				quoted = 0;
+
+			break;
+
+		case '"':
+			if (quoted == 0)
+				quoted = 2;
+			else if (quoted == 2)
+				quoted = 0;
+
+			break;
+
+		case ')':
+			if (!quoted && --paren_depth == 0) {
+				/* Go -- give script to the shell */
+				if (comm) {
+					error = exec_comm(comm, word, word_length, max_length,
+									  flags, pwordexp, ifs, ifs_white);
+					free(comm);
+				}
+
+				return error;
+			}
+
+			/* This is just part of the script */
+			break;
+
+		case '(':
+			if (!quoted)
+				++paren_depth;
+		}
+
+		comm = w_addchar(comm, &comm_length, &comm_maxlen, words[*offset]);
+		if (comm == NULL)
+			return WRDE_NOSPACE;
+	}
+
+	/* Premature end */
+	free(comm);
+
+	return WRDE_SYNTAX;
+}
+
+static int
+parse_backtick(char **word, size_t * word_length, size_t * max_length,
+			   const char *words, size_t * offset, int flags,
+			   wordexp_t * pwordexp, const char *ifs,
+			   const char *ifs_white)
+{
+	/* We are poised just after "`" */
+	int error;
+	int squoting = 0;
+	size_t comm_length;
+	size_t comm_maxlen;
+	char *comm = w_newword(&comm_length, &comm_maxlen);
+
+	for (; words[*offset]; ++(*offset)) {
+		switch (words[*offset]) {
+		case '`':
+			/* Go -- give the script to the shell */
+			error = exec_comm(comm, word, word_length, max_length, flags,
+							  pwordexp, ifs, ifs_white);
+			free(comm);
+			return error;
+
+		case '\\':
+			if (squoting) {
+				error = parse_qtd_backslash(&comm, &comm_length, &comm_maxlen,
+										words, offset);
+
+				if (error) {
+					free(comm);
+					return error;
+				}
+
+				break;
+			}
+
+			++(*offset);
+			error = parse_backslash(&comm, &comm_length, &comm_maxlen, words,
+								offset);
+
+			if (error) {
+				free(comm);
+				return error;
+			}
+
+			break;
+
+		case '\'':
+			squoting = 1 - squoting;
+		default:
+			comm = w_addchar(comm, &comm_length, &comm_maxlen,
+						  words[*offset]);
+			if (comm == NULL)
+				return WRDE_NOSPACE;
+		}
+	}
+
+	/* Premature end */
+	free(comm);
+	return WRDE_SYNTAX;
+}
+
+static int
+parse_param(char **word, size_t * word_length, size_t * max_length,
+			const char *words, size_t * offset, int flags,
+			wordexp_t * pwordexp, const char *ifs, const char *ifs_white,
+			int quoted)
+{
+	/* We are poised just after "$" */
+	enum action {
+		ACT_NONE,
+		ACT_RP_SHORT_LEFT = '#',
+		ACT_RP_LONG_LEFT = 'L',
+		ACT_RP_SHORT_RIGHT = '%',
+		ACT_RP_LONG_RIGHT = 'R',
+		ACT_NULL_ERROR = '?',
+		ACT_NULL_SUBST = '-',
+		ACT_NONNULL_SUBST = '+',
+		ACT_NULL_ASSIGN = '='
+	};
+	size_t env_length;
+	size_t env_maxlen;
+	size_t pat_length;
+	size_t pat_maxlen;
+	size_t start = *offset;
+	char *env;
+	char *pattern;
+	char *value = NULL;
+	enum action action = ACT_NONE;
+	int depth = 0;
+	int colon_seen = 0;
+	int seen_hash = 0;
+	int free_value = 0;
+	int pattern_is_quoted = 0;	/* 1 for singly-quoted, 2 for doubly-quoted */
+	int error;
+	int special = 0;
+	char buffer[21];
+	int brace = words[*offset] == '{';
+
+	env = w_newword(&env_length, &env_maxlen);
+	pattern = w_newword(&pat_length, &pat_maxlen);
+
+	if (brace)
+		++ * offset;
+
+	/* First collect the parameter name. */
+
+	if (words[*offset] == '#') {
+		seen_hash = 1;
+		if (!brace)
+			goto envsubst;
+		++*offset;
+	}
+
+	if (isalpha(words[*offset]) || words[*offset] == '_') {
+		/* Normal parameter name. */
+		do {
+			env = w_addchar(env, &env_length, &env_maxlen, words[*offset]);
+			if (env == NULL)
+				goto no_space;
+		}
+		while (isalnum(words[++*offset]) || words[*offset] == '_');
+	} else if (isdigit(words[*offset])) {
+		/* Numeric parameter name. */
+		special = 1;
+		do {
+			env = w_addchar(env, &env_length, &env_maxlen, words[*offset]);
+			if (env == NULL)
+				goto no_space;
+			if (!brace)
+				goto envsubst;
+		}
+		while (isdigit(words[++*offset]));
+	} else if (strchr("*@$", words[*offset]) != NULL) {
+		/* Special parameter. */
+		special = 1;
+		env = w_addchar(env, &env_length, &env_maxlen, words[*offset]);
+		if (env == NULL)
+			goto no_space;
+		++*offset;
+	} else {
+		if (brace)
+			goto syntax;
+	}
+
+	if (brace) {
+		/* Check for special action to be applied to the value. */
+		switch (words[*offset]) {
+		case '}':
+			/* Evaluate. */
+			goto envsubst;
+
+		case '#':
+			action = ACT_RP_SHORT_LEFT;
+			if (words[1 + *offset] == '#') {
+				++*offset;
+				action = ACT_RP_LONG_LEFT;
+			}
+			break;
+
+		case '%':
+			action = ACT_RP_SHORT_RIGHT;
+			if (words[1 + *offset] == '%') {
+				++*offset;
+				action = ACT_RP_LONG_RIGHT;
+			}
+			break;
+
+		case ':':
+			if (strchr("-=?+", words[1 + *offset]) == NULL)
+				goto syntax;
+
+			colon_seen = 1;
+			action = words[++*offset];
+			break;
+
+		case '-':
+		case '=':
+		case '?':
+		case '+':
+			action = words[*offset];
+			break;
+
+		default:
+			goto syntax;
+		}
+
+		/* Now collect the pattern, but don't expand it yet. */
+		++*offset;
+		for (; words[*offset]; ++(*offset)) {
+			switch (words[*offset]) {
+			case '{':
+				if (!pattern_is_quoted)
+					++depth;
+				break;
+
+			case '}':
+				if (!pattern_is_quoted) {
+					if (depth == 0)
+						goto envsubst;
+					--depth;
+				}
+				break;
+
+			case '\\':
+				if (pattern_is_quoted)
+					/* Quoted; treat as normal character. */
+					break;
+
+				/* Otherwise, it's an escape: next character is literal. */
+				if (words[++*offset] == '\0')
+					goto syntax;
+
+				pattern = w_addchar(pattern, &pat_length, &pat_maxlen, '\\');
+				if (pattern == NULL)
+					goto no_space;
+
+				break;
+
+			case '\'':
+				if (pattern_is_quoted == 0)
+					pattern_is_quoted = 1;
+				else if (pattern_is_quoted == 1)
+					pattern_is_quoted = 0;
+
+				break;
+
+			case '"':
+				if (pattern_is_quoted == 0)
+					pattern_is_quoted = 2;
+				else if (pattern_is_quoted == 2)
+					pattern_is_quoted = 0;
+
+				break;
+			}
+
+			pattern = w_addchar(pattern, &pat_length, &pat_maxlen,
+								words[*offset]);
+			if (pattern == NULL)
+				goto no_space;
+		}
+	}
+
+	/* End of input string -- remember to reparse the character that we
+	 * stopped at.  */
+	--(*offset);
+
+  envsubst:
+	if (words[start] == '{' && words[*offset] != '}')
+		goto syntax;
+
+	if (env == NULL) {
+		if (seen_hash) {
+			/* $# expands to the number of positional parameters */
+			buffer[20] = '\0';
+			value = _itoa(__libc_argc - 1, &buffer[20]);
+			seen_hash = 0;
+		} else {
+			/* Just $ on its own */
+			*offset = start - 1;
+			*word = w_addchar(*word, word_length, max_length, '$');
+			return *word ? 0 : WRDE_NOSPACE;
+		}
+	}
+	/* Is it a numeric parameter? */
+	else if (isdigit(env[0])) {
+		int n = atoi(env);
+
+		if (n >= __libc_argc)
+			/* Substitute NULL. */
+			value = NULL;
+		else
+			/* Replace with appropriate positional parameter. */
+			value = __libc_argv[n];
+	}
+	/* Is it a special parameter? */
+	else if (special) {
+		/* Is it `$$'? */
+		if (*env == '$') {
+			buffer[20] = '\0';
+			value = _itoa(getpid(), &buffer[20]);
+		}
+		/* Is it `${#*}' or `${#@}'? */
+		else if ((*env == '*' || *env == '@') && seen_hash) {
+			buffer[20] = '\0';
+			value = _itoa(__libc_argc > 0 ? __libc_argc - 1 : 0,
+							   &buffer[20]);
+			*word = w_addstr(*word, word_length, max_length, value);
+			free(env);
+			free(pattern);
+			return *word ? 0 : WRDE_NOSPACE;
+		}
+		/* Is it `$*' or `$@' (unquoted) ? */
+		else if (*env == '*' || (*env == '@' && !quoted)) {
+			size_t plist_len = 0;
+			int p;
+			char *end;
+
+			/* Build up value parameter by parameter (copy them) */
+			for (p = 1; __libc_argv[p]; ++p)
+				plist_len += strlen(__libc_argv[p]) + 1;	/* for space */
+			value = malloc(plist_len);
+			if (value == NULL)
+				goto no_space;
+			end = value;
+			*end = 0;
+			for (p = 1; __libc_argv[p]; ++p) {
+				if (p > 1)
+					*end++ = ' ';
+				end = stpcpy(end, __libc_argv[p]);
+			}
+
+			free_value = 1;
+		} else {
+			/* Must be a quoted `$@' */
+			assert(*env == '@' && quoted);
+
+			/* Each parameter is a separate word ("$@") */
+			if (__libc_argc == 2)
+				value = __libc_argv[1];
+			else if (__libc_argc > 2) {
+				int p;
+
+				/* Append first parameter to current word. */
+				value = w_addstr(*word, word_length, max_length,
+								 __libc_argv[1]);
+				if (value == NULL || w_addword(pwordexp, value))
+					goto no_space;
+
+				for (p = 2; __libc_argv[p + 1]; p++) {
+					char *newword = strdup(__libc_argv[p]);
+
+					if (newword == NULL || w_addword(pwordexp, newword))
+						goto no_space;
+				}
+
+				/* Start a new word with the last parameter. */
+				*word = w_newword(word_length, max_length);
+				value = __libc_argv[p];
+			} else {
+				free(env);
+				free(pattern);
+				return 0;
+			}
+		}
+	} else
+		value = getenv(env);
+
+	if (value == NULL && (flags & WRDE_UNDEF)) {
+		/* Variable not defined. */
+		error = WRDE_BADVAL;
+		goto do_error;
+	}
+
+	if (action != ACT_NONE) {
+		int expand_pattern = 0;
+
+		/* First, find out if we need to expand pattern (i.e. if we will
+		 * use it). */
+		switch (action) {
+		case ACT_RP_SHORT_LEFT:
+		case ACT_RP_LONG_LEFT:
+		case ACT_RP_SHORT_RIGHT:
+		case ACT_RP_LONG_RIGHT:
+			/* Always expand for these. */
+			expand_pattern = 1;
+			break;
+
+		case ACT_NULL_ERROR:
+		case ACT_NULL_SUBST:
+		case ACT_NULL_ASSIGN:
+			if (!value || (!*value && colon_seen))
+				/* If param is unset, or set but null and a colon has been seen,
+				   the expansion of the pattern will be needed. */
+				expand_pattern = 1;
+
+			break;
+
+		case ACT_NONNULL_SUBST:
+			/* Expansion of word will be needed if parameter is set and not null,
+			   or set null but no colon has been seen. */
+			if (value && (*value || !colon_seen))
+				expand_pattern = 1;
+
+			break;
+
+		default:
+			assert(!"Unrecognised action!");
+		}
+
+		if (expand_pattern) {
+			/* We need to perform tilde expansion, parameter expansion,
+			   command substitution, and arithmetic expansion.  We also
+			   have to be a bit careful with wildcard characters, as
+			   pattern might be given to fnmatch soon.  To do this, we
+			   convert quotes to escapes. */
+
+			char *expanded;
+			size_t exp_len;
+			size_t exp_maxl;
+			char *p;
+			int quotes = 0;		/* 1: single quotes; 2: double */
+
+			expanded = w_newword(&exp_len, &exp_maxl);
+			for (p = pattern; p && *p; p++) {
+				size_t _offset;
+
+				switch (*p) {
+				case '"':
+					if (quotes == 2)
+						quotes = 0;
+					else if (quotes == 0)
+						quotes = 2;
+					else
+						break;
+
+					continue;
+
+				case '\'':
+					if (quotes == 1)
+						quotes = 0;
+					else if (quotes == 0)
+						quotes = 1;
+					else
+						break;
+
+					continue;
+
+				case '*':
+				case '?':
+					if (quotes) {
+						/* Convert quoted wildchar to escaped wildchar. */
+						expanded = w_addchar(expanded, &exp_len,
+											 &exp_maxl, '\\');
+
+						if (expanded == NULL)
+							goto no_space;
+					}
+					break;
+
+				case '$':
+					_offset = 0;
+					error = parse_dollars(&expanded, &exp_len, &exp_maxl, p,
+									  &_offset, flags, NULL, NULL, NULL, 1);
+					if (error) {
+						if (free_value)
+							free(value);
+
+						free(expanded);
+
+						goto do_error;
+					}
+
+					p += _offset;
+					continue;
+
+				case '~':
+					if (quotes || exp_len)
+						break;
+
+					_offset = 0;
+					error = parse_tilde(&expanded, &exp_len, &exp_maxl, p,
+										&_offset, 0);
+					if (error) {
+						if (free_value)
+							free(value);
+
+						free(expanded);
+
+						goto do_error;
+					}
+
+					p += _offset;
+					continue;
+
+				case '\\':
+					expanded = w_addchar(expanded, &exp_len, &exp_maxl, '\\');
+					++p;
+					assert(*p);	/* checked when extracted initially */
+					if (expanded == NULL)
+						goto no_space;
+				}
+
+				expanded = w_addchar(expanded, &exp_len, &exp_maxl, *p);
+
+				if (expanded == NULL)
+					goto no_space;
+			}
+
+			free(pattern);
+
+			pattern = expanded;
+		}
+
+		switch (action) {
+		case ACT_RP_SHORT_LEFT:
+		case ACT_RP_LONG_LEFT:
+		case ACT_RP_SHORT_RIGHT:
+		case ACT_RP_LONG_RIGHT:
+		{
+			char *p;
+			char c;
+			char *end;
+
+			if (value == NULL || pattern == NULL || *pattern == '\0')
+				break;
+
+			end = value + strlen(value);
+
+			switch (action) {
+			case ACT_RP_SHORT_LEFT:
+				for (p = value; p <= end; ++p) {
+					c = *p;
+					*p = '\0';
+					if (fnmatch(pattern, value, 0) != FNM_NOMATCH) {
+						*p = c;
+						if (free_value) {
+							char *newval = strdup(p);
+
+							if (newval == NULL) {
+								free(value);
+								goto no_space;
+							}
+							free(value);
+							value = newval;
+						} else
+							value = p;
+						break;
+					}
+					*p = c;
+				}
+
+				break;
+
+			case ACT_RP_LONG_LEFT:
+				for (p = end; p >= value; --p) {
+					c = *p;
+					*p = '\0';
+					if (fnmatch(pattern, value, 0) != FNM_NOMATCH) {
+						*p = c;
+						if (free_value) {
+							char *newval = strdup(p);
+
+							if (newval == NULL) {
+								free(value);
+								goto no_space;
+							}
+							free(value);
+							value = newval;
+						} else
+							value = p;
+						break;
+					}
+					*p = c;
+				}
+
+				break;
+
+			case ACT_RP_SHORT_RIGHT:
+				for (p = end; p >= value; --p) {
+					if (fnmatch(pattern, p, 0) != FNM_NOMATCH) {
+						char *newval;
+
+						newval = malloc(p - value + 1);
+
+						if (newval == NULL) {
+							if (free_value)
+								free(value);
+							goto no_space;
+						}
+
+						*(char *) mempcpy(newval, value, p - value) = '\0';
+						if (free_value)
+							free(value);
+						value = newval;
+						free_value = 1;
+						break;
+					}
+				}
+
+				break;
+
+			case ACT_RP_LONG_RIGHT:
+				for (p = value; p <= end; ++p) {
+					if (fnmatch(pattern, p, 0) != FNM_NOMATCH) {
+						char *newval;
+
+						newval = malloc(p - value + 1);
+
+						if (newval == NULL) {
+							if (free_value)
+								free(value);
+							goto no_space;
+						}
+
+						*(char *) mempcpy(newval, value, p - value) = '\0';
+						if (free_value)
+							free(value);
+						value = newval;
+						free_value = 1;
+						break;
+					}
+				}
+
+				break;
+
+			default:
+				break;
+			}
+
+			break;
+		}
+
+		case ACT_NULL_ERROR:
+			if (value && *value)
+				/* Substitute parameter */
+				break;
+
+			error = 0;
+			if (!colon_seen && value)
+				/* Substitute NULL */
+				;
+			else if (*pattern)
+				fprintf(stderr, "%s: %s\n", env, pattern);
+			else {
+				fprintf(stderr, "%s: parameter null or not set\n", env);
+				error = WRDE_BADVAL;
+			}
+
+			if (free_value)
+				free(value);
+			goto do_error;
+
+		case ACT_NULL_SUBST:
+			if (value && *value)
+				/* Substitute parameter */
+				break;
+
+			if (free_value)
+				free(value);
+
+			if (!colon_seen && value)
+				/* Substitute NULL */
+				goto success;
+
+			value = pattern ? strdup(pattern) : pattern;
+			free_value = 1;
+
+			if (pattern && !value)
+				goto no_space;
+
+			break;
+
+		case ACT_NONNULL_SUBST:
+			if (value && (*value || !colon_seen)) {
+				if (free_value)
+					free(value);
+
+				value = pattern ? strdup(pattern) : pattern;
+				free_value = 1;
+
+				if (pattern && !value)
+					goto no_space;
+
+				break;
+			}
+
+			/* Substitute NULL */
+			if (free_value)
+				free(value);
+			goto success;
+
+		case ACT_NULL_ASSIGN:
+			if (value && *value)
+				/* Substitute parameter */
+				break;
+
+			if (!colon_seen && value) {
+				/* Substitute NULL */
+				if (free_value)
+					free(value);
+				goto success;
+			}
+
+			if (free_value)
+				free(value);
+
+			value = pattern ? strdup(pattern) : pattern;
+			free_value = 1;
+
+			if (pattern && !value)
+				goto no_space;
+
+			setenv(env, value, 1);
+			break;
+
+		default:
+			assert(!"Unrecognised action!");
+		}
+	}
+
+	free(env);
+	env = NULL;
+	free(pattern);
+	pattern = NULL;
+
+	if (seen_hash) {
+		char param_length[21];
+
+		param_length[20] = '\0';
+		*word = w_addstr(*word, word_length, max_length,
+						 _itoa(value ? strlen(value) : 0,
+									&param_length[20]));
+		if (free_value) {
+			assert(value != NULL);
+			free(value);
+		}
+
+		return *word ? 0 : WRDE_NOSPACE;
+	}
+
+	if (value == NULL)
+		return 0;
+
+	if (quoted || !pwordexp) {
+		/* Quoted - no field split */
+		*word = w_addstr(*word, word_length, max_length, value);
+		if (free_value)
+			free(value);
+
+		return *word ? 0 : WRDE_NOSPACE;
+	} else {
+		/* Need to field-split */
+		char *value_copy = strdup(value);	/* Don't modify value */
+		char *field_begin = value_copy;
+		int seen_nonws_ifs = 0;
+
+		if (free_value)
+			free(value);
+
+		if (value_copy == NULL)
+			goto no_space;
+
+		do {
+			char *field_end = field_begin;
+			char *next_field;
+
+			/* If this isn't the first field, start a new word */
+			if (field_begin != value_copy) {
+				if (w_addword(pwordexp, *word) == WRDE_NOSPACE) {
+					free(value_copy);
+					goto no_space;
+				}
+
+				*word = w_newword(word_length, max_length);
+			}
+
+			/* Skip IFS whitespace before the field */
+			field_begin += strspn(field_begin, ifs_white);
+
+			if (!seen_nonws_ifs && *field_begin == 0)
+				/* Nothing but whitespace */
+				break;
+
+			/* Search for the end of the field */
+			field_end = field_begin + strcspn(field_begin, ifs);
+
+			/* Set up pointer to the character after end of field and
+			   skip whitespace IFS after it. */
+			next_field = field_end + strspn(field_end, ifs_white);
+
+			/* Skip at most one non-whitespace IFS character after the field */
+			seen_nonws_ifs = 0;
+			if (*next_field && strchr(ifs, *next_field)) {
+				seen_nonws_ifs = 1;
+				next_field++;
+			}
+
+			/* Null-terminate it */
+			*field_end = 0;
+
+			/* Tag a copy onto the current word */
+			*word = w_addstr(*word, word_length, max_length, field_begin);
+
+			if (*word == NULL && *field_begin != '\0') {
+				free(value_copy);
+				goto no_space;
+			}
+
+			field_begin = next_field;
+		}
+		while (seen_nonws_ifs || *field_begin);
+
+		free(value_copy);
+	}
+
+	return 0;
+
+  success:
+	error = 0;
+	goto do_error;
+
+  no_space:
+	error = WRDE_NOSPACE;
+	goto do_error;
+
+  syntax:
+	error = WRDE_SYNTAX;
+
+  do_error:
+	free(env);
+
+	free(pattern);
+
+	return error;
+}
+#else
+static __inline__ int
+parse_backtick(char **word, size_t * word_length, size_t * max_length,
+			   const char *words, size_t * offset, int flags,
+			   wordexp_t * pwordexp, const char *ifs,
+			   const char *ifs_white)
+{
+	return 0;
+}
+#endif
+
+static int
+parse_dollars(char **word, size_t * word_length, size_t * max_length,
+			  const char *words, size_t * offset, int flags,
+			  wordexp_t * pwordexp, const char *ifs, const char *ifs_white,
+			  int quoted)
+{
+	/* We are poised _at_ "$" */
+	switch (words[1 + *offset]) {
+	case '"':
+	case '\'':
+	case 0:
+		*word = w_addchar(*word, word_length, max_length, '$');
+		return *word ? 0 : WRDE_NOSPACE;
+
+#ifdef __WORDEXP_FULL
+	case '(':
+		if (words[2 + *offset] == '(') {
+			/* Differentiate between $((1+3)) and $((echo);(ls)) */
+			int i = 3 + *offset;
+			int depth = 0;
+
+			while (words[i] && !(depth == 0 && words[i] == ')')) {
+				if (words[i] == '(')
+					++depth;
+				else if (words[i] == ')')
+					--depth;
+
+				++i;
+			}
+
+			if (words[i] == ')' && words[i + 1] == ')') {
+				(*offset) += 3;
+				/* Call parse_arith -- 0 is for "no brackets" */
+				return parse_arith(word, word_length, max_length, words,
+								   offset, flags, 0);
+			}
+		}
+
+		if (flags & WRDE_NOCMD)
+			return WRDE_CMDSUB;
+
+		(*offset) += 2;
+		return parse_comm(word, word_length, max_length, words, offset,
+						  flags, quoted ? NULL : pwordexp, ifs, ifs_white);
+
+	case '[':
+		(*offset) += 2;
+		/* Call parse_arith -- 1 is for "brackets" */
+		return parse_arith(word, word_length, max_length, words, offset,
+						   flags, 1);
+
+	case '{':
+	default:
+		++(*offset);			/* parse_param needs to know if "{" is there */
+		return parse_param(word, word_length, max_length, words, offset,
+						   flags, pwordexp, ifs, ifs_white, quoted);
+#else
+	default:
+		++(*offset);			/* parse_param needs to know if "{" is there */
+		return 0;
+#endif
+	}
+}
+
+static int
+parse_dquote(char **word, size_t * word_length, size_t * max_length,
+			 const char *words, size_t * offset, int flags,
+			 wordexp_t * pwordexp, const char *ifs, const char *ifs_white)
+{
+	/* We are poised just after a double-quote */
+	int error;
+
+	for (; words[*offset]; ++(*offset)) {
+		switch (words[*offset]) {
+		case '"':
+			return 0;
+
+		case '$':
+			error = parse_dollars(word, word_length, max_length, words, offset,
+							  flags, pwordexp, ifs, ifs_white, 1);
+			/* The ``1'' here is to tell parse_dollars not to
+			 * split the fields.  It may need to, however ("$@").
+			 */
+			if (error)
+				return error;
+
+			break;
+
+		case '`':
+			if (flags & WRDE_NOCMD)
+				return WRDE_CMDSUB;
+
+			++(*offset);
+			error = parse_backtick(word, word_length, max_length, words,
+								   offset, flags, NULL, NULL, NULL);
+			/* The first NULL here is to tell parse_backtick not to
+			 * split the fields.
+			 */
+			if (error)
+				return error;
+
+			break;
+
+		case '\\':
+			error = parse_qtd_backslash(word, word_length, max_length, words,
+									offset);
+
+			if (error)
+				return error;
+
+			break;
+
+		default:
+			*word = w_addchar(*word, word_length, max_length, words[*offset]);
+			if (*word == NULL)
+				return WRDE_NOSPACE;
+		}
+	}
+
+	/* Unterminated string */
+	return WRDE_SYNTAX;
+}
+
+/*
+ * wordfree() is to be called after pwordexp is finished with.
+ */
+
+void wordfree(wordexp_t * pwordexp)
+{
+
+	/* wordexp can set pwordexp to NULL */
+	if (pwordexp && pwordexp->we_wordv) {
+		char **wordv = pwordexp->we_wordv;
+
+		for (wordv += pwordexp->we_offs; *wordv; ++wordv)
+			free(*wordv);
+
+		free(pwordexp->we_wordv);
+		pwordexp->we_wordv = NULL;
+	}
+}
+libc_hidden_def(wordfree)
+
+/*
+ * wordexp()
+ */
+
+int wordexp(const char *words, wordexp_t * we, int flags)
+{
+	size_t words_offset;
+	size_t word_length;
+	size_t max_length;
+	char *word = w_newword(&word_length, &max_length);
+	int error;
+	char *ifs;
+	char ifs_white[4];
+	wordexp_t old_word = *we;
+
+	if (flags & WRDE_REUSE) {
+		/* Minimal implementation of WRDE_REUSE for now */
+		wordfree(we);
+		old_word.we_wordv = NULL;
+	}
+
+	if ((flags & WRDE_APPEND) == 0) {
+		we->we_wordc = 0;
+
+		if (flags & WRDE_DOOFFS) {
+			we->we_wordv = calloc(1 + we->we_offs, sizeof(char *));
+			if (we->we_wordv == NULL) {
+				error = WRDE_NOSPACE;
+				goto do_error;
+			}
+		} else {
+			we->we_wordv = calloc(1, sizeof(char *));
+			if (we->we_wordv == NULL) {
+				error = WRDE_NOSPACE;
+				goto do_error;
+			}
+
+			we->we_offs = 0;
+		}
+	}
+
+	/* Find out what the field separators are.
+	 * There are two types: whitespace and non-whitespace.
+	 */
+	ifs = getenv("IFS");
+
+	if (!ifs)
+		/* IFS unset - use <space><tab><newline>. */
+		ifs = strcpy(ifs_white, " \t\n");
+	else {
+		char *ifsch = ifs;
+		char *whch = ifs_white;
+
+		/* Start off with no whitespace IFS characters */
+		ifs_white[0] = '\0';
+
+		while (*ifsch != '\0') {
+			if ((*ifsch == ' ') || (*ifsch == '\t') || (*ifsch == '\n')) {
+				/* Whitespace IFS.  See first whether it is already in our
+				   collection.  */
+				char *runp = ifs_white;
+
+				while (runp < whch && *runp != '\0' && *runp != *ifsch)
+					++runp;
+
+				if (runp == whch)
+					*whch++ = *ifsch;
+			}
+
+			++ifsch;
+		}
+		*whch = '\0';
+	}
+
+	for (words_offset = 0; words[words_offset]; ++words_offset)
+		switch (words[words_offset]) {
+		case '\\':
+			error = parse_backslash(&word, &word_length, &max_length, words,
+								&words_offset);
+
+			if (error)
+				goto do_error;
+
+			break;
+
+		case '$':
+			error = parse_dollars(&word, &word_length, &max_length, words,
+								  &words_offset, flags, we, ifs, ifs_white,
+								  0);
+
+			if (error)
+				goto do_error;
+
+			break;
+
+		case '`':
+			if (flags & WRDE_NOCMD) {
+				error = WRDE_CMDSUB;
+				goto do_error;
+			}
+
+			++words_offset;
+			error = parse_backtick(&word, &word_length, &max_length, words,
+								   &words_offset, flags, we, ifs,
+								   ifs_white);
+
+			if (error)
+				goto do_error;
+
+			break;
+
+		case '"':
+			++words_offset;
+			error = parse_dquote(&word, &word_length, &max_length, words,
+								 &words_offset, flags, we, ifs, ifs_white);
+
+			if (error)
+				goto do_error;
+
+			if (!word_length) {
+				error = w_addword(we, NULL);
+
+				if (error)
+					return error;
+			}
+
+			break;
+
+		case '\'':
+			++words_offset;
+			error = parse_squote(&word, &word_length, &max_length, words,
+								 &words_offset);
+
+			if (error)
+				goto do_error;
+
+			if (!word_length) {
+				error = w_addword(we, NULL);
+
+				if (error)
+					return error;
+			}
+
+			break;
+
+		case '~':
+			error = parse_tilde(&word, &word_length, &max_length, words,
+								&words_offset, we->we_wordc);
+
+			if (error)
+				goto do_error;
+
+			break;
+
+		case '*':
+		case '[':
+		case '?':
+			error = parse_glob(&word, &word_length, &max_length, words,
+							   &words_offset, flags, we, ifs, ifs_white);
+
+			if (error)
+				goto do_error;
+
+			break;
+
+		default:
+			/* Is it a word separator? */
+			if (strchr(" \t", words[words_offset]) == NULL) {
+				char ch = words[words_offset];
+
+				/* Not a word separator -- but is it a valid word char? */
+				if (strchr("\n|&;<>(){}", ch)) {
+					/* Fail */
+					error = WRDE_BADCHAR;
+					goto do_error;
+				}
+
+				/* "Ordinary" character -- add it to word */
+				word = w_addchar(word, &word_length, &max_length, ch);
+				if (word == NULL) {
+					error = WRDE_NOSPACE;
+					goto do_error;
+				}
+
+				break;
+			}
+
+			/* If a word has been delimited, add it to the list. */
+			if (word != NULL) {
+				error = w_addword(we, word);
+				if (error)
+					goto do_error;
+			}
+
+			word = w_newword(&word_length, &max_length);
+		}
+
+	/* End of string */
+
+	/* There was a word separator at the end */
+	if (word == NULL)			/* i.e. w_newword */
+		return 0;
+
+	/* There was no field separator at the end */
+	return w_addword(we, word);
+
+  do_error:
+	/* Error:
+	 *  free memory used (unless error is WRDE_NOSPACE), and
+	 *  set we members back to what they were.
+	 */
+
+	free(word);
+
+	if (error == WRDE_NOSPACE)
+		return WRDE_NOSPACE;
+
+	if ((flags & WRDE_APPEND) == 0)
+		wordfree(we);
+
+	*we = old_word;
+	return error;
+}