Index: /trunk/Makefile
===================================================================
--- /trunk/Makefile	(revision 2447)
+++ /trunk/Makefile	(revision 2448)
@@ -742,6 +742,4 @@
 	mkdir -p $(PATH_BUILTTOOLS)/bin $(PATH_BUILTTOOLS)/lib $(PATH_BUILTTOOLS)/include $(PATH_BUILTTOOLS)/omfhack
 	
-$(PATH_BUILTTOOLS)/bin/dllar.cmd $(PATH_BUILTTOOLS_TMP)/bin/dllar.cmd: $(PATH_TOP)/src/misc/dllar.cmd
-	cp $< $@
 $(PATH_BUILTTOOLS)/omfhack/ranlib.exe $(PATH_BUILTTOOLS_TMP)/omfhack/ranlib.exe: $(PATH_TOP)/tools/bin/true.exe
 	cp $< $@
@@ -997,5 +995,5 @@
 	for dir in $(GCC_CONFIGURE_DIRS); do \
 		echo $$dir; \
-		if $(MAKE) $(MAKEOPT) -j 1 $(@:gcc-autoconf-%=%) -f $(PWD)/config.gmk -C src/$$dir ; then \
+		if $(MAKE) $(MAKEOPT) -j 1 $(@:gcc-autoconf-%=%) -f $(PWD)/config.gmk -C $$dir ; then \
 			true; \
 		else \
@@ -1013,6 +1011,6 @@
 # let the build/bootstrap create the gcc import .def file before kicking off a build.
 gcc-bootstrap gcc-build: gcc/gcc/config/i386/emx-libgcc_so_d.def
-gcc/gcc/config/i386/emx-libgcc_so_d.def: libc/src/lib/libgcc_d.awk $(PATH_OBJD)/emx/omf/libc.def libc/src/lib/libc.def
-	$(GAWK) -f libc/src/lib/libgcc_d.awk $(filter %.def,$^) > $@
+gcc/gcc/config/i386/emx-libgcc_so_d.def: libc/src/libc/libgcc_d.awk $(PATH_OBJD)/libc/omf/libc.def libc/src/libc/libc.def
+	$(GAWK) -f libc/src/libc/libgcc_d.awk $(filter %.def,$^) > $@
 
 
@@ -1023,5 +1021,5 @@
 # For the 2nd stage we need a hack for using the right specs when linking...
 #SPEC_HACK = $(if $(wildchar $(PATH_OBJ)/.all-stage1),\
-#              -specs $(PATH_TOP)/libc/src/lib/libc.specs, \
+#              -specs $(PATH_TOP)/libc/src/libc/libc.specs, \
 #              -specs $(PATH_TOP)/tools/x86.os2/gcc/staged/lib/gcc-lib/i386-pc-os2-emx/$(GCC_VERSION)/specs)
 SPECS_HACK =
@@ -1096,5 +1094,5 @@
 gcc-builtunix-stage2:
 	$(MAKE) $(MAKEOPT) -C $(PATH_OBJ)/gcc prefix=$(PATH_BUILTTOOLS_TMPD) install
-##	cp $(PATH_TOP)/libc/src/lib/libc.specs $(PATH_OBJ)/gcc/gcc/specs
+##	cp $(PATH_TOP)/libc/src/libc/libc.specs $(PATH_OBJ)/gcc/gcc/specs
 
 
@@ -1166,5 +1164,5 @@
 endif
 	for dir in $(BINUTILS_CONFIGURE_DIRS); do \
-		if $(MAKE) $(MAKEOPT) -j 1 $(@:binutils-autoconf-%=%) -f $(PWD)/config.gmk -C src/$$dir ; then \
+		if $(MAKE) $(MAKEOPT) -j 1 $(@:binutils-autoconf-%=%) -f $(PWD)/config.gmk -C $$dir ; then \
 			true; \
 		else \
@@ -1372,12 +1370,12 @@
 emx-build emx-install:
 	mkdir -p $(PATH_OBJ)/emx
-	$(MAKE) $(MAKEOPT) -C $(PATH_TOP)/emx -f $(MAKEFILE) $@-it
+	$(MAKE) $(MAKEOPT) -f $(PATH_TOP)/emx/Makefile.gmk -C $(PATH_TOP)/emx -f $(MAKEFILE) $@-it
 
 emx-build-it:
-	$(MAKE) $(MAKEOPT) -j 1 -C $(PATH_TOP)/emx $(EMX_DEFINES) tools
-	$(MAKE) $(MAKEOPT) -C $(PATH_TOP)/emx $(EMX_DEFINES) all
+	$(MAKE) $(MAKEOPT) -j 1 -f $(PATH_TOP)/emx/Makefile.gmk -C $(PATH_TOP)/emx $(EMX_DEFINES) tools
+	$(MAKE) $(MAKEOPT) -f $(PATH_TOP)/emx/Makefile.gmk -C $(PATH_TOP)/emx $(EMX_DEFINES) all
 
 emx-install-it:
-	$(MAKE) $(MAKEOPT) -C $(PATH_TOP)/emx $(EMX_DEFINES) INS=$(ALL_PREFIX)/ install
+	$(MAKE) $(MAKEOPT) -f $(PATH_TOP)/emx/Makefile.gmk -C $(PATH_TOP)/emx $(EMX_DEFINES) INS=$(ALL_PREFIX)/ install
 
 					
@@ -1388,12 +1386,12 @@
 # Install the compiled emx stuff to builtunix.
 emx-builtunix-stage2:
-	$(MAKE) $(MAKEOPT) -C $(PATH_TOP)/emx $(EMX_DEFINES) INS=$(PATH_BUILTTOOLS_TMP)/  install
+	$(MAKE) $(MAKEOPT)-f $(PATH_TOP)/emx/Makefile.gmk -C $(PATH_TOP)/emx $(EMX_DEFINES) INS=$(PATH_BUILTTOOLS_TMP)/  install
 
 # Quick bootstrap workers.			
 emx-quick:
-	GCCLOAD=3 $(MAKE) $(MAKEOPT) -C $(PATH_TOP)/emx $(EMX_DEFINES) all
+	GCCLOAD=3 $(MAKE) $(MAKEOPT) -f $(PATH_TOP)/emx/Makefile.gmk -C $(PATH_TOP)/emx $(EMX_DEFINES) all
 			
 emx-quick-install:
-	$(MAKE) $(MAKEOPT) -C $(PATH_TOP)/emx $(EMX_DEFINES) INS=$(PATH_BUILTTOOLS)/ install
+	$(MAKE) $(MAKEOPT)-f $(PATH_TOP)/emx/Makefile.gmk -C $(PATH_TOP)/emx $(EMX_DEFINES) INS=$(PATH_BUILTTOOLS)/ install
 			    	
 
@@ -1441,9 +1439,9 @@
 
 libc-build-it:
-	$(MAKE) $(MAKEOPT) -j 1 -C $(PATH_TOP)/libc $(LIBC_DEFINES) tools
-	$(MAKE) $(MAKEOPT) -C $(PATH_TOP)/libc $(LIBC_DEFINES) all
+	$(MAKE) $(MAKEOPT) -j 1 -f $(PATH_TOP)/libc/Makefile.gmk -C $(PATH_TOP)/libc $(LIBC_DEFINES) tools
+	$(MAKE) $(MAKEOPT) -f $(PATH_TOP)/libc/Makefile.gmk -C $(PATH_TOP)/libc $(LIBC_DEFINES) all
 
 libc-install-it:
-	$(MAKE) $(MAKEOPT) -C $(PATH_TOP)/libc $(LIBC_DEFINES) INS=$(ALL_PREFIX)/ install
+	$(MAKE) $(MAKEOPT) -f $(PATH_TOP)/libc/Makefile.gmk -C $(PATH_TOP)/libc $(LIBC_DEFINES) INS=$(ALL_PREFIX)/ install
 
 					
@@ -1454,12 +1452,12 @@
 # Install the compiled libc stuff to builtunix.
 libc-builtunix-stage2:
-	$(MAKE) $(MAKEOPT) -C $(PATH_TOP)/libc $(LIBC_DEFINES) INS=$(PATH_BUILTTOOLS_TMP)/  install
+	$(MAKE) $(MAKEOPT) -f $(PATH_TOP)/libc/Makefile.gmk -C $(PATH_TOP)/libc $(LIBC_DEFINES) INS=$(PATH_BUILTTOOLS_TMP)/  install
 
 # Quick bootstrap workers.			
 libc-quick:
-	GCCLOAD=3 $(MAKE) $(MAKEOPT) -f $(PATH_TOP)/libc/libonly.gmk -C $(PATH_TOP)/libc $(LIBC_DEFINES) all
+	GCCLOAD=3 $(MAKE) $(MAKEOPT) -f $(PATH_TOP)/libc/Makefile.gmk -C $(PATH_TOP)/libc $(LIBC_DEFINES) all
 
 libc-quick-install:
-	$(MAKE) $(MAKEOPT) -f $(PATH_TOP)/libc/libonly.gmk -C $(PATH_TOP)/libc $(LIBC_DEFINES) INS=$(PATH_BUILTTOOLS)/ install
+	$(MAKE) $(MAKEOPT) -f $(PATH_TOP)/libc/Makefile.gmk -C $(PATH_TOP)/libc $(LIBC_DEFINES) INS=$(PATH_BUILTTOOLS)/ install
 		
 			    	
@@ -1572,9 +1570,6 @@
 	cp $(PATH_TOP)/doc/COPYING.LIB              $(ALL_PREFIX)/doc/GCC-$(GCC_VERSION)
 	cp $(PATH_TOP)/doc/COPYING                  $(ALL_PREFIX)/doc/GCC-$(GCC_VERSION)
-#	cp $(PATH_TOP)/ChangeLog                    $(ALL_PREFIX)/doc/GCC-$(GCC_VERSION)/ChangeLog.os2
 	cp $(PATH_TOP)/libc/ChangeLog.LIBC          $(ALL_PREFIX)/doc/GCC-$(GCC_VERSION)
-	cp $(PATH_TOP)/src/misc/MakeOmfLibs.cmd     $(ALL_PREFIX)/lib
-	cp $(PATH_TOP)/src/misc/dllar.cmd           $(ALL_PREFIX)/bin
-	cp $(PATH_TOP)/src/misc/gccenv.cmd          $(ALL_PREFIX)/bin
+	cp $(PATH_TOP)/emx/ChangeLog.emx            $(ALL_PREFIX)/doc/GCC-$(GCC_VERSION)
 			
 
Index: /trunk/binutils/gas/as.c
===================================================================
--- /trunk/binutils/gas/as.c	(revision 2447)
+++ /trunk/binutils/gas/as.c	(revision 2448)
@@ -224,5 +224,5 @@
 
 #ifdef BFD_ASSEMBLER
-  fprintf (stderr, _("GNU assembler version %s (%s) using BFD version %s (Innotek Build 2005-11-15 02:02)"),
+  fprintf (stderr, _("GNU assembler version %s (%s) using BFD version %s (Innotek Build 2005-11-15 03:52)"),
 	   VERSION, TARGET_ALIAS, BFD_VERSION_STRING);
 #else
@@ -546,7 +546,7 @@
 	  /* This output is intended to follow the GNU standards document.  */
 #ifdef BFD_ASSEMBLER
-	  printf (_("GNU assembler %s (Innotek Build 2005-11-15 02:02)\n"), BFD_VERSION_STRING);
+	  printf (_("GNU assembler %s (Innotek Build 2005-11-15 03:52)\n"), BFD_VERSION_STRING);
 #else
-	  printf (_("GNU assembler %s (Innotek Build 2005-11-15 02:02)\n"), VERSION);
+	  printf (_("GNU assembler %s (Innotek Build 2005-11-15 03:52)\n"), VERSION);
 #endif
 	  printf (_("Copyright 2002 Free Software Foundation, Inc.\n"));
Index: unk/emx/ChangeLog.LIBC
===================================================================
--- /trunk/emx/ChangeLog.LIBC	(revision 2447)
+++ 	(revision )
@@ -1,596 +1,0 @@
-/* $Id$ */
-
-TODO: open replace on RAMFS fails with error 32!
-
-2005-11-12: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - emxomf:
-        o Fixed problems with symbol truncation.
-          Kudos to Yuri for tracking down the places which required attention.
-    - libc:
-        o Committed the getdirents implementation (forgot to add it apparently).
-        o Created proper backend for fcntl removing F_GETOSFD in the process. Using
-          fcntl to set O_NONBLOCK on sockets works now.
-        o Fixed a generic error handling bug in ioctl, write, read, dup and dup
-          which was causing incorrect errnos.
-        o Changed line buffer from 512 to 8192 bytes in _response().
-        o Corrected shmat to return -1 instead of NULL on failure.
-        o Fixed bug in the sigsuspend (includes pause ++) handling,
-          would usually never return.
-
-2005-10-31: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed sharedpm problem on legacy systems. (Thanks to Andrew Below
-          for pointing it out.)
-
-2005-10-26: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Implemented getdirents().
-
-2005-09-26: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Implemented __libc_Back_ioFHToPath using __LIBC_FH::pszNativePath.
-
-2005-09-25: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Implemented fchdir().
-        o Implemented inheritance of open directory handles. Unfortunately,
-          I ran out of size bits for the bundle type, so the SPM bit is no
-          longer compatible with earlier versions. The consequences
-          of this are related to inheritance and signaling - so recompile!
-
-2005-08-28: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Reworked the open backend, adding directory support. Some O_*
-          flags was changed in the process, breaking the old ABI.
-          This is not fully tested.
-        o Added more BSD fields to struct stat, breaking the old ABI.
-          The mtime field and ctime fields will now keep the same values
-          and the creation time is to be found in birthtime. This means that
-          ctime will be updated in a few places where it doesn't on unix - but
-          this is probably better than previously where it wasn't ever updated
-          when it should.
-        o Removed forwarder dlls since struct stat, O_* and __LIBC_FH is
-          soon going to be incompatible with rc1 and older versions.
-    - version.smak:
-        o Changed version number back to 3.3.5 / 0.6 rc2.
-
-2005-08-27: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed lot's of unix attribute (in EA) handling.
-        o Started preparing for open() to work on directories so
-          fchdir() can be implemented and opendir reimplemented.
-          This will break libsocket backwards compatability.
-        o Added _hstrdup.
-        o Fixed two cases where the signal semaphore was incorrectly unlocked
-          after signalDeliver().
-        o Don't try the '.exe' too early on executables (exec/spawn), this broke
-          execution of './configure' and other scripts with no extension.
-
-2005-08-24: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed bad panic format types in safesems.
-
-2005-08-21: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - emxbind, emxomfld:
-        o Default stack size set to 1MB.
-          The old defaults were 8MB (emxbind) and 8KB (emxomfld).
-    - libc:
-        o Filled in the NULLs in sys_signame and sys_siglist.
-        o Added __libc_Back_gfProcessHandleHashBangScripts and
-          __libc_Back_gfProcessHandlePCBatchScripts for use in shells which
-          can handle such scripts more efficiently than libc.
-        o Fixed some bugs related to finding the interpreter in the spawn/exec backend.
-        o Merged the signal semaphore handling into the safe sems and
-          made signals use them instead.
-        o Tried to workaround the race conditions in __libc_Back_safesemEvSleep/Wakeup.
-          These might affect SysV sems.
-        o Corrected the declarations of _DLL_InitTerm.
-
-2005-08-20: Lorne Sunley <lsunley@mb.sympatico.  >
-    - libc:
-        o Added OBJ_FORK to the allocations in sysv_shm.
-
-2005-08-20: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Define _EMX_SOURCE (__USE_EMX) along with _BSD_SOURCE and _SVID_SOURCE as
-          defaults in features.h.
-        o Protect the fork operations by the means of must complete so
-          signals won't interrupt us till we're finished. This might leave
-          unkillable processes around if fork goes highwire.
-        o Better exception logging during fork.
-        o Use MMX memcpy in fork (if supported).
-        o The C function __libc_Back_processFork() replaces the pure assembly __fork().
-        o Added _memcpy_amd.
-        o Fixed some logging statements in sharedpm.c.
-        o Log __fmutex_release_internal_must_complete.
-        o Corrected a few prototypes in process.h to use pid_t.
-
-2005-08-13: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added SH_COMPAT to share.h and emulate it as SH_DENYNO (just like watcom).
-          The SH_COMPAT shareing mode is not available to OS/2 processes, only DOS / os2krnl.
-
-2005-08-02: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o __libc_back_fsNativeFileModeSet(): The long set api is broken
-          in 14.103b & c (at least) so avoid it where it isn't strictly required.
-
-2005-07-24: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libos2:
-        o Added some missing INCL_DOSERRORS #defines (very odd ones).
-    - emximp:
-        o Fixed bad done string allocation.
-    - ld:
-        o Fixed a case of memory access after free.
-        o Switched back to alloca and adding 23 MB of stack.
-
-2005-07-21: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o unistd.h prototype of encrypt() shall return void not int.
-        o Fixed __USE_GNU tests in ftw.h and sys/dirent.h.
-
-2005-07-17: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o LIBC_ASSERT*() are for internal libc errors, LIBCLOG_ERROR*() are
-          for user related error. Big code adjustements.
-        o Fixed a few smaller issues.
-        o Started fixing exec() backend.
-        o Fixed some more mktime / localtime bugs.
-        o Fixed crash on simple LIBC_ASSERT() caused by NULL format string.
-        o Generate device numbers for devices and pipes too.
-        o Fixed mixup of Dev and Inode during filehandle inheritance.
-        o Fixed __dup and __dup2 bug in relation to the FD_CLOEXEC clearing.
-        o Fixed bug in codepage normalization during setlocale().
-        o Fixed bug in regex where the lock was overwritten after initialization.
-        o Switch the glibc locks to smutex to avoid leaking event semaphores.
-        o Added _smutex_try_request().
-        o Fixed __libc_back_fsResolve to always set fInUnixTree so the result can
-          be adjusted correctly on failure as well.
-    - version.smak:
-        o Changed version number back to 3.3.5 / 0.6 rc1.
-
-2005-07-11: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libos2:
-        o UniStrFromUcs added and UniStrToUcs to uconv.h.
-          Added UniStrFromUcs, UniStrToUcs, UniMalloc and UniFree to unicode.imp.
-
-2005-07-10: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Replaced BSD regex with the new GLIBC implementation.
-        o Fixed two bad bugs in the handling of the list of free
-          SPM notification structures.
-        o Moved the codeset standardization up a bit so nl_langinfo
-          and setlocale reports the same codeset.
-
-2005-07-06: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Changed utimes() to allow NULL pointer parameter.
-          Please note that BSD will crash in if you try it there.
-        o Renamed the BSD setmode to bsd_setmode and put back the
-          PC setmode.
-
-2005-07-05: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed spawn/fork + fork() + exec/spawn/fork in the child.
-        o Kill any known decentants to prevent them from being
-          adopted by our parent. (On UNIX processes begin made
-          orphants are adopted and killed by the init process.)
-        o Added signal handler types for POSIX, BSD and GNU conformance.
-        o Reap embryos when the waiter thread is querying spm about
-          the death certificate. This, together with a tiny fix
-          in __spawnve() cures the bad spm process leaks when spawning
-          non-libc processes seen with make when building libc.
-
-2005-07-04: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added the BSD optreset global to getopt.
-        o Changed PC setmode to _setmode. As it collides with a BSD 4.4. interface.
-        o Added the BSD 4.4. setmode/getmode functions from FreeBSD.
-        o Added getsid and getpgid, correcting the getpgrp implementation.
-        o Added/replaced setbuf, setbuffer and setlinebuf from BSD.
-
-2005-07-03: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Collected the different panic routines into one single routine
-          in the backend, __libc_Back_panic[V](). The routine supports
-          very simple printf like message formatting. By default it wil
-          dump any available registers and attempt dumping the process
-          before killing it. This behaviour can be configured with the
-          env var.: LIBC_PANIC=[nodump][terse][quiet][breakpoint]
-
-2005-07-02: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added obstack.h and it's implementation from GLIBC.
-        o malloc and realloc must set errno to ENOMEM on failure.
-        o Fixed assertion during realloc(p, -256) to return failure
-          instead. Added a few more overflow checks.
-        o Added %m (GLIBC extension) to the printf familiy. %m means
-          priting strerror(errno), it takes no arguments.
-        o Fixed serveral bugs in the C/POSIX locale
-        o Implemented the LC_MESSAGES locale.
-        o Fixed mixup in fts.c port.
-        o Replaced the EMX ftw with the BSD one so we implement the SuS specs.
-        o Clear FD_CLOEXEC on the handle returned by dup, dup2 and fcntl(F_DUPFD,,).
-        o Fixed a buffer size validation bug in the backend for getcwd and
-          friends. Was requiring a byte to much.
-        o Updated some TCPIP headers with GLIBC __USE_MISC #includes. (more to go)
-        o sys/fcntl.h shall include sys/stat.h in XSI mode.
-        o Added stpncpy from GLIBC.
-        o Added sys/builtin.h to sys/smutex.h.
-        o Updated features.h and sys/gnu/cdefs.h with more recent versions from cvs.
-        o Ported from GLIBC 2.3.x CVS.
-        o Fixed some waitid() and waitpid() problems related to stopping and resuming children.
-        o Updated argz.h because of bustage caused by new cdefs.h (THROW).
-    - libcrypt:
-        o Created stub library.
-    - version.smak, libc.smak:
-        o Back to betas, beta6 now.
-
-2005-07-01: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Made isinf[lf] return -1 for negative infinity like GLIBC does.
-        o Added prototypes for nan[lf] to math.h, gcc inlines these.
-        o Ported GLIBC argp and getopt (argp requires the GLIBC one).
-          This means no optreset anylonger.
-        o Some corrections / hacks in the weak_alias departement.
-        o Shopped missing math stuff from GLIBC.
-        o Added fpu_control.h, ieee754.h and endian.h from the GLIBC tradition.
-
-2005-06-30: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added fwide() (dummy until LIBC07).
-        o Renamed struct _FILE to struct __sFILE to match BSD.
-        o Added wait.h for GLIBC compatability, content is #include <sys/wait.h>.
-        o Added _D_EXACT_NAMLEN and _D_ALLOC_NAMLEN macros to sys/dirent.h to
-          make GLIBC code happy.
-        o Added REG_NOERROR to regex.h to make GLIBC code happy.
-        o The three default heap handles can be duplicates of one another, this
-          could cause deadlocks in certain cases usually involing tiled memory.
-        o Added asprintf() and vasprintf().
-        o Added get_current_dir_name() (GLIBC extension).
-        o Added the strdupa() and strndupa() GLIBC extensions. These are macros
-          use alloca() to allocate the memory for the string.
-        o Added the getdelim() and getline() GLIBC extensions.
-        o Added getlogin_r() (still just a fake).
-        o Added TEMP_FAILURE_RETRY() macro to unistd.h. This is yet another GLIBC hack.
-
-2005-06-29: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - *:
-        o Fixed stack alignment, it must be 16 bytes not 4!
-        o Fixed bustage caused by the include cleanup.
-    - libc:
-        o Added ieeefp.h and functions from FreeBSD - this is
-          the SysV/386 FP control interface. (inline only)
-        o Added fgets_unlocked and gets_unlocked.
-
-2005-06-28: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - *:
-        o Released v0.6 beta 5.
-        o Changed versions to v0.6 rc1.
-        o Created the libc06b5 forwarder dll.
-    - libc:
-        o Added _NSIG and making NSIG and _NSIG equal to SIGRTMAX + 1.
-        o Added memrawchr and strchrnul from glibc, enabling us to shop .S
-          files from glibc at the same time.
-        o On glibc lot's of limits.h stuff is included from direct.h because of
-          need for NAME_MAX, let's do something similar.
-        o Corrected MAXNAMLEN / d_name field length.
-
-2005-06-27: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - emxomfld, ld:
-        o Generate .def-file for dlls without one. (This only makes sense for
-          emxomfld since ld doesn't implement __declspec(dllexport) yet, but
-          anyway.)
-    - emxomf, emxomfld:
-        o Kicked out all the old weak handling (from early 3.2.2 alphas).
-
-2005-06-26: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added [__]isinf[fl] which seems to have been mislaid during the
-          math source import.
-        o Rewrote the libcXXXX.dll install rule to not play with emxload since
-          emxload sticks around when first loaded.
-        o Made unsetenv() cause tzset reload just like putenv() and setenv().
-        o Changed putenv() behaviour for removal (no '=' in input) to be identical
-          to unsetenv(). This solves duplicate variable testcase.
-        o Changed filestreams opened for both reading and writing to switch
-          more willingly between read and write mode.
-        o Made sscan() return EOF on EOF.
-        o Made sscan() skip blanks in input for '%%'.
-        o Implemented the stdio_unlocked stuff with BSD and GLIBC extension.
-          TODO: Require a new locktype which support recursive usage! Currently
-                a hack using 8 free flag bits is used.
-        o Corrected realpath() behaviour to return the path up to the failure
-          point on error. _realrealpath() also does this now.
-          (This also saves us a temp buffer and a copy of the result.)
-        o Fixed a bug in the handling of ".." in the path resolver.
-        o Extended that path resolver to check the directoryness of the input
-          according to flags and any trailing slashes.
-        o Change the path resolver to be very strict about UNC - UNC have exactly
-          two slashes at the start of the path.
-
-2005-06-25: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed SIGINT and similar issues with fork().
-          TODO: LIBC signals depending on 16-bit OS/2 signals will
-                still cause trouble, this needs fixing.
-        o Extended the fmutex error message.
-        o Fixed regression in the fmutex must completion code (bad fs handling).
-
-2005-06-23: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed some more incorrectness of the 'C' locale, it only
-          defines the first 128 chars.
-        o Build hack for math.h.
-        o Updated sys/stat.h, sys/resource.h and sys/_types.h to
-          FreeBSD 5.3 level.
-        o btowc(): WEOF is 32-bit, wchar_t is 16.
-        o *printf(): wide char support.
-        o sysctl(): Changed the boottime alogrithm.
-        o strxfrm(): Corrected the return values.
-        o __ftime(): Corrected regression causing the time to be 35 years wrong.
-        o strftime(): Added C99 %F.
-        o strptime(): Fixed a few parsing and calculation bugs.
-
-2005-06-19: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o File resize optimization: The JFS, HPFS and probably NET
-          will never return space which isn't zeroed when expanding
-          a file. Associate a file system information object with the
-          filehandles to keep track of such features. This also fixes
-          the fsStatFH() implementation trouble.
-          This attribute doesn't apply to CDFS. While RAMFS fails
-          the test, it zeros at open but not at setfilesize.
-        o Fixed invalid inode and dev numbers for new files, was passing
-          the wrong path around.
-
-2005-06-13: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Auto init fmutexes.
-        o Fixed potential deadlock the first time a must-complete
-          fmutex was entered.
-        o Replaced mktemp and mkstemp with BSD versions. Also adding
-          mkstemps, mkdtemp, arc4random, arc4random_addrandom and
-          arc4random_stir.
-        o Limited the namespace pollution caused by machine/param.h
-          (included by sys/param.h which is used by lot's of tcpip headers).
-          Define _BSD_NAMESPACE_POLLUTION to get it all.
-        o Fixed bug in getitimer/setitmer, it didn't zero the old value struct
-          if the timer wasn't running.
-        o Fixed a bug in __ftime(), the time was jolting around.
-
-2005-06-12: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Changed the LIBC_PATHREADWRITERS to a generic LIBC_HOOK_DLLS.
-          See src/emx/src/lib/sys/hooks.c for details.
-
-2005-06-11: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o The smallcnv stuff is gone, waste of space since we're not really into
-          static linking. Should've done this when switching to gdtoa.
-        o Ported the msun and some other math bits from current FreeBSD libc.
-          This mostly replaces the EMX math, except for some double long variants
-          and some EMX specific ones. This is a risky change, but it's needed
-          if we're gonna catch up on the C99 bits and make libstdc++ happy.
-          There are some new headers, complex.h and fenv.h being the importan ones.
-          float.h have gotten some updates while math.h is totally replaced.
-          More than 100 standard functions were added!
-          NOTE: msun is using MATH_ERREXCEPT (math_errhandling) and not
-                MATH_ERRNO for error reporting.
-          I really hope this is not gonna uncover more OS/2 387 mess.
-        o Handle .cmd, .bat, .btm and hash-bang script files if DosExecPgm()
-          fails. (I'm a little bit uncertain about argv[0], but it appears to work.)
-
-2005-06-05: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o the setitimer backend was making incorrect assumptions about the
-          HTIMER range - NULLHANDLE is valid for HTIMER. Changed it to use ~0U
-          as invalid handle. (untested)
-        o Default TCPIP mode is __USB_LIBC_TCPIP. When either TCPV40HDRS or TCPV41HDRS
-          are defined we are in strict mode and __USB_LIBC_TCPIP will not be defined.
-    - libomflib, emxomfar:
-        o Allow multiple modules by the same basename. This is not in tradition with
-          other librarians, but it solves incompatible behaviour between emxomfar and ar.
-    - ld:
-        o Avoid using alloca since we might easily run out of stack for big objects
-          with debuginfo.
-    - emxomf:
-        o Added support for new EMX a.out stab N_EXP (0x6c). This encodes export
-          definitions. (gcc can do __declspec(dllexport) now.)
-          TODO: ld needs updating, probably this is the right time to drop the
-                old ld and fixup the binutils port!
-
-2005-05-08: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added _getenv_[int|long|longlong]. Using this for LIBC_THREAD_MIN_STACK_SIZE.
-        o Ported the BSD SysV Semaphore module.
-        o Added a signal notification callback to the thread structure.
-        o Changed tcpip term callback to more generic exitlist callback (SPM).
-        o Ported the BSD SysV Shared Memory module.
-
-2005-05-05: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added fts.h and ported the BSD implementation.
-          It's not 100% correct since we're lacking fchdir and cannot open
-          directories - will update it when this is in place.
-        o Disabled the UF_ and SF_ defines in sys/stat.h since we don't have st_flags.
-        o Added mkfifo (stub).
-        o Added lutimes and futimes, replacing __utimes.
-
-2005-05-01: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed incorrect d_type returned by readdir and readdir_r.
-        o Changed chdir() to unix style, added _chdir_os2() as a backwards compatible
-          api. _chdir2() and chdir() are operating identically now.
-        o Fixed several incorrect/incomplete path resolve cases. Some causing
-          invalid ino values.
-        o Unlock the libc DLL before installing it (cp, make or someone might be using it).
-        o Unix root rewrite rule ends it's pszTo with a slash, this caused
-          two slashes and thus UNC trouble.
-        o Quick rewrite of access() (also affects eaccess()) to work in chroot environment.
-        o Added O_BINARY to all opens in bsd/db.
-
-2005-04-30: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libmoddef:
-        o Allow empty definition strings. (weakld failed on python _curses_m)
-    - weakld:
-        o Fixed incorrect .def-file parse error message.
-    - sys/param.h:
-        o Added MAXBSIZE, BKVASIZE and BKVAMASK which are used by some BSD tools.
-    - libc:
-        o Added fchmod and reimplemented chmod and lchmod. Still missing FS level
-          unix attribute handling, but this is a start.
-
-2005-04-25: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added the sysctl interface from BSD. Not all values are
-          supported, nor are we compatible with tcpip41 sysctl yet.
-
-2005-04-24: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed bug in getfsstate(). (df from coreutils works now!)
-        o Implemented process priority management. Added nice(), setpriority()
-          and getpriority() in the process.
-        o Added process enumeration and access function to sharedpm.
-
-2005-04-23: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - emxomf:
-        o Refined the 'G' hack fixing globals in the text segment.
-    - libc:
-        o Added cs:eip to the abnormal termination message. (signals.c)
-        o Default stack size 512KB when caller specifies 0. (beginthr.c)
-        o Use the env.var. LIBC_THREAD_MIN_STACK_SIZE value as a byte count
-          specifying the minimum stack size. When not specified minium size
-          defaults to 4096. (beginthr.c)
-        o Added the libsocket and libsyslog libraries to the libc IMPORT library.
-          There are now two sets of libc_dll.a/lib libraries, one for tcpipv4 and
-          one for tcpipv41+ (default).
-        o Added nanosleep() and changed usleep() and sleep() to use it.
-        o Added wmemcpy(), wmemset(), wmemcmp(), wmemchr() and wmemmove(). (untested)
-        o Added SUN/HP/RTLinux api gethrtime() as a wrapper around the DosTmr* apis.
-        o Rewrote atexit() fixing problem with the callbacks calling exit() recursivly
-          and adding on_exit().
-        o Added stdio_ext.h and implemented __fpending() and __fbufsize().
-          (Just to make coreutils easier to port.)
-
-2005-03-23: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - src/lib/sys/__spawnve.c:
-        o Fixed double free of pFS (should've been pSig).
-          Thanks for froloff.
-
-2005-03-19: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - 386/builtin.h:
-        o Fixed serveral bugs in the atomic inc/dec functions.
-          Added a testcase for these.
-    - libc:
-        o Fixed various typos in the socket per process counting. Thanks to
-          nickk for point these out.
-
-2005-03-13: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - version.smak:
-        o 6b4 -> 6b5.
-
-    - libc:
-        o Implemented socket duplication.
-        o Fixed various socket close & fork bugs.
-        o Applied parts of tcpipver patches from Lorne and Froloff.
-        o Fixed various UNC trouble reported by David.
-        o Fixed open problem in DosEx.
-        o Fixed incorrect pool allocation in DosEx.
-        o Fixed missing free pool item in DoxEx - *big* leak.
-        o Fixed TID/PID mixup when calling DosVerifyPidTid() from fmutex wait loop.
-        o Applied patch from Nickk for broken settimeofday().
-        o Moved iconv into LIBC.
-        o Ported GLIBC intl and made it a part of LIBC.
-        o Implemented -Zargs-wild and -Zargs-resp crt0 variations.
-        o Added support for single quoted arguments. (pray this doesn't screw up...)
-        o Replaced the __atod implementation with the NETLIB gdtoa implementation
-          used by BSD. (The old routine kept hitting assertions.)
-        o Created libc06a4 forwarder dll.
-
-    - libiconv, libdl, libm:
-        o Made these empty stub libraries.
-
-    - emxomf:
-        o Fixed getopt(,,"l::") problem. BSD getopt doesn't pass FLAG_PERMUTE for getopt and
-          thus it would consume the next argument unless it was an option. Using
-          getopt_long(,,"l::", NULL, NULL) solves the problem.
-
-    - testcases:
-        o Testcases for various new problems/code.
-
-2005-02-01: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed bogus bubble sort in setlocale/LC_COLLATE.
-
-2005-01-31: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Applied readdir_r() errno fix from Lorne.
-        o Fixed lstat() backend on request from Lorne.
-
-2005-01-30: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Applies setlocale patch from Lorne which fixes two bugs in LC_COLLATE.
-
-2005-01-28: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Applied setlocale patch from Lorne.
-        o Faked the C99 lconv additions by copying the local ones.
-
-2005-01-16: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libos2:
-        o Added SafeDosStartSession from Dmitry Froloff.
-    - libc:
-        o Fixed year problem in settimeofday.
-        o Check if fxsave/fxrstor is supported before using them in fork().
-          ASSUMES cpuid eax=1 works on all targets.
-        o Implemented nl_langinfo(CODESET).
-        o Added bunch a of ASCII codeset name conversions.
-        o Fixed bug in socket inherit over exec/spawn. Thanks to Froloff.
-        o Forgot to take the signal semaphore when receiving a signal
-          from the 16bit handler. Thanks to Froloff.
-        o rmdir errno fix from Lorne.
-        o rmdir shall fail on symlink.
-        o rmdir shall return ENOTDIR if the path isn't a directory (but exists).
-        o Fixed setlocale(LC_ALL/LC_MONETARY, "C").
-        o Changed the process reaper to use internal signal api to skip some overhead.
-        o Fixed a return path from signal raise where the signal sem wasn't
-          released. (The out of queue node hang.)
-    - libsocket:
-        o os2_select: Fixed a couple of filehandle conversion bugs. Thanks to Froloff.
-        o soclose shouldn't return EBADF but ENOSOCK according to the specs.
-    - libsocket, libc:
-        o Return ENOSOCK instead of ENOSYS when attempting socket operation on filehandle.
-
-
-2005-01-??: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Fixed problem with fork'ed children beliving they were
-          still forking after fork() returned. (DLL load issue)
-        o Fixed signal queue node leak. Thanks to Lorne.
-
-2004-12-20: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - libc:
-        o Added inode and dev calculation for fstat and stat.
-          TODO: save unix EAs. opendir d_fileno?
-        o Ported all string/w* functions from FreeBSD except wcsxfrm.c.
-
-2004-12-12: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - os2emx.h:
-        o Corrected define of NP_NBLK. (thanks to froloff)
-    - __mcount:
-        o Export stub in all builds but the profiling build.
-    - libdl:
-        o Removed and stubbed it (install). It's all in LIBC now.
-          TODO: make libm and libdl stubbing in LIBC!
-
-2004-12-09: knut st. osmundsen <bird-gccos2-spam@anduin.net>
-    - waitpid(), waitid(), wait(), wait4(), wait3(),
-      __libc_Back_processWait():
-        o Fixed missing WNOHANG handling.
-          Created waitpid-1.c testcase in testcase/misc for this problem.
-        o Clearified error codes ECHILD and EINVAL, use the waitpid() specs.
-
-    - ChangeLog.Libc:
-        o Created this file.
-
Index: /trunk/emx/ChangeLog.emx
===================================================================
--- /trunk/emx/ChangeLog.emx	(revision 2448)
+++ /trunk/emx/ChangeLog.emx	(revision 2448)
@@ -0,0 +1,79 @@
+/* $Id$ */
+
+TODO: open replace on RAMFS fails with error 32!
+
+2004-11-14: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - ChangeLog.emx:
+        o Renamed and cleaned out all the libc stuff.
+        o Reorganizing the repository.
+
+2005-11-12: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - emxomf:
+        o Fixed problems with symbol truncation.
+          Kudos to Yuri for tracking down the places which required attention.
+
+2005-08-28: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - version.smak:
+        o Changed version number back to 3.3.5 / 0.6 rc2.
+
+2005-08-21: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - emxbind, emxomfld:
+        o Default stack size set to 1MB.
+          The old defaults were 8MB (emxbind) and 8KB (emxomfld).
+
+2005-07-24: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - emximp:
+        o Fixed bad done string allocation.
+    - ld:
+        o Fixed a case of memory access after free.
+        o Switched back to alloca and adding 23 MB of stack.
+
+2005-07-17: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - version.smak:
+        o Changed version number back to 3.3.5 / 0.6 rc1.
+
+2005-06-27: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - emxomfld, ld:
+        o Generate .def-file for dlls without one. (This only makes sense for
+          emxomfld since ld doesn't implement __declspec(dllexport) yet, but
+          anyway.)
+    - emxomf, emxomfld:
+        o Kicked out all the old weak handling (from early 3.2.2 alphas).
+
+2005-06-05: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - libomflib, emxomfar:
+        o Allow multiple modules by the same basename. This is not in tradition with
+          other librarians, but it solves incompatible behaviour between emxomfar and ar.
+    - ld:
+        o Avoid using alloca since we might easily run out of stack for big objects
+          with debuginfo.
+    - emxomf:
+        o Added support for new EMX a.out stab N_EXP (0x6c). This encodes export
+          definitions. (gcc can do __declspec(dllexport) now.)
+          TODO: ld needs updating, probably this is the right time to drop the
+                old ld and fixup the binutils port!
+
+2005-04-30: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - libmoddef:
+        o Allow empty definition strings. (weakld failed on python _curses_m)
+    - weakld:
+        o Fixed incorrect .def-file parse error message.
+
+2005-04-23: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - emxomf:
+        o Refined the 'G' hack fixing globals in the text segment.
+
+2005-03-13: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - version.smak:
+        o 6b4 -> 6b5.
+
+    - emxomf:
+        o Fixed getopt(,,"l::") problem. BSD getopt doesn't pass FLAG_PERMUTE for getopt and
+          thus it would consume the next argument unless it was an option. Using
+          getopt_long(,,"l::", NULL, NULL) solves the problem.
+
+
+2004-12-09: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - ChangeLog.Libc:
+        o Created this file.
+
Index: /trunk/emx/src/misc/MakeOmfLibs.cmd
===================================================================
--- /trunk/emx/src/misc/MakeOmfLibs.cmd	(revision 2448)
+++ /trunk/emx/src/misc/MakeOmfLibs.cmd	(revision 2448)
@@ -0,0 +1,171 @@
+/* $Id: MakeOmfLibs.cmd,v 1.8 2004/11/17 08:08:03 bird Exp $
+ *
+ * Generates the OMF libraries.
+ *
+ * Copyright (c) 2003 InnoTek Systemberatung GmbH
+ * Author: knut st. osmundsen <bird@anduin.net>
+ *
+ *
+ * This file is part of GCC.
+ *
+ * GCC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GCC 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GCC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+    call hlpRexxUtilInit;
+    signal on novalue name NoValueHandler_label_doesnt_exist_btw;
+
+    /*
+     * Figure out the usr/lib directory location.
+     * Either as parameter or we assume this script is located there.
+     */
+    parse arg sDir sDummy;
+    if (sDir = '') then
+    do
+        parse source . . sSrc
+        sDir = filespec('drive', sSrc) || strip(filespec('path', sSrc), 'T', '\');
+    end
+
+    /*
+     * Setup the environment
+     */
+    Address CMD '@setlocal';
+    sEMXOMF = sDir'\..\bin\emxomf.exe -t';
+    sOldBeginLibPath = hlpEnvGet('BEGINLIBPATH');
+    call hlpEnvSet 'BEGINLIBPATH', sDir'..\lib;'sOldBeginLibPath
+    if (hlpEnvGet('GCC_WEAKSYMS') <> '') then
+        say 'warning: GCC_WEAKSYMS is set, sure you wanna use old weak handling?';
+
+    /*
+     * Do Da work.
+     */
+    call SysFileDelete sDir'\weaksyms.omf'; /* don't need this around! */
+    iRc = doDir(sDir, sEMXOMF' -s');
+    iRc2= doDir(sDir'\tcpipv4', sEMXOMF' -s');
+    if (iRc2 > iRc) then
+        iRc = iRc2;
+    iRc2= doDir(sDir'\dbg', sEMXOMF);
+    if (iRc2 > iRc) then
+        iRc = iRc2;
+    iRc2= doDir(sDir'\dbg\tcpipv4', sEMXOMF);
+    if (iRc2 > iRc) then
+        iRc = iRc2;
+    iRc2= doDir(sDir'\gcc-lib\i386-pc-os2-emx\3.3.5', sEMXOMF' -s');
+    if (iRc2 > iRc) then
+        iRc = iRc2;
+
+    /*
+     * restore environment
+     */
+    call hlpEnvSet 'BEGINLIBPATH', sOldBeginLibPath
+    Address CMD '@endlocal';
+
+    if (iRc <> 0) then
+        say 'warning: one or more operations failed, check the above output. :-)'.
+exit(iRc);
+
+/**
+ * Process a given directory.
+ */
+doDir: procedure
+parse arg sDir, sEMXOMF
+    say 'info: processing directory 'sDir'...';
+    iRc = 0;
+
+    /* Is libstdc++.a in this directory, if so, do it first. */
+    asLibs.0 = 0;
+    rc = SysFileTree(sDir'\libstdc++.a', 'asLibs', 'OF');
+    if (rc = 0 & asLibs.0 > 0) then
+    do
+        Address CMD sEMXOMF '-p128' asLibs.1;
+        if (rc <> 0 & rc > iRc) then
+            iRc = rc;
+    end
+
+    /* do all */
+    asLibs.0 = 0;
+    rc = SysFileTree(sDir'\*.a', 'asLibs', 'OF');
+    if (rc = 0) then
+    do
+        do i = 1 to asLibs.0
+            Address CMD sEMXOMF '-p128' asLibs.i;
+            if (rc <> 0 & rc > iRc) then
+                iRc = rc;
+        end
+    end
+    else
+    do
+        say 'error: SysFileTree failed. rc='rc;
+        iRc = 12;
+    end
+
+return iRc;
+
+/**
+ * Sets the value of sEnvVar to sValue.
+ * @returns Old value of sEnvVar.
+ * @returns '' if not found.
+ * @param   sEnvVar     Environment variable to set.
+ * @param   sValue      The new value.
+ */
+hlpEnvSet: procedure
+parse arg sEnvVar, sValue
+    parse upper source sRexxVer . .
+    if (sRexxVer = 'OS/2') then
+    do
+        if ((translate(sEnvVar) = 'BEGINLIBPATH') | (translate(sEnvVar) = 'ENDLIBPATH')) then
+            return SysSetExtLibPath(sValue, substr(sEnvVar, 1, 1));
+        if (length(sValue) >= 1024) then
+        do
+            say 'Warning: 'sEnvVar' is too long,' length(sValue)' char.';
+            say '    This may make CMD.EXE unstable after a SET operation to print the environment.';
+        end
+        sEnv = 'OS2ENVIRONMENT';
+    end
+    else
+        sEnv = 'ENVIRONMENT';
+return value(sEnvVar, sValue, sEnv);
+
+/**
+ * Gets the value of sEnvVar.
+ * @returns Value of sEnvVar if found.
+ * @returns '' if not found.
+ * @param   sEnvVar     Environment variable to get.
+ */
+hlpEnvGet: procedure
+parse arg sEnvVar
+    parse upper source sRexxVer . .
+    if (sRexxVer = 'OS/2') then
+    do
+        if ((translate(sEnvVar) = 'BEGINLIBPATH') | (translate(sEnvVar) = 'ENDLIBPATH')) then
+            return SysQueryExtLibPath(substr(sEnvVar, 1, 1));
+        sEnv = 'OS2ENVIRONMENT';
+    end
+    else
+        sEnv = 'ENVIRONMENT';
+return value(sEnvVar,, sEnv);
+
+/**
+ * Loads the RexxUtil dll.
+ */
+hlpRexxUtilInit: procedure
+    if (RxFuncQuery('SysLoadFuncs') = 1) then
+    do
+        call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs';
+        call SysLoadFuncs;
+    end
+return 0;
+
+
Index: /trunk/emx/src/misc/dllar.cmd
===================================================================
--- /trunk/emx/src/misc/dllar.cmd	(revision 2448)
+++ /trunk/emx/src/misc/dllar.cmd	(revision 2448)
@@ -0,0 +1,443 @@
+/* dllar - a tool to build both a .dll and an .a file
+ * from a set of object (.o) files for EMX/OS2.
+ *
+ * Written by Andrew Zabolotny, bit@freya.etu.ru
+ *
+ * This program will accept a set of files on the command line.
+ * All the public symbols from the .o files will be exported into
+ * a .DEF file, then linker will be run (through gcc) against them to
+ * build a shared library consisting of all given .o files. All libraries
+ * (.a) will be first decompressed into component .o files then act as
+ * described above. You can optionally give a description (-d "description")
+ * which will be put into .DLL. To see the list of accepted options (as well
+ * as command-line format) simply run this program without options. The .DLL
+ * is built to be imported by name (there is no guarantee that new versions
+ * of the library you build will have same ordinals for same symbols).
+ *
+ * dllar is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * dllar 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with dllar; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+/* To successfuly run this program you will need:
+ * - Current drive should have LFN support (HPFS, ext2, network, etc)
+ *   (Sometimes dllar generates filenames which won't fit 8.3 scheme)
+ * - gcc
+ *   (used to build the .dll)
+ * - emxexp
+ *   (used to create .def file from .o files)
+ * - emximp
+ *   (used to create .a file from .def file)
+ * - GNU text utilites (cat, sort, uniq)
+ *   used to process emxexp output
+ * - lxlite (optional, see flag below)
+ *   (used for general .dll cleanup)
+ */
+
+    flag_USE_LXLITE = 1;
+
+    /*
+     * Load REXX Util Functions.
+     */
+    if (RxFuncQuery('SysLoadFuncs') = 1) then
+    do
+        call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs';
+        call SysLoadFuncs;
+    end
+
+    /*
+     * Parse commandline / setup globals.
+     */
+    parse arg cmdLine;
+    cmdLine = cmdLine||" "||value('DLLAR_CMDLINE',,'OS2ENVIRONMENT');
+    outFile = '';
+    inputFiles.0 = 0;
+    description = '';
+    CC = 'gcc.exe';
+    CFLAGS = '-s -Zcrtdll';
+    EXTRA_CFLAGS = '';
+    EXPORT_BY_ORDINALS = 0;
+    exclude_symbols = '';
+    library_flags = '';
+    curDir = directory();
+    curDirS = curDir;
+    if (right(curDirS, 1) \= '\') then
+        curDirS = curDirS||'\';
+
+    do I = 1 to words(cmdLine)
+        tmp = word(cmdLine, I);
+        if left(tmp, 1) = '-' then
+        do
+            select
+            when abbrev('output', substr(tmp, 2), 1) then
+            do
+                i = i + 1;
+                outFile = word(cmdLine, i);
+            end;
+            when abbrev('description', substr(tmp, 2), 1) then
+                description = GetLongArg();
+            when abbrev('flags', substr(tmp, 2), 1) then
+                CFLAGS = GetLongArg();
+            when abbrev('cc', substr(tmp, 2), 1) then
+                CC = translate(GetLongArg(), '\', '/');
+            when abbrev('help', substr(tmp, 2), 1) then
+                call PrintHelp;
+            when abbrev('ordinals', substr(tmp, 2), 3) then
+                EXPORT_BY_ORDINALS = 1;
+            when abbrev('exclude', substr(tmp, 2), 2) then
+                exclude_symbols = exclude_symbols||GetLongArg()' ';
+            when abbrev('libflags', substr(tmp, 2), 4) then
+                library_flags = library_flags||GetLongArg()' ';
+            when abbrev('nocrtdll', substr(tmp, 2), 5) then
+                CFLAGS = '-s';
+            when abbrev('nolxlite', substr(tmp, 2), 5) then
+                flag_USE_LXLITE = 0;
+            otherwise
+                EXTRA_CFLAGS = EXTRA_CFLAGS' 'tmp;
+            end /*select*/
+        end
+        else
+        do
+            rc = SysFileTree(tmp, "files", "FO");
+            if (rc = 0) then
+            do J = 1 to files.0
+                inputFiles.0 = inputFiles.0 + 1;
+                K = inputFiles.0;
+                inputFiles.K = files.J;
+            end;
+            else
+                files.0 = 0;
+            if (files.0 = 0) then
+            do
+                say 'ERROR: No file(s) found: "'tmp'"';
+                exit 8;
+            end;
+            drop files.;
+        end;
+    end; /* iterate cmdline words */
+
+    /* check arg sanity */
+    if (inputFiles.0 = 0) then
+    do
+        say 'dllar: no input files'
+        call PrintHelp;
+    end;
+
+    /*
+     * Now extract all .o files from .a files
+     */
+    do I = 1 to inputFiles.0
+        if (right(inputFiles.I, 2) = '.a') then
+        do
+            fullname = inputFiles.I;
+            inputFiles.I = '$_'filespec('NAME', fullname);
+            inputFiles.I = left(inputFiles.I, length(inputFiles.I) - 2);
+            Address CMD '@mkdir 'inputFiles.I;
+            if (rc \= 0) then
+            do
+                say 'Failed to create subdirectory ./'inputFiles.I;
+                call CleanUp;
+                exit 8;
+            end;
+
+            /* Prefix with '!' to indicate archive */
+            inputFiles.I = '!'inputFiles.I;
+            call doCommand('cd 'substr(inputFiles.I, 2)' && ar x 'fullname);
+            call directory(curDir);
+            rc = SysFileTree(substr(inputFiles.I, 2)'\*.o', 'files', 'FO');
+            if (rc = 0) then
+            do
+                inputFiles.0 = inputFiles.0 + 1;
+                K = inputFiles.0;
+                inputFiles.K = substr(inputFiles.I, 2)'/*.o';
+                /* Remove all empty files from archive since emxexp will barf */
+                do J = 1 to files.0
+                    if (stream(files.J, 'C', 'QUERY SIZE') <= 32) then
+                        call SysFileDelete(files.J);
+                end;
+                drop files.;
+            end
+            else
+                say 'WARNING: there are no files in archive "'substr(inputFiles.I, 2)'"';
+        end;
+    end;
+
+    /*
+     * Now remove extra directory prefixes
+     */
+    do I = 1 to inputFiles.0
+        if (left(inputFiles.I, length(curDirS)) = curDirS) then
+            inputFiles.I = substr(inputFiles.I, length(curDirS) + 1);
+    end;
+
+    /*
+     * Output filename(s).
+     */
+    do_backup = 0;
+    if (outFile = '') then
+    do
+        do_backup = 1;
+        outFile = inputFiles.1;
+    end;
+
+    /* If its an archive, remove the '!' and the '$_' prefixes */
+    if (left(outFile, 3) = '!$_') then
+        outFile = substr(outFile, 4);
+    dotpos = lastpos('.', outFile);
+    if (dotpos > 0) then
+    do
+        ext = translate(substr(outFile, dotpos + 1));
+        if ((ext = 'DLL') | (ext = 'O') | (ext = 'A')) then
+            outFile = substr(outFile, 1, dotpos - 1);
+    end;
+
+    EXTRA_CFLAGS = substr(EXTRA_CFLAGS, 2);
+
+    defFile = outFile'.def';
+    dllFile = outFile'.dll';
+    arcFile = outFile'.a';
+
+    if (do_backup & stream(arcFile, 'C', 'query exists') \= '') then
+        call doCommand('ren 'arcFile' 'outFile'_s.a');
+
+    /*
+     * Extract public symbols from all the object files.
+     */
+    tmpdefFile = '$_'filespec('NAME', defFile);
+    call SysFileDelete(tmpdefFile);
+    do I = 1 to inputFiles.0
+        if (left(inputFiles.I, 1) \= '!') then
+            call doCommand('emxexp -u' inputFiles.I' >>'tmpdefFile);
+    end;
+
+    /*
+     * Create the def file.
+     */
+    call SysFileDelete(defFile);
+    call stream defFile, 'c', 'open write';
+    call lineOut defFile, 'LIBRARY 'filespec('NAME', outFile)' 'library_flags;
+    if (length(description) > 0) then
+        call lineOut defFile, 'DESCRIPTION "'description'"';
+    call lineOut defFile, 'EXPORTS';
+
+    queTmp = RxQueue('Create');
+    queOld = RxQueue('Set', queTmp);
+    call doCommand('cat 'tmpdefFile' | sort.exe | uniq.exe | rxqueue.exe' queTmp);
+
+    ordinal = 1;
+    do while queued() > 0
+        parse pull line;
+        if (length(line) > 0) & (word(line, 1) \= ';') & (export_ok(line)) then
+        do
+            if (EXPORT_BY_ORDINALS) then
+            do
+                iPos = pos(';', line);
+                if (iPos > 1) then
+                    line = strip(substr(line, 1, iPos - 1), 'T');
+                line = line||' @'||ordinal||' NONAME';
+                ordinal = ordinal + 1;
+            end;
+            call lineOut defFile, line;
+        end;
+    end;
+    call RxQueue 'Delete', RxQueue('Set', queOld);
+    call stream defFile, 'C', 'CLOSE';
+    call SysFileDelete(tmpdefFile);
+    drop line ordinal tmpdefFile;          /* try prevent running out of memory... */
+
+
+if 0 then
+do
+    /*
+     * Do linking, create implib, and apply lxlite.
+     *  We just apply long cmdline hack here to save us trouble with slashes and such.
+     *  The hack is to make a shell script for we execute using sh.exe. (.exe is of vital importance!)
+     *  OLD: call doCommand('gcc 'CFLAGS' -Zdll -o 'dllFile defFile||gccCmdl' 'EXTRA_CFLAGS);
+     */
+    sTmpFile = SysTempFileName('.\dllar-??.???');
+    call lineout sTmpFile, '#!/bin/sh'
+    call charout sTmpFile, CC CFLAGS' -Zdll -o 'translate(dllFile defFile, '/', '\');
+    do I = 1 to inputFiles.0
+        if (left(inputFiles.I, 1) \= '!') then
+            call charout sTmpFile, ' 'translate(inputFiles.I, '/', '\');;
+    end;
+    call lineout sTmpFile, ' 'EXTRA_CFLAGS
+    call stream dsTmpFile, 'c', 'close'
+    call doCommand 'sh.exe 'sTmpFile;
+    call SysFileDelete sTmpFile;
+    drop sTmpFile;
+end
+else
+do
+    /*
+     * Do linking, create implib, and apply lxlite.
+     */
+    gccCmdl = '';
+    do I = 1 to inputFiles.0
+        if (left(inputFiles.I, 1) \= '!') then
+            gccCmdl = gccCmdl' 'inputFiles.I;
+    end;
+    call doCommand(CC CFLAGS' -Zdll -o 'dllFile defFile||gccCmdl' 'EXTRA_CFLAGS);
+end
+
+    call doCommand('emximp -o 'arcFile defFile);
+    if (flag_USE_LXLITE) then
+    do
+        add_flags = '';
+        if (EXPORT_BY_ORDINALS) then
+            add_flags = '-ynd';
+        call doCommand('lxlite -cs -t: -mrn -mln 'add_flags' 'dllFile);
+    end;
+
+    /*
+     * Successful exit.
+     */
+    call CleanUp 1;
+exit 0;
+
+/**
+ * Print usage and exit script with rc=1.
+ */
+PrintHelp:
+ say 'Usage: dllar [-o[utput] output_file] [-d[escription] "dll descrption"]'
+ say '       [-cc "CC"] [-f[lags] "CFLAGS"] [-ord[inals]] -ex[clude] "symbol(s)"'
+ say '       [-libf[lags] "{INIT|TERM}{GLOBAL|INSTANCE}"] [-nocrt[dll]]'
+ say '       [*.o] [*.a]'
+ say '*> "output_file" should have no extension.'
+ say '   If it has the .o, .a or .dll extension, it is automatically removed.'
+ say '   The import library name is derived from this and is set to "name".a.'
+ say '*> "cc" is used to use another GCC executable.   (default: gcc.exe)'
+ say '*> "flags" should be any set of valid GCC flags. (default: -s -Zcrtdll)'
+ say '   These flags will be put at the start of GCC command line.'
+ say '*> -ord[inals] tells dllar to export entries by ordinals. Be careful.'
+ say '*> -ex[clude] defines symbols which will not be exported. You can define'
+ say '   multiple symbols, for example -ex "myfunc yourfunc _GLOBAL*".'
+ say '   If the last character of a symbol is "*", all symbols beginning'
+ say '   with the prefix before "*" will be exclude, (see _GLOBAL* above).'
+ say '*> -libf[lags] can be used to add INITGLOBAL/INITINSTANCE and/or'
+ say '   TERMGLOBAL/TERMINSTANCE flags to the dynamically-linked library.'
+ say '*> -nocrtdll switch will disable linking the library against emx''s'
+ say '   C runtime DLLs.'
+ say '*> All other switches (for example -L./ or -lmylib) will be passed'
+ say '   unchanged to GCC at the end of command line.'
+ say '*> If you create a DLL from a library and you do not specify -o,'
+ say '   the basename for DLL and import library will be set to library name,'
+ say '   the initial library will be renamed to 'name'_s.a (_s for static)'
+ say '   i.e. "dllar gcc.a" will create gcc.dll and gcc.a, and the initial'
+ say '   library will be renamed into gcc_s.a.'
+ say '--------'
+ say 'Example:'
+ say '   dllar -o gcc290.dll libgcc.a -d "GNU C runtime library" -ord'
+ say '    -ex "__main __ctordtor*" -libf "INITINSTANCE TERMINSTANCE"'
+ call CleanUp;
+exit 1;
+
+
+/**
+ * Get long arg i + 1 from cmdline taking quoting into account.
+ * @returns     Long argument.
+ * @Uses        i, cmdline
+ * @Modifies    i
+ */
+GetLongArg:
+    i = i + 1;
+    _tmp_ = word(cmdLine, i);
+    if (left(_tmp_, 1) = '"') | (left(_tmp_, 1) = "'") then
+    do
+        do while (i < words(cmdLine) & (length(_tmp_) <= 1 | right(_tmp_, 1) \= left(_tmp_, 1)))
+            i = i + 1;
+            if (_tmp_ = '') then
+                _tmp_ = word(cmdLine, i);
+            else
+                _tmp_ = _tmp_' 'word(cmdLine, i);
+        end;
+        if (right(_tmp_, 1) = left(_tmp_, 1)) then
+            _tmp_ = substr(_tmp_, 2, length(_tmp_) - 2);
+    end;
+return _tmp_;
+
+/**
+ * Checks if the export is ok or not.
+ * @returns 1 if ok.
+ * @returns 0 if not ok.
+ */
+export_ok: procedure expose exclude_symbols;
+    parse arg line;
+    cWords = words(exclude_symbols)
+    do i = 1 to cWords
+        noexport = '"'word(exclude_symbols, i);
+        if (right(noexport, 1) = '*') then
+            noexport = left(noexport, length(noexport) - 1)
+        else
+            noexport = noexport'"';
+        if (pos(noexport, line) > 0) then
+            return 0;
+    end;
+return 1;
+
+/**
+ * Execute a command.
+ * If exit code of the commnad <> 0 CleanUp() is called and we'll exit the script.
+ * @Uses    Whatever CleanUp() uses.
+ */
+doCommand: procedure expose inputFiles.
+    parse arg _cmd_;
+    say _cmd_;
+    if (length(_cmd_) > 1023) then
+    do
+        /* Trick: use a different shell to launch the command since CMD.EXE has a
+         *  1024 byte limit on the length of the command line ...
+         * Note that .exe is important!
+         */
+        say 'INFO: doCommand: applying commandlength hack, cmdlen:' length(_cmd_) '. (1)'
+        call value '__TMP__',_cmd_,'OS2ENVIRONMENT';
+        Address CMD 'sh.exe -c "$__TMP__"';
+        rcCmd = rc;
+        call value '__TMP__','','OS2ENVIRONMENT';
+    end
+    else
+    do
+        Address CMD '@'_cmd_;
+        rcCmd = rc;
+    end
+
+    if (rcCmd \= 0) then
+    do
+        say 'command failed, exit code='rcCmd;
+        call CleanUp;
+        exit rcCmd;
+    end;
+    drop _cmd_;                            /* prevent running out of memory... */
+return;
+
+/*
+ * Cleanup temporary files and output
+ * @Uses    inputFiles.
+ * @Uses    out
+ */
+CleanUp: procedure expose inputFiles. outFile
+    parse arg fSuccess
+    call directory(curDir);
+    do i = inputFiles.0 to 1 by -1
+        if (left(inputFiles.I, 1) = '!') then
+            Address CMD 'rm -rf' substr(inputFiles.I, 2);
+    end;
+
+    /*
+     * Kill result in case of failure as there is just to many stupid make/nmake
+     * things out there which doesn't do this.
+     */
+    if (fSuccess = '') then
+        Address CMD 'rm -f' outFile||'.a' outFile||'.def' outFile||'.dll'
+return;
Index: /trunk/emx/src/misc/gccenv.cmd
===================================================================
--- /trunk/emx/src/misc/gccenv.cmd	(revision 2448)
+++ /trunk/emx/src/misc/gccenv.cmd	(revision 2448)
@@ -0,0 +1,365 @@
+/* $Id$
+ *
+ * GCC environment script.
+ *
+ * Copyright (c) 2003 InnoTek Systemberatung GmbH
+ * Author: knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with This program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ * Typical init.
+ */
+signal on novalue name NoValueHandler
+if (RxFuncQuery('SysLoadFuncs') = 1) then
+do
+    call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs';
+    call SysLoadFuncs;
+end
+call FixCMDEnv
+
+/*
+ * Parse any args.
+ */
+parse arg sPath sLinker sDummy
+if (sPath = '') then
+do
+    /* Default is that this script resides in /usr/bin/. */
+    parse source . . sSrc
+    sPath = filespec('drive', sSrc)||strip(filespec('path', strip(filespec('path', sSrc), 'T', '\')), 'T', '\');
+end
+
+sLinker = translate(sLinker);
+if (sLinker <> '' & sLinker <> 'VAC308' & sLinker <> 'VAC365' & sLinker <> 'LINK386') then
+do
+    say 'Syntax error: Invalid linker '''sLinker''' specified.';
+    say ''
+    call Usage;
+    exit 8;
+end
+
+if (stream(sPath'\bin\gcc.exe', 'c', 'query exist') = '') then
+do
+    say 'Error: cannot find gcc.exe in '''sPath'\usr''!';
+    say ''
+    call Usage;
+    exit 8;
+end
+
+
+/*
+ * Do work.
+ */
+call GCC322plus sPath, 'gcc335', 0, sLinker;
+exit 0;
+
+
+/**
+ * Display usage info for script.
+ */
+Usage: procedure
+    say 'syntax: gccenv.cmd [gcc-usr-path [linker]]';
+    say ''
+    say '[gcc-usr-path] is the path to the /usr directory of the gcc distro.'
+    say 'If [gcc-usr-path] isn''t specified, the script assumes it''s located'
+    say 'in /usr/bin of the gcc distro and deducts the path based on that.'
+    say ''
+    say '[linker] is the EMXOMFLD_TYPE as described by emxomfld.exe usage. It''s'
+    say 'thus either LINK386, VAC308 or VAC365.'
+    say ''
+    say 'Copyright (c) 2003 InnoTek Systemberatung GmbH'
+    say ''
+return 0;
+
+
+
+/**
+ * Innotek GCC 3.2.x and higher - this environment is EMX RT free.
+ * @param   sPath       The path of the /usr directory in the GCC distro.
+ * @param   sToolId     Tool identificator. gcc335
+ * @param   fRM         If set we'll remove the environment setup.
+ *                      If clear we'll install it.
+ * @param   sLinker     Which linker to use. If blank use emxomfld default linker.
+ */
+GCC322plus: procedure
+    parse arg sPath, sToolId, fRM, sLinker
+
+    /*
+     * EMX/GCC main directory.
+     */
+
+    /* parse out the version / constants */
+    chMajor = '3';
+    chMinor = left(right(sToolId, 2), 1);
+    chRel   = right(sToolId, 1);
+    sVer    = chMajor'.'chMinor'.'chRel
+    sVerShrt= chMajor||chMinor||chRel;
+    sTrgt   = 'i386-pc-os2-emx'
+
+    sGCCBack    = translate(sPath, '\', '/');
+    sGCCForw    = translate(sPath, '/', '\');
+    call EnvSet      fRM, 'PATH_EMXPGCC',   sGCCBack;
+    call EnvSet      fRM, 'CCENV',          'EMX'
+    call EnvSet      fRM, 'BUILD_ENV',      'EMX'
+    call EnvSet      fRM, 'BUILD_PLATFORM', 'OS2'
+
+    call EnvAddFront fRM, 'BEGINLIBPATH',       sGCCBack'\'sTrgt'\lib;'sGCCBack'\lib;'
+    call EnvAddFront fRM, 'DPATH',              sGCCBack'\lib;'
+    /*call EnvAddFront fRM, 'HELP',               sGCCBack'\lib;'*/
+    call EnvAddFront fRM, 'PATH',               sGCCBack'\'sTrgt'\bin;'sGCCBack'\bin;'
+    /*call EnvAddFront fRM, 'DPATH',              sGCCBack'\book;'
+    call EnvAddFront fRM, 'BOOKSHELF',          sGCCBack'\book;'
+    call EnvAddFront fRM, 'HELP',               sGCCBack'\help;' */
+    call EnvAddFront fRM, 'C_INCLUDE_PATH',     sGCCForw'/include;'
+    call EnvAddFront fRM, 'C_INCLUDE_PATH',     sGCCForw'/lib/gcc-lib/'sTrgt'/'sVer'/include;'
+    call EnvAddFront fRM, 'C_INCLUDE_PATH',     sGCCForw'/lib/gcc-lib/'sTrgt'/'sVer'/include;'
+    call EnvAddFront fRM, 'CPLUS_INCLUDE_PATH', sGCCForw'/include;'
+    call EnvAddFront fRM, 'CPLUS_INCLUDE_PATH', sGCCForw'/include/c++/'sVer'/backward;'
+    call EnvAddFront fRM, 'CPLUS_INCLUDE_PATH', sGCCForw'/include/c++/'sVer'/'sTrgt';'
+    call EnvAddFront fRM, 'CPLUS_INCLUDE_PATH', sGCCForw'/include/c++/'sVer'/;'
+    call EnvAddFront fRM, 'LIBRARY_PATH',       sGCCForw'/lib'
+    call EnvAddFront fRM, 'LIBRARY_PATH',       sGCCForw'/lib/gcc-lib/'sTrgt'/'sVer';'
+    call EnvAddFront fRM, 'INFOPATH',           sGCCForw'/info'
+    /* is this used? */
+    call EnvSet      fRM, 'PROTODIR',           sGCCForw'/include/c++/gen'
+
+    /* use link386? */
+    if (sLinker = 'LINK386') then
+    do
+        call EnvSet  fRM, 'EMXOMFLD_TYPE',      'LINK386';
+        call EnvSet  fRM, 'EMXOMFLD_LINKER',    'link386.exe';
+    end
+
+    /* use vac308? */
+    if (sLinker = 'VAC308') then
+    do
+        call EnvSet  fRM, 'EMXOMFLD_TYPE',      'VAC308';
+        call EnvSet  fRM, 'EMXOMFLD_LINKER',    'ilink.exe';
+    end
+
+    /* use default or VAC365? */
+    if (sLinker = '' | sLinker = 'VAC365') then
+    do
+        call EnvSet  1, 'EMXOMFLD_TYPE';
+        call EnvSet  1, 'EMXOMFLD_LINKER';
+    end
+
+return 0;
+
+
+
+/**
+ * Add sToAdd in front of sEnvVar.
+ * Note: sToAdd now is allowed to be alist!
+ *
+ * Known features: Don't remove sToAdd from original value if sToAdd
+ *                 is at the end and don't end with a ';'.
+ */
+EnvAddFront: procedure
+    parse arg fRM, sEnvVar, sToAdd, sSeparator
+
+    /* sets default separator if not specified. */
+    if (sSeparator = '') then sSeparator = ';';
+
+    /* checks that sToAdd ends with an ';'. Adds one if not. */
+    if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then
+        sToAdd = sToAdd || sSeparator;
+
+    /* check and evt. remove ';' at start of sToAdd */
+    if (substr(sToAdd, 1, 1) = ';') then
+        sToAdd = substr(sToAdd, 2);
+
+    /* loop thru sToAdd */
+    rc = 0;
+    i = length(sToAdd);
+    do while i > 1 & rc = 0
+        j = lastpos(sSeparator, sToAdd, i-1);
+        rc = EnvAddFront2(fRM, sEnvVar, substr(sToAdd, j+1, i - j), sSeparator);
+        i = j;
+    end
+
+return rc;
+
+/**
+ * Add sToAdd in front of sEnvVar.
+ *
+ * Known features: Don't remove sToAdd from original value if sToAdd
+ *                 is at the end and don't end with a ';'.
+ */
+EnvAddFront2: procedure
+    parse arg fRM, sEnvVar, sToAdd, sSeparator
+
+    /* sets default separator if not specified. */
+    if (sSeparator = '') then sSeparator = ';';
+
+    /* checks that sToAdd ends with a separator. Adds one if not. */
+    if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then
+        sToAdd = sToAdd || sSeparator;
+
+    /* check and evt. remove the separator at start of sToAdd */
+    if (substr(sToAdd, 1, 1) = sSeparator) then
+        sToAdd = substr(sToAdd, 2);
+
+    /* Get original variable value */
+    sOrgEnvVar = EnvGet(sEnvVar);
+
+    /* Remove previously sToAdd if exists. (Changing sOrgEnvVar). */
+    i = pos(translate(sToAdd), translate(sOrgEnvVar));
+    if (i > 0) then
+        sOrgEnvVar = substr(sOrgEnvVar, 1, i-1) || substr(sOrgEnvVar, i + length(sToAdd));
+
+    /* set environment */
+    if (fRM) then
+        return EnvSet(0, sEnvVar, sOrgEnvVar);
+return EnvSet(0, sEnvVar, sToAdd||sOrgEnvVar);
+
+
+/**
+ * Add sToAdd as the end of sEnvVar.
+ * Note: sToAdd now is allowed to be alist!
+ *
+ * Known features: Don't remove sToAdd from original value if sToAdd
+ *                 is at the end and don't end with a ';'.
+ */
+EnvAddEnd: procedure
+    parse arg fRM, sEnvVar, sToAdd, sSeparator
+
+    /* sets default separator if not specified. */
+    if (sSeparator = '') then sSeparator = ';';
+
+    /* checks that sToAdd ends with a separator. Adds one if not. */
+    if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then
+        sToAdd = sToAdd || sSeparator;
+
+    /* check and evt. remove ';' at start of sToAdd */
+    if (substr(sToAdd, 1, 1) = sSeparator) then
+        sToAdd = substr(sToAdd, 2);
+
+    /* loop thru sToAdd */
+    rc = 0;
+    i = length(sToAdd);
+    do while i > 1 & rc = 0
+        j = lastpos(sSeparator, sToAdd, i-1);
+        rc = EnvAddEnd2(fRM, sEnvVar, substr(sToAdd, j+1, i - j), sSeparator);
+        i = j;
+    end
+
+return rc;
+
+/**
+ * Add sToAdd as the end of sEnvVar.
+ *
+ * Known features: Don't remove sToAdd from original value if sToAdd
+ *                 is at the end and don't end with a ';'.
+ */
+EnvAddEnd2: procedure
+    parse arg fRM, sEnvVar, sToAdd, sSeparator
+
+    /* sets default separator if not specified. */
+    if (sSeparator = '') then sSeparator = ';';
+
+    /* checks that sToAdd ends with a separator. Adds one if not. */
+    if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then
+        sToAdd = sToAdd || sSeparator;
+
+    /* check and evt. remove separator at start of sToAdd */
+    if (substr(sToAdd, 1, 1) = sSeparator) then
+        sToAdd = substr(sToAdd, 2);
+
+    /* Get original variable value */
+    sOrgEnvVar = EnvGet(sEnvVar);
+
+    if (sOrgEnvVar <> '') then
+    do
+        /* Remove previously sToAdd if exists. (Changing sOrgEnvVar). */
+        i = pos(translate(sToAdd), translate(sOrgEnvVar));
+        if (i > 0) then
+            sOrgEnvVar = substr(sOrgEnvVar, 1, i-1) || substr(sOrgEnvVar, i + length(sToAdd));
+
+        /* checks that sOrgEnvVar ends with a separator. Adds one if not. */
+        if (sOrgEnvVar = '') then
+            if (right(sOrgEnvVar,1) <> sSeparator) then
+                sOrgEnvVar = sOrgEnvVar || sSeparator;
+    end
+
+    /* set environment */
+    if (fRM) then return EnvSet(0, sEnvVar, sOrgEnvVar);
+return EnvSet(0, sEnvVar, sOrgEnvVar||sToAdd);
+
+
+/**
+ * Sets sEnvVar to sValue.
+ */
+EnvSet: procedure
+    parse arg fRM, sEnvVar, sValue
+
+    /* if we're to remove this, make valuestring empty! */
+    if (fRM) then
+        sValue = '';
+    sEnvVar = translate(sEnvVar);
+
+    /*
+     * Begin/EndLibpath fix:
+     *      We'll have to set internal these using both commandline 'SET'
+     *      and internal VALUE in order to export it and to be able to
+     *      get it (with EnvGet) again.
+     */
+    if ((sEnvVar = 'BEGINLIBPATH') | (sEnvVar = 'ENDLIBPATH')) then
+    do
+        if (length(sValue) >= 1024) then
+            say 'Warning: 'sEnvVar' is too long,' length(sValue)' char.';
+        return SysSetExtLibPath(sValue, substr(sEnvVar, 1, 1));
+    end
+
+    if (length(sValue) >= 1024) then
+    do
+        say 'Warning: 'sEnvVar' is too long,' length(sValue)' char.';
+        say '    This may make CMD.EXE unstable after a SET operation to print the environment.';
+    end
+    sRc = VALUE(sEnvVar, sValue, 'OS2ENVIRONMENT');
+return 0;
+
+/**
+ * Gets the value of sEnvVar.
+ */
+EnvGet: procedure
+    parse arg sEnvVar
+    if ((translate(sEnvVar) = 'BEGINLIBPATH') | (translate(sEnvVar) = 'ENDLIBPATH')) then
+        return SysQueryExtLibPath(substr(sEnvVar, 1, 1));
+return value(sEnvVar,, 'OS2ENVIRONMENT');
+
+
+/**
+ *  Workaround for bug in CMD.EXE.
+ *  It messes up when REXX have expanded the environment.
+ */
+FixCMDEnv: procedure
+    /* check for 4OS2 first */
+    Address CMD '@set 4os2test_env=%@eval[2 + 2]';
+    if (value('4os2test_env',, 'OS2ENVIRONMENT') = '4') then
+        return 0;
+
+    /* force environment expansion by setting a lot of variables and freeing them. */
+    do i = 1 to 100
+        Address CMD '@set dummyenvvar'||i'=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    end
+    do i = 1 to 100
+        Address CMD '@set dummyenvvar'||i'=';
+    end
+return 0;
+
Index: /trunk/emx/src/misc/misc.smak
===================================================================
--- /trunk/emx/src/misc/misc.smak	(revision 2448)
+++ /trunk/emx/src/misc/misc.smak	(revision 2448)
@@ -0,0 +1,17 @@
+.MODULE := misc
+.MDESC  := Various scripts and other oddments.
+.INSDIR := bin/
+
+INS.FILES += $(INS)$(.INSDIR)dllar.cmd
+$(INS)$(.INSDIR)dllar.cmd: src/misc/dllar.cmd
+	$(call CP,$^,$@)
+	
+INS.FILES += $(INS)$(.INSDIR)gccenv.cmd
+$(INS)$(.INSDIR)gccenv.cmd: src/misc/gccenv.cmd
+	$(call CP,$^,$@)
+
+INS.FILES += $(INS)$(.INSDIR)MakeOmfLibs.cmd
+$(INS)$(.INSDIR)MakeOmfLibs.cmd: src/misc/MakeOmfLibs.cmd
+	$(call CP,$^,$@)
+
+include comend.smak
Index: /trunk/gcc/gcc/config/i386/emx-libgcc_so_d.def
===================================================================
--- /trunk/gcc/gcc/config/i386/emx-libgcc_so_d.def	(revision 2447)
+++ /trunk/gcc/gcc/config/i386/emx-libgcc_so_d.def	(revision 2448)
@@ -1,4 +1,4 @@
 ; Auto-generated file, DO NOT EDIT!!! (see libgcc_d.awk) */
-LIBRARY libc06b5 INITINSTANCE TERMINSTANCE
+LIBRARY libc06r2 INITINSTANCE TERMINSTANCE
 EXPORTS
 EXPORTS
Index: /trunk/gcc/gcc/version.c
===================================================================
--- /trunk/gcc/gcc/version.c	(revision 2447)
+++ /trunk/gcc/gcc/version.c	(revision 2448)
@@ -7,5 +7,5 @@
    organization's name in parentheses at the end of the string.  */
 
-const char version_string[] = "3.3.5 (Innotek Build 2005-11-15 02:02)";
+const char version_string[] = "3.3.5 (Innotek Build 2005-11-15 03:52)";
 
 /* This is the location of the online document giving instructions for
Index: /trunk/libc/Makefile.gmk
===================================================================
--- /trunk/libc/Makefile.gmk	(revision 2447)
+++ /trunk/libc/Makefile.gmk	(revision 2448)
@@ -85,9 +85,4 @@
 A = .$(if $(findstring omf,$(.TKIND)),lib,a)
 
-# Use the tool we built.
-GETTOOL ?= $.$(TOOLFMT)/$1$E
-# Use the tool we built if present
-GETTOOL2 ?= `test -f '$.$(TOOLFMT)/$1$E' && echo '$.$(TOOLFMT)/'`$1$E
-
 # The C compiler
 CC = gcc -c -Zmt -fmessage-length=0
@@ -97,5 +92,5 @@
 endif
 CFLAGS.INC  += -Isrc/include
-CFLAGS.INC  += -Isrc/libc/bsd/include
+CFLAGS.INC  += -Isrc/fbsdlibc/include
 CFLAGS      = -Wall -Wundef -Wmissing-prototypes -mstack-arg-probe $(CFLAGS.INC) $(CFLAGS.$(MODE)) $(CFLAGS.KIND)
 # The additional C compiler flags for different build modes
@@ -152,5 +147,5 @@
 
 # emxbind tool
-EMXBIND = $(call GETTOOL2,emxbind)
+EMXBIND = emxbind
 # emxbind flags
 EMXBINDFLAGS = -bq $(EMXBINDFLAGS.$(MODE))
@@ -172,5 +167,5 @@
 
 # The tool to create an archive
-AR = $(if $(findstring .lib,$@), $(call GETTOOL2,emxomfar),ar)
+AR = $(if $(findstring .lib,$@), emxomfar,ar)
 ARFLAGS = crs
 DO.LIBRARY = $(call RM,$@); $(AR) $(ARFLAGS)$1 $@ $(^O)
@@ -179,10 +174,10 @@
 # removing unused stuff (like empty lines and comments)
 # and sorting alphabetically (looks nicer).
-EMXEXP = $(call GETTOOL2,emxexp)
+EMXEXP = emxexp
 EMXEXPFLAGS = -u
 DO.EMXEXP = $(EMXEXP) $(strip $(EMXEXPFLAGS) $1) | sed -e "/^$$/d" -e "/^ *;/d" | sort -d >>$2
 
 # The tool to create import libraries
-IMPLIB = $(call GETTOOL2,emximp)
+IMPLIB = emximp
 IMPLIBFLAGS.prof = -m
 IMPLIBFLAGS.lazy = -l
@@ -208,5 +203,5 @@
 #   or not. Unfortunately make isn't up to the job of figuring this out, so we
 #	must use the shell.
-EMXOMF = $(call GETTOOL2,emxomf)
+EMXOMF = emxomf
 DO.EMXOMF = $(EMXOMF) $(strip $1 -o) $@ $(if $<,$<, $(subst /omf-prof/,/aout-prof/,$(subst /omf-log/,/aout-log/,$(subst /omf/,/aout/,$(@:.obj=.o)))) )
 
@@ -294,5 +289,5 @@
 #------------ Submakefiles ------------
 ifndef SUBMAK
-SUBMAK := version.smak $(wildcard src/*/*.smak) include/include.smak $(wildcard bsd/*/*.smak) $(wildcard gnu/*/*.smak)
+SUBMAK := version.smak $(filter-out $(wildcard src/msun/*.smak),$(wildcard src/*/*.smak)) include/include.smak $(wildcard bsd/*/*.smak) $(wildcard gnu/*/*.smak)
 endif
 
Index: /trunk/libc/src/fbsdlibc/db/Makefile.inc
===================================================================
--- /trunk/libc/src/fbsdlibc/db/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/Makefile.inc	(revision 2448)
@@ -0,0 +1,11 @@
+#	from @(#)Makefile.inc	8.2 (Berkeley) 2/21/94
+# $FreeBSD: src/lib/libc/db/Makefile.inc,v 1.4 2002/11/18 09:50:54 ru Exp $
+#
+CFLAGS+=-D__DBINTERFACE_PRIVATE
+
+.include "${.CURDIR}/db/btree/Makefile.inc"
+.include "${.CURDIR}/db/db/Makefile.inc"
+.include "${.CURDIR}/db/hash/Makefile.inc"
+.include "${.CURDIR}/db/man/Makefile.inc"
+.include "${.CURDIR}/db/mpool/Makefile.inc"
+.include "${.CURDIR}/db/recno/Makefile.inc"
Index: /trunk/libc/src/fbsdlibc/db/README
===================================================================
--- /trunk/libc/src/fbsdlibc/db/README	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/README	(revision 2448)
@@ -0,0 +1,40 @@
+#	@(#)README	8.27 (Berkeley) 9/1/94
+
+This is version 1.85 of the Berkeley DB code.
+
+For information on compiling and installing this software, see the file
+PORT/README.
+
+Newer versions of this software will periodically be made available by
+anonymous ftp from ftp.cs.berkeley.edu.  An archive in compressed format
+is in ucb/4bsd/db.tar.Z, or in gzip format in ucb/4bsd/db.tar.gz.  If
+you'd like to receive announcements of future releases of this software,
+send email to the contact address below.
+
+Email questions may be addressed to Keith Bostic at bostic@cs.berkeley.edu.
+
+============================================
+Distribution contents:
+
+Makefile.inc	Ignore this, it's the 4.4BSD subsystem Makefile.
+PORT		The per OS/architecture directories to use to build
+		libdb.a, if you're not running 4.4BSD.  See the file
+		PORT/README for more information.
+README		This file.
+btree		The B+tree routines.
+changelog	List of changes, per version.
+db		The dbopen(3) interface routine.
+docs		Various USENIX papers, and the formatted manual pages.
+hash		The extended linear hashing routines.
+man		The unformatted manual pages.
+mpool		The memory pool routines.
+recno		The fixed/variable length record routines.
+test		Test package.
+
+============================================
+Debugging:
+
+If you're running a memory checker (e.g. Purify) on DB, make sure that
+you recompile it with "-DPURIFY" in the CFLAGS, first.  By default,
+allocated pages are not initialized by the DB code, and they will show
+up as reads of uninitialized memory in the buffer write routines.
Index: /trunk/libc/src/fbsdlibc/db/btree/Makefile.inc
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/Makefile.inc	(revision 2448)
@@ -0,0 +1,8 @@
+#	from @(#)Makefile.inc	8.2 (Berkeley) 7/14/94
+# $FreeBSD: src/lib/libc/db/btree/Makefile.inc,v 1.4 2002/11/18 09:50:54 ru Exp $
+
+.PATH: ${.CURDIR}/db/btree
+
+SRCS+=	bt_close.c bt_conv.c bt_debug.c bt_delete.c bt_get.c bt_open.c \
+	bt_overflow.c bt_page.c bt_put.c bt_search.c bt_seq.c bt_split.c \
+	bt_utils.c
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_close.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_close.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_close.c	(revision 2448)
@@ -0,0 +1,204 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_close.c	8.7 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_close.c,v 1.8 2002/03/22 21:52:00 obrien Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "btree.h"
+
+static int bt_meta(BTREE *);
+
+/*
+ * BT_CLOSE -- Close a btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_close(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	int fd;
+#ifdef __EMX__
+	char *tempname;
+	int r;
+#endif /* __EMX__ */
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Sync the tree. */
+	if (__bt_sync(dbp, 0) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Close the memory pool. */
+	if (mpool_close(t->bt_mp) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Free random memory. */
+	if (t->bt_cursor.key.data != NULL) {
+		free(t->bt_cursor.key.data);
+		t->bt_cursor.key.size = 0;
+		t->bt_cursor.key.data = NULL;
+	}
+	if (t->bt_rkey.data) {
+		free(t->bt_rkey.data);
+		t->bt_rkey.size = 0;
+		t->bt_rkey.data = NULL;
+	}
+	if (t->bt_rdata.data) {
+		free(t->bt_rdata.data);
+		t->bt_rdata.size = 0;
+		t->bt_rdata.data = NULL;
+	}
+
+	fd = t->bt_fd;
+#ifdef __EMX__
+	tempname = t->tempname;
+	free(t);
+	free(dbp);
+	r = _close(fd) ? RET_ERROR : RET_SUCCESS;
+	if (tempname != NULL) {
+		int e = errno;
+		(void)unlink (tempname);
+		free (tempname);
+		errno = e;
+	}
+	return r;
+#else /* not __EMX__ */
+	free(t);
+	free(dbp);
+	return (_close(fd) ? RET_ERROR : RET_SUCCESS);
+#endif
+}
+
+/*
+ * BT_SYNC -- sync the btree to disk.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_sync(dbp, flags)
+	const DB *dbp;
+	u_int flags;
+{
+	BTREE *t;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Sync doesn't currently take any flags. */
+	if (flags != 0) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED))
+		return (RET_SUCCESS);
+
+	if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
+		return (RET_ERROR);
+
+	if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
+		F_CLR(t, B_MODIFIED);
+
+	return (status);
+}
+
+/*
+ * BT_META -- write the tree meta data to disk.
+ *
+ * Parameters:
+ *	t:	tree
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_meta(t)
+	BTREE *t;
+{
+	BTMETA m;
+	void *p;
+
+	if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
+		return (RET_ERROR);
+
+	/* Fill in metadata. */
+	m.magic = BTREEMAGIC;
+	m.version = BTREEVERSION;
+	m.psize = t->bt_psize;
+	m.free = t->bt_free;
+	m.nrecs = t->bt_nrecs;
+	m.flags = F_ISSET(t, SAVEMETA);
+
+	memmove(p, &m, sizeof(BTMETA));
+	mpool_put(t->bt_mp, p, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_conv.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_conv.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_conv.c	(revision 2448)
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_conv.c	8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_conv.c,v 1.2 2002/03/21 22:46:25 obrien Exp $");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+static void mswap(PAGE *);
+
+/*
+ * __BT_BPGIN, __BT_BPGOUT --
+ *	Convert host-specific number layout to/from the host-independent
+ *	format stored on disk.
+ *
+ * Parameters:
+ *	t:	tree
+ *	pg:	page number
+ *	h:	page to convert
+ */
+void
+__bt_pgin(t, pg, pp)
+	void *t;
+	pgno_t pg;
+	void *pp;
+{
+	PAGE *h;
+	indx_t i, top;
+	u_char flags;
+	char *p;
+
+	if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+		return;
+	if (pg == P_META) {
+		mswap(pp);
+		return;
+	}
+
+	h = pp;
+	M_32_SWAP(h->pgno);
+	M_32_SWAP(h->prevpg);
+	M_32_SWAP(h->nextpg);
+	M_32_SWAP(h->flags);
+	M_16_SWAP(h->lower);
+	M_16_SWAP(h->upper);
+
+	top = NEXTINDEX(h);
+	if ((h->flags & P_TYPE) == P_BINTERNAL)
+		for (i = 0; i < top; i++) {
+			M_16_SWAP(h->linp[i]);
+			p = (char *)GETBINTERNAL(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(pgno_t);
+			if (*(u_char *)p & P_BIGKEY) {
+				p += sizeof(u_char);
+				P_32_SWAP(p);
+				p += sizeof(pgno_t);
+				P_32_SWAP(p);
+			}
+		}
+	else if ((h->flags & P_TYPE) == P_BLEAF)
+		for (i = 0; i < top; i++) {
+			M_16_SWAP(h->linp[i]);
+			p = (char *)GETBLEAF(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			flags = *(u_char *)p;
+			if (flags & (P_BIGKEY | P_BIGDATA)) {
+				p += sizeof(u_char);
+				if (flags & P_BIGKEY) {
+					P_32_SWAP(p);
+					p += sizeof(pgno_t);
+					P_32_SWAP(p);
+				}
+				if (flags & P_BIGDATA) {
+					p += sizeof(u_int32_t);
+					P_32_SWAP(p);
+					p += sizeof(pgno_t);
+					P_32_SWAP(p);
+				}
+			}
+		}
+}
+
+void
+__bt_pgout(t, pg, pp)
+	void *t;
+	pgno_t pg;
+	void *pp;
+{
+	PAGE *h;
+	indx_t i, top;
+	u_char flags;
+	char *p;
+
+	if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+		return;
+	if (pg == P_META) {
+		mswap(pp);
+		return;
+	}
+
+	h = pp;
+	top = NEXTINDEX(h);
+	if ((h->flags & P_TYPE) == P_BINTERNAL)
+		for (i = 0; i < top; i++) {
+			p = (char *)GETBINTERNAL(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(pgno_t);
+			if (*(u_char *)p & P_BIGKEY) {
+				p += sizeof(u_char);
+				P_32_SWAP(p);
+				p += sizeof(pgno_t);
+				P_32_SWAP(p);
+			}
+			M_16_SWAP(h->linp[i]);
+		}
+	else if ((h->flags & P_TYPE) == P_BLEAF)
+		for (i = 0; i < top; i++) {
+			p = (char *)GETBLEAF(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			flags = *(u_char *)p;
+			if (flags & (P_BIGKEY | P_BIGDATA)) {
+				p += sizeof(u_char);
+				if (flags & P_BIGKEY) {
+					P_32_SWAP(p);
+					p += sizeof(pgno_t);
+					P_32_SWAP(p);
+				}
+				if (flags & P_BIGDATA) {
+					p += sizeof(u_int32_t);
+					P_32_SWAP(p);
+					p += sizeof(pgno_t);
+					P_32_SWAP(p);
+				}
+			}
+			M_16_SWAP(h->linp[i]);
+		}
+
+	M_32_SWAP(h->pgno);
+	M_32_SWAP(h->prevpg);
+	M_32_SWAP(h->nextpg);
+	M_32_SWAP(h->flags);
+	M_16_SWAP(h->lower);
+	M_16_SWAP(h->upper);
+}
+
+/*
+ * MSWAP -- Actually swap the bytes on the meta page.
+ *
+ * Parameters:
+ *	p:	page to convert
+ */
+static void
+mswap(pg)
+	PAGE *pg;
+{
+	char *p;
+
+	p = (char *)pg;
+	P_32_SWAP(p);		/* magic */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* version */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* psize */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* free */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* nrecs */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* flags */
+	p += sizeof(u_int32_t);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_debug.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_debug.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_debug.c	(revision 2448)
@@ -0,0 +1,332 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_debug.c	8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_debug.c,v 1.2 2002/03/22 21:52:01 obrien Exp $");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+#if defined(DEBUG) || defined __EMX__
+/*
+ * BT_DUMP -- Dump the tree
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB
+ */
+void
+__bt_dump(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	PAGE *h;
+	pgno_t i;
+	char *sep;
+
+	t = dbp->internal;
+	(void)fprintf(stderr, "%s: pgsz %d",
+	    F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
+	if (F_ISSET(t, R_RECNO))
+		(void)fprintf(stderr, " keys %lu", t->bt_nrecs);
+#undef X
+#define	X(flag, name) \
+	if (F_ISSET(t, flag)) { \
+		(void)fprintf(stderr, "%s%s", sep, name); \
+		sep = ", "; \
+	}
+	if (t->flags != 0) {
+		sep = " flags (";
+		X(R_FIXLEN,	"FIXLEN");
+		X(B_INMEM,	"INMEM");
+		X(B_NODUPS,	"NODUPS");
+		X(B_RDONLY,	"RDONLY");
+		X(R_RECNO,	"RECNO");
+		X(B_METADIRTY,"METADIRTY");
+		(void)fprintf(stderr, ")\n");
+	}
+#undef X
+
+	for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
+		__bt_dpage(h);
+		(void)mpool_put(t->bt_mp, h, 0);
+	}
+}
+
+/*
+ * BT_DMPAGE -- Dump the meta page
+ *
+ * Parameters:
+ *	h:	pointer to the PAGE
+ */
+void
+__bt_dmpage(h)
+	PAGE *h;
+{
+	BTMETA *m;
+	char *sep;
+
+	m = (BTMETA *)h;
+	(void)fprintf(stderr, "magic %lx\n", m->magic);
+	(void)fprintf(stderr, "version %lu\n", m->version);
+	(void)fprintf(stderr, "psize %lu\n", m->psize);
+	(void)fprintf(stderr, "free %lu\n", m->free);
+	(void)fprintf(stderr, "nrecs %lu\n", m->nrecs);
+	(void)fprintf(stderr, "flags %lu", m->flags);
+#undef X
+#define	X(flag, name) \
+	if (m->flags & flag) { \
+		(void)fprintf(stderr, "%s%s", sep, name); \
+		sep = ", "; \
+	}
+	if (m->flags) {
+		sep = " (";
+		X(B_NODUPS,	"NODUPS");
+		X(R_RECNO,	"RECNO");
+		(void)fprintf(stderr, ")");
+	}
+}
+
+/*
+ * BT_DNPAGE -- Dump the page
+ *
+ * Parameters:
+ *	n:	page number to dump.
+ */
+void
+__bt_dnpage(dbp, pgno)
+	DB *dbp;
+	pgno_t pgno;
+{
+	BTREE *t;
+	PAGE *h;
+
+	t = dbp->internal;
+	if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) {
+		__bt_dpage(h);
+		(void)mpool_put(t->bt_mp, h, 0);
+	}
+}
+
+/*
+ * BT_DPAGE -- Dump the page
+ *
+ * Parameters:
+ *	h:	pointer to the PAGE
+ */
+void
+__bt_dpage(h)
+	PAGE *h;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	RINTERNAL *ri;
+	RLEAF *rl;
+	indx_t cur, top;
+	char *sep;
+
+	(void)fprintf(stderr, "    page %d: (", h->pgno);
+#undef X
+#define	X(flag, name) \
+	if (h->flags & flag) { \
+		(void)fprintf(stderr, "%s%s", sep, name); \
+		sep = ", "; \
+	}
+	sep = "";
+	X(P_BINTERNAL,	"BINTERNAL")		/* types */
+	X(P_BLEAF,	"BLEAF")
+	X(P_RINTERNAL,	"RINTERNAL")		/* types */
+	X(P_RLEAF,	"RLEAF")
+	X(P_OVERFLOW,	"OVERFLOW")
+	X(P_PRESERVE,	"PRESERVE");
+	(void)fprintf(stderr, ")\n");
+#undef X
+
+	(void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg);
+	if (h->flags & P_OVERFLOW)
+		return;
+
+	top = NEXTINDEX(h);
+	(void)fprintf(stderr, " lower %3d upper %3d nextind %d\n",
+	    h->lower, h->upper, top);
+	for (cur = 0; cur < top; cur++) {
+		(void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]);
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+			bi = GETBINTERNAL(h, cur);
+			(void)fprintf(stderr,
+			    "size %03d pgno %03d", bi->ksize, bi->pgno);
+			if (bi->flags & P_BIGKEY)
+				(void)fprintf(stderr, " (indirect)");
+			else if (bi->ksize)
+				(void)fprintf(stderr,
+				    " {%.*s}", (int)bi->ksize, bi->bytes);
+			break;
+		case P_RINTERNAL:
+			ri = GETRINTERNAL(h, cur);
+			(void)fprintf(stderr, "entries %03d pgno %03d",
+				ri->nrecs, ri->pgno);
+			break;
+		case P_BLEAF:
+			bl = GETBLEAF(h, cur);
+			if (bl->flags & P_BIGKEY)
+				(void)fprintf(stderr,
+				    "big key page %lu size %u/",
+				    *(pgno_t *)bl->bytes,
+				    *(u_int32_t *)(bl->bytes + sizeof(pgno_t)));
+			else if (bl->ksize)
+				(void)fprintf(stderr, "%s/", bl->bytes);
+			if (bl->flags & P_BIGDATA)
+				(void)fprintf(stderr,
+				    "big data page %lu size %u",
+				    *(pgno_t *)(bl->bytes + bl->ksize),
+				    *(u_int32_t *)(bl->bytes + bl->ksize +
+				    sizeof(pgno_t)));
+			else if (bl->dsize)
+				(void)fprintf(stderr, "%.*s",
+				    (int)bl->dsize, bl->bytes + bl->ksize);
+			break;
+		case P_RLEAF:
+			rl = GETRLEAF(h, cur);
+			if (rl->flags & P_BIGDATA)
+				(void)fprintf(stderr,
+				    "big data page %lu size %u",
+				    *(pgno_t *)rl->bytes,
+				    *(u_int32_t *)(rl->bytes + sizeof(pgno_t)));
+			else if (rl->dsize)
+				(void)fprintf(stderr,
+				    "%.*s", (int)rl->dsize, rl->bytes);
+			break;
+		}
+		(void)fprintf(stderr, "\n");
+	}
+}
+#endif
+
+#ifdef STATISTICS
+/*
+ * BT_STAT -- Gather/print the tree statistics
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB
+ */
+void
+__bt_stat(dbp)
+	DB *dbp;
+{
+	extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit;
+	extern u_long bt_sortsplit, bt_split;
+	BTREE *t;
+	PAGE *h;
+	pgno_t i, pcont, pinternal, pleaf;
+	u_long ifree, lfree, nkeys;
+	int levels;
+
+	t = dbp->internal;
+	pcont = pinternal = pleaf = 0;
+	nkeys = ifree = lfree = 0;
+	for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+		case P_RINTERNAL:
+			++pinternal;
+			ifree += h->upper - h->lower;
+			break;
+		case P_BLEAF:
+		case P_RLEAF:
+			++pleaf;
+			lfree += h->upper - h->lower;
+			nkeys += NEXTINDEX(h);
+			break;
+		case P_OVERFLOW:
+			++pcont;
+			break;
+		}
+		(void)mpool_put(t->bt_mp, h, 0);
+	}
+
+	/* Count the levels of the tree. */
+	for (i = P_ROOT, levels = 0 ;; ++levels) {
+		h = mpool_get(t->bt_mp, i, 0);
+		if (h->flags & (P_BLEAF|P_RLEAF)) {
+			if (levels == 0)
+				levels = 1;
+			(void)mpool_put(t->bt_mp, h, 0);
+			break;
+		}
+		i = F_ISSET(t, R_RECNO) ?
+		    GETRINTERNAL(h, 0)->pgno :
+		    GETBINTERNAL(h, 0)->pgno;
+		(void)mpool_put(t->bt_mp, h, 0);
+	}
+
+	(void)fprintf(stderr, "%d level%s with %ld keys",
+	    levels, levels == 1 ? "" : "s", nkeys);
+	if (F_ISSET(t, R_RECNO))
+		(void)fprintf(stderr, " (%ld header count)", t->bt_nrecs);
+	(void)fprintf(stderr,
+	    "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n",
+	    pinternal + pleaf + pcont, pleaf, pinternal, pcont);
+	(void)fprintf(stderr, "%ld cache hits, %ld cache misses\n",
+	    bt_cache_hit, bt_cache_miss);
+	(void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n",
+	    bt_split, bt_rootsplit, bt_sortsplit);
+	pleaf *= t->bt_psize - BTDATAOFF;
+	if (pleaf)
+		(void)fprintf(stderr,
+		    "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n",
+		    ((double)(pleaf - lfree) / pleaf) * 100,
+		    pleaf - lfree, lfree);
+	pinternal *= t->bt_psize - BTDATAOFF;
+	if (pinternal)
+		(void)fprintf(stderr,
+		    "%.0f%% internal fill (%ld bytes used, %ld bytes free\n",
+		    ((double)(pinternal - ifree) / pinternal) * 100,
+		    pinternal - ifree, ifree);
+	if (bt_pfxsaved)
+		(void)fprintf(stderr, "prefix checking removed %lu bytes.\n",
+		    bt_pfxsaved);
+}
+#endif
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_delete.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_delete.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_delete.c	(revision 2448)
@@ -0,0 +1,660 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_delete.c	8.13 (Berkeley) 7/28/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_delete.c,v 1.2 2002/03/21 22:46:25 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_bdelete(BTREE *, const DBT *);
+static int __bt_curdel(BTREE *, const DBT *, PAGE *, u_int);
+static int __bt_pdelete(BTREE *, PAGE *);
+static int __bt_relink(BTREE *, PAGE *);
+static int __bt_stkacq(BTREE *, PAGE **, CURSOR *);
+
+/*
+ * __bt_delete
+ *	Delete the item(s) referenced by a key.
+ *
+ * Return RET_SPECIAL if the key is not found.
+ */
+int
+__bt_delete(dbp, key, flags)
+	const DB *dbp;
+	const DBT *key;
+	u_int flags;
+{
+	BTREE *t;
+	CURSOR *c;
+	PAGE *h;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Check for change to a read-only tree. */
+	if (F_ISSET(t, B_RDONLY)) {
+		errno = EPERM;
+		return (RET_ERROR);
+	}
+
+	switch (flags) {
+	case 0:
+		status = __bt_bdelete(t, key);
+		break;
+	case R_CURSOR:
+		/*
+		 * If flags is R_CURSOR, delete the cursor.  Must already
+		 * have started a scan and not have already deleted it.
+		 */
+		c = &t->bt_cursor;
+		if (F_ISSET(c, CURS_INIT)) {
+			if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+				return (RET_ERROR);
+
+			/*
+			 * If the page is about to be emptied, we'll need to
+			 * delete it, which means we have to acquire a stack.
+			 */
+			if (NEXTINDEX(h) == 1)
+				if (__bt_stkacq(t, &h, &t->bt_cursor))
+					return (RET_ERROR);
+
+			status = __bt_dleaf(t, NULL, h, c->pg.index);
+
+			if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) {
+				if (__bt_pdelete(t, h))
+					return (RET_ERROR);
+			} else
+				mpool_put(t->bt_mp,
+				    h, status == RET_SUCCESS ? MPOOL_DIRTY : 0);
+			break;
+		}
+		/* FALLTHROUGH */
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+	if (status == RET_SUCCESS)
+		F_SET(t, B_MODIFIED);
+	return (status);
+}
+
+/*
+ * __bt_stkacq --
+ *	Acquire a stack so we can delete a cursor entry.
+ *
+ * Parameters:
+ *	  t:	tree
+ *	 hp:	pointer to current, pinned PAGE pointer
+ *	  c:	pointer to the cursor
+ *
+ * Returns:
+ *	0 on success, 1 on failure
+ */
+static int
+__bt_stkacq(t, hp, c)
+	BTREE *t;
+	PAGE **hp;
+	CURSOR *c;
+{
+	BINTERNAL *bi;
+	EPG *e;
+	EPGNO *parent;
+	PAGE *h;
+	indx_t index;
+	pgno_t pgno;
+	recno_t nextpg, prevpg;
+	int exact, level;
+	
+	/*
+	 * Find the first occurrence of the key in the tree.  Toss the
+	 * currently locked page so we don't hit an already-locked page.
+	 */
+	h = *hp;
+	mpool_put(t->bt_mp, h, 0);
+	if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+		return (1);
+	h = e->page;
+
+	/* See if we got it in one shot. */
+	if (h->pgno == c->pg.pgno)
+		goto ret;
+
+	/*
+	 * Move right, looking for the page.  At each move we have to move
+	 * up the stack until we don't have to move to the next page.  If
+	 * we have to change pages at an internal level, we have to fix the
+	 * stack back up.
+	 */
+	while (h->pgno != c->pg.pgno) {
+		if ((nextpg = h->nextpg) == P_INVALID)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+
+		/* Move up the stack. */
+		for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+			/* Get the parent page. */
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				return (1);
+
+			/* Move to the next index. */
+			if (parent->index != NEXTINDEX(h) - 1) {
+				index = parent->index + 1;
+				BT_PUSH(t, h->pgno, index);
+				break;
+			}
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		/* Restore the stack. */
+		while (level--) {
+			/* Push the next level down onto the stack. */
+			bi = GETBINTERNAL(h, index);
+			pgno = bi->pgno;
+			BT_PUSH(t, pgno, 0);
+
+			/* Lose the currently pinned page. */
+			mpool_put(t->bt_mp, h, 0);
+
+			/* Get the next level down. */
+			if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+				return (1);
+			index = 0;
+		}
+		mpool_put(t->bt_mp, h, 0);
+		if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
+			return (1);
+	}
+
+	if (h->pgno == c->pg.pgno)
+		goto ret;
+
+	/* Reacquire the original stack. */
+	mpool_put(t->bt_mp, h, 0);
+	if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+		return (1);
+	h = e->page;
+
+	/*
+	 * Move left, looking for the page.  At each move we have to move
+	 * up the stack until we don't have to change pages to move to the
+	 * next page.  If we have to change pages at an internal level, we
+	 * have to fix the stack back up.
+	 */
+	while (h->pgno != c->pg.pgno) {
+		if ((prevpg = h->prevpg) == P_INVALID)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+
+		/* Move up the stack. */
+		for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+			/* Get the parent page. */
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				return (1);
+
+			/* Move to the next index. */
+			if (parent->index != 0) {
+				index = parent->index - 1;
+				BT_PUSH(t, h->pgno, index);
+				break;
+			}
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		/* Restore the stack. */
+		while (level--) {
+			/* Push the next level down onto the stack. */
+			bi = GETBINTERNAL(h, index);
+			pgno = bi->pgno;
+
+			/* Lose the currently pinned page. */
+			mpool_put(t->bt_mp, h, 0);
+
+			/* Get the next level down. */
+			if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+				return (1);
+
+			index = NEXTINDEX(h) - 1;
+			BT_PUSH(t, pgno, index);
+		}
+		mpool_put(t->bt_mp, h, 0);
+		if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
+			return (1);
+	}
+	
+
+ret:	mpool_put(t->bt_mp, h, 0);
+	return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
+}
+
+/*
+ * __bt_bdelete --
+ *	Delete all key/data pairs matching the specified key.
+ *
+ * Parameters:
+ *	  t:	tree
+ *	key:	key to delete
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+__bt_bdelete(t, key)
+	BTREE *t;
+	const DBT *key;
+{
+	EPG *e;
+	PAGE *h;
+	int deleted, exact, redo;
+
+	deleted = 0;
+
+	/* Find any matching record; __bt_search pins the page. */
+loop:	if ((e = __bt_search(t, key, &exact)) == NULL)
+		return (deleted ? RET_SUCCESS : RET_ERROR);
+	if (!exact) {
+		mpool_put(t->bt_mp, e->page, 0);
+		return (deleted ? RET_SUCCESS : RET_SPECIAL);
+	}
+
+	/*
+	 * Delete forward, then delete backward, from the found key.  If
+	 * there are duplicates and we reach either side of the page, do
+	 * the key search again, so that we get them all.
+	 */
+	redo = 0;
+	h = e->page;
+	do {
+		if (__bt_dleaf(t, key, h, e->index)) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		if (F_ISSET(t, B_NODUPS)) {
+			if (NEXTINDEX(h) == 0) {
+				if (__bt_pdelete(t, h))
+					return (RET_ERROR);
+			} else
+				mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			return (RET_SUCCESS);
+		}
+		deleted = 1;
+	} while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
+
+	/* Check for right-hand edge of the page. */
+	if (e->index == NEXTINDEX(h))
+		redo = 1;
+
+	/* Delete from the key to the beginning of the page. */
+	while (e->index-- > 0) {
+		if (__bt_cmp(t, key, e) != 0)
+			break;
+		if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		if (e->index == 0)
+			redo = 1;
+	}
+
+	/* Check for an empty page. */
+	if (NEXTINDEX(h) == 0) {
+		if (__bt_pdelete(t, h))
+			return (RET_ERROR);
+		goto loop;
+	}
+
+	/* Put the page. */
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	if (redo)
+		goto loop;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_pdelete --
+ *	Delete a single page from the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	leaf page
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ *
+ * Side-effects:
+ *	mpool_put's the page
+ */
+static int
+__bt_pdelete(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	BINTERNAL *bi;
+	PAGE *pg;
+	EPGNO *parent;
+	indx_t cnt, index, *ip, offset;
+	u_int32_t nksize;
+	char *from;
+
+	/*
+	 * Walk the parent page stack -- a LIFO stack of the pages that were
+	 * traversed when we searched for the page where the delete occurred.
+	 * Each stack entry is a page number and a page index offset.  The
+	 * offset is for the page traversed on the search.  We've just deleted
+	 * a page, so we have to delete the key from the parent page.
+	 *
+	 * If the delete from the parent page makes it empty, this process may
+	 * continue all the way up the tree.  We stop if we reach the root page
+	 * (which is never deleted, it's just not worth the effort) or if the
+	 * delete does not empty the page.
+	 */
+	while ((parent = BT_POP(t)) != NULL) {
+		/* Get the parent page. */
+		if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+			return (RET_ERROR);
+		
+		index = parent->index;
+		bi = GETBINTERNAL(pg, index);
+
+		/* Free any overflow pages. */
+		if (bi->flags & P_BIGKEY &&
+		    __ovfl_delete(t, bi->bytes) == RET_ERROR) {
+			mpool_put(t->bt_mp, pg, 0);
+			return (RET_ERROR);
+		}
+
+		/*
+		 * Free the parent if it has only the one key and it's not the
+		 * root page. If it's the rootpage, turn it back into an empty
+		 * leaf page.
+		 */
+		if (NEXTINDEX(pg) == 1)
+			if (pg->pgno == P_ROOT) {
+				pg->lower = BTDATAOFF;
+				pg->upper = t->bt_psize;
+				pg->flags = P_BLEAF;
+			} else {
+				if (__bt_relink(t, pg) || __bt_free(t, pg))
+					return (RET_ERROR);
+				continue;
+			}
+		else {
+			/* Pack remaining key items at the end of the page. */
+			nksize = NBINTERNAL(bi->ksize);
+			from = (char *)pg + pg->upper;
+			memmove(from + nksize, from, (char *)bi - from);
+			pg->upper += nksize;
+
+			/* Adjust indices' offsets, shift the indices down. */
+			offset = pg->linp[index];
+			for (cnt = index, ip = &pg->linp[0]; cnt--; ++ip)
+				if (ip[0] < offset)
+					ip[0] += nksize;
+			for (cnt = NEXTINDEX(pg) - index; --cnt; ++ip)
+				ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
+			pg->lower -= sizeof(indx_t);
+		}
+
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+		break;
+	}
+
+	/* Free the leaf page, as long as it wasn't the root. */
+	if (h->pgno == P_ROOT) {
+		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+		return (RET_SUCCESS);
+	}
+	return (__bt_relink(t, h) || __bt_free(t, h));
+}
+
+/*
+ * __bt_dleaf --
+ *	Delete a single record from a leaf page.
+ *
+ * Parameters:
+ *	t:	tree
+ *    key:	referenced key
+ *	h:	page
+ *	index:	index on page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_dleaf(t, key, h, index)
+	BTREE *t;
+	const DBT *key;
+	PAGE *h;
+	u_int index;
+{
+	BLEAF *bl;
+	indx_t cnt, *ip, offset;
+	u_int32_t nbytes;
+	void *to;
+	char *from;
+
+	/* If this record is referenced by the cursor, delete the cursor. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == index &&
+	    __bt_curdel(t, key, h, index))
+		return (RET_ERROR);
+
+	/* If the entry uses overflow pages, make them available for reuse. */
+	to = bl = GETBLEAF(h, index);
+	if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
+		return (RET_ERROR);
+	if (bl->flags & P_BIGDATA &&
+	    __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Pack the remaining key/data items at the end of the page. */
+	nbytes = NBLEAF(bl);
+	from = (char *)h + h->upper;
+	memmove(from + nbytes, from, (char *)to - from);
+	h->upper += nbytes;
+
+	/* Adjust the indices' offsets, shift the indices down. */
+	offset = h->linp[index];
+	for (cnt = index, ip = &h->linp[0]; cnt--; ++ip)
+		if (ip[0] < offset)
+			ip[0] += nbytes;
+	for (cnt = NEXTINDEX(h) - index; --cnt; ++ip)
+		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+	h->lower -= sizeof(indx_t);
+
+	/* If the cursor is on this page, adjust it as necessary. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > index)
+		--t->bt_cursor.pg.index;
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_curdel --
+ *	Delete the cursor.
+ *
+ * Parameters:
+ *	t:	tree
+ *    key:	referenced key (or NULL)
+ *	h:	page
+ *  index:	index on page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+static int
+__bt_curdel(t, key, h, index)
+	BTREE *t;
+	const DBT *key;
+	PAGE *h;
+	u_int index;
+{
+	CURSOR *c;
+	EPG e;
+	PAGE *pg;
+	int curcopy, status;
+
+	/*
+	 * If there are duplicates, move forward or backward to one.
+	 * Otherwise, copy the key into the cursor area.
+	 */
+	c = &t->bt_cursor;
+	F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE);
+
+	curcopy = 0;
+	if (!F_ISSET(t, B_NODUPS)) {
+		/*
+		 * We're going to have to do comparisons.  If we weren't
+		 * provided a copy of the key, i.e. the user is deleting
+		 * the current cursor position, get one.
+		 */
+		if (key == NULL) {
+			e.page = h;
+			e.index = index;
+			if ((status = __bt_ret(t, &e,
+			    &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
+				return (status);
+			curcopy = 1;
+			key = &c->key;
+		}
+		/* Check previous key, if not at the beginning of the page. */
+		if (index > 0) {
+			e.page = h;
+			e.index = index - 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_BEFORE);
+				goto dup2;
+			}
+		}
+		/* Check next key, if not at the end of the page. */
+		if (index < NEXTINDEX(h) - 1) {
+			e.page = h;
+			e.index = index + 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_AFTER);
+				goto dup2;
+			}
+		}
+		/* Check previous key if at the beginning of the page. */
+		if (index == 0 && h->prevpg != P_INVALID) {
+			if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+				return (RET_ERROR);
+			e.page = pg;
+			e.index = NEXTINDEX(pg) - 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_BEFORE);
+				goto dup1;
+			}
+			mpool_put(t->bt_mp, pg, 0);
+		}
+		/* Check next key if at the end of the page. */
+		if (index == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
+			if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+				return (RET_ERROR);
+			e.page = pg;
+			e.index = 0;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_AFTER);
+dup1:				mpool_put(t->bt_mp, pg, 0);
+dup2:				c->pg.pgno = e.page->pgno;
+				c->pg.index = e.index;
+				return (RET_SUCCESS);
+			}
+			mpool_put(t->bt_mp, pg, 0);
+		}
+	}
+	e.page = h;
+	e.index = index;
+	if (curcopy || (status =
+	    __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
+		F_SET(c, CURS_ACQUIRE);
+		return (RET_SUCCESS);
+	}
+	return (status);
+}
+
+/*
+ * __bt_relink --
+ *	Link around a deleted page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to be deleted
+ */
+static int
+__bt_relink(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	PAGE *pg;
+
+	if (h->nextpg != P_INVALID) {
+		if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+			return (RET_ERROR);
+		pg->prevpg = h->prevpg;
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+	}
+	if (h->prevpg != P_INVALID) {
+		if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+			return (RET_ERROR);
+		pg->nextpg = h->nextpg;
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+	}
+	return (0);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_get.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_get.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_get.c	(revision 2448)
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_get.c	8.6 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_get.c,v 1.2 2002/03/22 21:52:01 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __BT_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to find
+ *	data:	data to return
+ *	flag:	currently unused
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__bt_get(dbp, key, data, flags)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	int exact, status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Get currently doesn't take any flags. */
+	if (flags) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if ((e = __bt_search(t, key, &exact)) == NULL)
+		return (RET_ERROR);
+	if (!exact) {
+		mpool_put(t->bt_mp, e->page, 0);
+		return (RET_SPECIAL);
+	}
+
+	status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0);
+
+	/*
+	 * If the user is doing concurrent access, we copied the
+	 * key/data, toss the page.
+	 */
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_open.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_open.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_open.c	(revision 2448)
@@ -0,0 +1,478 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_open.c	8.10 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_open.c,v 1.11 2002/03/22 21:52:01 obrien Exp $");
+
+/*
+ * Implementation of btree access method for 4.4BSD.
+ *
+ * The design here was originally based on that of the btree access method
+ * used in the Postgres database system at UC Berkeley.  This implementation
+ * is wholly independent of the Postgres code.
+ */
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef __EMX__
+#include <io.h>
+#endif
+#include "un-namespace.h"
+
+#include <db.h>
+#include "btree.h"
+
+#ifdef DEBUG
+#undef	MINPSIZE
+#define	MINPSIZE	128
+#endif
+
+static int byteorder(void);
+static int nroot(BTREE *);
+#ifndef __EMX__
+static int tmp(void);
+#endif
+
+/*
+ * __BT_OPEN -- Open a btree.
+ *
+ * Creates and fills a DB struct, and calls the routine that actually
+ * opens the btree.
+ *
+ * Parameters:
+ *	fname:	filename (NULL for in-memory trees)
+ *	flags:	open flag bits
+ *	mode:	open permission bits
+ *	b:	BTREEINFO pointer
+ *
+ * Returns:
+ *	NULL on failure, pointer to DB on success.
+ *
+ */
+DB *
+__bt_open(fname, flags, mode, openinfo, dflags)
+	const char *fname;
+	int flags, mode, dflags;
+	const BTREEINFO *openinfo;
+{
+	struct stat sb;
+	BTMETA m;
+	BTREE *t;
+	BTREEINFO b;
+	DB *dbp;
+	pgno_t ncache;
+	ssize_t nr;
+	int machine_lorder;
+
+	t = NULL;
+
+	/*
+	 * Intention is to make sure all of the user's selections are okay
+	 * here and then use them without checking.  Can't be complete, since
+	 * we don't know the right page size, lorder or flags until the backing
+	 * file is opened.  Also, the file's page size can cause the cachesize
+	 * to change.
+	 */
+	machine_lorder = byteorder();
+	if (openinfo) {
+		b = *openinfo;
+
+		/* Flags: R_DUP. */
+		if (b.flags & ~(R_DUP))
+			goto einval;
+
+		/*
+		 * Page size must be indx_t aligned and >= MINPSIZE.  Default
+		 * page size is set farther on, based on the underlying file
+		 * transfer size.
+		 */
+		if (b.psize &&
+		    (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
+		    b.psize & (sizeof(indx_t) - 1) ))
+			goto einval;
+
+		/* Minimum number of keys per page; absolute minimum is 2. */
+		if (b.minkeypage) {
+			if (b.minkeypage < 2)
+				goto einval;
+		} else
+			b.minkeypage = DEFMINKEYPAGE;
+
+		/* If no comparison, use default comparison and prefix. */
+		if (b.compare == NULL) {
+			b.compare = __bt_defcmp;
+			if (b.prefix == NULL)
+				b.prefix = __bt_defpfx;
+		}
+
+		if (b.lorder == 0)
+			b.lorder = machine_lorder;
+	} else {
+		b.compare = __bt_defcmp;
+		b.cachesize = 0;
+		b.flags = 0;
+		b.lorder = machine_lorder;
+		b.minkeypage = DEFMINKEYPAGE;
+		b.prefix = __bt_defpfx;
+		b.psize = 0;
+	}
+
+	/* Check for the ubiquitous PDP-11. */
+	if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN)
+		goto einval;
+
+	/* Allocate and initialize DB and BTREE structures. */
+	if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL)
+		goto err;
+	memset(t, 0, sizeof(BTREE));
+	t->bt_fd = -1;			/* Don't close unopened fd on error. */
+	t->bt_lorder = b.lorder;
+	t->bt_order = NOT;
+	t->bt_cmp = b.compare;
+	t->bt_pfx = b.prefix;
+	t->bt_rfd = -1;
+
+	if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL)
+		goto err;
+	memset(t->bt_dbp, 0, sizeof(DB));
+	if (t->bt_lorder != machine_lorder)
+		F_SET(t, B_NEEDSWAP);
+
+	dbp->type = DB_BTREE;
+	dbp->internal = t;
+	dbp->close = __bt_close;
+	dbp->del = __bt_delete;
+	dbp->fd = __bt_fd;
+	dbp->get = __bt_get;
+	dbp->put = __bt_put;
+	dbp->seq = __bt_seq;
+	dbp->sync = __bt_sync;
+
+	/*
+	 * If no file name was supplied, this is an in-memory btree and we
+	 * open a backing temporary file.  Otherwise, it's a disk-based tree.
+	 */
+	if (fname) {
+		switch (flags & O_ACCMODE) {
+		case O_RDONLY:
+			F_SET(t, B_RDONLY);
+			break;
+		case O_RDWR:
+			break;
+		case O_WRONLY:
+		default:
+			goto einval;
+		}
+		
+#ifdef __EMX__
+		if ((t->bt_fd = _open(fname, flags | O_BINARY, mode)) < 0)
+#else
+		if ((t->bt_fd = _open(fname, flags, mode)) < 0)
+#endif
+			goto err;
+
+	} else {
+		if ((flags & O_ACCMODE) != O_RDWR)
+			goto einval;
+#ifdef __EMX__
+		{
+		char namestr[] = "btXXXXXX";
+		char absname[MAXPATHLEN];
+		if ((t->bt_fd = mkstemp (namestr)) == -1)
+			goto err;
+		setmode (t->bt_fd, O_BINARY);
+		if (_abspath (absname, namestr, sizeof (absname)) == 0)
+			t->tempname = strdup (absname);
+		}
+#else /* not __EMX__ */
+		if ((t->bt_fd = tmp()) == -1)
+			goto err;
+#endif /* not __EMX__ */
+		F_SET(t, B_INMEM);
+	}
+
+	if (_fcntl(t->bt_fd, F_SETFD, 1) == -1)
+		goto err;
+
+	if (_fstat(t->bt_fd, &sb))
+		goto err;
+	if (sb.st_size) {
+		if ((nr = _read(t->bt_fd, &m, sizeof(BTMETA))) < 0)
+			goto err;
+		if (nr != sizeof(BTMETA))
+			goto eftype;
+
+		/*
+		 * Read in the meta-data.  This can change the notion of what
+		 * the lorder, page size and flags are, and, when the page size
+		 * changes, the cachesize value can change too.  If the user
+		 * specified the wrong byte order for an existing database, we
+		 * don't bother to return an error, we just clear the NEEDSWAP
+		 * bit.
+		 */
+		if (m.magic == BTREEMAGIC)
+			F_CLR(t, B_NEEDSWAP);
+		else {
+			F_SET(t, B_NEEDSWAP);
+			M_32_SWAP(m.magic);
+			M_32_SWAP(m.version);
+			M_32_SWAP(m.psize);
+			M_32_SWAP(m.free);
+			M_32_SWAP(m.nrecs);
+			M_32_SWAP(m.flags);
+		}
+		if (m.magic != BTREEMAGIC || m.version != BTREEVERSION)
+			goto eftype;
+		if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 ||
+		    m.psize & (sizeof(indx_t) - 1) )
+			goto eftype;
+		if (m.flags & ~SAVEMETA)
+			goto eftype;
+		b.psize = m.psize;
+		F_SET(t, m.flags);
+		t->bt_free = m.free;
+		t->bt_nrecs = m.nrecs;
+	} else {
+		/*
+		 * Set the page size to the best value for I/O to this file.
+		 * Don't overflow the page offset type.
+		 */
+		if (b.psize == 0) {
+			b.psize = sb.st_blksize;
+			if (b.psize < MINPSIZE)
+				b.psize = MINPSIZE;
+			if (b.psize > MAX_PAGE_OFFSET + 1)
+				b.psize = MAX_PAGE_OFFSET + 1;
+		}
+
+		/* Set flag if duplicates permitted. */
+		if (!(b.flags & R_DUP))
+			F_SET(t, B_NODUPS);
+
+		t->bt_free = P_INVALID;
+		t->bt_nrecs = 0;
+		F_SET(t, B_METADIRTY);
+	}
+
+	t->bt_psize = b.psize;
+
+	/* Set the cache size; must be a multiple of the page size. */
+	if (b.cachesize && b.cachesize & (b.psize - 1) )
+		b.cachesize += (~b.cachesize & (b.psize - 1) ) + 1;
+	if (b.cachesize < b.psize * MINCACHE)
+		b.cachesize = b.psize * MINCACHE;
+
+	/* Calculate number of pages to cache. */
+	ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize;
+
+	/*
+	 * The btree data structure requires that at least two keys can fit on
+	 * a page, but other than that there's no fixed requirement.  The user
+	 * specified a minimum number per page, and we translated that into the
+	 * number of bytes a key/data pair can use before being placed on an
+	 * overflow page.  This calculation includes the page header, the size
+	 * of the index referencing the leaf item and the size of the leaf item
+	 * structure.  Also, don't let the user specify a minkeypage such that
+	 * a key/data pair won't fit even if both key and data are on overflow
+	 * pages.
+	 */
+	t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage -
+	    (sizeof(indx_t) + NBLEAFDBT(0, 0));
+	if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t))
+		t->bt_ovflsize =
+		    NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t);
+
+	/* Initialize the buffer pool. */
+	if ((t->bt_mp =
+	    mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
+		goto err;
+	if (!F_ISSET(t, B_INMEM))
+		mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);
+
+	/* Create a root page if new tree. */
+	if (nroot(t) == RET_ERROR)
+		goto err;
+
+	/* Global flags. */
+	if (dflags & DB_LOCK)
+		F_SET(t, B_DB_LOCK);
+	if (dflags & DB_SHMEM)
+		F_SET(t, B_DB_SHMEM);
+	if (dflags & DB_TXN)
+		F_SET(t, B_DB_TXN);
+
+	return (dbp);
+
+einval:	errno = EINVAL;
+	goto err;
+
+eftype:	errno = EFTYPE;
+	goto err;
+
+err:	if (t) {
+		if (t->bt_dbp)
+			free(t->bt_dbp);
+		if (t->bt_fd != -1)
+			(void)_close(t->bt_fd);
+#ifdef __EMX__
+		if (t->tempname != NULL) {
+			(void)unlink(t->tempname);
+			free(t->tempname);
+		}
+#endif /* __EMX__ */
+		free(t);
+	}
+	return (NULL);
+}
+
+/*
+ * NROOT -- Create the root of a new tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+nroot(t)
+	BTREE *t;
+{
+	PAGE *meta, *root;
+	pgno_t npg;
+
+	if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) {
+		mpool_put(t->bt_mp, meta, 0);
+		return (RET_SUCCESS);
+	}
+	if (errno != EINVAL)		/* It's OK to not exist. */
+		return (RET_ERROR);
+	errno = 0;
+
+	if ((meta = mpool_new(t->bt_mp, &npg)) == NULL)
+		return (RET_ERROR);
+
+	if ((root = mpool_new(t->bt_mp, &npg)) == NULL)
+		return (RET_ERROR);
+
+	if (npg != P_ROOT)
+		return (RET_ERROR);
+	root->pgno = npg;
+	root->prevpg = root->nextpg = P_INVALID;
+	root->lower = BTDATAOFF;
+	root->upper = t->bt_psize;
+	root->flags = P_BLEAF;
+	memset(meta, 0, t->bt_psize);
+	mpool_put(t->bt_mp, meta, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, root, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+#ifndef __EMX__ /* bird */
+static int
+tmp()
+{
+	sigset_t set, oset;
+	int fd;
+	char *envtmp = NULL;
+	char path[MAXPATHLEN];
+
+	if (issetugid() == 0)
+		envtmp = getenv("TMPDIR");
+	(void)snprintf(path,
+	    sizeof(path), "%s/bt.XXXXXXXXXX", envtmp ? envtmp : "/tmp");
+
+	(void)sigfillset(&set);
+	(void)_sigprocmask(SIG_BLOCK, &set, &oset);
+	if ((fd = mkstemp(path)) != -1)
+		(void)unlink(path);
+	(void)_sigprocmask(SIG_SETMASK, &oset, NULL);
+	return(fd);
+}
+#endif /*!EMX*/
+
+static int
+byteorder()
+{
+	u_int32_t x;
+	u_char *p;
+
+	x = 0x01020304;
+	p = (u_char *)&x;
+	switch (*p) {
+	case 1:
+		return (BIG_ENDIAN);
+	case 4:
+		return (LITTLE_ENDIAN);
+	default:
+		return (0);
+	}
+}
+
+int
+__bt_fd(dbp)
+        const DB *dbp;
+{
+	BTREE *t;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* In-memory database can't have a file descriptor. */
+	if (F_ISSET(t, B_INMEM)) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (t->bt_fd);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_overflow.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_overflow.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_overflow.c	(revision 2448)
@@ -0,0 +1,231 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_overflow.c	8.5 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_overflow.c,v 1.3 2002/03/22 21:52:01 obrien Exp $");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * Big key/data code.
+ *
+ * Big key and data entries are stored on linked lists of pages.  The initial
+ * reference is byte string stored with the key or data and is the page number
+ * and size.  The actual record is stored in a chain of pages linked by the
+ * nextpg field of the PAGE header.
+ *
+ * The first page of the chain has a special property.  If the record is used
+ * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set
+ * in the header.
+ *
+ * XXX
+ * A single DBT is written to each chain, so a lot of space on the last page
+ * is wasted.  This is a fairly major bug for some data sets.
+ */
+
+/*
+ * __OVFL_GET -- Get an overflow key/data item.
+ *
+ * Parameters:
+ *	t:	tree
+ *	p:	pointer to { pgno_t, u_int32_t }
+ *	buf:	storage address
+ *	bufsz:	storage size
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_get(t, p, ssz, buf, bufsz)
+	BTREE *t;
+	void *p;
+	size_t *ssz;
+	void **buf;
+	size_t *bufsz;
+{
+	PAGE *h;
+	pgno_t pg;
+	size_t nb, plen;
+	u_int32_t sz;
+
+	memmove(&pg, p, sizeof(pgno_t));
+	memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
+	*ssz = sz;
+
+#ifdef DEBUG
+	if (pg == P_INVALID || sz == 0)
+		abort();
+#endif
+	/* Make the buffer bigger as necessary. */
+	if (*bufsz < sz) {
+		*buf = (char *)(*buf == NULL ? malloc(sz) : reallocf(*buf, sz));
+		if (*buf == NULL)
+			return (RET_ERROR);
+		*bufsz = sz;
+	}
+
+	/*
+	 * Step through the linked list of pages, copying the data on each one
+	 * into the buffer.  Never copy more than the data's length.
+	 */
+	plen = t->bt_psize - BTDATAOFF;
+	for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+
+		nb = MIN(sz, plen);
+		memmove(p, (char *)h + BTDATAOFF, nb);
+		mpool_put(t->bt_mp, h, 0);
+
+		if ((sz -= nb) == 0)
+			break;
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_PUT -- Store an overflow key/data item.
+ *
+ * Parameters:
+ *	t:	tree
+ *	data:	DBT to store
+ *	pgno:	storage page number
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_put(t, dbt, pg)
+	BTREE *t;
+	const DBT *dbt;
+	pgno_t *pg;
+{
+	PAGE *h, *last;
+	void *p;
+	pgno_t npg;
+	size_t nb, plen;
+	u_int32_t sz;
+
+	/*
+	 * Allocate pages and copy the key/data record into them.  Store the
+	 * number of the first page in the chain.
+	 */
+	plen = t->bt_psize - BTDATAOFF;
+	for (last = NULL, p = dbt->data, sz = dbt->size;;
+	    p = (char *)p + plen, last = h) {
+		if ((h = __bt_new(t, &npg)) == NULL)
+			return (RET_ERROR);
+
+		h->pgno = npg;
+		h->nextpg = h->prevpg = P_INVALID;
+		h->flags = P_OVERFLOW;
+		h->lower = h->upper = 0;
+
+		nb = MIN(sz, plen);
+		memmove((char *)h + BTDATAOFF, p, nb);
+
+		if (last) {
+			last->nextpg = h->pgno;
+			mpool_put(t->bt_mp, last, MPOOL_DIRTY);
+		} else
+			*pg = h->pgno;
+
+		if ((sz -= nb) == 0) {
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		}
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_DELETE -- Delete an overflow chain.
+ *
+ * Parameters:
+ *	t:	tree
+ *	p:	pointer to { pgno_t, u_int32_t }
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_delete(t, p)
+	BTREE *t;
+	void *p;
+{
+	PAGE *h;
+	pgno_t pg;
+	size_t plen;
+	u_int32_t sz;
+
+	memmove(&pg, p, sizeof(pgno_t));
+	memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
+
+#ifdef DEBUG
+	if (pg == P_INVALID || sz == 0)
+		abort();
+#endif
+	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+		return (RET_ERROR);
+
+	/* Don't delete chains used by internal pages. */
+	if (h->flags & P_PRESERVE) {
+		mpool_put(t->bt_mp, h, 0);
+		return (RET_SUCCESS);
+	}
+
+	/* Step through the chain, calling the free routine for each page. */
+	for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
+		pg = h->nextpg;
+		__bt_free(t, h);
+		if (sz <= plen)
+			break;
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+	}
+	return (RET_SUCCESS);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_page.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_page.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_page.c	(revision 2448)
@@ -0,0 +1,103 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_page.c	8.3 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_page.c,v 1.3 2002/03/22 21:52:01 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __bt_free --
+ *	Put a page on the freelist.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to free
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ *
+ * Side-effect:
+ *	mpool_put's the page.
+ */
+int
+__bt_free(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	/* Insert the page at the head of the free list. */
+	h->prevpg = P_INVALID;
+	h->nextpg = t->bt_free;
+	t->bt_free = h->pgno;
+	F_SET(t, B_METADIRTY);
+
+	/* Make sure the page gets written back. */
+	return (mpool_put(t->bt_mp, h, MPOOL_DIRTY));
+}
+
+/*
+ * __bt_new --
+ *	Get a new page, preferably from the freelist.
+ *
+ * Parameters:
+ *	t:	tree
+ *	npg:	storage for page number.
+ *
+ * Returns:
+ *	Pointer to a page, NULL on error.
+ */
+PAGE *
+__bt_new(t, npg)
+	BTREE *t;
+	pgno_t *npg;
+{
+	PAGE *h;
+
+	if (t->bt_free != P_INVALID &&
+	    (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) {
+		*npg = t->bt_free;
+		t->bt_free = h->nextpg;
+		F_SET(t, B_METADIRTY);
+		return (h);
+	}
+	return (mpool_new(t->bt_mp, npg));
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_put.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_put.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_put.c	(revision 2448)
@@ -0,0 +1,326 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_put.c	8.8 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_put.c,v 1.4 2003/05/30 11:05:08 tmm Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static EPG *bt_fast(BTREE *, const DBT *, const DBT *, int *);
+
+/*
+ * __BT_PUT -- Add a btree item to the tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key
+ *	data:	data
+ *	flag:	R_NOOVERWRITE
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the
+ *	tree and R_NOOVERWRITE specified.
+ */
+int
+__bt_put(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	DBT tkey, tdata;
+	EPG *e;
+	PAGE *h;
+	indx_t index, nxtindex;
+	pgno_t pg;
+	u_int32_t nbytes, tmp;
+	int dflags, exact, status;
+	char *dest, db[NOVFLSIZE], kb[NOVFLSIZE];
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Check for change to a read-only tree. */
+	if (F_ISSET(t, B_RDONLY)) {
+		errno = EPERM;
+		return (RET_ERROR);
+	}
+
+	switch (flags) {
+	case 0:
+	case R_NOOVERWRITE:
+		break;
+	case R_CURSOR:
+		/*
+		 * If flags is R_CURSOR, put the cursor.  Must already
+		 * have started a scan and not have already deleted it.
+		 */
+		if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+		    !F_ISSET(&t->bt_cursor,
+		        CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+			break;
+		/* FALLTHROUGH */
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * If the key/data pair won't fit on a page, store it on overflow
+	 * pages.  Only put the key on the overflow page if the pair are
+	 * still too big after moving the data to an overflow page.
+	 *
+	 * XXX
+	 * If the insert fails later on, the overflow pages aren't recovered.
+	 */
+	dflags = 0;
+	if (key->size + data->size > t->bt_ovflsize) {
+		if (key->size > t->bt_ovflsize) {
+storekey:		if (__ovfl_put(t, key, &pg) == RET_ERROR)
+				return (RET_ERROR);
+			tkey.data = kb;
+			tkey.size = NOVFLSIZE;
+			memmove(kb, &pg, sizeof(pgno_t));
+			tmp = key->size;
+			memmove(kb + sizeof(pgno_t),
+			    &tmp, sizeof(u_int32_t));
+			dflags |= P_BIGKEY;
+			key = &tkey;
+		}
+		if (key->size + data->size > t->bt_ovflsize) {
+			if (__ovfl_put(t, data, &pg) == RET_ERROR)
+				return (RET_ERROR);
+			tdata.data = db;
+			tdata.size = NOVFLSIZE;
+			memmove(db, &pg, sizeof(pgno_t));
+			tmp = data->size;
+			memmove(db + sizeof(pgno_t),
+			    &tmp, sizeof(u_int32_t));
+			dflags |= P_BIGDATA;
+			data = &tdata;
+		}
+		if (key->size + data->size > t->bt_ovflsize)
+			goto storekey;
+	}
+
+	/* Replace the cursor. */
+	if (flags == R_CURSOR) {
+		if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL)
+			return (RET_ERROR);
+		index = t->bt_cursor.pg.index;
+		goto delete;
+	}
+
+	/*
+	 * Find the key to delete, or, the location at which to insert.
+	 * Bt_fast and __bt_search both pin the returned page.
+	 */
+	if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL)
+		if ((e = __bt_search(t, key, &exact)) == NULL)
+			return (RET_ERROR);
+	h = e->page;
+	index = e->index;
+
+	/*
+	 * Add the key/data pair to the tree.  If an identical key is already
+	 * in the tree, and R_NOOVERWRITE is set, an error is returned.  If
+	 * R_NOOVERWRITE is not set, the key is either added (if duplicates are
+	 * permitted) or an error is returned.
+	 */
+	switch (flags) {
+	case R_NOOVERWRITE:
+		if (!exact)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+		return (RET_SPECIAL);
+	default:
+		if (!exact || !F_ISSET(t, B_NODUPS))
+			break;
+		/*
+		 * !!!
+		 * Note, the delete may empty the page, so we need to put a
+		 * new entry into the page immediately.
+		 */
+delete:		if (__bt_dleaf(t, key, h, index) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		break;
+	}
+
+	/*
+	 * If not enough room, or the user has put a ceiling on the number of
+	 * keys permitted in the page, split the page.  The split code will
+	 * insert the key and data and unpin the current page.  If inserting
+	 * into the offset array, shift the pointers up.
+	 */
+	nbytes = NBLEAFDBT(key->size, data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+		if ((status = __bt_split(t, h, key,
+		    data, dflags, nbytes, index)) != RET_SUCCESS)
+			return (status);
+		goto success;
+	}
+
+	if (index < (nxtindex = NEXTINDEX(h)))
+		memmove(h->linp + index + 1, h->linp + index,
+		    (nxtindex - index) * sizeof(indx_t));
+	h->lower += sizeof(indx_t);
+
+	h->linp[index] = h->upper -= nbytes;
+	dest = (char *)h + h->upper;
+	WR_BLEAF(dest, key, data, dflags);
+
+	/* If the cursor is on this page, adjust it as necessary. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= index)
+		++t->bt_cursor.pg.index;
+
+	if (t->bt_order == NOT) {
+		if (h->nextpg == P_INVALID) {
+			if (index == NEXTINDEX(h) - 1) {
+				t->bt_order = FORWARD;
+				t->bt_last.index = index;
+				t->bt_last.pgno = h->pgno;
+			}
+		} else if (h->prevpg == P_INVALID) {
+			if (index == 0) {
+				t->bt_order = BACK;
+				t->bt_last.index = 0;
+				t->bt_last.pgno = h->pgno;
+			}
+		}
+	}
+
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+success:
+	if (flags == R_SETCURSOR)
+		__bt_setcur(t, e->page->pgno, e->index);
+
+	F_SET(t, B_MODIFIED);
+	return (RET_SUCCESS);
+}
+
+#ifdef STATISTICS
+u_long bt_cache_hit, bt_cache_miss;
+#endif
+
+/*
+ * BT_FAST -- Do a quick check for sorted data.
+ *
+ * Parameters:
+ *	t:	tree
+ *	key:	key to insert
+ *
+ * Returns:
+ * 	EPG for new record or NULL if not found.
+ */
+static EPG *
+bt_fast(t, key, data, exactp)
+	BTREE *t;
+	const DBT *key, *data;
+	int *exactp;
+{
+	PAGE *h;
+	u_int32_t nbytes;
+	int cmp;
+
+	if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) {
+		t->bt_order = NOT;
+		return (NULL);
+	}
+	t->bt_cur.page = h;
+	t->bt_cur.index = t->bt_last.index;
+
+	/*
+	 * If won't fit in this page or have too many keys in this page,
+	 * have to search to get split stack.
+	 */
+	nbytes = NBLEAFDBT(key->size, data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t))
+		goto miss;
+
+	if (t->bt_order == FORWARD) {
+		if (t->bt_cur.page->nextpg != P_INVALID)
+			goto miss;
+		if (t->bt_cur.index != NEXTINDEX(h) - 1)
+			goto miss;
+		if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0)
+			goto miss;
+		t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index;
+	} else {
+		if (t->bt_cur.page->prevpg != P_INVALID)
+			goto miss;
+		if (t->bt_cur.index != 0)
+			goto miss;
+		if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0)
+			goto miss;
+		t->bt_last.index = 0;
+	}
+	*exactp = cmp == 0;
+#ifdef STATISTICS
+	++bt_cache_hit;
+#endif
+	return (&t->bt_cur);
+
+miss:
+#ifdef STATISTICS
+	++bt_cache_miss;
+#endif
+	t->bt_order = NOT;
+	mpool_put(t->bt_mp, h, 0);
+	return (NULL);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_search.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_search.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_search.c	(revision 2448)
@@ -0,0 +1,216 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_search.c	8.8 (Berkeley) 7/31/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_search.c,v 1.2 2002/03/21 22:46:25 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_snext(BTREE *, PAGE *, const DBT *, int *);
+static int __bt_sprev(BTREE *, PAGE *, const DBT *, int *);
+
+/*
+ * __bt_search --
+ *	Search a btree for a key.
+ *
+ * Parameters:
+ *	t:	tree to search
+ *	key:	key to find
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	The EPG for matching record, if any, or the EPG for the location
+ *	of the key, if it were inserted into the tree, is entered into
+ *	the bt_cur field of the tree.  A pointer to the field is returned.
+ */
+EPG *
+__bt_search(t, key, exactp)
+	BTREE *t;
+	const DBT *key;
+	int *exactp;
+{
+	PAGE *h;
+	indx_t base, index, lim;
+	pgno_t pg;
+	int cmp;
+
+	BT_CLR(t);
+	for (pg = P_ROOT;;) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (NULL);
+
+		/* Do a binary search on the current page. */
+		t->bt_cur.page = h;
+		for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
+			t->bt_cur.index = index = base + (lim >> 1);
+			if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
+				if (h->flags & P_BLEAF) {
+					*exactp = 1;
+					return (&t->bt_cur);
+				}
+				goto next;
+			}
+			if (cmp > 0) {
+				base = index + 1;
+				--lim;
+			}
+		}
+
+		/*
+		 * If it's a leaf page, we're almost done.  If no duplicates
+		 * are allowed, or we have an exact match, we're done.  Else,
+		 * it's possible that there were matching keys on this page,
+		 * which later deleted, and we're on a page with no matches
+		 * while there are matches on other pages.  If at the start or
+		 * end of a page, check the adjacent page.
+		 */
+		if (h->flags & P_BLEAF) {
+			if (!F_ISSET(t, B_NODUPS)) {
+				if (base == 0 &&
+				    h->prevpg != P_INVALID &&
+				    __bt_sprev(t, h, key, exactp))
+					return (&t->bt_cur);
+				if (base == NEXTINDEX(h) &&
+				    h->nextpg != P_INVALID &&
+				    __bt_snext(t, h, key, exactp))
+					return (&t->bt_cur);
+			}
+			*exactp = 0;
+			t->bt_cur.index = base;
+			return (&t->bt_cur);
+		}
+
+		/*
+		 * No match found.  Base is the smallest index greater than
+		 * key and may be zero or a last + 1 index.  If it's non-zero,
+		 * decrement by one, and record the internal page which should
+		 * be a parent page for the key.  If a split later occurs, the
+		 * inserted page will be to the right of the saved page.
+		 */
+		index = base ? base - 1 : base;
+
+next:		BT_PUSH(t, h->pgno, index);
+		pg = GETBINTERNAL(h, index)->pgno;
+		mpool_put(t->bt_mp, h, 0);
+	}
+}
+
+/*
+ * __bt_snext --
+ *	Check for an exact match after the key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	current page
+ *	key:	key
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	If an exact match found.
+ */
+static int
+__bt_snext(t, h, key, exactp)
+	BTREE *t;
+	PAGE *h;
+	const DBT *key;
+	int *exactp;
+{
+	EPG e;
+
+	/*
+	 * Get the next page.  The key is either an exact
+	 * match, or not as good as the one we already have.
+	 */
+	if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+		return (0);
+	e.index = 0;
+	if (__bt_cmp(t, key, &e) == 0) {
+		mpool_put(t->bt_mp, h, 0);
+		t->bt_cur = e;
+		*exactp = 1;
+		return (1);
+	}
+	mpool_put(t->bt_mp, e.page, 0);
+	return (0);
+}
+
+/*
+ * __bt_sprev --
+ *	Check for an exact match before the key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	current page
+ *	key:	key
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	If an exact match found.
+ */
+static int
+__bt_sprev(t, h, key, exactp)
+	BTREE *t;
+	PAGE *h;
+	const DBT *key;
+	int *exactp;
+{
+	EPG e;
+
+	/*
+	 * Get the previous page.  The key is either an exact
+	 * match, or not as good as the one we already have.
+	 */
+	if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+		return (0);
+	e.index = NEXTINDEX(e.page) - 1;
+	if (__bt_cmp(t, key, &e) == 0) {
+		mpool_put(t->bt_mp, h, 0);
+		t->bt_cur = e;
+		*exactp = 1;
+		return (1);
+	}
+	mpool_put(t->bt_mp, e.page, 0);
+	return (0);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_seq.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_seq.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_seq.c	(revision 2448)
@@ -0,0 +1,463 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_seq.c	8.7 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_seq.c,v 1.3 2002/03/21 22:46:25 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_first(BTREE *, const DBT *, EPG *, int *);
+static int __bt_seqadv(BTREE *, EPG *, int);
+static int __bt_seqset(BTREE *, EPG *, DBT *, int);
+
+/*
+ * Sequential scan support.
+ *
+ * The tree can be scanned sequentially, starting from either end of the
+ * tree or from any specific key.  A scan request before any scanning is
+ * done is initialized as starting from the least node.
+ */
+
+/*
+ * __bt_seq --
+ *	Btree sequential scan interface.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key for positioning and return value
+ *	data:	data return value
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__bt_seq(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key, *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG e;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/*
+	 * If scan unitialized as yet, or starting at a specific record, set
+	 * the scan to a specific key.  Both __bt_seqset and __bt_seqadv pin
+	 * the page the cursor references if they're successful.
+	 */
+	switch (flags) {
+	case R_NEXT:
+	case R_PREV:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			status = __bt_seqadv(t, &e, flags);
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_FIRST:
+	case R_LAST:
+	case R_CURSOR:
+		status = __bt_seqset(t, &e, key, flags);
+		break;
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (status == RET_SUCCESS) {
+		__bt_setcur(t, e.page->pgno, e.index);
+
+		status =
+		    __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0);
+
+		/*
+		 * If the user is doing concurrent access, we copied the
+		 * key/data, toss the page.
+		 */
+		if (F_ISSET(t, B_DB_LOCK))
+			mpool_put(t->bt_mp, e.page, 0);
+		else
+			t->bt_pinned = e.page;
+	}
+	return (status);
+}
+
+/*
+ * __bt_seqset --
+ *	Set the sequential scan to a specific key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	ep:	storage for returned key
+ *	key:	key for initial scan position
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
+ *
+ * Side effects:
+ *	Pins the page the cursor references.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqset(t, ep, key, flags)
+	BTREE *t;
+	EPG *ep;
+	DBT *key;
+	int flags;
+{
+	PAGE *h;
+	pgno_t pg;
+	int exact;
+
+	/*
+	 * Find the first, last or specific key in the tree and point the
+	 * cursor at it.  The cursor may not be moved until a new key has
+	 * been found.
+	 */
+	switch (flags) {
+	case R_CURSOR:				/* Keyed scan. */
+		/*
+		 * Find the first instance of the key or the smallest key
+		 * which is greater than or equal to the specified key.
+		 */
+		if (key->data == NULL || key->size == 0) {
+			errno = EINVAL;
+			return (RET_ERROR);
+		}
+		return (__bt_first(t, key, ep, &exact));
+	case R_FIRST:				/* First record. */
+	case R_NEXT:
+		/* Walk down the left-hand side of the tree. */
+		for (pg = P_ROOT;;) {
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+
+			/* Check for an empty tree. */
+			if (NEXTINDEX(h) == 0) {
+				mpool_put(t->bt_mp, h, 0);
+				return (RET_SPECIAL);
+			}
+
+			if (h->flags & (P_BLEAF | P_RLEAF))
+				break;
+			pg = GETBINTERNAL(h, 0)->pgno;
+			mpool_put(t->bt_mp, h, 0);
+		}
+		ep->page = h;
+		ep->index = 0;
+		break;
+	case R_LAST:				/* Last record. */
+	case R_PREV:
+		/* Walk down the right-hand side of the tree. */
+		for (pg = P_ROOT;;) {
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+
+			/* Check for an empty tree. */
+			if (NEXTINDEX(h) == 0) {
+				mpool_put(t->bt_mp, h, 0);
+				return (RET_SPECIAL);
+			}
+
+			if (h->flags & (P_BLEAF | P_RLEAF))
+				break;
+			pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		ep->page = h;
+		ep->index = NEXTINDEX(h) - 1;
+		break;
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_seqadvance --
+ *	Advance the sequential scan.
+ *
+ * Parameters:
+ *	t:	tree
+ *	flags:	R_NEXT, R_PREV
+ *
+ * Side effects:
+ *	Pins the page the new key/data record is on.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqadv(t, ep, flags)
+	BTREE *t;
+	EPG *ep;
+	int flags;
+{
+	CURSOR *c;
+	PAGE *h;
+	indx_t index;
+	pgno_t pg;
+	int exact;
+
+	/*
+	 * There are a couple of states that we can be in.  The cursor has
+	 * been initialized by the time we get here, but that's all we know.
+	 */
+	c = &t->bt_cursor;
+
+	/*
+	 * The cursor was deleted where there weren't any duplicate records,
+	 * so the key was saved.  Find out where that key would go in the
+	 * current tree.  It doesn't matter if the returned key is an exact
+	 * match or not -- if it's an exact match, the record was added after
+	 * the delete so we can just return it.  If not, as long as there's
+	 * a record there, return it.
+	 */
+	if (F_ISSET(c, CURS_ACQUIRE))
+		return (__bt_first(t, &c->key, ep, &exact));
+
+	/* Get the page referenced by the cursor. */
+	if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+		return (RET_ERROR);
+
+	/*
+ 	 * Find the next/previous record in the tree and point the cursor at
+	 * it.  The cursor may not be moved until a new key has been found.
+	 */
+	switch (flags) {
+	case R_NEXT:			/* Next record. */
+		/*
+		 * The cursor was deleted in duplicate records, and moved
+		 * forward to a record that has yet to be returned.  Clear
+		 * that flag, and return the record.
+		 */
+		if (F_ISSET(c, CURS_AFTER))
+			goto usecurrent;
+		index = c->pg.index;
+		if (++index == NEXTINDEX(h)) {
+			pg = h->nextpg;
+			mpool_put(t->bt_mp, h, 0);
+			if (pg == P_INVALID)
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+			index = 0;
+		}
+		break;
+	case R_PREV:			/* Previous record. */
+		/*
+		 * The cursor was deleted in duplicate records, and moved
+		 * backward to a record that has yet to be returned.  Clear
+		 * that flag, and return the record.
+		 */
+		if (F_ISSET(c, CURS_BEFORE)) {
+usecurrent:		F_CLR(c, CURS_AFTER | CURS_BEFORE);
+			ep->page = h;
+			ep->index = c->pg.index;
+			return (RET_SUCCESS);
+		}
+		index = c->pg.index;
+		if (index == 0) {
+			pg = h->prevpg;
+			mpool_put(t->bt_mp, h, 0);
+			if (pg == P_INVALID)
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+			index = NEXTINDEX(h) - 1;
+		} else
+			--index;
+		break;
+	}
+
+	ep->page = h;
+	ep->index = index;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_first --
+ *	Find the first entry.
+ *
+ * Parameters:
+ *	t:	the tree
+ *    key:	the key
+ *  erval:	return EPG
+ * exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	The first entry in the tree greater than or equal to key,
+ *	or RET_SPECIAL if no such key exists.
+ */
+static int
+__bt_first(t, key, erval, exactp)
+	BTREE *t;
+	const DBT *key;
+	EPG *erval;
+	int *exactp;
+{
+	PAGE *h;
+	EPG *ep, save;
+	pgno_t pg;
+
+	/*
+	 * Find any matching record; __bt_search pins the page.
+	 *
+	 * If it's an exact match and duplicates are possible, walk backwards
+	 * in the tree until we find the first one.  Otherwise, make sure it's
+	 * a valid key (__bt_search may return an index just past the end of a
+	 * page) and return it.
+	 */
+	if ((ep = __bt_search(t, key, exactp)) == NULL)
+		return (0);
+	if (*exactp) {
+		if (F_ISSET(t, B_NODUPS)) {
+			*erval = *ep;
+			return (RET_SUCCESS);
+		}
+			
+		/*
+		 * Walk backwards, as long as the entry matches and there are
+		 * keys left in the tree.  Save a copy of each match in case
+		 * we go too far.
+		 */
+		save = *ep;
+		h = ep->page;
+		do {
+			if (save.page->pgno != ep->page->pgno) {
+				mpool_put(t->bt_mp, save.page, 0);
+				save = *ep;
+			} else
+				save.index = ep->index;
+
+			/*
+			 * Don't unpin the page the last (or original) match
+			 * was on, but make sure it's unpinned if an error
+			 * occurs.
+			 */
+			if (ep->index == 0) {
+				if (h->prevpg == P_INVALID)
+					break;
+				if (h->pgno != save.page->pgno)
+					mpool_put(t->bt_mp, h, 0);
+				if ((h = mpool_get(t->bt_mp,
+				    h->prevpg, 0)) == NULL) {
+					if (h->pgno == save.page->pgno)
+						mpool_put(t->bt_mp,
+						    save.page, 0);
+					return (RET_ERROR);
+				}
+				ep->page = h;
+				ep->index = NEXTINDEX(h);
+			}
+			--ep->index;
+		} while (__bt_cmp(t, key, ep) == 0);
+
+		/*
+		 * Reach here with the last page that was looked at pinned,
+		 * which may or may not be the same as the last (or original)
+		 * match page.  If it's not useful, release it.
+		 */
+		if (h->pgno != save.page->pgno)
+			mpool_put(t->bt_mp, h, 0);
+
+		*erval = save;
+		return (RET_SUCCESS);
+	}
+
+	/* If at the end of a page, find the next entry. */
+	if (ep->index == NEXTINDEX(ep->page)) {
+		h = ep->page;
+		pg = h->nextpg;
+		mpool_put(t->bt_mp, h, 0);
+		if (pg == P_INVALID)
+			return (RET_SPECIAL);
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+		ep->index = 0;
+		ep->page = h;
+	}
+	*erval = *ep;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_setcur --
+ *	Set the cursor to an entry in the tree.
+ *
+ * Parameters:
+ *	t:	the tree
+ *   pgno:	page number
+ *  index:	page index
+ */
+void
+__bt_setcur(t, pgno, index)
+	BTREE *t;
+	pgno_t pgno;
+	u_int index;
+{
+	/* Lose any already deleted key. */
+	if (t->bt_cursor.key.data != NULL) {
+		free(t->bt_cursor.key.data);
+		t->bt_cursor.key.size = 0;
+		t->bt_cursor.key.data = NULL;
+	}
+	F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+
+	/* Update the cursor. */
+	t->bt_cursor.pg.pgno = pgno;
+	t->bt_cursor.pg.index = index;
+	F_SET(&t->bt_cursor, CURS_INIT);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_split.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_split.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_split.c	(revision 2448)
@@ -0,0 +1,828 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_split.c	8.9 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_split.c,v 1.5.6.1 2004/09/18 03:57:38 kuriyama Exp $");
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int	 bt_broot(BTREE *, PAGE *, PAGE *, PAGE *);
+static PAGE	*bt_page (BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static int	 bt_preserve(BTREE *, pgno_t);
+static PAGE	*bt_psplit (BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t);
+static PAGE	*bt_root (BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static int	 bt_rroot(BTREE *, PAGE *, PAGE *, PAGE *);
+static recno_t	 rec_total(PAGE *);
+
+#ifdef STATISTICS
+u_long	bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
+#endif
+
+/*
+ * __BT_SPLIT -- Split the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	sp:	page to split
+ *	key:	key to insert
+ *	data:	data to insert
+ *	flags:	BIGKEY/BIGDATA flags
+ *	ilen:	insert length
+ *	skip:	index to leave open
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_split(t, sp, key, data, flags, ilen, argskip)
+	BTREE *t;
+	PAGE *sp;
+	const DBT *key, *data;
+	int flags;
+	size_t ilen;
+	u_int32_t argskip;
+{
+	BINTERNAL *bi;
+	BLEAF *bl, *tbl;
+	DBT a, b;
+	EPGNO *parent;
+	PAGE *h, *l, *r, *lchild, *rchild;
+	indx_t nxtindex;
+	u_int16_t skip;
+	u_int32_t n, nbytes, nksize;
+	int parentsplit;
+	char *dest;
+
+	/*
+	 * Split the page into two pages, l and r.  The split routines return
+	 * a pointer to the page into which the key should be inserted and with
+	 * skip set to the offset which should be used.  Additionally, l and r
+	 * are pinned.
+	 */
+	skip = argskip;
+	h = sp->pgno == P_ROOT ?
+	    bt_root(t, sp, &l, &r, &skip, ilen) :
+	    bt_page(t, sp, &l, &r, &skip, ilen);
+	if (h == NULL)
+		return (RET_ERROR);
+
+	/*
+	 * Insert the new key/data pair into the leaf page.  (Key inserts
+	 * always cause a leaf page to split first.)
+	 */
+	h->linp[skip] = h->upper -= ilen;
+	dest = (char *)h + h->upper;
+	if (F_ISSET(t, R_RECNO))
+		WR_RLEAF(dest, data, flags)
+	else
+		WR_BLEAF(dest, key, data, flags)
+
+	/* If the root page was split, make it look right. */
+	if (sp->pgno == P_ROOT &&
+	    (F_ISSET(t, R_RECNO) ?
+	    bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+		goto err2;
+
+	/*
+	 * Now we walk the parent page stack -- a LIFO stack of the pages that
+	 * were traversed when we searched for the page that split.  Each stack
+	 * entry is a page number and a page index offset.  The offset is for
+	 * the page traversed on the search.  We've just split a page, so we
+	 * have to insert a new key into the parent page.
+	 *
+	 * If the insert into the parent page causes it to split, may have to
+	 * continue splitting all the way up the tree.  We stop if the root
+	 * splits or the page inserted into didn't have to split to hold the
+	 * new key.  Some algorithms replace the key for the old page as well
+	 * as the new page.  We don't, as there's no reason to believe that the
+	 * first key on the old page is any better than the key we have, and,
+	 * in the case of a key being placed at index 0 causing the split, the
+	 * key is unavailable.
+	 *
+	 * There are a maximum of 5 pages pinned at any time.  We keep the left
+	 * and right pages pinned while working on the parent.   The 5 are the
+	 * two children, left parent and right parent (when the parent splits)
+	 * and the root page or the overflow key page when calling bt_preserve.
+	 * This code must make sure that all pins are released other than the
+	 * root page or overflow page which is unlocked elsewhere.
+	 */
+	while ((parent = BT_POP(t)) != NULL) {
+		lchild = l;
+		rchild = r;
+
+		/* Get the parent page. */
+		if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+			goto err2;
+
+	 	/*
+		 * The new key goes ONE AFTER the index, because the split
+		 * was to the right.
+		 */
+		skip = parent->index + 1;
+
+		/*
+		 * Calculate the space needed on the parent page.
+		 *
+		 * Prefix trees: space hack when inserting into BINTERNAL
+		 * pages.  Retain only what's needed to distinguish between
+		 * the new entry and the LAST entry on the page to its left.
+		 * If the keys compare equal, retain the entire key.  Note,
+		 * we don't touch overflow keys, and the entire key must be
+		 * retained for the next-to-left most key on the leftmost
+		 * page of each level, or the search will fail.  Applicable
+		 * ONLY to internal pages that have leaf pages as children.
+		 * Further reduction of the key between pairs of internal
+		 * pages loses too much information.
+		 */
+		switch (rchild->flags & P_TYPE) {
+		case P_BINTERNAL:
+			bi = GETBINTERNAL(rchild, 0);
+			nbytes = NBINTERNAL(bi->ksize);
+			break;
+		case P_BLEAF:
+			bl = GETBLEAF(rchild, 0);
+			nbytes = NBINTERNAL(bl->ksize);
+			if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
+			    (h->prevpg != P_INVALID || skip > 1)) {
+				tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1);
+				a.size = tbl->ksize;
+				a.data = tbl->bytes;
+				b.size = bl->ksize;
+				b.data = bl->bytes;
+				nksize = t->bt_pfx(&a, &b);
+				n = NBINTERNAL(nksize);
+				if (n < nbytes) {
+#ifdef STATISTICS
+					bt_pfxsaved += nbytes - n;
+#endif
+					nbytes = n;
+				} else
+					nksize = 0;
+			} else
+				nksize = 0;
+			break;
+		case P_RINTERNAL:
+		case P_RLEAF:
+			nbytes = NRINTERNAL;
+			break;
+		default:
+			abort();
+		}
+
+		/* Split the parent page if necessary or shift the indices. */
+		if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+			sp = h;
+			h = h->pgno == P_ROOT ?
+			    bt_root(t, h, &l, &r, &skip, nbytes) :
+			    bt_page(t, h, &l, &r, &skip, nbytes);
+			if (h == NULL)
+				goto err1;
+			parentsplit = 1;
+		} else {
+			if (skip < (nxtindex = NEXTINDEX(h)))
+				memmove(h->linp + skip + 1, h->linp + skip,
+				    (nxtindex - skip) * sizeof(indx_t));
+			h->lower += sizeof(indx_t);
+			parentsplit = 0;
+		}
+
+		/* Insert the key into the parent page. */
+		switch (rchild->flags & P_TYPE) {
+		case P_BINTERNAL:
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			memmove(dest, bi, nbytes);
+			((BINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		case P_BLEAF:
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			WR_BINTERNAL(dest, nksize ? nksize : bl->ksize,
+			    rchild->pgno, bl->flags & P_BIGKEY);
+			memmove(dest, bl->bytes, nksize ? nksize : bl->ksize);
+			if (bl->flags & P_BIGKEY &&
+			    bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
+				goto err1;
+			break;
+		case P_RINTERNAL:
+			/*
+			 * Update the left page count.  If split
+			 * added at index 0, fix the correct page.
+			 */
+			if (skip > 0)
+				dest = (char *)h + h->linp[skip - 1];
+			else
+				dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+			((RINTERNAL *)dest)->nrecs = rec_total(lchild);
+			((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+			/* Update the right page count. */
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			((RINTERNAL *)dest)->nrecs = rec_total(rchild);
+			((RINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		case P_RLEAF:
+			/*
+			 * Update the left page count.  If split
+			 * added at index 0, fix the correct page.
+			 */
+			if (skip > 0)
+				dest = (char *)h + h->linp[skip - 1];
+			else
+				dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+			((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild);
+			((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+			/* Update the right page count. */
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild);
+			((RINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		default:
+			abort();
+		}
+
+		/* Unpin the held pages. */
+		if (!parentsplit) {
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		}
+
+		/* If the root page was split, make it look right. */
+		if (sp->pgno == P_ROOT &&
+		    (F_ISSET(t, R_RECNO) ?
+		    bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+			goto err1;
+
+		mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+		mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+	}
+
+	/* Unpin the held pages. */
+	mpool_put(t->bt_mp, l, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, r, MPOOL_DIRTY);
+
+	/* Clear any pages left on the stack. */
+	return (RET_SUCCESS);
+
+	/*
+	 * If something fails in the above loop we were already walking back
+	 * up the tree and the tree is now inconsistent.  Nothing much we can
+	 * do about it but release any memory we're holding.
+	 */
+err1:	mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+
+err2:	mpool_put(t->bt_mp, l, 0);
+	mpool_put(t->bt_mp, r, 0);
+	__dbpanic(t->bt_dbp);
+	return (RET_ERROR);
+}
+
+/*
+ * BT_PAGE -- Split a non-root page of a btree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	lp:	pointer to left page pointer
+ *	rp:	pointer to right page pointer
+ *	skip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_page(t, h, lp, rp, skip, ilen)
+	BTREE *t;
+	PAGE *h, **lp, **rp;
+	indx_t *skip;
+	size_t ilen;
+{
+	PAGE *l, *r, *tp;
+	pgno_t npg;
+
+#ifdef STATISTICS
+	++bt_split;
+#endif
+	/* Put the new right page for the split into place. */
+	if ((r = __bt_new(t, &npg)) == NULL)
+		return (NULL);
+	r->pgno = npg;
+	r->lower = BTDATAOFF;
+	r->upper = t->bt_psize;
+	r->nextpg = h->nextpg;
+	r->prevpg = h->pgno;
+	r->flags = h->flags & P_TYPE;
+
+	/*
+	 * If we're splitting the last page on a level because we're appending
+	 * a key to it (skip is NEXTINDEX()), it's likely that the data is
+	 * sorted.  Adding an empty page on the side of the level is less work
+	 * and can push the fill factor much higher than normal.  If we're
+	 * wrong it's no big deal, we'll just do the split the right way next
+	 * time.  It may look like it's equally easy to do a similar hack for
+	 * reverse sorted data, that is, split the tree left, but it's not.
+	 * Don't even try.
+	 */
+	if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) {
+#ifdef STATISTICS
+		++bt_sortsplit;
+#endif
+		h->nextpg = r->pgno;
+		r->lower = BTDATAOFF + sizeof(indx_t);
+		*skip = 0;
+		*lp = h;
+		*rp = r;
+		return (r);
+	}
+
+	/* Put the new left page for the split into place. */
+	if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) {
+		mpool_put(t->bt_mp, r, 0);
+		return (NULL);
+	}
+#ifdef PURIFY
+	memset(l, 0xff, t->bt_psize);
+#endif
+	l->pgno = h->pgno;
+	l->nextpg = r->pgno;
+	l->prevpg = h->prevpg;
+	l->lower = BTDATAOFF;
+	l->upper = t->bt_psize;
+	l->flags = h->flags & P_TYPE;
+
+	/* Fix up the previous pointer of the page after the split page. */
+	if (h->nextpg != P_INVALID) {
+		if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) {
+			free(l);
+			/* XXX mpool_free(t->bt_mp, r->pgno); */
+			return (NULL);
+		}
+		tp->prevpg = r->pgno;
+		mpool_put(t->bt_mp, tp, MPOOL_DIRTY);
+	}
+
+	/*
+	 * Split right.  The key/data pairs aren't sorted in the btree page so
+	 * it's simpler to copy the data from the split page onto two new pages
+	 * instead of copying half the data to the right page and compacting
+	 * the left page in place.  Since the left page can't change, we have
+	 * to swap the original and the allocated left page after the split.
+	 */
+	tp = bt_psplit(t, h, l, r, skip, ilen);
+
+	/* Move the new left page onto the old left page. */
+	memmove(h, l, t->bt_psize);
+	if (tp == l)
+		tp = h;
+	free(l);
+
+	*lp = h;
+	*rp = r;
+	return (tp);
+}
+
+/*
+ * BT_ROOT -- Split the root page of a btree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	lp:	pointer to left page pointer
+ *	rp:	pointer to right page pointer
+ *	skip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_root(t, h, lp, rp, skip, ilen)
+	BTREE *t;
+	PAGE *h, **lp, **rp;
+	indx_t *skip;
+	size_t ilen;
+{
+	PAGE *l, *r, *tp;
+	pgno_t lnpg, rnpg;
+
+#ifdef STATISTICS
+	++bt_split;
+	++bt_rootsplit;
+#endif
+	/* Put the new left and right pages for the split into place. */
+	if ((l = __bt_new(t, &lnpg)) == NULL ||
+	    (r = __bt_new(t, &rnpg)) == NULL)
+		return (NULL);
+	l->pgno = lnpg;
+	r->pgno = rnpg;
+	l->nextpg = r->pgno;
+	r->prevpg = l->pgno;
+	l->prevpg = r->nextpg = P_INVALID;
+	l->lower = r->lower = BTDATAOFF;
+	l->upper = r->upper = t->bt_psize;
+	l->flags = r->flags = h->flags & P_TYPE;
+
+	/* Split the root page. */
+	tp = bt_psplit(t, h, l, r, skip, ilen);
+
+	*lp = l;
+	*rp = r;
+	return (tp);
+}
+
+/*
+ * BT_RROOT -- Fix up the recno root page after it has been split.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	l:	left page
+ *	r:	right page
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_rroot(t, h, l, r)
+	BTREE *t;
+	PAGE *h, *l, *r;
+{
+	char *dest;
+
+	/* Insert the left and right keys, set the header information. */
+	h->linp[0] = h->upper = t->bt_psize - NRINTERNAL;
+	dest = (char *)h + h->upper;
+	WR_RINTERNAL(dest,
+	    l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno);
+
+	h->linp[1] = h->upper -= NRINTERNAL;
+	dest = (char *)h + h->upper;
+	WR_RINTERNAL(dest,
+	    r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno);
+
+	h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+	/* Unpin the root page, set to recno internal page. */
+	h->flags &= ~P_TYPE;
+	h->flags |= P_RINTERNAL;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * BT_BROOT -- Fix up the btree root page after it has been split.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	l:	left page
+ *	r:	right page
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_broot(t, h, l, r)
+	BTREE *t;
+	PAGE *h, *l, *r;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	u_int32_t nbytes;
+	char *dest;
+
+	/*
+	 * If the root page was a leaf page, change it into an internal page.
+	 * We copy the key we split on (but not the key's data, in the case of
+	 * a leaf page) to the new root page.
+	 *
+	 * The btree comparison code guarantees that the left-most key on any
+	 * level of the tree is never used, so it doesn't need to be filled in.
+	 */
+	nbytes = NBINTERNAL(0);
+	h->linp[0] = h->upper = t->bt_psize - nbytes;
+	dest = (char *)h + h->upper;
+	WR_BINTERNAL(dest, 0, l->pgno, 0);
+
+	switch (h->flags & P_TYPE) {
+	case P_BLEAF:
+		bl = GETBLEAF(r, 0);
+		nbytes = NBINTERNAL(bl->ksize);
+		h->linp[1] = h->upper -= nbytes;
+		dest = (char *)h + h->upper;
+		WR_BINTERNAL(dest, bl->ksize, r->pgno, 0);
+		memmove(dest, bl->bytes, bl->ksize);
+
+		/*
+		 * If the key is on an overflow page, mark the overflow chain
+		 * so it isn't deleted when the leaf copy of the key is deleted.
+		 */
+		if (bl->flags & P_BIGKEY &&
+		    bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
+			return (RET_ERROR);
+		break;
+	case P_BINTERNAL:
+		bi = GETBINTERNAL(r, 0);
+		nbytes = NBINTERNAL(bi->ksize);
+		h->linp[1] = h->upper -= nbytes;
+		dest = (char *)h + h->upper;
+		memmove(dest, bi, nbytes);
+		((BINTERNAL *)dest)->pgno = r->pgno;
+		break;
+	default:
+		abort();
+	}
+
+	/* There are two keys on the page. */
+	h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+	/* Unpin the root page, set to btree internal page. */
+	h->flags &= ~P_TYPE;
+	h->flags |= P_BINTERNAL;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * BT_PSPLIT -- Do the real work of splitting the page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to be split
+ *	l:	page to put lower half of data
+ *	r:	page to put upper half of data
+ *	pskip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert.
+ */
+static PAGE *
+bt_psplit(t, h, l, r, pskip, ilen)
+	BTREE *t;
+	PAGE *h, *l, *r;
+	indx_t *pskip;
+	size_t ilen;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	CURSOR *c;
+	RLEAF *rl;
+	PAGE *rval;
+	void *src;
+	indx_t full, half, nxt, off, skip, top, used;
+	u_int32_t nbytes;
+	int bigkeycnt, isbigkey;
+
+	/*
+	 * Split the data to the left and right pages.  Leave the skip index
+	 * open.  Additionally, make some effort not to split on an overflow
+	 * key.  This makes internal page processing faster and can save
+	 * space as overflow keys used by internal pages are never deleted.
+	 */
+	bigkeycnt = 0;
+	skip = *pskip;
+	full = t->bt_psize - BTDATAOFF;
+	half = full / 2;
+	used = 0;
+	for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) {
+		if (skip == off) {
+			nbytes = ilen;
+			isbigkey = 0;		/* XXX: not really known. */
+		} else
+			switch (h->flags & P_TYPE) {
+			case P_BINTERNAL:
+				src = bi = GETBINTERNAL(h, nxt);
+				nbytes = NBINTERNAL(bi->ksize);
+				isbigkey = bi->flags & P_BIGKEY;
+				break;
+			case P_BLEAF:
+				src = bl = GETBLEAF(h, nxt);
+				nbytes = NBLEAF(bl);
+				isbigkey = bl->flags & P_BIGKEY;
+				break;
+			case P_RINTERNAL:
+				src = GETRINTERNAL(h, nxt);
+				nbytes = NRINTERNAL;
+				isbigkey = 0;
+				break;
+			case P_RLEAF:
+				src = rl = GETRLEAF(h, nxt);
+				nbytes = NRLEAF(rl);
+				isbigkey = 0;
+				break;
+			default:
+				abort();
+			}
+
+		/*
+		 * If the key/data pairs are substantial fractions of the max
+		 * possible size for the page, it's possible to get situations
+		 * where we decide to try and copy too much onto the left page.
+		 * Make sure that doesn't happen.
+		 */
+		if ((skip <= off && used + nbytes + sizeof(indx_t) >= full)
+		    || nxt == top - 1) {
+			--off;
+			break;
+		}
+
+		/* Copy the key/data pair, if not the skipped index. */
+		if (skip != off) {
+			++nxt;
+
+			l->linp[off] = l->upper -= nbytes;
+			memmove((char *)l + l->upper, src, nbytes);
+		}
+
+		used += nbytes + sizeof(indx_t);
+		if (used >= half) {
+			if (!isbigkey || bigkeycnt == 3)
+				break;
+			else
+				++bigkeycnt;
+		}
+	}
+
+	/*
+	 * Off is the last offset that's valid for the left page.
+	 * Nxt is the first offset to be placed on the right page.
+	 */
+	l->lower += (off + 1) * sizeof(indx_t);
+
+	/*
+	 * If splitting the page that the cursor was on, the cursor has to be
+	 * adjusted to point to the same record as before the split.  If the
+	 * cursor is at or past the skipped slot, the cursor is incremented by
+	 * one.  If the cursor is on the right page, it is decremented by the
+	 * number of records split to the left page.
+	 */
+	c = &t->bt_cursor;
+	if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) {
+		if (c->pg.index >= skip)
+			++c->pg.index;
+		if (c->pg.index < nxt)			/* Left page. */
+			c->pg.pgno = l->pgno;
+		else {					/* Right page. */
+			c->pg.pgno = r->pgno;
+			c->pg.index -= nxt;
+		}
+	}
+
+	/*
+	 * If the skipped index was on the left page, just return that page.
+	 * Otherwise, adjust the skip index to reflect the new position on
+	 * the right page.
+	 */
+	if (skip <= off) {
+		skip = MAX_PAGE_OFFSET;
+		rval = l;
+	} else {
+		rval = r;
+		*pskip -= nxt;
+	}
+
+	for (off = 0; nxt < top; ++off) {
+		if (skip == nxt) {
+			++off;
+			skip = MAX_PAGE_OFFSET;
+		}
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+			src = bi = GETBINTERNAL(h, nxt);
+			nbytes = NBINTERNAL(bi->ksize);
+			break;
+		case P_BLEAF:
+			src = bl = GETBLEAF(h, nxt);
+			nbytes = NBLEAF(bl);
+			break;
+		case P_RINTERNAL:
+			src = GETRINTERNAL(h, nxt);
+			nbytes = NRINTERNAL;
+			break;
+		case P_RLEAF:
+			src = rl = GETRLEAF(h, nxt);
+			nbytes = NRLEAF(rl);
+			break;
+		default:
+			abort();
+		}
+		++nxt;
+		r->linp[off] = r->upper -= nbytes;
+		memmove((char *)r + r->upper, src, nbytes);
+	}
+	r->lower += off * sizeof(indx_t);
+
+	/* If the key is being appended to the page, adjust the index. */
+	if (skip == top)
+		r->lower += sizeof(indx_t);
+
+	return (rval);
+}
+
+/*
+ * BT_PRESERVE -- Mark a chain of pages as used by an internal node.
+ *
+ * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the
+ * record that references them gets deleted.  Chains pointed to by internal
+ * pages never get deleted.  This routine marks a chain as pointed to by an
+ * internal page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	pg:	page number of first page in the chain.
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+static int
+bt_preserve(t, pg)
+	BTREE *t;
+	pgno_t pg;
+{
+	PAGE *h;
+
+	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+		return (RET_ERROR);
+	h->flags |= P_PRESERVE;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+/*
+ * REC_TOTAL -- Return the number of recno entries below a page.
+ *
+ * Parameters:
+ *	h:	page
+ *
+ * Returns:
+ *	The number of recno entries below a page.
+ *
+ * XXX
+ * These values could be set by the bt_psplit routine.  The problem is that the
+ * entry has to be popped off of the stack etc. or the values have to be passed
+ * all the way back to bt_split/bt_rroot and it's not very clean.
+ */
+static recno_t
+rec_total(h)
+	PAGE *h;
+{
+	recno_t recs;
+	indx_t nxt, top;
+
+	for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt)
+		recs += GETRINTERNAL(h, nxt)->nrecs;
+	return (recs);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/bt_utils.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/bt_utils.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/bt_utils.c	(revision 2448)
@@ -0,0 +1,263 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_utils.c	8.8 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_utils.c,v 1.3 2003/01/01 18:48:42 schweikh Exp $");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __bt_ret --
+ *	Build return key/data pair.
+ *
+ * Parameters:
+ *	t:	tree
+ *	e:	key/data pair to be returned
+ *	key:	user's key structure (NULL if not to be filled in)
+ *	rkey:	memory area to hold key
+ *	data:	user's data structure (NULL if not to be filled in)
+ *	rdata:	memory area to hold data
+ *       copy:	always copy the key/data item
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_ret(t, e, key, rkey, data, rdata, copy)
+	BTREE *t;
+	EPG *e;
+	DBT *key, *rkey, *data, *rdata;
+	int copy;
+{
+	BLEAF *bl;
+	void *p;
+
+	bl = GETBLEAF(e->page, e->index);
+
+	/*
+	 * We must copy big keys/data to make them contigous.  Otherwise,
+	 * leave the page pinned and don't copy unless the user specified
+	 * concurrent access.
+	 */
+	if (key == NULL)
+		goto dataonly;
+
+	if (bl->flags & P_BIGKEY) {
+		if (__ovfl_get(t, bl->bytes,
+		    &key->size, &rkey->data, &rkey->size))
+			return (RET_ERROR);
+		key->data = rkey->data;
+	} else if (copy || F_ISSET(t, B_DB_LOCK)) {
+		if (bl->ksize > rkey->size) {
+			p = (void *)(rkey->data == NULL ?
+			    malloc(bl->ksize) : realloc(rkey->data, bl->ksize));
+			if (p == NULL)
+				return (RET_ERROR);
+			rkey->data = p;
+			rkey->size = bl->ksize;
+		}
+		memmove(rkey->data, bl->bytes, bl->ksize);
+		key->size = bl->ksize;
+		key->data = rkey->data;
+	} else {
+		key->size = bl->ksize;
+		key->data = bl->bytes;
+	}
+
+dataonly:
+	if (data == NULL)
+		return (RET_SUCCESS);
+
+	if (bl->flags & P_BIGDATA) {
+		if (__ovfl_get(t, bl->bytes + bl->ksize,
+		    &data->size, &rdata->data, &rdata->size))
+			return (RET_ERROR);
+		data->data = rdata->data;
+	} else if (copy || F_ISSET(t, B_DB_LOCK)) {
+		/* Use +1 in case the first record retrieved is 0 length. */
+		if (bl->dsize + 1 > rdata->size) {
+			p = (void *)(rdata->data == NULL ?
+			    malloc(bl->dsize + 1) :
+			    realloc(rdata->data, bl->dsize + 1));
+			if (p == NULL)
+				return (RET_ERROR);
+			rdata->data = p;
+			rdata->size = bl->dsize + 1;
+		}
+		memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize);
+		data->size = bl->dsize;
+		data->data = rdata->data;
+	} else {
+		data->size = bl->dsize;
+		data->data = bl->bytes + bl->ksize;
+	}
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * __BT_CMP -- Compare a key to a given record.
+ *
+ * Parameters:
+ *	t:	tree
+ *	k1:	DBT pointer of first arg to comparison
+ *	e:	pointer to EPG for comparison
+ *
+ * Returns:
+ *	< 0 if k1 is < record
+ *	= 0 if k1 is = record
+ *	> 0 if k1 is > record
+ */
+int
+__bt_cmp(t, k1, e)
+	BTREE *t;
+	const DBT *k1;
+	EPG *e;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	DBT k2;
+	PAGE *h;
+	void *bigkey;
+
+	/*
+	 * The left-most key on internal pages, at any level of the tree, is
+	 * guaranteed by the following code to be less than any user key.
+	 * This saves us from having to update the leftmost key on an internal
+	 * page when the user inserts a new key in the tree smaller than
+	 * anything we've yet seen.
+	 */
+	h = e->page;
+	if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
+		return (1);
+
+	bigkey = NULL;
+	if (h->flags & P_BLEAF) {
+		bl = GETBLEAF(h, e->index);
+		if (bl->flags & P_BIGKEY)
+			bigkey = bl->bytes;
+		else {
+			k2.data = bl->bytes;
+			k2.size = bl->ksize;
+		}
+	} else {
+		bi = GETBINTERNAL(h, e->index);
+		if (bi->flags & P_BIGKEY)
+			bigkey = bi->bytes;
+		else {
+			k2.data = bi->bytes;
+			k2.size = bi->ksize;
+		}
+	}
+
+	if (bigkey) {
+		if (__ovfl_get(t, bigkey,
+		    &k2.size, &t->bt_rdata.data, &t->bt_rdata.size))
+			return (RET_ERROR);
+		k2.data = t->bt_rdata.data;
+	}
+	return ((*t->bt_cmp)(k1, &k2));
+}
+
+/*
+ * __BT_DEFCMP -- Default comparison routine.
+ *
+ * Parameters:
+ *	a:	DBT #1
+ *	b: 	DBT #2
+ *
+ * Returns:
+ *	< 0 if a is < b
+ *	= 0 if a is = b
+ *	> 0 if a is > b
+ */
+int
+__bt_defcmp(a, b)
+	const DBT *a, *b;
+{
+	size_t len;
+	u_char *p1, *p2;
+
+	/*
+	 * XXX
+	 * If a size_t doesn't fit in an int, this routine can lose.
+	 * What we need is an integral type which is guaranteed to be
+	 * larger than a size_t, and there is no such thing.
+	 */
+	len = MIN(a->size, b->size);
+	for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
+		if (*p1 != *p2)
+			return ((int)*p1 - (int)*p2);
+	return ((int)a->size - (int)b->size);
+}
+
+/*
+ * __BT_DEFPFX -- Default prefix routine.
+ *
+ * Parameters:
+ *	a:	DBT #1
+ *	b: 	DBT #2
+ *
+ * Returns:
+ *	Number of bytes needed to distinguish b from a.
+ */
+size_t
+__bt_defpfx(a, b)
+	const DBT *a, *b;
+{
+	u_char *p1, *p2;
+	size_t cnt, len;
+
+	cnt = 1;
+	len = MIN(a->size, b->size);
+	for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
+		if (*p1 != *p2)
+			return (cnt);
+
+	/* a->size must be <= b->size, or they wouldn't be in this order. */
+	return (a->size < b->size ? a->size + 1 : a->size);
+}
Index: /trunk/libc/src/fbsdlibc/db/btree/btree.h
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/btree.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/btree.h	(revision 2448)
@@ -0,0 +1,387 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ *
+ *	@(#)btree.h	8.11 (Berkeley) 8/17/94
+ * $FreeBSD: src/lib/libc/db/btree/btree.h,v 1.3 2002/03/22 23:41:40 obrien Exp $
+ */
+
+/* Macros to set/clear/test flags. */
+#define	F_SET(p, f)	(p)->flags |= (f)
+#define	F_CLR(p, f)	(p)->flags &= ~(f)
+#define	F_ISSET(p, f)	((p)->flags & (f))
+
+#include <mpool.h>
+
+#define	DEFMINKEYPAGE	(2)		/* Minimum keys per page */
+#define	MINCACHE	(5)		/* Minimum cached pages */
+#define	MINPSIZE	(512)		/* Minimum page size */
+
+/*
+ * Page 0 of a btree file contains a copy of the meta-data.  This page is also
+ * used as an out-of-band page, i.e. page pointers that point to nowhere point
+ * to page 0.  Page 1 is the root of the btree.
+ */
+#define	P_INVALID	 0		/* Invalid tree page number. */
+#define	P_META		 0		/* Tree metadata page number. */
+#define	P_ROOT		 1		/* Tree root page number. */
+
+/*
+ * There are five page layouts in the btree: btree internal pages (BINTERNAL),
+ * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages
+ * (RLEAF) and overflow pages.  All five page types have a page header (PAGE).
+ * This implementation requires that values within structures NOT be padded.
+ * (ANSI C permits random padding.)  If your compiler pads randomly you'll have
+ * to do some work to get this package to run.
+ */
+typedef struct _page {
+	pgno_t	pgno;			/* this page's page number */
+	pgno_t	prevpg;			/* left sibling */
+	pgno_t	nextpg;			/* right sibling */
+
+#define	P_BINTERNAL	0x01		/* btree internal page */
+#define	P_BLEAF		0x02		/* leaf page */
+#define	P_OVERFLOW	0x04		/* overflow page */
+#define	P_RINTERNAL	0x08		/* recno internal page */
+#define	P_RLEAF		0x10		/* leaf page */
+#define P_TYPE		0x1f		/* type mask */
+#define	P_PRESERVE	0x20		/* never delete this chain of pages */
+	u_int32_t flags;
+
+	indx_t	lower;			/* lower bound of free space on page */
+	indx_t	upper;			/* upper bound of free space on page */
+	indx_t	linp[1];		/* indx_t-aligned VAR. LENGTH DATA */
+} PAGE;
+
+/* First and next index. */
+#define	BTDATAOFF							\
+	(sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) +		\
+	    sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t))
+#define	NEXTINDEX(p)	(((p)->lower - BTDATAOFF) / sizeof(indx_t))
+
+/*
+ * For pages other than overflow pages, there is an array of offsets into the
+ * rest of the page immediately following the page header.  Each offset is to
+ * an item which is unique to the type of page.  The h_lower offset is just
+ * past the last filled-in index.  The h_upper offset is the first item on the
+ * page.  Offsets are from the beginning of the page.
+ *
+ * If an item is too big to store on a single page, a flag is set and the item
+ * is a { page, size } pair such that the page is the first page of an overflow
+ * chain with size bytes of item.  Overflow pages are simply bytes without any
+ * external structure.
+ *
+ * The page number and size fields in the items are pgno_t-aligned so they can
+ * be manipulated without copying.  (This presumes that 32 bit items can be
+ * manipulated on this system.)
+ */
+#define	LALIGN(n)	(((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1))
+#define	NOVFLSIZE	(sizeof(pgno_t) + sizeof(u_int32_t))
+
+/*
+ * For the btree internal pages, the item is a key.  BINTERNALs are {key, pgno}
+ * pairs, such that the key compares less than or equal to all of the records
+ * on that page.  For a tree without duplicate keys, an internal page with two
+ * consecutive keys, a and b, will have all records greater than or equal to a
+ * and less than b stored on the page associated with a.  Duplicate keys are
+ * somewhat special and can cause duplicate internal and leaf page records and
+ * some minor modifications of the above rule.
+ */
+typedef struct _binternal {
+	u_int32_t ksize;		/* key size */
+	pgno_t	pgno;			/* page number stored on */
+#define	P_BIGDATA	0x01		/* overflow data */
+#define	P_BIGKEY	0x02		/* overflow key */
+	u_char	flags;
+	char	bytes[1];		/* data */
+} BINTERNAL;
+
+/* Get the page's BINTERNAL structure at index indx. */
+#define	GETBINTERNAL(pg, indx)						\
+	((BINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBINTERNAL(len)							\
+	LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len))
+
+/* Copy a BINTERNAL entry to the page. */
+#define	WR_BINTERNAL(p, size, pgno, flags) {				\
+	*(u_int32_t *)p = size;						\
+	p += sizeof(u_int32_t);						\
+	*(pgno_t *)p = pgno;						\
+	p += sizeof(pgno_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+}
+
+/*
+ * For the recno internal pages, the item is a page number with the number of
+ * keys found on that page and below.
+ */
+typedef struct _rinternal {
+	recno_t	nrecs;			/* number of records */
+	pgno_t	pgno;			/* page number stored below */
+} RINTERNAL;
+
+/* Get the page's RINTERNAL structure at index indx. */
+#define	GETRINTERNAL(pg, indx)						\
+	((RINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRINTERNAL							\
+	LALIGN(sizeof(recno_t) + sizeof(pgno_t))
+
+/* Copy a RINTERAL entry to the page. */
+#define	WR_RINTERNAL(p, nrecs, pgno) {					\
+	*(recno_t *)p = nrecs;						\
+	p += sizeof(recno_t);						\
+	*(pgno_t *)p = pgno;						\
+}
+
+/* For the btree leaf pages, the item is a key and data pair. */
+typedef struct _bleaf {
+	u_int32_t	ksize;		/* size of key */
+	u_int32_t	dsize;		/* size of data */
+	u_char	flags;			/* P_BIGDATA, P_BIGKEY */
+	char	bytes[1];		/* data */
+} BLEAF;
+
+/* Get the page's BLEAF structure at index indx. */
+#define	GETBLEAF(pg, indx)						\
+	((BLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBLEAF(p)	NBLEAFDBT((p)->ksize, (p)->dsize)
+
+/* Get the number of bytes in the user's key/data pair. */
+#define NBLEAFDBT(ksize, dsize)						\
+	LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) +	\
+	    (ksize) + (dsize))
+
+/* Copy a BLEAF entry to the page. */
+#define	WR_BLEAF(p, key, data, flags) {					\
+	*(u_int32_t *)p = key->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_int32_t *)p = data->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+	memmove(p, key->data, key->size);				\
+	p += key->size;							\
+	memmove(p, data->data, data->size);				\
+}
+
+/* For the recno leaf pages, the item is a data entry. */
+typedef struct _rleaf {
+	u_int32_t	dsize;		/* size of data */
+	u_char	flags;			/* P_BIGDATA */
+	char	bytes[1];
+} RLEAF;
+
+/* Get the page's RLEAF structure at index indx. */
+#define	GETRLEAF(pg, indx)						\
+	((RLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRLEAF(p)	NRLEAFDBT((p)->dsize)
+
+/* Get the number of bytes from the user's data. */
+#define	NRLEAFDBT(dsize)						\
+	LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize))
+
+/* Copy a RLEAF entry to the page. */
+#define	WR_RLEAF(p, data, flags) {					\
+	*(u_int32_t *)p = data->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+	memmove(p, data->data, data->size);				\
+}
+
+/*
+ * A record in the tree is either a pointer to a page and an index in the page
+ * or a page number and an index.  These structures are used as a cursor, stack
+ * entry and search returns as well as to pass records to other routines.
+ *
+ * One comment about searches.  Internal page searches must find the largest
+ * record less than key in the tree so that descents work.  Leaf page searches
+ * must find the smallest record greater than key so that the returned index
+ * is the record's correct position for insertion.
+ */
+typedef struct _epgno {
+	pgno_t	pgno;			/* the page number */
+	indx_t	index;			/* the index on the page */
+} EPGNO;
+
+typedef struct _epg {
+	PAGE	*page;			/* the (pinned) page */
+	indx_t	 index;			/* the index on the page */
+} EPG;
+
+/*
+ * About cursors.  The cursor (and the page that contained the key/data pair
+ * that it referenced) can be deleted, which makes things a bit tricky.  If
+ * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set
+ * or there simply aren't any duplicates of the key) we copy the key that it
+ * referenced when it's deleted, and reacquire a new cursor key if the cursor
+ * is used again.  If there are duplicates keys, we move to the next/previous
+ * key, and set a flag so that we know what happened.  NOTE: if duplicate (to
+ * the cursor) keys are added to the tree during this process, it is undefined
+ * if they will be returned or not in a cursor scan.
+ *
+ * The flags determine the possible states of the cursor:
+ *
+ * CURS_INIT	The cursor references *something*.
+ * CURS_ACQUIRE	The cursor was deleted, and a key has been saved so that
+ *		we can reacquire the right position in the tree.
+ * CURS_AFTER, CURS_BEFORE
+ *		The cursor was deleted, and now references a key/data pair
+ *		that has not yet been returned, either before or after the
+ *		deleted key/data pair.
+ * XXX
+ * This structure is broken out so that we can eventually offer multiple
+ * cursors as part of the DB interface.
+ */
+typedef struct _cursor {
+	EPGNO	 pg;			/* B: Saved tree reference. */
+	DBT	 key;			/* B: Saved key, or key.data == NULL. */
+	recno_t	 rcursor;		/* R: recno cursor (1-based) */
+
+#define	CURS_ACQUIRE	0x01		/*  B: Cursor needs to be reacquired. */
+#define	CURS_AFTER	0x02		/*  B: Unreturned cursor after key. */
+#define	CURS_BEFORE	0x04		/*  B: Unreturned cursor before key. */
+#define	CURS_INIT	0x08		/* RB: Cursor initialized. */
+	u_int8_t flags;
+} CURSOR;
+
+/*
+ * The metadata of the tree.  The nrecs field is used only by the RECNO code.
+ * This is because the btree doesn't really need it and it requires that every
+ * put or delete call modify the metadata.
+ */
+typedef struct _btmeta {
+	u_int32_t	magic;		/* magic number */
+	u_int32_t	version;	/* version */
+	u_int32_t	psize;		/* page size */
+	u_int32_t	free;		/* page number of first free page */
+	u_int32_t	nrecs;		/* R: number of records */
+
+#define	SAVEMETA	(B_NODUPS | R_RECNO)
+	u_int32_t	flags;		/* bt_flags & SAVEMETA */
+} BTMETA;
+
+/* The in-memory btree/recno data structure. */
+typedef struct _btree {
+	MPOOL	 *bt_mp;		/* memory pool cookie */
+
+	DB	 *bt_dbp;		/* pointer to enclosing DB */
+
+	EPG	  bt_cur;		/* current (pinned) page */
+	PAGE	 *bt_pinned;		/* page pinned across calls */
+
+	CURSOR	  bt_cursor;		/* cursor */
+
+#define	BT_PUSH(t, p, i) {						\
+	t->bt_sp->pgno = p; 						\
+	t->bt_sp->index = i; 						\
+	++t->bt_sp;							\
+}
+#define	BT_POP(t)	(t->bt_sp == t->bt_stack ? NULL : --t->bt_sp)
+#define	BT_CLR(t)	(t->bt_sp = t->bt_stack)
+	EPGNO	  bt_stack[50];		/* stack of parent pages */
+	EPGNO	 *bt_sp;		/* current stack pointer */
+
+	DBT	  bt_rkey;		/* returned key */
+	DBT	  bt_rdata;		/* returned data */
+
+	int	  bt_fd;		/* tree file descriptor */
+
+	pgno_t	  bt_free;		/* next free page */
+	u_int32_t bt_psize;		/* page size */
+	indx_t	  bt_ovflsize;		/* cut-off for key/data overflow */
+	int	  bt_lorder;		/* byte order */
+					/* sorted order */
+	enum { NOT, BACK, FORWARD } bt_order;
+	EPGNO	  bt_last;		/* last insert */
+
+					/* B: key comparison function */
+	int	(*bt_cmp)(const DBT *, const DBT *);
+					/* B: prefix comparison function */
+	size_t	(*bt_pfx)(const DBT *, const DBT *);
+					/* R: recno input function */
+	int	(*bt_irec)(struct _btree *, recno_t);
+
+	FILE	 *bt_rfp;		/* R: record FILE pointer */
+	int	  bt_rfd;		/* R: record file descriptor */
+
+	caddr_t	  bt_cmap;		/* R: current point in mapped space */
+	caddr_t	  bt_smap;		/* R: start of mapped space */
+	caddr_t   bt_emap;		/* R: end of mapped space */
+	size_t	  bt_msize;		/* R: size of mapped region. */
+
+	recno_t	  bt_nrecs;		/* R: number of records */
+	size_t	  bt_reclen;		/* R: fixed record length */
+	u_char	  bt_bval;		/* R: delimiting byte/pad character */
+
+/*
+ * NB:
+ * B_NODUPS and R_RECNO are stored on disk, and may not be changed.
+ */
+#define	B_INMEM		0x00001		/* in-memory tree */
+#define	B_METADIRTY	0x00002		/* need to write metadata */
+#define	B_MODIFIED	0x00004		/* tree modified */
+#define	B_NEEDSWAP	0x00008		/* if byte order requires swapping */
+#define	B_RDONLY	0x00010		/* read-only tree */
+
+#define	B_NODUPS	0x00020		/* no duplicate keys permitted */
+#define	R_RECNO		0x00080		/* record oriented tree */
+
+#define	R_CLOSEFP	0x00040		/* opened a file pointer */
+#define	R_EOF		0x00100		/* end of input file reached. */
+#define	R_FIXLEN	0x00200		/* fixed length records */
+#define	R_MEMMAPPED	0x00400		/* memory mapped file. */
+#define	R_INMEM		0x00800		/* in-memory file */
+#define	R_MODIFIED	0x01000		/* modified file */
+#define	R_RDONLY	0x02000		/* read-only file */
+
+#define	B_DB_LOCK	0x04000		/* DB_LOCK specified. */
+#define	B_DB_SHMEM	0x08000		/* DB_SHMEM specified. */
+#define	B_DB_TXN	0x10000		/* DB_TXN specified. */
+	u_int32_t flags;
+#ifdef __EMX__
+	char *tempname;			/* Name of temporary file */
+#endif /* __EMX__ */
+} BTREE;
+
+#include "extern.h"
Index: /trunk/libc/src/fbsdlibc/db/btree/extern.h
===================================================================
--- /trunk/libc/src/fbsdlibc/db/btree/extern.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/btree/extern.h	(revision 2448)
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1991, 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.
+ * 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.
+ *
+ *	@(#)extern.h	8.10 (Berkeley) 7/20/94
+ * $FreeBSD: src/lib/libc/db/btree/extern.h,v 1.3 2002/03/22 09:18:22 obrien Exp $
+ */
+
+int	 __bt_close(DB *);
+int	 __bt_cmp(BTREE *, const DBT *, EPG *);
+int	 __bt_crsrdel(BTREE *, EPGNO *);
+int	 __bt_defcmp(const DBT *, const DBT *);
+size_t	 __bt_defpfx(const DBT *, const DBT *);
+int	 __bt_delete(const DB *, const DBT *, u_int);
+int	 __bt_dleaf(BTREE *, const DBT *, PAGE *, u_int);
+int	 __bt_fd(const DB *);
+int	 __bt_free(BTREE *, PAGE *);
+int	 __bt_get(const DB *, const DBT *, DBT *, u_int);
+PAGE	*__bt_new(BTREE *, pgno_t *);
+void	 __bt_pgin(void *, pgno_t, void *);
+void	 __bt_pgout(void *, pgno_t, void *);
+int	 __bt_push(BTREE *, pgno_t, int);
+int	 __bt_put(const DB *dbp, DBT *, const DBT *, u_int);
+int	 __bt_ret(BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int);
+EPG	*__bt_search(BTREE *, const DBT *, int *);
+int	 __bt_seq(const DB *, DBT *, DBT *, u_int);
+void	 __bt_setcur(BTREE *, pgno_t, u_int);
+int	 __bt_split(BTREE *, PAGE *,
+	    const DBT *, const DBT *, int, size_t, u_int32_t);
+int	 __bt_sync(const DB *, u_int);
+
+int	 __ovfl_delete(BTREE *, void *);
+int	 __ovfl_get(BTREE *, void *, size_t *, void **, size_t *);
+int	 __ovfl_put(BTREE *, const DBT *, pgno_t *);
+
+#if defined(DEBUG) || defined(__EMX__)
+void	 __bt_dmpage(PAGE *);
+void	 __bt_dnpage(DB *, pgno_t);
+void	 __bt_dpage(PAGE *);
+void	 __bt_dump(DB *);
+#endif
+#ifdef STATISTICS
+void	 __bt_stat(DB *);
+#endif
Index: /trunk/libc/src/fbsdlibc/db/changelog
===================================================================
--- /trunk/libc/src/fbsdlibc/db/changelog	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/changelog	(revision 2448)
@@ -0,0 +1,103 @@
+1.84 -> 1.85
+	recno:	#ifdef out use of mmap, it's not portable enough.
+
+1.83 -> 1.84	Thu Aug 18 15:46:07 EDT 1994
+	recno:	Rework fixed-length records so that closing and reopening
+		the file now works.  Pad short records on input.  Never do
+		signed comparison in recno input reading functions.
+
+1.82 -> 1.83	Tue Jul 26 15:33:44 EDT 1994
+	btree:	Rework cursor deletion code yet again; bugs with
+		deleting empty pages that only contained the cursor
+		record.
+
+1.81 -> 1.82	Sat Jul 16 11:01:50 EDT 1994
+	btree:	Fix bugs introduced by new cursor/deletion code.
+		Replace return kbuf/dbuf with real DBT's.
+
+1.80 -> 1.81
+	btree:	Fix bugs introduced by new cursor/deletion code.
+	all:	Add #defines for Purify.
+
+1.79 -> 1.80	Wed Jul 13 22:41:54 EDT 1994
+	btree	Change deletion to coalesce empty pages.  This is a major
+		change, cursors and duplicate pages all had to be reworked.
+		Return to a fixed stack.
+	recno:	Affected by cursor changes.  New cursor structures should
+		permit multiple cursors in the future.
+
+1.78 -> 1.79	Mon Jun 20 17:36:47 EDT 1994
+	all:	Minor cleanups of 1.78 for porting reasons; only
+		major change was inlining check of NULL pointer
+		so that __fix_realloc goes away.
+
+1.77 -> 1.78	Thu Jun 16 19:06:43 EDT 1994
+	all:	Move "standard" size typedef's into db.h.
+
+1.76 -> 1.77	Thu Jun 16 16:48:38 EDT 1994
+	hash:	Delete __init_ routine, has special meaning to OSF 2.0.
+
+1.74 -> 1.76
+	all:	Finish up the port to the Alpha.
+
+1.73 -> 1.74
+	recno:	Don't put the record if rec_search fails, in rec_rdelete.
+		Create fixed-length intermediate records past "end" of DB
+		correctly.
+		Realloc bug when reading in fixed records.
+	all:	First cut at port to Alpha (64-bit architecture) using
+		4.4BSD basic integral types typedef's.
+		Cast allocation pointers to shut up old compilers.
+		Rework PORT directory into OS/machine directories.
+
+1.72 -> 1.73
+	btree:	If enough duplicate records were inserted and then deleted
+		that internal pages had references to empty pages of the
+		duplicate keys, the search function ended up on the wrong
+		page.
+
+1.7  -> 1.72	12 Oct 1993
+	hash:	Support NET/2 hash formats.
+
+1.7  -> 1.71	16 Sep 1993
+	btree/recno:
+		Fix bug in internal search routines that caused
+		return of invalid pointers.
+
+1.6  -> 1.7	07 Sep 1993
+	hash:	Fixed big key overflow bugs.
+	test:	Portability hacks, rewrite test script, Makefile.
+	btree/recno:
+		Stop copying non-overflow key/data pairs.
+	PORT:	Break PORT directory up into per architecture/OS
+		subdirectories.
+
+1.5  -> 1.6	06 Jun 1993
+	hash:	In PAIRFITS, the first comparison should look at (P)[2].
+		The hash_realloc function was walking off the end of memory.
+		The overflow page number was wrong when bumping splitpoint.
+
+1.4  -> 1.5	23 May 1993
+	hash:	Set hash default fill factor dynamically.
+	recno:	Fixed bug in sorted page splits.
+		Add page size parameter support.
+		Allow recno to specify the name of the underlying btree;
+			used for vi recovery.
+	btree/recno:
+		Support 64K pages.
+	btree/hash/recno:
+		Provide access to an underlying file descriptor.
+		Change sync routines to take a flag argument, recno
+			uses this to sync out the underlying btree.
+
+1.3  -> 1.4	10 May 1993
+	recno:	Delete the R_CURSORLOG flag from the recno interface.
+		Zero-length record fix for non-mmap reads.
+		Try and make SIZE_T_MAX test in open portable.
+
+1.2  -> 1.3	01 May 1993
+	btree:	Ignore user byte-order setting when reading already
+		existing database.  Fixes to byte-order conversions.
+
+1.1  -> 1.2	15 Apr 1993
+		No bug fixes, only compatibility hacks.
Index: /trunk/libc/src/fbsdlibc/db/db.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/db/db.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/db.smak	(revision 2448)
@@ -0,0 +1,5 @@
+libc.TSRC += $(wildcard src/fbsdlibc/db/btree/*.c)
+libc.TSRC += $(wildcard src/fbsdlibc/db/db/*.c)
+libc.TSRC += $(wildcard src/fbsdlibc/db/hash/*.c)
+libc.TSRC += $(wildcard src/fbsdlibc/db/mpool/*.c)
+libc.TSRC += $(wildcard src/fbsdlibc/db/recno/*.c)
Index: /trunk/libc/src/fbsdlibc/db/db/Makefile.inc
===================================================================
--- /trunk/libc/src/fbsdlibc/db/db/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/db/Makefile.inc	(revision 2448)
@@ -0,0 +1,6 @@
+#       from @(#)Makefile.inc	8.1 (Berkeley) 6/4/93
+# $FreeBSD: src/lib/libc/db/db/Makefile.inc,v 1.4 2002/11/18 09:50:54 ru Exp $
+
+.PATH: ${.CURDIR}/db/db
+
+SRCS+=	db.c
Index: /trunk/libc/src/fbsdlibc/db/db/db.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/db/db.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/db/db.c	(revision 2448)
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1991, 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)db.c	8.4 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/db/db.c,v 1.2 2002/03/22 21:52:01 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <db.h>
+
+DB *
+dbopen(fname, flags, mode, type, openinfo)
+	const char *fname;
+	int flags, mode;
+	DBTYPE type;
+	const void *openinfo;
+{
+
+#define	DB_FLAGS	(DB_LOCK | DB_SHMEM | DB_TXN)
+#ifdef __EMX__ /* TODO: add the missing flags! */
+#define	USE_OPEN_FLAGS							\
+	(O_CREAT | O_EXCL /*| O_EXLOCK*/ | O_NONBLOCK | O_RDONLY |		\
+	 O_RDWR | /*O_SHLOCK |*/ O_TRUNC | O_BINARY)
+#else
+#define	USE_OPEN_FLAGS							\
+	(O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY |		\
+	 O_RDWR | O_SHLOCK | O_TRUNC)
+#endif
+
+	if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
+		switch (type) {
+		case DB_BTREE:
+			return (__bt_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		case DB_HASH:
+			return (__hash_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		case DB_RECNO:
+			return (__rec_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		}
+	errno = EINVAL;
+	return (NULL);
+}
+
+static int
+__dberr()
+{
+	return (RET_ERROR);
+}
+
+/*
+ * __DBPANIC -- Stop.
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB structure.
+ */
+void
+__dbpanic(dbp)
+	DB *dbp;
+{
+	/* The only thing that can succeed is a close. */
+	dbp->del = (int (*)())__dberr;
+	dbp->fd = (int (*)())__dberr;
+	dbp->get = (int (*)())__dberr;
+	dbp->put = (int (*)())__dberr;
+	dbp->seq = (int (*)())__dberr;
+	dbp->sync = (int (*)())__dberr;
+}
Index: /trunk/libc/src/fbsdlibc/db/hash/Makefile.inc
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/Makefile.inc	(revision 2448)
@@ -0,0 +1,7 @@
+#       from @(#)Makefile.inc	8.1 (Berkeley) 6/4/93
+# $FreeBSD: src/lib/libc/db/hash/Makefile.inc,v 1.5 2002/11/18 09:50:54 ru Exp $
+
+.PATH: ${.CURDIR}/db/hash
+
+SRCS+=	hash.c hash_bigkey.c hash_buf.c hash_func.c hash_log2.c \
+	hash_page.c ndbm.c
Index: /trunk/libc/src/fbsdlibc/db/hash/README
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/README	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/README	(revision 2448)
@@ -0,0 +1,72 @@
+#	@(#)README	8.1 (Berkeley) 6/4/93
+
+This package implements a superset of the hsearch and dbm/ndbm libraries.
+
+Test Programs:
+	All test programs which need key/data pairs expect them entered
+	with key and data on separate lines
+
+	tcreat3.c	
+		Takes 
+			bucketsize (bsize), 
+			fill factor (ffactor), and
+			initial number of elements (nelem).  
+		Creates a hash table named hashtest containing the 
+		keys/data pairs entered from standard in.
+	thash4.c
+		Takes
+			bucketsize (bsize), 
+			fill factor (ffactor), 
+			initial number of elements (nelem)
+			bytes of cache (ncached), and
+			file from which to read data  (fname)
+		Creates a table from the key/data pairs on standard in and
+		then does a read of each key/data in fname
+	tdel.c
+		Takes
+			bucketsize (bsize), and
+			fill factor (ffactor).
+			file from which to read data (fname)
+		Reads each key/data pair from fname and deletes the
+		key from the hash table hashtest
+	tseq.c
+		Reads the key/data pairs in the file hashtest and writes them
+		to standard out.
+	tread2.c
+		Takes
+			butes of cache (ncached).
+		Reads key/data pairs from standard in and looks them up
+		in the file hashtest.
+	tverify.c
+		Reads key/data pairs from standard in, looks them up
+		in the file hashtest, and verifies that the data is
+		correct.
+
+NOTES:
+
+The file search.h is provided for using the hsearch compatible interface
+on BSD systems.  On System V derived systems, search.h should appear in 
+/usr/include.
+
+The man page ../man/db.3 explains the interface to the hashing system.
+The file hash.ps is a postscript copy of a paper explaining
+the history, implementation, and performance of the hash package.
+
+"bugs" or idiosyncracies
+
+If you have a lot of overflows, it is possible to run out of overflow
+pages.  Currently, this will cause a message to be printed on stderr.
+Eventually, this will be indicated by a return error code.
+
+If you are using the ndbm interface and exit without flushing or closing the
+file, you may lose updates since the package buffers all writes.  Also,
+the db interface only creates a single database file.  To avoid overwriting
+the user's original file, the suffix ".db" is appended to the file name
+passed to dbm_open.  Additionally, if your code "knows" about the historic
+.dir and .pag files, it will break.  
+
+There is a fundamental difference between this package and the old hsearch.
+Hsearch requires the user to maintain the keys and data in the application's
+allocated memory while hash takes care of all storage management.  The down
+side is that the byte strings passed in the ENTRY structure must be null
+terminated (both the keys and the data).
Index: /trunk/libc/src/fbsdlibc/db/hash/extern.h
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/extern.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/extern.h	(revision 2448)
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1991, 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.
+ * 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.
+ *
+ *	@(#)extern.h	8.4 (Berkeley) 6/16/94
+ * $FreeBSD: src/lib/libc/db/hash/extern.h,v 1.3 2002/03/22 09:18:22 obrien Exp $
+ */
+
+BUFHEAD	*__add_ovflpage(HTAB *, BUFHEAD *);
+int	 __addel(HTAB *, BUFHEAD *, const DBT *, const DBT *);
+int	 __big_delete(HTAB *, BUFHEAD *);
+int	 __big_insert(HTAB *, BUFHEAD *, const DBT *, const DBT *);
+int	 __big_keydata(HTAB *, BUFHEAD *, DBT *, DBT *, int);
+int	 __big_return(HTAB *, BUFHEAD *, int, DBT *, int);
+int	 __big_split(HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *,
+		int, u_int32_t, SPLIT_RETURN *);
+int	 __buf_free(HTAB *, int, int);
+void	 __buf_init(HTAB *, int);
+u_int32_t	 __call_hash(HTAB *, char *, int);
+int	 __delpair(HTAB *, BUFHEAD *, int);
+int	 __expand_table(HTAB *);
+int	 __find_bigpair(HTAB *, BUFHEAD *, int, char *, int);
+u_int16_t	 __find_last_page(HTAB *, BUFHEAD **);
+void	 __free_ovflpage(HTAB *, BUFHEAD *);
+BUFHEAD	*__get_buf(HTAB *, u_int32_t, BUFHEAD *, int);
+int	 __get_page(HTAB *, char *, u_int32_t, int, int, int);
+int	 __ibitmap(HTAB *, int, int, int);
+u_int32_t	 __log2(u_int32_t);
+int	 __put_page(HTAB *, char *, u_int32_t, int, int);
+void	 __reclaim_buf(HTAB *, BUFHEAD *);
+int	 __split_page(HTAB *, u_int32_t, u_int32_t);
+
+/* Default hash routine. */
+extern u_int32_t (*__default_hash)(const void *, size_t);
+
+#ifdef HASH_STATISTICS
+extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
+#endif
Index: /trunk/libc/src/fbsdlibc/db/hash/hash.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/hash.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/hash.c	(revision 2448)
@@ -0,0 +1,1016 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash.c	8.9 (Berkeley) 6/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash.c,v 1.11 2002/03/21 22:46:26 obrien Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+#include "un-namespace.h"
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int   alloc_segs(HTAB *, int);
+static int   flush_meta(HTAB *);
+static int   hash_access(HTAB *, ACTION, DBT *, DBT *);
+static int   hash_close(DB *);
+static int   hash_delete(const DB *, const DBT *, u_int32_t);
+static int   hash_fd(const DB *);
+static int   hash_get(const DB *, const DBT *, DBT *, u_int32_t);
+static int   hash_put(const DB *, DBT *, const DBT *, u_int32_t);
+static void *hash_realloc(SEGMENT **, int, int);
+static int   hash_seq(const DB *, DBT *, DBT *, u_int32_t);
+static int   hash_sync(const DB *, u_int32_t);
+static int   hdestroy(HTAB *);
+static HTAB *init_hash(HTAB *, const char *, HASHINFO *);
+static int   init_htab(HTAB *, int);
+#if BYTE_ORDER == LITTLE_ENDIAN
+static void  swap_header(HTAB *);
+static void  swap_header_copy(HASHHDR *, HASHHDR *);
+#endif
+
+/* Fast arithmetic, relying on powers of 2, */
+#define MOD(x, y)		((x) & ((y) - 1))
+
+#define RETURN_ERROR(ERR, LOC)	{ save_errno = ERR; goto LOC; }
+
+/* Return values */
+#define	SUCCESS	 (0)
+#define	ERROR	(-1)
+#define	ABNORMAL (1)
+
+#ifdef HASH_STATISTICS
+int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
+#endif
+
+/************************** INTERFACE ROUTINES ***************************/
+/* OPEN/CLOSE */
+
+extern DB *
+__hash_open(file, flags, mode, info, dflags)
+	const char *file;
+	int flags, mode, dflags;
+	const HASHINFO *info;	/* Special directives for create */
+{
+	HTAB *hashp;
+	struct stat statbuf;
+	DB *dbp;
+	int bpages, hdrsize, new_table, nsegs, save_errno;
+
+	if ((flags & O_ACCMODE) == O_WRONLY) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
+		return (NULL);
+	hashp->fp = -1;
+
+	/*
+	 * Even if user wants write only, we need to be able to read
+	 * the actual file, so we need to open it read/write. But, the
+	 * field in the hashp structure needs to be accurate so that
+	 * we can check accesses.
+	 */
+	hashp->flags = flags;
+
+	new_table = 0;
+	if (!file || (flags & O_TRUNC) ||
+	    (stat(file, &statbuf) && (errno == ENOENT))) {
+		if (errno == ENOENT)
+			errno = 0; /* Just in case someone looks at errno */
+		new_table = 1;
+	}
+	if (file) {
+#ifdef __EMX__
+		if ((hashp->fp = _open(file, flags | O_BINARY, mode)) == -1)
+#else
+		if ((hashp->fp = _open(file, flags, mode)) == -1)
+#endif
+			RETURN_ERROR(errno, error0);
+
+		/* if the .db file is empty, and we had permission to create
+		   a new .db file, then reinitialize the database */
+		if ((flags & O_CREAT) &&
+		     _fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0)
+			new_table = 1;
+
+		(void)_fcntl(hashp->fp, F_SETFD, 1);
+	}
+	if (new_table) {
+		if (!(hashp = init_hash(hashp, file, (HASHINFO *)info)))
+			RETURN_ERROR(errno, error1);
+	} else {
+		/* Table already exists */
+		if (info && info->hash)
+			hashp->hash = info->hash;
+		else
+			hashp->hash = __default_hash;
+
+		hdrsize = _read(hashp->fp, &hashp->hdr, sizeof(HASHHDR));
+#if BYTE_ORDER == LITTLE_ENDIAN
+		swap_header(hashp);
+#endif
+		if (hdrsize == -1)
+			RETURN_ERROR(errno, error1);
+		if (hdrsize != sizeof(HASHHDR))
+			RETURN_ERROR(EFTYPE, error1);
+		/* Verify file type, versions and hash function */
+		if (hashp->MAGIC != HASHMAGIC)
+			RETURN_ERROR(EFTYPE, error1);
+#define	OLDHASHVERSION	1
+		if (hashp->VERSION != HASHVERSION &&
+		    hashp->VERSION != OLDHASHVERSION)
+			RETURN_ERROR(EFTYPE, error1);
+		if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
+			RETURN_ERROR(EFTYPE, error1);
+		/*
+		 * Figure out how many segments we need.  Max_Bucket is the
+		 * maximum bucket number, so the number of buckets is
+		 * max_bucket + 1.
+		 */
+		nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
+			 hashp->SGSIZE;
+		hashp->nsegs = 0;
+		if (alloc_segs(hashp, nsegs))
+			/*
+			 * If alloc_segs fails, table will have been destroyed
+			 * and errno will have been set.
+			 */
+			return (NULL);
+		/* Read in bitmaps */
+		bpages = (hashp->SPARES[hashp->OVFL_POINT] +
+		    (hashp->BSIZE << BYTE_SHIFT) - 1) >>
+		    (hashp->BSHIFT + BYTE_SHIFT);
+
+		hashp->nmaps = bpages;
+		(void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *));
+	}
+
+	/* Initialize Buffer Manager */
+	if (info && info->cachesize)
+		__buf_init(hashp, info->cachesize);
+	else
+		__buf_init(hashp, DEF_BUFSIZE);
+
+	hashp->new_file = new_table;
+	hashp->save_file = file && (hashp->flags & O_RDWR);
+	hashp->cbucket = -1;
+	if (!(dbp = (DB *)malloc(sizeof(DB)))) {
+		save_errno = errno;
+		hdestroy(hashp);
+		errno = save_errno;
+		return (NULL);
+	}
+	dbp->internal = hashp;
+	dbp->close = hash_close;
+	dbp->del = hash_delete;
+	dbp->fd = hash_fd;
+	dbp->get = hash_get;
+	dbp->put = hash_put;
+	dbp->seq = hash_seq;
+	dbp->sync = hash_sync;
+	dbp->type = DB_HASH;
+
+#ifdef DEBUG
+	(void)fprintf(stderr,
+"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
+	    "init_htab:",
+	    "TABLE POINTER   ", hashp,
+	    "BUCKET SIZE     ", hashp->BSIZE,
+	    "BUCKET SHIFT    ", hashp->BSHIFT,
+	    "DIRECTORY SIZE  ", hashp->DSIZE,
+	    "SEGMENT SIZE    ", hashp->SGSIZE,
+	    "SEGMENT SHIFT   ", hashp->SSHIFT,
+	    "FILL FACTOR     ", hashp->FFACTOR,
+	    "MAX BUCKET      ", hashp->MAX_BUCKET,
+	    "OVFL POINT	     ", hashp->OVFL_POINT,
+	    "LAST FREED      ", hashp->LAST_FREED,
+	    "HIGH MASK       ", hashp->HIGH_MASK,
+	    "LOW  MASK       ", hashp->LOW_MASK,
+	    "NSEGS           ", hashp->nsegs,
+	    "NKEYS           ", hashp->NKEYS);
+#endif
+#ifdef HASH_STATISTICS
+	hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
+#endif
+	return (dbp);
+
+error1:
+	if (hashp != NULL)
+		(void)_close(hashp->fp);
+
+error0:
+	free(hashp);
+	errno = save_errno;
+	return (NULL);
+}
+
+static int
+hash_close(dbp)
+	DB *dbp;
+{
+	HTAB *hashp;
+	int retval;
+
+	if (!dbp)
+		return (ERROR);
+
+	hashp = (HTAB *)dbp->internal;
+	retval = hdestroy(hashp);
+	free(dbp);
+	return (retval);
+}
+
+static int
+hash_fd(dbp)
+	const DB *dbp;
+{
+	HTAB *hashp;
+
+	if (!dbp)
+		return (ERROR);
+
+	hashp = (HTAB *)dbp->internal;
+	if (hashp->fp == -1) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (hashp->fp);
+}
+
+/************************** LOCAL CREATION ROUTINES **********************/
+static HTAB *
+init_hash(hashp, file, info)
+	HTAB *hashp;
+	const char *file;
+	HASHINFO *info;
+{
+	struct stat statbuf;
+	int nelem;
+
+	nelem = 1;
+	hashp->NKEYS = 0;
+	hashp->LORDER = BYTE_ORDER;
+	hashp->BSIZE = DEF_BUCKET_SIZE;
+	hashp->BSHIFT = DEF_BUCKET_SHIFT;
+	hashp->SGSIZE = DEF_SEGSIZE;
+	hashp->SSHIFT = DEF_SEGSIZE_SHIFT;
+	hashp->DSIZE = DEF_DIRSIZE;
+	hashp->FFACTOR = DEF_FFACTOR;
+	hashp->hash = __default_hash;
+	memset(hashp->SPARES, 0, sizeof(hashp->SPARES));
+	memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS));
+
+	/* Fix bucket size to be optimal for file system */
+	if (file != NULL) {
+		if (stat(file, &statbuf))
+			return (NULL);
+		hashp->BSIZE = statbuf.st_blksize;
+		hashp->BSHIFT = __log2(hashp->BSIZE);
+	}
+
+	if (info) {
+		if (info->bsize) {
+			/* Round pagesize up to power of 2 */
+			hashp->BSHIFT = __log2(info->bsize);
+			hashp->BSIZE = 1 << hashp->BSHIFT;
+			if (hashp->BSIZE > MAX_BSIZE) {
+				errno = EINVAL;
+				return (NULL);
+			}
+		}
+		if (info->ffactor)
+			hashp->FFACTOR = info->ffactor;
+		if (info->hash)
+			hashp->hash = info->hash;
+		if (info->nelem)
+			nelem = info->nelem;
+		if (info->lorder) {
+			if (info->lorder != BIG_ENDIAN &&
+			    info->lorder != LITTLE_ENDIAN) {
+				errno = EINVAL;
+				return (NULL);
+			}
+			hashp->LORDER = info->lorder;
+		}
+	}
+	/* init_htab should destroy the table and set errno if it fails */
+	if (init_htab(hashp, nelem))
+		return (NULL);
+	else
+		return (hashp);
+}
+/*
+ * This calls alloc_segs which may run out of memory.  Alloc_segs will destroy
+ * the table and set errno, so we just pass the error information along.
+ *
+ * Returns 0 on No Error
+ */
+static int
+init_htab(hashp, nelem)
+	HTAB *hashp;
+	int nelem;
+{
+	int nbuckets, nsegs;
+	int l2;
+
+	/*
+	 * Divide number of elements by the fill factor and determine a
+	 * desired number of buckets.  Allocate space for the next greater
+	 * power of two number of buckets.
+	 */
+	nelem = (nelem - 1) / hashp->FFACTOR + 1;
+
+	l2 = __log2(MAX(nelem, 2));
+	nbuckets = 1 << l2;
+
+	hashp->SPARES[l2] = l2 + 1;
+	hashp->SPARES[l2 + 1] = l2 + 1;
+	hashp->OVFL_POINT = l2;
+	hashp->LAST_FREED = 2;
+
+	/* First bitmap page is at: splitpoint l2 page offset 1 */
+	if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0))
+		return (-1);
+
+	hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1;
+	hashp->HIGH_MASK = (nbuckets << 1) - 1;
+	hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >>
+	    hashp->BSHIFT) + 1;
+
+	nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
+	nsegs = 1 << __log2(nsegs);
+
+	if (nsegs > hashp->DSIZE)
+		hashp->DSIZE = nsegs;
+	return (alloc_segs(hashp, nsegs));
+}
+
+/********************** DESTROY/CLOSE ROUTINES ************************/
+
+/*
+ * Flushes any changes to the file if necessary and destroys the hashp
+ * structure, freeing all allocated space.
+ */
+static int
+hdestroy(hashp)
+	HTAB *hashp;
+{
+	int i, save_errno;
+
+	save_errno = 0;
+
+#ifdef HASH_STATISTICS
+	(void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n",
+	    hash_accesses, hash_collisions);
+	(void)fprintf(stderr, "hdestroy: expansions %ld\n",
+	    hash_expansions);
+	(void)fprintf(stderr, "hdestroy: overflows %ld\n",
+	    hash_overflows);
+	(void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n",
+	    hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs);
+
+	for (i = 0; i < NCACHED; i++)
+		(void)fprintf(stderr,
+		    "spares[%d] = %d\n", i, hashp->SPARES[i]);
+#endif
+	/*
+	 * Call on buffer manager to free buffers, and if required,
+	 * write them to disk.
+	 */
+	if (__buf_free(hashp, 1, hashp->save_file))
+		save_errno = errno;
+	if (hashp->dir) {
+		free(*hashp->dir);	/* Free initial segments */
+		/* Free extra segments */
+		while (hashp->exsegs--)
+			free(hashp->dir[--hashp->nsegs]);
+		free(hashp->dir);
+	}
+	if (flush_meta(hashp) && !save_errno)
+		save_errno = errno;
+	/* Free Bigmaps */
+	for (i = 0; i < hashp->nmaps; i++)
+		if (hashp->mapp[i])
+			free(hashp->mapp[i]);
+
+	if (hashp->fp != -1)
+		(void)_close(hashp->fp);
+#ifdef __EMX__
+	if (hashp->tempname != NULL) {
+		(void)unlink (hashp->tempname);
+		free (hashp->tempname);
+		}
+#endif /* __EMX__ */
+
+	free(hashp);
+
+	if (save_errno) {
+		errno = save_errno;
+		return (ERROR);
+	}
+	return (SUCCESS);
+}
+/*
+ * Write modified pages to disk
+ *
+ * Returns:
+ *	 0 == OK
+ *	-1 ERROR
+ */
+static int
+hash_sync(dbp, flags)
+	const DB *dbp;
+	u_int32_t flags;
+{
+	HTAB *hashp;
+
+	if (flags != 0) {
+		errno = EINVAL;
+		return (ERROR);
+	}
+
+	if (!dbp)
+		return (ERROR);
+
+	hashp = (HTAB *)dbp->internal;
+	if (!hashp->save_file)
+		return (0);
+	if (__buf_free(hashp, 0, 1) || flush_meta(hashp))
+		return (ERROR);
+	hashp->new_file = 0;
+	return (0);
+}
+
+/*
+ * Returns:
+ *	 0 == OK
+ *	-1 indicates that errno should be set
+ */
+static int
+flush_meta(hashp)
+	HTAB *hashp;
+{
+	HASHHDR *whdrp;
+#if BYTE_ORDER == LITTLE_ENDIAN
+	HASHHDR whdr;
+#endif
+	int fp, i, wsize;
+
+	if (!hashp->save_file)
+		return (0);
+	hashp->MAGIC = HASHMAGIC;
+	hashp->VERSION = HASHVERSION;
+	hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY));
+
+	fp = hashp->fp;
+	whdrp = &hashp->hdr;
+#if BYTE_ORDER == LITTLE_ENDIAN
+	whdrp = &whdr;
+	swap_header_copy(&hashp->hdr, whdrp);
+#endif
+	if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
+	    ((wsize = _write(fp, whdrp, sizeof(HASHHDR))) == -1))
+		return (-1);
+	else
+		if (wsize != sizeof(HASHHDR)) {
+			errno = EFTYPE;
+			hashp->dbmerrno = errno; /* bird: errno */
+			return (-1);
+		}
+	for (i = 0; i < NCACHED; i++)
+		if (hashp->mapp[i])
+			if (__put_page(hashp, (char *)hashp->mapp[i],
+				hashp->BITMAPS[i], 0, 1))
+				return (-1);
+	return (0);
+}
+
+/*******************************SEARCH ROUTINES *****************************/
+/*
+ * All the access routines return
+ *
+ * Returns:
+ *	 0 on SUCCESS
+ *	 1 to indicate an external ERROR (i.e. key not found, etc)
+ *	-1 to indicate an internal ERROR (i.e. out of memory, etc)
+ */
+static int
+hash_get(dbp, key, data, flag)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int32_t flag;
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag) {
+		hashp->dbmerrno = errno = EINVAL;   /* bird: errno */
+		return (ERROR);
+	}
+	return (hash_access(hashp, HASH_GET, (DBT *)key, data));
+}
+
+static int
+hash_put(dbp, key, data, flag)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int32_t flag;
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag && flag != R_NOOVERWRITE) {
+		hashp->dbmerrno = EINVAL;           /* bird: errno */
+		errno = EINVAL;
+		return (ERROR);
+	}
+	if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+		hashp->dbmerrno = errno = EPERM;    /* bird: errno */
+		return (ERROR);
+	}
+	return (hash_access(hashp, flag == R_NOOVERWRITE ?
+	    HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data));
+}
+
+static int
+hash_delete(dbp, key, flag)
+	const DB *dbp;
+	const DBT *key;
+	u_int32_t flag;		/* Ignored */
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag && flag != R_CURSOR) {
+		hashp->dbmerrno = errno = EINVAL;   /* bird: errno */
+		return (ERROR);
+	}
+	if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+		hashp->dbmerrno = errno = EPERM;    /* bird: errno */
+		return (ERROR);
+	}
+	return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
+}
+
+/*
+ * Assume that hashp has been set in wrapper routine.
+ */
+static int
+hash_access(hashp, action, key, val)
+	HTAB *hashp;
+	ACTION action;
+	DBT *key, *val;
+{
+	BUFHEAD *rbufp;
+	BUFHEAD *bufp, *save_bufp;
+	u_int16_t *bp;
+	int n, ndx, off, size;
+	char *kp;
+	u_int16_t pageno;
+
+#ifdef HASH_STATISTICS
+	hash_accesses++;
+#endif
+
+	off = hashp->BSIZE;
+	size = key->size;
+	kp = (char *)key->data;
+	rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0);
+	if (!rbufp)
+		return (ERROR);
+	save_bufp = rbufp;
+
+	/* Pin the bucket chain */
+	rbufp->flags |= BUF_PIN;
+	for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;)
+		if (bp[1] >= REAL_KEY) {
+			/* Real key/data pair */
+			if (size == off - *bp &&
+			    memcmp(kp, rbufp->page + *bp, size) == 0)
+				goto found;
+			off = bp[1];
+#ifdef HASH_STATISTICS
+			hash_collisions++;
+#endif
+			bp += 2;
+			ndx += 2;
+		} else if (bp[1] == OVFLPAGE) {
+			rbufp = __get_buf(hashp, *bp, rbufp, 0);
+			if (!rbufp) {
+				save_bufp->flags &= ~BUF_PIN;
+				return (ERROR);
+			}
+			/* FOR LOOP INIT */
+			bp = (u_int16_t *)rbufp->page;
+			n = *bp++;
+			ndx = 1;
+			off = hashp->BSIZE;
+		} else if (bp[1] < REAL_KEY) {
+			if ((ndx =
+			    __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0)
+				goto found;
+			if (ndx == -2) {
+				bufp = rbufp;
+				if (!(pageno =
+				    __find_last_page(hashp, &bufp))) {
+					ndx = 0;
+					rbufp = bufp;
+					break;	/* FOR */
+				}
+				rbufp = __get_buf(hashp, pageno, bufp, 0);
+				if (!rbufp) {
+					save_bufp->flags &= ~BUF_PIN;
+					return (ERROR);
+				}
+				/* FOR LOOP INIT */
+				bp = (u_int16_t *)rbufp->page;
+				n = *bp++;
+				ndx = 1;
+				off = hashp->BSIZE;
+			} else {
+				save_bufp->flags &= ~BUF_PIN;
+				return (ERROR);
+			}
+		}
+
+	/* Not found */
+	switch (action) {
+	case HASH_PUT:
+	case HASH_PUTNEW:
+		if (__addel(hashp, rbufp, key, val)) {
+			save_bufp->flags &= ~BUF_PIN;
+			return (ERROR);
+		} else {
+			save_bufp->flags &= ~BUF_PIN;
+			return (SUCCESS);
+		}
+	case HASH_GET:
+	case HASH_DELETE:
+	default:
+		save_bufp->flags &= ~BUF_PIN;
+		return (ABNORMAL);
+	}
+
+found:
+	switch (action) {
+	case HASH_PUTNEW:
+		save_bufp->flags &= ~BUF_PIN;
+		return (ABNORMAL);
+	case HASH_GET:
+		bp = (u_int16_t *)rbufp->page;
+		if (bp[ndx + 1] < REAL_KEY) {
+			if (__big_return(hashp, rbufp, ndx, val, 0))
+				return (ERROR);
+		} else {
+			val->data = (u_char *)rbufp->page + (int)bp[ndx + 1];
+			val->size = bp[ndx] - bp[ndx + 1];
+		}
+		break;
+	case HASH_PUT:
+		if ((__delpair(hashp, rbufp, ndx)) ||
+		    (__addel(hashp, rbufp, key, val))) {
+			save_bufp->flags &= ~BUF_PIN;
+			return (ERROR);
+		}
+		break;
+	case HASH_DELETE:
+		if (__delpair(hashp, rbufp, ndx))
+			return (ERROR);
+		break;
+	default:
+		abort();
+	}
+	save_bufp->flags &= ~BUF_PIN;
+	return (SUCCESS);
+}
+
+static int
+hash_seq(dbp, key, data, flag)
+	const DB *dbp;
+	DBT *key, *data;
+	u_int32_t flag;
+{
+	u_int32_t bucket;
+	BUFHEAD *bufp;
+	HTAB *hashp;
+	u_int16_t *bp, ndx;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag && flag != R_FIRST && flag != R_NEXT) {
+		hashp->dbmerrno = errno = EINVAL;   /* bird: errno */
+		return (ERROR);
+	}
+#ifdef HASH_STATISTICS
+	hash_accesses++;
+#endif
+	if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
+		hashp->cbucket = 0;
+		hashp->cndx = 1;
+		hashp->cpage = NULL;
+	}
+
+	for (bp = NULL; !bp || !bp[0]; ) {
+		if (!(bufp = hashp->cpage)) {
+			for (bucket = hashp->cbucket;
+			    bucket <= hashp->MAX_BUCKET;
+			    bucket++, hashp->cndx = 1) {
+				bufp = __get_buf(hashp, bucket, NULL, 0);
+				if (!bufp)
+					return (ERROR);
+				hashp->cpage = bufp;
+				bp = (u_int16_t *)bufp->page;
+				if (bp[0])
+					break;
+			}
+			hashp->cbucket = bucket;
+			if (hashp->cbucket > hashp->MAX_BUCKET) {
+				hashp->cbucket = -1;
+				return (ABNORMAL);
+			}
+		} else
+			bp = (u_int16_t *)hashp->cpage->page;
+
+#ifdef DEBUG
+		assert(bp);
+		assert(bufp);
+#endif
+		while (bp[hashp->cndx + 1] == OVFLPAGE) {
+			bufp = hashp->cpage =
+			    __get_buf(hashp, bp[hashp->cndx], bufp, 0);
+			if (!bufp)
+				return (ERROR);
+			bp = (u_int16_t *)(bufp->page);
+			hashp->cndx = 1;
+		}
+		if (!bp[0]) {
+			hashp->cpage = NULL;
+			++hashp->cbucket;
+		}
+	}
+	ndx = hashp->cndx;
+	if (bp[ndx + 1] < REAL_KEY) {
+		if (__big_keydata(hashp, bufp, key, data, 1))
+			return (ERROR);
+	} else {
+		key->data = (u_char *)hashp->cpage->page + bp[ndx];
+		key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
+		data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
+		data->size = bp[ndx] - bp[ndx + 1];
+		ndx += 2;
+		if (ndx > bp[0]) {
+			hashp->cpage = NULL;
+			hashp->cbucket++;
+			hashp->cndx = 1;
+		} else
+			hashp->cndx = ndx;
+	}
+	return (SUCCESS);
+}
+
+/********************************* UTILITIES ************************/
+
+/*
+ * Returns:
+ *	 0 ==> OK
+ *	-1 ==> Error
+ */
+extern int
+__expand_table(hashp)
+	HTAB *hashp;
+{
+	u_int32_t old_bucket, new_bucket;
+	int dirsize, new_segnum, spare_ndx;
+
+#ifdef HASH_STATISTICS
+	hash_expansions++;
+#endif
+	new_bucket = ++hashp->MAX_BUCKET;
+	old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK);
+
+	new_segnum = new_bucket >> hashp->SSHIFT;
+
+	/* Check if we need a new segment */
+	if (new_segnum >= hashp->nsegs) {
+		/* Check if we need to expand directory */
+		if (new_segnum >= hashp->DSIZE) {
+			/* Reallocate directory */
+			dirsize = hashp->DSIZE * sizeof(SEGMENT *);
+			if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1))
+				return (-1);
+			hashp->DSIZE = dirsize << 1;
+		}
+		if ((hashp->dir[new_segnum] =
+		    (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL)
+			return (-1);
+		hashp->exsegs++;
+		hashp->nsegs++;
+	}
+	/*
+	 * If the split point is increasing (MAX_BUCKET's log base 2
+	 * * increases), we need to copy the current contents of the spare
+	 * split bucket to the next bucket.
+	 */
+	spare_ndx = __log2(hashp->MAX_BUCKET + 1);
+	if (spare_ndx > hashp->OVFL_POINT) {
+		hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT];
+		hashp->OVFL_POINT = spare_ndx;
+	}
+
+	if (new_bucket > hashp->HIGH_MASK) {
+		/* Starting a new doubling */
+		hashp->LOW_MASK = hashp->HIGH_MASK;
+		hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK;
+	}
+	/* Relocate records to the new bucket */
+	return (__split_page(hashp, old_bucket, new_bucket));
+}
+
+/*
+ * If realloc guarantees that the pointer is not destroyed if the realloc
+ * fails, then this routine can go away.
+ */
+static void *
+hash_realloc(p_ptr, oldsize, newsize)
+	SEGMENT **p_ptr;
+	int oldsize, newsize;
+{
+	void *p;
+
+	if ( (p = malloc(newsize)) ) {
+		memmove(p, *p_ptr, oldsize);
+		memset((char *)p + oldsize, 0, newsize - oldsize);
+		free(*p_ptr);
+		*p_ptr = p;
+	}
+	return (p);
+}
+
+extern u_int32_t
+__call_hash(hashp, k, len)
+	HTAB *hashp;
+	char *k;
+	int len;
+{
+	int n, bucket;
+
+	n = hashp->hash(k, len);
+	bucket = n & hashp->HIGH_MASK;
+	if (bucket > hashp->MAX_BUCKET)
+		bucket = bucket & hashp->LOW_MASK;
+	return (bucket);
+}
+
+/*
+ * Allocate segment table.  On error, destroy the table and set errno.
+ *
+ * Returns 0 on success
+ */
+static int
+alloc_segs(hashp, nsegs)
+	HTAB *hashp;
+	int nsegs;
+{
+	int i;
+	SEGMENT store;
+
+	int save_errno;
+
+	if ((hashp->dir =
+	    (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) {
+		save_errno = errno;
+		(void)hdestroy(hashp);
+		errno = save_errno;
+		return (-1);
+	}
+	/* Allocate segments */
+	if ((store =
+	    (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) {
+		save_errno = errno;
+		(void)hdestroy(hashp);
+		errno = save_errno;
+		return (-1);
+	}
+	for (i = 0; i < nsegs; i++, hashp->nsegs++)
+		hashp->dir[i] = &store[i << hashp->SSHIFT];
+	return (0);
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+/*
+ * Hashp->hdr needs to be byteswapped.
+ */
+static void
+swap_header_copy(srcp, destp)
+	HASHHDR *srcp, *destp;
+{
+	int i;
+
+	P_32_COPY(srcp->magic, destp->magic);
+	P_32_COPY(srcp->version, destp->version);
+	P_32_COPY(srcp->lorder, destp->lorder);
+	P_32_COPY(srcp->bsize, destp->bsize);
+	P_32_COPY(srcp->bshift, destp->bshift);
+	P_32_COPY(srcp->dsize, destp->dsize);
+	P_32_COPY(srcp->ssize, destp->ssize);
+	P_32_COPY(srcp->sshift, destp->sshift);
+	P_32_COPY(srcp->ovfl_point, destp->ovfl_point);
+	P_32_COPY(srcp->last_freed, destp->last_freed);
+	P_32_COPY(srcp->max_bucket, destp->max_bucket);
+	P_32_COPY(srcp->high_mask, destp->high_mask);
+	P_32_COPY(srcp->low_mask, destp->low_mask);
+	P_32_COPY(srcp->ffactor, destp->ffactor);
+	P_32_COPY(srcp->nkeys, destp->nkeys);
+	P_32_COPY(srcp->hdrpages, destp->hdrpages);
+	P_32_COPY(srcp->h_charkey, destp->h_charkey);
+	for (i = 0; i < NCACHED; i++) {
+		P_32_COPY(srcp->spares[i], destp->spares[i]);
+		P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]);
+	}
+}
+
+static void
+swap_header(hashp)
+	HTAB *hashp;
+{
+	HASHHDR *hdrp;
+	int i;
+
+	hdrp = &hashp->hdr;
+
+	M_32_SWAP(hdrp->magic);
+	M_32_SWAP(hdrp->version);
+	M_32_SWAP(hdrp->lorder);
+	M_32_SWAP(hdrp->bsize);
+	M_32_SWAP(hdrp->bshift);
+	M_32_SWAP(hdrp->dsize);
+	M_32_SWAP(hdrp->ssize);
+	M_32_SWAP(hdrp->sshift);
+	M_32_SWAP(hdrp->ovfl_point);
+	M_32_SWAP(hdrp->last_freed);
+	M_32_SWAP(hdrp->max_bucket);
+	M_32_SWAP(hdrp->high_mask);
+	M_32_SWAP(hdrp->low_mask);
+	M_32_SWAP(hdrp->ffactor);
+	M_32_SWAP(hdrp->nkeys);
+	M_32_SWAP(hdrp->hdrpages);
+	M_32_SWAP(hdrp->h_charkey);
+	for (i = 0; i < NCACHED; i++) {
+		M_32_SWAP(hdrp->spares[i]);
+		M_16_SWAP(hdrp->bitmaps[i]);
+	}
+}
+#endif
Index: /trunk/libc/src/fbsdlibc/db/hash/hash.h
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/hash.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/hash.h	(revision 2448)
@@ -0,0 +1,298 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ *
+ *	@(#)hash.h	8.3 (Berkeley) 5/31/94
+ * $FreeBSD: src/lib/libc/db/hash/hash.h,v 1.6 2002/03/21 22:46:26 obrien Exp $
+ */
+
+/* Operations */
+typedef enum {
+	HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
+} ACTION;
+
+/* Buffer Management structures */
+typedef struct _bufhead BUFHEAD;
+
+struct _bufhead {
+	BUFHEAD		*prev;		/* LRU links */
+	BUFHEAD		*next;		/* LRU links */
+	BUFHEAD		*ovfl;		/* Overflow page buffer header */
+	u_int32_t	 addr;		/* Address of this page */
+	char		*page;		/* Actual page data */
+	char	 	flags;
+#define	BUF_MOD		0x0001
+#define BUF_DISK	0x0002
+#define	BUF_BUCKET	0x0004
+#define	BUF_PIN		0x0008
+};
+
+#define IS_BUCKET(X)	((X) & BUF_BUCKET)
+
+typedef BUFHEAD **SEGMENT;
+
+/* Hash Table Information */
+typedef struct hashhdr {		/* Disk resident portion */
+	int		magic;		/* Magic NO for hash tables */
+	int		version;	/* Version ID */
+	u_int32_t	lorder;		/* Byte Order */
+	int		bsize;		/* Bucket/Page Size */
+	int		bshift;		/* Bucket shift */
+	int		dsize;		/* Directory Size */
+	int		ssize;		/* Segment Size */
+	int		sshift;		/* Segment shift */
+	int		ovfl_point;	/* Where overflow pages are being
+					 * allocated */
+	int		last_freed;	/* Last overflow page freed */
+	int		max_bucket;	/* ID of Maximum bucket in use */
+	int		high_mask;	/* Mask to modulo into entire table */
+	int		low_mask;	/* Mask to modulo into lower half of
+					 * table */
+	int		ffactor;	/* Fill factor */
+	int		nkeys;		/* Number of keys in hash table */
+	int		hdrpages;	/* Size of table header */
+	int		h_charkey;	/* value of hash(CHARKEY) */
+#define NCACHED	32			/* number of bit maps and spare
+					 * points */
+	int		spares[NCACHED];/* spare pages for overflow */
+	u_int16_t	bitmaps[NCACHED];	/* address of overflow page
+						 * bitmaps */
+} HASHHDR;
+
+typedef struct htab	 {		/* Memory resident data structure */
+	HASHHDR 	hdr;		/* Header */
+	int		nsegs;		/* Number of allocated segments */
+	int		exsegs;		/* Number of extra allocated
+					 * segments */
+	u_int32_t			/* Hash function */
+	    (*hash)(const void *, size_t);
+	int		flags;		/* Flag values */
+	int		fp;		/* File pointer */
+	char		*tmp_buf;	/* Temporary Buffer for BIG data */
+	char		*tmp_key;	/* Temporary Buffer for BIG keys */
+	BUFHEAD 	*cpage;		/* Current page */
+	int		cbucket;	/* Current bucket */
+	int		cndx;		/* Index of next item on cpage */
+        /* bird: this used to be errno but that crashes with the errno define in errno.h and stdlib.h. */
+	int		dbmerrno;	/* Error Number -- for DBM
+					 * compatability */
+	int		new_file;	/* Indicates if fd is backing store
+					 * or no */
+	int		save_file;	/* Indicates whether we need to flush
+					 * file at
+					 * exit */
+	u_int32_t	*mapp[NCACHED];	/* Pointers to page maps */
+	int		nmaps;		/* Initial number of bitmaps */
+	int		nbufs;		/* Number of buffers left to
+					 * allocate */
+	BUFHEAD 	bufhead;	/* Header of buffer lru list */
+	SEGMENT 	*dir;		/* Hash Bucket directory */
+#ifdef __EMX__
+	char		*tempname;	/* Name of temporary file */
+#endif /* __EMX__ */
+} HTAB;
+
+/*
+ * Constants
+ */
+#define	MAX_BSIZE		65536		/* 2^16 */
+#define MIN_BUFFERS		6
+#define MINHDRSIZE		512
+#define DEF_BUFSIZE		65536		/* 64 K */
+#define DEF_BUCKET_SIZE		4096
+#define DEF_BUCKET_SHIFT	12		/* log2(BUCKET) */
+#define DEF_SEGSIZE		256
+#define DEF_SEGSIZE_SHIFT	8		/* log2(SEGSIZE)	 */
+#define DEF_DIRSIZE		256
+#define DEF_FFACTOR		65536
+#define MIN_FFACTOR		4
+#define SPLTMAX			8
+#define CHARKEY			"%$sniglet^&"
+#define NUMKEY			1038583
+#define BYTE_SHIFT		3
+#define INT_TO_BYTE		2
+#define INT_BYTE_SHIFT		5
+#define ALL_SET			((u_int32_t)0xFFFFFFFF)
+#define ALL_CLEAR		0
+
+#define PTROF(X)	((BUFHEAD *)((ptrdiff_t)(X)&~0x3))
+#define ISMOD(X)	((u_int32_t)(ptrdiff_t)(X)&0x1)
+#define DOMOD(X)	((X) = (char *)((ptrdiff_t)(X)|0x1))
+#define ISDISK(X)	((u_int32_t)(ptrdiff_t)(X)&0x2)
+#define DODISK(X)	((X) = (char *)((ptrdiff_t)(X)|0x2))
+
+#define BITS_PER_MAP	32
+
+/* Given the address of the beginning of a big map, clear/set the nth bit */
+#define CLRBIT(A, N)	((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
+#define SETBIT(A, N)	((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
+#define ISSET(A, N)	((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
+
+/* Overflow management */
+/*
+ * Overflow page numbers are allocated per split point.  At each doubling of
+ * the table, we can allocate extra pages.  So, an overflow page number has
+ * the top 5 bits indicate which split point and the lower 11 bits indicate
+ * which page at that split point is indicated (pages within split points are
+ * numberered starting with 1).
+ */
+
+#define SPLITSHIFT	11
+#define SPLITMASK	0x7FF
+#define SPLITNUM(N)	(((u_int32_t)(N)) >> SPLITSHIFT)
+#define OPAGENUM(N)	((N) & SPLITMASK)
+#define	OADDR_OF(S,O)	((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O))
+
+#define BUCKET_TO_PAGE(B) \
+	(B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0)
+#define OADDR_TO_PAGE(B) 	\
+	BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
+
+/*
+ * page.h contains a detailed description of the page format.
+ *
+ * Normally, keys and data are accessed from offset tables in the top of
+ * each page which point to the beginning of the key and data.  There are
+ * four flag values which may be stored in these offset tables which indicate
+ * the following:
+ *
+ *
+ * OVFLPAGE	Rather than a key data pair, this pair contains
+ *		the address of an overflow page.  The format of
+ *		the pair is:
+ *		    OVERFLOW_PAGE_NUMBER OVFLPAGE
+ *
+ * PARTIAL_KEY	This must be the first key/data pair on a page
+ *		and implies that page contains only a partial key.
+ *		That is, the key is too big to fit on a single page
+ *		so it starts on this page and continues on the next.
+ *		The format of the page is:
+ *		    KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
+ *
+ *		    KEY_OFF -- offset of the beginning of the key
+ *		    PARTIAL_KEY -- 1
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    OVFLPAGE -- 0
+ *
+ * FULL_KEY	This must be the first key/data pair on the page.  It
+ *		is used in two cases.
+ *
+ *		Case 1:
+ *		    There is a complete key on the page but no data
+ *		    (because it wouldn't fit).  The next page contains
+ *		    the data.
+ *
+ *		    Page format it:
+ *		    KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
+ *
+ *		    KEY_OFF -- offset of the beginning of the key
+ *		    FULL_KEY -- 2
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    OVFLPAGE -- 0
+ *
+ *		Case 2:
+ *		    This page contains no key, but part of a large
+ *		    data field, which is continued on the next page.
+ *
+ *		    Page format it:
+ *		    DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
+ *
+ *		    KEY_OFF -- offset of the beginning of the data on
+ *				this page
+ *		    FULL_KEY -- 2
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    OVFLPAGE -- 0
+ *
+ * FULL_KEY_DATA
+ *		This must be the first key/data pair on the page.
+ *		There are two cases:
+ *
+ *		Case 1:
+ *		    This page contains a key and the beginning of the
+ *		    data field, but the data field is continued on the
+ *		    next page.
+ *
+ *		    Page format is:
+ *		    KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
+ *
+ *		    KEY_OFF -- offset of the beginning of the key
+ *		    FULL_KEY_DATA -- 3
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    DATA_OFF -- offset of the beginning of the data
+ *
+ *		Case 2:
+ *		    This page contains the last page of a big data pair.
+ *		    There is no key, only the  tail end of the data
+ *		    on this page.
+ *
+ *		    Page format is:
+ *		    DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
+ *
+ *		    DATA_OFF -- offset of the beginning of the data on
+ *				this page
+ *		    FULL_KEY_DATA -- 3
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    OVFLPAGE -- 0
+ *
+ *		    OVFL_PAGENO and OVFLPAGE are optional (they are
+ *		    not present if there is no next page).
+ */
+
+#define OVFLPAGE	0
+#define PARTIAL_KEY	1
+#define FULL_KEY	2
+#define FULL_KEY_DATA	3
+#define	REAL_KEY	4
+
+/* Short hands for accessing structure */
+#define BSIZE		hdr.bsize
+#define BSHIFT		hdr.bshift
+#define DSIZE		hdr.dsize
+#define SGSIZE		hdr.ssize
+#define SSHIFT		hdr.sshift
+#define LORDER		hdr.lorder
+#define OVFL_POINT	hdr.ovfl_point
+#define	LAST_FREED	hdr.last_freed
+#define MAX_BUCKET	hdr.max_bucket
+#define FFACTOR		hdr.ffactor
+#define HIGH_MASK	hdr.high_mask
+#define LOW_MASK	hdr.low_mask
+#define NKEYS		hdr.nkeys
+#define HDRPAGES	hdr.hdrpages
+#define SPARES		hdr.spares
+#define BITMAPS		hdr.bitmaps
+#define VERSION		hdr.version
+#define MAGIC		hdr.magic
+#define NEXT_FREE	hdr.next_free
+#define H_CHARKEY	hdr.h_charkey
Index: /trunk/libc/src/fbsdlibc/db/hash/hash_bigkey.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/hash_bigkey.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/hash_bigkey.c	(revision 2448)
@@ -0,0 +1,671 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_bigkey.c	8.3 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_bigkey.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+
+/*
+ * PACKAGE: hash
+ * DESCRIPTION:
+ *	Big key/data handling for the hashing package.
+ *
+ * ROUTINES:
+ * External
+ *	__big_keydata
+ *	__big_split
+ *	__big_insert
+ *	__big_return
+ *	__big_delete
+ *	__find_last_page
+ * Internal
+ *	collect_key
+ *	collect_data
+ */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int collect_key(HTAB *, BUFHEAD *, int, DBT *, int);
+static int collect_data(HTAB *, BUFHEAD *, int, int);
+
+/*
+ * Big_insert
+ *
+ * You need to do an insert and the key/data pair is too big
+ *
+ * Returns:
+ * 0 ==> OK
+ *-1 ==> ERROR
+ */
+extern int
+__big_insert(hashp, bufp, key, val)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	const DBT *key, *val;
+{
+	u_int16_t *p;
+	int key_size, n, val_size;
+	u_int16_t space, move_bytes, off;
+	char *cp, *key_data, *val_data;
+
+	cp = bufp->page;		/* Character pointer of p. */
+	p = (u_int16_t *)cp;
+
+	key_data = (char *)key->data;
+	key_size = key->size;
+	val_data = (char *)val->data;
+	val_size = val->size;
+
+	/* First move the Key */
+	for (space = FREESPACE(p) - BIGOVERHEAD; key_size;
+	    space = FREESPACE(p) - BIGOVERHEAD) {
+		move_bytes = MIN(space, key_size);
+		off = OFFSET(p) - move_bytes;
+		memmove(cp + off, key_data, move_bytes);
+		key_size -= move_bytes;
+		key_data += move_bytes;
+		n = p[0];
+		p[++n] = off;
+		p[0] = ++n;
+		FREESPACE(p) = off - PAGE_META(n);
+		OFFSET(p) = off;
+		p[n] = PARTIAL_KEY;
+		bufp = __add_ovflpage(hashp, bufp);
+		if (!bufp)
+			return (-1);
+		n = p[0];
+		if (!key_size) {
+			if (FREESPACE(p)) {
+				move_bytes = MIN(FREESPACE(p), val_size);
+				off = OFFSET(p) - move_bytes;
+				p[n] = off;
+				memmove(cp + off, val_data, move_bytes);
+				val_data += move_bytes;
+				val_size -= move_bytes;
+				p[n - 2] = FULL_KEY_DATA;
+				FREESPACE(p) = FREESPACE(p) - move_bytes;
+				OFFSET(p) = off;
+			} else
+				p[n - 2] = FULL_KEY;
+		}
+		p = (u_int16_t *)bufp->page;
+		cp = bufp->page;
+		bufp->flags |= BUF_MOD;
+	}
+
+	/* Now move the data */
+	for (space = FREESPACE(p) - BIGOVERHEAD; val_size;
+	    space = FREESPACE(p) - BIGOVERHEAD) {
+		move_bytes = MIN(space, val_size);
+		/*
+		 * Here's the hack to make sure that if the data ends on the
+		 * same page as the key ends, FREESPACE is at least one.
+		 */
+		if (space == val_size && val_size == val->size)
+			move_bytes--;
+		off = OFFSET(p) - move_bytes;
+		memmove(cp + off, val_data, move_bytes);
+		val_size -= move_bytes;
+		val_data += move_bytes;
+		n = p[0];
+		p[++n] = off;
+		p[0] = ++n;
+		FREESPACE(p) = off - PAGE_META(n);
+		OFFSET(p) = off;
+		if (val_size) {
+			p[n] = FULL_KEY;
+			bufp = __add_ovflpage(hashp, bufp);
+			if (!bufp)
+				return (-1);
+			cp = bufp->page;
+			p = (u_int16_t *)cp;
+		} else
+			p[n] = FULL_KEY_DATA;
+		bufp->flags |= BUF_MOD;
+	}
+	return (0);
+}
+
+/*
+ * Called when bufp's page  contains a partial key (index should be 1)
+ *
+ * All pages in the big key/data pair except bufp are freed.  We cannot
+ * free bufp because the page pointing to it is lost and we can't get rid
+ * of its pointer.
+ *
+ * Returns:
+ * 0 => OK
+ *-1 => ERROR
+ */
+extern int
+__big_delete(hashp, bufp)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+{
+	BUFHEAD *last_bfp, *rbufp;
+	u_int16_t *bp, pageno;
+	int key_done, n;
+
+	rbufp = bufp;
+	last_bfp = NULL;
+	bp = (u_int16_t *)bufp->page;
+	pageno = 0;
+	key_done = 0;
+
+	while (!key_done || (bp[2] != FULL_KEY_DATA)) {
+		if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)
+			key_done = 1;
+
+		/*
+		 * If there is freespace left on a FULL_KEY_DATA page, then
+		 * the data is short and fits entirely on this page, and this
+		 * is the last page.
+		 */
+		if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))
+			break;
+		pageno = bp[bp[0] - 1];
+		rbufp->flags |= BUF_MOD;
+		rbufp = __get_buf(hashp, pageno, rbufp, 0);
+		if (last_bfp)
+			__free_ovflpage(hashp, last_bfp);
+		last_bfp = rbufp;
+		if (!rbufp)
+			return (-1);		/* Error. */
+		bp = (u_int16_t *)rbufp->page;
+	}
+
+	/*
+	 * If we get here then rbufp points to the last page of the big
+	 * key/data pair.  Bufp points to the first one -- it should now be
+	 * empty pointing to the next page after this pair.  Can't free it
+	 * because we don't have the page pointing to it.
+	 */
+
+	/* This is information from the last page of the pair. */
+	n = bp[0];
+	pageno = bp[n - 1];
+
+	/* Now, bp is the first page of the pair. */
+	bp = (u_int16_t *)bufp->page;
+	if (n > 2) {
+		/* There is an overflow page. */
+		bp[1] = pageno;
+		bp[2] = OVFLPAGE;
+		bufp->ovfl = rbufp->ovfl;
+	} else
+		/* This is the last page. */
+		bufp->ovfl = NULL;
+	n -= 2;
+	bp[0] = n;
+	FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
+	OFFSET(bp) = hashp->BSIZE - 1;
+
+	bufp->flags |= BUF_MOD;
+	if (rbufp)
+		__free_ovflpage(hashp, rbufp);
+	if (last_bfp != rbufp)
+		__free_ovflpage(hashp, last_bfp);
+
+	hashp->NKEYS--;
+	return (0);
+}
+/*
+ * Returns:
+ *  0 = key not found
+ * -1 = get next overflow page
+ * -2 means key not found and this is big key/data
+ * -3 error
+ */
+extern int
+__find_bigpair(hashp, bufp, ndx, key, size)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int ndx;
+	char *key;
+	int size;
+{
+	u_int16_t *bp;
+	char *p;
+	int ksize;
+	u_int16_t bytes;
+	char *kkey;
+
+	bp = (u_int16_t *)bufp->page;
+	p = bufp->page;
+	ksize = size;
+	kkey = key;
+
+	for (bytes = hashp->BSIZE - bp[ndx];
+	    bytes <= size && bp[ndx + 1] == PARTIAL_KEY;
+	    bytes = hashp->BSIZE - bp[ndx]) {
+		if (memcmp(p + bp[ndx], kkey, bytes))
+			return (-2);
+		kkey += bytes;
+		ksize -= bytes;
+		bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);
+		if (!bufp)
+			return (-3);
+		p = bufp->page;
+		bp = (u_int16_t *)p;
+		ndx = 1;
+	}
+
+	if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
+#ifdef HASH_STATISTICS
+		++hash_collisions;
+#endif
+		return (-2);
+	} else
+		return (ndx);
+}
+
+/*
+ * Given the buffer pointer of the first overflow page of a big pair,
+ * find the end of the big pair
+ *
+ * This will set bpp to the buffer header of the last page of the big pair.
+ * It will return the pageno of the overflow page following the last page
+ * of the pair; 0 if there isn't any (i.e. big pair is the last key in the
+ * bucket)
+ */
+extern u_int16_t
+__find_last_page(hashp, bpp)
+	HTAB *hashp;
+	BUFHEAD **bpp;
+{
+	BUFHEAD *bufp;
+	u_int16_t *bp, pageno;
+	int n;
+
+	bufp = *bpp;
+	bp = (u_int16_t *)bufp->page;
+	for (;;) {
+		n = bp[0];
+
+		/*
+		 * This is the last page if: the tag is FULL_KEY_DATA and
+		 * either only 2 entries OVFLPAGE marker is explicit there
+		 * is freespace on the page.
+		 */
+		if (bp[2] == FULL_KEY_DATA &&
+		    ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp))))
+			break;
+
+		pageno = bp[n - 1];
+		bufp = __get_buf(hashp, pageno, bufp, 0);
+		if (!bufp)
+			return (0);	/* Need to indicate an error! */
+		bp = (u_int16_t *)bufp->page;
+	}
+
+	*bpp = bufp;
+	if (bp[0] > 2)
+		return (bp[3]);
+	else
+		return (0);
+}
+
+/*
+ * Return the data for the key/data pair that begins on this page at this
+ * index (index should always be 1).
+ */
+extern int
+__big_return(hashp, bufp, ndx, val, set_current)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int ndx;
+	DBT *val;
+	int set_current;
+{
+	BUFHEAD *save_p;
+	u_int16_t *bp, len, off, save_addr;
+	char *tp;
+
+	bp = (u_int16_t *)bufp->page;
+	while (bp[ndx + 1] == PARTIAL_KEY) {
+		bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+		if (!bufp)
+			return (-1);
+		bp = (u_int16_t *)bufp->page;
+		ndx = 1;
+	}
+
+	if (bp[ndx + 1] == FULL_KEY) {
+		bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+		if (!bufp)
+			return (-1);
+		bp = (u_int16_t *)bufp->page;
+		save_p = bufp;
+		save_addr = save_p->addr;
+		off = bp[1];
+		len = 0;
+	} else
+		if (!FREESPACE(bp)) {
+			/*
+			 * This is a hack.  We can't distinguish between
+			 * FULL_KEY_DATA that contains complete data or
+			 * incomplete data, so we require that if the data
+			 * is complete, there is at least 1 byte of free
+			 * space left.
+			 */
+			off = bp[bp[0]];
+			len = bp[1] - off;
+			save_p = bufp;
+			save_addr = bufp->addr;
+			bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+			if (!bufp)
+				return (-1);
+			bp = (u_int16_t *)bufp->page;
+		} else {
+			/* The data is all on one page. */
+			tp = (char *)bp;
+			off = bp[bp[0]];
+			val->data = (u_char *)tp + off;
+			val->size = bp[1] - off;
+			if (set_current) {
+				if (bp[0] == 2) {	/* No more buckets in
+							 * chain */
+					hashp->cpage = NULL;
+					hashp->cbucket++;
+					hashp->cndx = 1;
+				} else {
+					hashp->cpage = __get_buf(hashp,
+					    bp[bp[0] - 1], bufp, 0);
+					if (!hashp->cpage)
+						return (-1);
+					hashp->cndx = 1;
+					if (!((u_int16_t *)
+					    hashp->cpage->page)[0]) {
+						hashp->cbucket++;
+						hashp->cpage = NULL;
+					}
+				}
+			}
+			return (0);
+		}
+
+	val->size = collect_data(hashp, bufp, (int)len, set_current);
+	if (val->size == -1)
+		return (-1);
+	if (save_p->addr != save_addr) {
+		/* We are pretty short on buffers. */
+		errno = EINVAL;			/* OUT OF BUFFERS */
+		return (-1);
+	}
+	memmove(hashp->tmp_buf, (save_p->page) + off, len);
+	val->data = (u_char *)hashp->tmp_buf;
+	return (0);
+}
+/*
+ * Count how big the total datasize is by recursing through the pages.  Then
+ * allocate a buffer and copy the data as you recurse up.
+ */
+static int
+collect_data(hashp, bufp, len, set)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int len, set;
+{
+	u_int16_t *bp;
+	char *p;
+	BUFHEAD *xbp;
+	u_int16_t save_addr;
+	int mylen, totlen;
+
+	p = bufp->page;
+	bp = (u_int16_t *)p;
+	mylen = hashp->BSIZE - bp[1];
+	save_addr = bufp->addr;
+
+	if (bp[2] == FULL_KEY_DATA) {		/* End of Data */
+		totlen = len + mylen;
+		if (hashp->tmp_buf)
+			free(hashp->tmp_buf);
+		if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL)
+			return (-1);
+		if (set) {
+			hashp->cndx = 1;
+			if (bp[0] == 2) {	/* No more buckets in chain */
+				hashp->cpage = NULL;
+				hashp->cbucket++;
+			} else {
+				hashp->cpage =
+				    __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+				if (!hashp->cpage)
+					return (-1);
+				else if (!((u_int16_t *)hashp->cpage->page)[0]) {
+					hashp->cbucket++;
+					hashp->cpage = NULL;
+				}
+			}
+		}
+	} else {
+		xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+		if (!xbp || ((totlen =
+		    collect_data(hashp, xbp, len + mylen, set)) < 1))
+			return (-1);
+	}
+	if (bufp->addr != save_addr) {
+		errno = EINVAL;			/* Out of buffers. */
+		return (-1);
+	}
+	memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen);
+	return (totlen);
+}
+
+/*
+ * Fill in the key and data for this big pair.
+ */
+extern int
+__big_keydata(hashp, bufp, key, val, set)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	DBT *key, *val;
+	int set;
+{
+	key->size = collect_key(hashp, bufp, 0, val, set);
+	if (key->size == -1)
+		return (-1);
+	key->data = (u_char *)hashp->tmp_key;
+	return (0);
+}
+
+/*
+ * Count how big the total key size is by recursing through the pages.  Then
+ * collect the data, allocate a buffer and copy the key as you recurse up.
+ */
+static int
+collect_key(hashp, bufp, len, val, set)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int len;
+	DBT *val;
+	int set;
+{
+	BUFHEAD *xbp;
+	char *p;
+	int mylen, totlen;
+	u_int16_t *bp, save_addr;
+
+	p = bufp->page;
+	bp = (u_int16_t *)p;
+	mylen = hashp->BSIZE - bp[1];
+
+	save_addr = bufp->addr;
+	totlen = len + mylen;
+	if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) {    /* End of Key. */
+		if (hashp->tmp_key != NULL)
+			free(hashp->tmp_key);
+		if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL)
+			return (-1);
+		if (__big_return(hashp, bufp, 1, val, set))
+			return (-1);
+	} else {
+		xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+		if (!xbp || ((totlen =
+		    collect_key(hashp, xbp, totlen, val, set)) < 1))
+			return (-1);
+	}
+	if (bufp->addr != save_addr) {
+		errno = EINVAL;		/* MIS -- OUT OF BUFFERS */
+		return (-1);
+	}
+	memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen);
+	return (totlen);
+}
+
+/*
+ * Returns:
+ *  0 => OK
+ * -1 => error
+ */
+extern int
+__big_split(hashp, op, np, big_keyp, addr, obucket, ret)
+	HTAB *hashp;
+	BUFHEAD *op;	/* Pointer to where to put keys that go in old bucket */
+	BUFHEAD *np;	/* Pointer to new bucket page */
+			/* Pointer to first page containing the big key/data */
+	BUFHEAD *big_keyp;
+	int addr;	/* Address of big_keyp */
+	u_int32_t   obucket;/* Old Bucket */
+	SPLIT_RETURN *ret;
+{
+	BUFHEAD *tmpp;
+	u_int16_t *tp;
+	BUFHEAD *bp;
+	DBT key, val;
+	u_int32_t change;
+	u_int16_t free_space, n, off;
+
+	bp = big_keyp;
+
+	/* Now figure out where the big key/data goes */
+	if (__big_keydata(hashp, big_keyp, &key, &val, 0))
+		return (-1);
+	change = (__call_hash(hashp, key.data, key.size) != obucket);
+
+	if ( (ret->next_addr = __find_last_page(hashp, &big_keyp)) ) {
+		if (!(ret->nextp =
+		    __get_buf(hashp, ret->next_addr, big_keyp, 0)))
+			return (-1);;
+	} else
+		ret->nextp = NULL;
+
+	/* Now make one of np/op point to the big key/data pair */
+#ifdef DEBUG
+	assert(np->ovfl == NULL);
+#endif
+	if (change)
+		tmpp = np;
+	else
+		tmpp = op;
+
+	tmpp->flags |= BUF_MOD;
+#ifdef DEBUG1
+	(void)fprintf(stderr,
+	    "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
+	    (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
+#endif
+	tmpp->ovfl = bp;	/* one of op/np point to big_keyp */
+	tp = (u_int16_t *)tmpp->page;
+#ifdef DEBUG
+	assert(FREESPACE(tp) >= OVFLSIZE);
+#endif
+	n = tp[0];
+	off = OFFSET(tp);
+	free_space = FREESPACE(tp);
+	tp[++n] = (u_int16_t)addr;
+	tp[++n] = OVFLPAGE;
+	tp[0] = n;
+	OFFSET(tp) = off;
+	FREESPACE(tp) = free_space - OVFLSIZE;
+
+	/*
+	 * Finally, set the new and old return values. BIG_KEYP contains a
+	 * pointer to the last page of the big key_data pair. Make sure that
+	 * big_keyp has no following page (2 elements) or create an empty
+	 * following page.
+	 */
+
+	ret->newp = np;
+	ret->oldp = op;
+
+	tp = (u_int16_t *)big_keyp->page;
+	big_keyp->flags |= BUF_MOD;
+	if (tp[0] > 2) {
+		/*
+		 * There may be either one or two offsets on this page.  If
+		 * there is one, then the overflow page is linked on normally
+		 * and tp[4] is OVFLPAGE.  If there are two, tp[4] contains
+		 * the second offset and needs to get stuffed in after the
+		 * next overflow page is added.
+		 */
+		n = tp[4];
+		free_space = FREESPACE(tp);
+		off = OFFSET(tp);
+		tp[0] -= 2;
+		FREESPACE(tp) = free_space + OVFLSIZE;
+		OFFSET(tp) = off;
+		tmpp = __add_ovflpage(hashp, big_keyp);
+		if (!tmpp)
+			return (-1);
+		tp[4] = n;
+	} else
+		tmpp = big_keyp;
+
+	if (change)
+		ret->newp = tmpp;
+	else
+		ret->oldp = tmpp;
+	return (0);
+}
Index: /trunk/libc/src/fbsdlibc/db/hash/hash_buf.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/hash_buf.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/hash_buf.c	(revision 2448)
@@ -0,0 +1,357 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_buf.c	8.5 (Berkeley) 7/15/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_buf.c,v 1.7 2002/03/21 22:46:26 obrien Exp $");
+
+/*
+ * PACKAGE: hash
+ *
+ * DESCRIPTION:
+ *	Contains buffer management
+ *
+ * ROUTINES:
+ * External
+ *	__buf_init
+ *	__get_buf
+ *	__buf_free
+ *	__reclaim_buf
+ * Internal
+ *	newbuf
+ */
+
+#include <sys/param.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static BUFHEAD *newbuf(HTAB *, u_int32_t, BUFHEAD *);
+
+/* Unlink B from its place in the lru */
+#define BUF_REMOVE(B) { \
+	(B)->prev->next = (B)->next; \
+	(B)->next->prev = (B)->prev; \
+}
+
+/* Insert B after P */
+#define BUF_INSERT(B, P) { \
+	(B)->next = (P)->next; \
+	(B)->prev = (P); \
+	(P)->next = (B); \
+	(B)->next->prev = (B); \
+}
+
+#define	MRU	hashp->bufhead.next
+#define	LRU	hashp->bufhead.prev
+
+#define MRU_INSERT(B)	BUF_INSERT((B), &hashp->bufhead)
+#define LRU_INSERT(B)	BUF_INSERT((B), LRU)
+
+/*
+ * We are looking for a buffer with address "addr".  If prev_bp is NULL, then
+ * address is a bucket index.  If prev_bp is not NULL, then it points to the
+ * page previous to an overflow page that we are trying to find.
+ *
+ * CAVEAT:  The buffer header accessed via prev_bp's ovfl field may no longer
+ * be valid.  Therefore, you must always verify that its address matches the
+ * address you are seeking.
+ */
+extern BUFHEAD *
+__get_buf(hashp, addr, prev_bp, newpage)
+	HTAB *hashp;
+	u_int32_t addr;
+	BUFHEAD *prev_bp;
+	int newpage;	/* If prev_bp set, indicates a new overflow page. */
+{
+	BUFHEAD *bp;
+	u_int32_t is_disk_mask;
+	int is_disk, segment_ndx;
+	SEGMENT segp;
+
+	is_disk = 0;
+	is_disk_mask = 0;
+	if (prev_bp) {
+		bp = prev_bp->ovfl;
+		if (!bp || (bp->addr != addr))
+			bp = NULL;
+		if (!newpage)
+			is_disk = BUF_DISK;
+	} else {
+		/* Grab buffer out of directory */
+		segment_ndx = addr & (hashp->SGSIZE - 1);
+
+		/* valid segment ensured by __call_hash() */
+		segp = hashp->dir[addr >> hashp->SSHIFT];
+#ifdef DEBUG
+		assert(segp != NULL);
+#endif
+		bp = PTROF(segp[segment_ndx]);
+		is_disk_mask = ISDISK(segp[segment_ndx]);
+		is_disk = is_disk_mask || !hashp->new_file;
+	}
+
+	if (!bp) {
+		bp = newbuf(hashp, addr, prev_bp);
+		if (!bp ||
+		    __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0))
+			return (NULL);
+		if (!prev_bp)
+			segp[segment_ndx] =
+			    (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask);
+	} else {
+		BUF_REMOVE(bp);
+		MRU_INSERT(bp);
+	}
+	return (bp);
+}
+
+/*
+ * We need a buffer for this page. Either allocate one, or evict a resident
+ * one (if we have as many buffers as we're allowed) and put this one in.
+ *
+ * If newbuf finds an error (returning NULL), it also sets errno.
+ */
+static BUFHEAD *
+newbuf(hashp, addr, prev_bp)
+	HTAB *hashp;
+	u_int32_t addr;
+	BUFHEAD *prev_bp;
+{
+	BUFHEAD *bp;		/* The buffer we're going to use */
+	BUFHEAD *xbp;		/* Temp pointer */
+	BUFHEAD *next_xbp;
+	SEGMENT segp;
+	int segment_ndx;
+	u_int16_t oaddr, *shortp;
+
+	oaddr = 0;
+	bp = LRU;
+	/*
+	 * If LRU buffer is pinned, the buffer pool is too small. We need to
+	 * allocate more buffers.
+	 */
+	if (hashp->nbufs || (bp->flags & BUF_PIN)) {
+		/* Allocate a new one */
+		if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
+			return (NULL);
+#ifdef PURIFY
+		memset(bp, 0xff, sizeof(BUFHEAD));
+#endif
+		if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) {
+			free(bp);
+			return (NULL);
+		}
+#ifdef PURIFY
+		memset(bp->page, 0xff, hashp->BSIZE);
+#endif
+		if (hashp->nbufs)
+			hashp->nbufs--;
+	} else {
+		/* Kick someone out */
+		BUF_REMOVE(bp);
+		/*
+		 * If this is an overflow page with addr 0, it's already been
+		 * flushed back in an overflow chain and initialized.
+		 */
+		if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) {
+			/*
+			 * Set oaddr before __put_page so that you get it
+			 * before bytes are swapped.
+			 */
+			shortp = (u_int16_t *)bp->page;
+			if (shortp[0])
+				oaddr = shortp[shortp[0] - 1];
+			if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page,
+			    bp->addr, (int)IS_BUCKET(bp->flags), 0))
+				return (NULL);
+			/*
+			 * Update the pointer to this page (i.e. invalidate it).
+			 *
+			 * If this is a new file (i.e. we created it at open
+			 * time), make sure that we mark pages which have been
+			 * written to disk so we retrieve them from disk later,
+			 * rather than allocating new pages.
+			 */
+			if (IS_BUCKET(bp->flags)) {
+				segment_ndx = bp->addr & (hashp->SGSIZE - 1);
+				segp = hashp->dir[bp->addr >> hashp->SSHIFT];
+#ifdef DEBUG
+				assert(segp != NULL);
+#endif
+
+				if (hashp->new_file &&
+				    ((bp->flags & BUF_MOD) ||
+				    ISDISK(segp[segment_ndx])))
+					segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
+				else
+					segp[segment_ndx] = NULL;
+			}
+			/*
+			 * Since overflow pages can only be access by means of
+			 * their bucket, free overflow pages associated with
+			 * this bucket.
+			 */
+			for (xbp = bp; xbp->ovfl;) {
+				next_xbp = xbp->ovfl;
+				xbp->ovfl = 0;
+				xbp = next_xbp;
+
+				/* Check that ovfl pointer is up date. */
+				if (IS_BUCKET(xbp->flags) ||
+				    (oaddr != xbp->addr))
+					break;
+
+				shortp = (u_int16_t *)xbp->page;
+				if (shortp[0])
+					/* set before __put_page */
+					oaddr = shortp[shortp[0] - 1];
+				if ((xbp->flags & BUF_MOD) && __put_page(hashp,
+				    xbp->page, xbp->addr, 0, 0))
+					return (NULL);
+				xbp->addr = 0;
+				xbp->flags = 0;
+				BUF_REMOVE(xbp);
+				LRU_INSERT(xbp);
+			}
+		}
+	}
+
+	/* Now assign this buffer */
+	bp->addr = addr;
+#ifdef DEBUG1
+	(void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n",
+	    bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0);
+#endif
+	bp->ovfl = NULL;
+	if (prev_bp) {
+		/*
+		 * If prev_bp is set, this is an overflow page, hook it in to
+		 * the buffer overflow links.
+		 */
+#ifdef DEBUG1
+		(void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
+		    prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
+		    (bp ? bp->addr : 0));
+#endif
+		prev_bp->ovfl = bp;
+		bp->flags = 0;
+	} else
+		bp->flags = BUF_BUCKET;
+	MRU_INSERT(bp);
+	return (bp);
+}
+
+extern void
+__buf_init(hashp, nbytes)
+	HTAB *hashp;
+	int nbytes;
+{
+	BUFHEAD *bfp;
+	int npages;
+
+	bfp = &(hashp->bufhead);
+	npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
+	npages = MAX(npages, MIN_BUFFERS);
+
+	hashp->nbufs = npages;
+	bfp->next = bfp;
+	bfp->prev = bfp;
+	/*
+	 * This space is calloc'd so these are already null.
+	 *
+	 * bfp->ovfl = NULL;
+	 * bfp->flags = 0;
+	 * bfp->page = NULL;
+	 * bfp->addr = 0;
+	 */
+}
+
+extern int
+__buf_free(hashp, do_free, to_disk)
+	HTAB *hashp;
+	int do_free, to_disk;
+{
+	BUFHEAD *bp;
+
+	/* Need to make sure that buffer manager has been initialized */
+	if (!LRU)
+		return (0);
+	for (bp = LRU; bp != &hashp->bufhead;) {
+		/* Check that the buffer is valid */
+		if (bp->addr || IS_BUCKET(bp->flags)) {
+			if (to_disk && (bp->flags & BUF_MOD) &&
+			    __put_page(hashp, bp->page,
+			    bp->addr, IS_BUCKET(bp->flags), 0))
+				return (-1);
+		}
+		/* Check if we are freeing stuff */
+		if (do_free) {
+			if (bp->page)
+				free(bp->page);
+			BUF_REMOVE(bp);
+			free(bp);
+			bp = LRU;
+		} else
+			bp = bp->prev;
+	}
+	return (0);
+}
+
+extern void
+__reclaim_buf(hashp, bp)
+	HTAB *hashp;
+	BUFHEAD *bp;
+{
+	bp->ovfl = 0;
+	bp->addr = 0;
+	bp->flags = 0;
+	BUF_REMOVE(bp);
+	LRU_INSERT(bp);
+}
Index: /trunk/libc/src/fbsdlibc/db/hash/hash_func.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/hash_func.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/hash_func.c	(revision 2448)
@@ -0,0 +1,215 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_func.c	8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_func.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+
+#include <sys/types.h>
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static u_int32_t hash1(const void *, size_t) __unused;
+static u_int32_t hash2(const void *, size_t) __unused;
+static u_int32_t hash3(const void *, size_t) __unused;
+static u_int32_t hash4(const void *, size_t);
+
+/* Global default hash function */
+u_int32_t (*__default_hash)(const void *, size_t) = hash4;
+
+/*
+ * HASH FUNCTIONS
+ *
+ * Assume that we've already split the bucket to which this key hashes,
+ * calculate that bucket, and check that in fact we did already split it.
+ *
+ * This came from ejb's hsearch.
+ */
+
+#define PRIME1		37
+#define PRIME2		1048583
+
+static u_int32_t
+hash1(keyarg, len)
+	const void *keyarg;
+	size_t len;
+{
+	const u_char *key;
+	u_int32_t h;
+
+	/* Convert string to integer */
+	for (key = keyarg, h = 0; len--;)
+		h = h * PRIME1 ^ (*key++ - ' ');
+	h %= PRIME2;
+	return (h);
+}
+
+/*
+ * Phong's linear congruential hash
+ */
+#define dcharhash(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
+
+static u_int32_t
+hash2(keyarg, len)
+	const void *keyarg;
+	size_t len;
+{
+	const u_char *e, *key;
+	u_int32_t h;
+	u_char c;
+
+	key = keyarg;
+	e = key + len;
+	for (h = 0; key != e;) {
+		c = *key++;
+		if (!c && key > e)
+			break;
+		dcharhash(h, c);
+	}
+	return (h);
+}
+
+/*
+ * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
+ * units.  On the first time through the loop we get the "leftover bytes"
+ * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
+ * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
+ * this routine is heavily used enough, it's worth the ugly coding.
+ *
+ * OZ's original sdbm hash
+ */
+static u_int32_t
+hash3(keyarg, len)
+	const void *keyarg;
+	size_t len;
+{
+	const u_char *key;
+	size_t loop;
+	u_int32_t h;
+
+#define HASHC   h = *key++ + 65599 * h
+
+	h = 0;
+	key = keyarg;
+	if (len > 0) {
+		loop = (len + 8 - 1) >> 3;
+
+		switch (len & (8 - 1)) {
+		case 0:
+			do {
+				HASHC;
+				/* FALLTHROUGH */
+		case 7:
+				HASHC;
+				/* FALLTHROUGH */
+		case 6:
+				HASHC;
+				/* FALLTHROUGH */
+		case 5:
+				HASHC;
+				/* FALLTHROUGH */
+		case 4:
+				HASHC;
+				/* FALLTHROUGH */
+		case 3:
+				HASHC;
+				/* FALLTHROUGH */
+		case 2:
+				HASHC;
+				/* FALLTHROUGH */
+		case 1:
+				HASHC;
+			} while (--loop);
+		}
+	}
+	return (h);
+}
+
+/* Hash function from Chris Torek. */
+static u_int32_t
+hash4(keyarg, len)
+	const void *keyarg;
+	size_t len;
+{
+	const u_char *key;
+	size_t loop;
+	u_int32_t h;
+
+#define HASH4a   h = (h << 5) - h + *key++;
+#define HASH4b   h = (h << 5) + h + *key++;
+#define HASH4 HASH4b
+
+	h = 0;
+	key = keyarg;
+	if (len > 0) {
+		loop = (len + 8 - 1) >> 3;
+
+		switch (len & (8 - 1)) {
+		case 0:
+			do {
+				HASH4;
+				/* FALLTHROUGH */
+		case 7:
+				HASH4;
+				/* FALLTHROUGH */
+		case 6:
+				HASH4;
+				/* FALLTHROUGH */
+		case 5:
+				HASH4;
+				/* FALLTHROUGH */
+		case 4:
+				HASH4;
+				/* FALLTHROUGH */
+		case 3:
+				HASH4;
+				/* FALLTHROUGH */
+		case 2:
+				HASH4;
+				/* FALLTHROUGH */
+		case 1:
+				HASH4;
+			} while (--loop);
+		}
+	}
+	return (h);
+}
Index: /trunk/libc/src/fbsdlibc/db/hash/hash_log2.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/hash_log2.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/hash_log2.c	(revision 2448)
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_log2.c	8.2 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_log2.c,v 1.2 2002/03/21 18:47:38 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+u_int32_t
+__log2(num)
+	u_int32_t num;
+{
+	u_int32_t i, limit;
+
+	limit = 1;
+	for (i = 0; limit < num; limit = limit << 1, i++);
+	return (i);
+}
Index: /trunk/libc/src/fbsdlibc/db/hash/hash_page.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/hash_page.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/hash_page.c	(revision 2448)
@@ -0,0 +1,965 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_page.c	8.7 (Berkeley) 8/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_page.c,v 1.8 2002/03/21 22:46:26 obrien Exp $");
+
+/*
+ * PACKAGE:  hashing
+ *
+ * DESCRIPTION:
+ *	Page manipulation for hashing package.
+ *
+ * ROUTINES:
+ *
+ * External
+ *	__get_page
+ *	__add_ovflpage
+ * Internal
+ *	overflow_page
+ *	open_temp
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+#ifdef __EMX__
+#include <io.h>
+#endif
+#include "un-namespace.h"
+
+#include <db.h>
+#ifndef __DBINTERFACE_PRIVATE
+#error "__DBINTERFACE_PRIVATE is not defined!"
+#endif
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static u_int32_t	*fetch_bitmap(HTAB *, int);
+static u_int32_t	 first_free(u_int32_t);
+static int	 open_temp(HTAB *);
+static u_int16_t	 overflow_page(HTAB *);
+static void	 putpair(char *, const DBT *, const DBT *);
+static void	 squeeze_key(u_int16_t *, const DBT *, const DBT *);
+static int	 ugly_split
+(HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int);
+
+#define	PAGE_INIT(P) { \
+	((u_int16_t *)(P))[0] = 0; \
+	((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \
+	((u_int16_t *)(P))[2] = hashp->BSIZE; \
+}
+
+/*
+ * This is called AFTER we have verified that there is room on the page for
+ * the pair (PAIRFITS has returned true) so we go right ahead and start moving
+ * stuff on.
+ */
+static void
+putpair(p, key, val)
+	char *p;
+	const DBT *key, *val;
+{
+	u_int16_t *bp, n, off;
+
+	bp = (u_int16_t *)p;
+
+	/* Enter the key first. */
+	n = bp[0];
+
+	off = OFFSET(bp) - key->size;
+	memmove(p + off, key->data, key->size);
+	bp[++n] = off;
+
+	/* Now the data. */
+	off -= val->size;
+	memmove(p + off, val->data, val->size);
+	bp[++n] = off;
+
+	/* Adjust page info. */
+	bp[0] = n;
+	bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t));
+	bp[n + 2] = off;
+}
+
+/*
+ * Returns:
+ *	 0 OK
+ *	-1 error
+ */
+extern int
+__delpair(hashp, bufp, ndx)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int ndx;
+{
+	u_int16_t *bp, newoff;
+	int n;
+	u_int16_t pairlen;
+
+	bp = (u_int16_t *)bufp->page;
+	n = bp[0];
+
+	if (bp[ndx + 1] < REAL_KEY)
+		return (__big_delete(hashp, bufp));
+	if (ndx != 1)
+		newoff = bp[ndx - 1];
+	else
+		newoff = hashp->BSIZE;
+	pairlen = newoff - bp[ndx + 1];
+
+	if (ndx != (n - 1)) {
+		/* Hard Case -- need to shuffle keys */
+		int i;
+		char *src = bufp->page + (int)OFFSET(bp);
+		char *dst = src + (int)pairlen;
+		memmove(dst, src, bp[ndx + 1] - OFFSET(bp));
+
+		/* Now adjust the pointers */
+		for (i = ndx + 2; i <= n; i += 2) {
+			if (bp[i + 1] == OVFLPAGE) {
+				bp[i - 2] = bp[i];
+				bp[i - 1] = bp[i + 1];
+			} else {
+				bp[i - 2] = bp[i] + pairlen;
+				bp[i - 1] = bp[i + 1] + pairlen;
+			}
+		}
+	}
+	/* Finally adjust the page data */
+	bp[n] = OFFSET(bp) + pairlen;
+	bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t);
+	bp[0] = n - 2;
+	hashp->NKEYS--;
+
+	bufp->flags |= BUF_MOD;
+	return (0);
+}
+/*
+ * Returns:
+ *	 0 ==> OK
+ *	-1 ==> Error
+ */
+extern int
+__split_page(hashp, obucket, nbucket)
+	HTAB *hashp;
+	u_int32_t obucket, nbucket;
+{
+	BUFHEAD *new_bufp, *old_bufp;
+	u_int16_t *ino;
+	char *np;
+	DBT key, val;
+	int n, ndx, retval;
+	u_int16_t copyto, diff, off, moved;
+	char *op;
+
+	copyto = (u_int16_t)hashp->BSIZE;
+	off = (u_int16_t)hashp->BSIZE;
+	old_bufp = __get_buf(hashp, obucket, NULL, 0);
+	if (old_bufp == NULL)
+		return (-1);
+	new_bufp = __get_buf(hashp, nbucket, NULL, 0);
+	if (new_bufp == NULL)
+		return (-1);
+
+	old_bufp->flags |= (BUF_MOD | BUF_PIN);
+	new_bufp->flags |= (BUF_MOD | BUF_PIN);
+
+	ino = (u_int16_t *)(op = old_bufp->page);
+	np = new_bufp->page;
+
+	moved = 0;
+
+	for (n = 1, ndx = 1; n < ino[0]; n += 2) {
+		if (ino[n + 1] < REAL_KEY) {
+			retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
+			    (int)copyto, (int)moved);
+			old_bufp->flags &= ~BUF_PIN;
+			new_bufp->flags &= ~BUF_PIN;
+			return (retval);
+
+		}
+		key.data = (u_char *)op + ino[n];
+		key.size = off - ino[n];
+
+		if (__call_hash(hashp, key.data, key.size) == obucket) {
+			/* Don't switch page */
+			diff = copyto - off;
+			if (diff) {
+				copyto = ino[n + 1] + diff;
+				memmove(op + copyto, op + ino[n + 1],
+				    off - ino[n + 1]);
+				ino[ndx] = copyto + ino[n] - ino[n + 1];
+				ino[ndx + 1] = copyto;
+			} else
+				copyto = ino[n + 1];
+			ndx += 2;
+		} else {
+			/* Switch page */
+			val.data = (u_char *)op + ino[n + 1];
+			val.size = ino[n] - ino[n + 1];
+			putpair(np, &key, &val);
+			moved += 2;
+		}
+
+		off = ino[n + 1];
+	}
+
+	/* Now clean up the page */
+	ino[0] -= moved;
+	FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3);
+	OFFSET(ino) = copyto;
+
+#ifdef DEBUG3
+	(void)fprintf(stderr, "split %d/%d\n",
+	    ((u_int16_t *)np)[0] / 2,
+	    ((u_int16_t *)op)[0] / 2);
+#endif
+	/* unpin both pages */
+	old_bufp->flags &= ~BUF_PIN;
+	new_bufp->flags &= ~BUF_PIN;
+	return (0);
+}
+
+/*
+ * Called when we encounter an overflow or big key/data page during split
+ * handling.  This is special cased since we have to begin checking whether
+ * the key/data pairs fit on their respective pages and because we may need
+ * overflow pages for both the old and new pages.
+ *
+ * The first page might be a page with regular key/data pairs in which case
+ * we have a regular overflow condition and just need to go on to the next
+ * page or it might be a big key/data pair in which case we need to fix the
+ * big key/data pair.
+ *
+ * Returns:
+ *	 0 ==> success
+ *	-1 ==> failure
+ */
+static int
+ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
+	HTAB *hashp;
+	u_int32_t obucket;	/* Same as __split_page. */
+	BUFHEAD *old_bufp, *new_bufp;
+	int copyto;	/* First byte on page which contains key/data values. */
+	int moved;		/* Number of pairs moved to new page. */
+{
+	BUFHEAD *bufp;		/* Buffer header for ino */
+	u_int16_t *ino;		/* Page keys come off of */
+	u_int16_t *np;		/* New page */
+	u_int16_t *op;		/* Page keys go on to if they aren't moving */
+
+	BUFHEAD *last_bfp;	/* Last buf header OVFL needing to be freed */
+	DBT key, val;
+	SPLIT_RETURN ret;
+	u_int16_t n, off, ov_addr, scopyto;
+	char *cino;		/* Character value of ino */
+
+	bufp = old_bufp;
+	ino = (u_int16_t *)old_bufp->page;
+	np = (u_int16_t *)new_bufp->page;
+	op = (u_int16_t *)old_bufp->page;
+	last_bfp = NULL;
+	scopyto = (u_int16_t)copyto;	/* ANSI */
+
+	n = ino[0] - 1;
+	while (n < ino[0]) {
+		if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
+			if (__big_split(hashp, old_bufp,
+			    new_bufp, bufp, bufp->addr, obucket, &ret))
+				return (-1);
+			old_bufp = ret.oldp;
+			if (!old_bufp)
+				return (-1);
+			op = (u_int16_t *)old_bufp->page;
+			new_bufp = ret.newp;
+			if (!new_bufp)
+				return (-1);
+			np = (u_int16_t *)new_bufp->page;
+			bufp = ret.nextp;
+			if (!bufp)
+				return (0);
+			cino = (char *)bufp->page;
+			ino = (u_int16_t *)cino;
+			last_bfp = ret.nextp;
+		} else if (ino[n + 1] == OVFLPAGE) {
+			ov_addr = ino[n];
+			/*
+			 * Fix up the old page -- the extra 2 are the fields
+			 * which contained the overflow information.
+			 */
+			ino[0] -= (moved + 2);
+			FREESPACE(ino) =
+			    scopyto - sizeof(u_int16_t) * (ino[0] + 3);
+			OFFSET(ino) = scopyto;
+
+			bufp = __get_buf(hashp, ov_addr, bufp, 0);
+			if (!bufp)
+				return (-1);
+
+			ino = (u_int16_t *)bufp->page;
+			n = 1;
+			scopyto = hashp->BSIZE;
+			moved = 0;
+
+			if (last_bfp)
+				__free_ovflpage(hashp, last_bfp);
+			last_bfp = bufp;
+		}
+		/* Move regular sized pairs of there are any */
+		off = hashp->BSIZE;
+		for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
+			cino = (char *)ino;
+			key.data = (u_char *)cino + ino[n];
+			key.size = off - ino[n];
+			val.data = (u_char *)cino + ino[n + 1];
+			val.size = ino[n] - ino[n + 1];
+			off = ino[n + 1];
+
+			if (__call_hash(hashp, key.data, key.size) == obucket) {
+				/* Keep on old page */
+				if (PAIRFITS(op, (&key), (&val)))
+					putpair((char *)op, &key, &val);
+				else {
+					old_bufp =
+					    __add_ovflpage(hashp, old_bufp);
+					if (!old_bufp)
+						return (-1);
+					op = (u_int16_t *)old_bufp->page;
+					putpair((char *)op, &key, &val);
+				}
+				old_bufp->flags |= BUF_MOD;
+			} else {
+				/* Move to new page */
+				if (PAIRFITS(np, (&key), (&val)))
+					putpair((char *)np, &key, &val);
+				else {
+					new_bufp =
+					    __add_ovflpage(hashp, new_bufp);
+					if (!new_bufp)
+						return (-1);
+					np = (u_int16_t *)new_bufp->page;
+					putpair((char *)np, &key, &val);
+				}
+				new_bufp->flags |= BUF_MOD;
+			}
+		}
+	}
+	if (last_bfp)
+		__free_ovflpage(hashp, last_bfp);
+	return (0);
+}
+
+/*
+ * Add the given pair to the page
+ *
+ * Returns:
+ *	0 ==> OK
+ *	1 ==> failure
+ */
+extern int
+__addel(hashp, bufp, key, val)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	const DBT *key, *val;
+{
+	u_int16_t *bp, *sop;
+	int do_expand;
+
+	bp = (u_int16_t *)bufp->page;
+	do_expand = 0;
+	while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
+		/* Exception case */
+		if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
+			/* This is the last page of a big key/data pair
+			   and we need to add another page */
+			break;
+		else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
+			bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+			if (!bufp)
+				return (-1);
+			bp = (u_int16_t *)bufp->page;
+		} else
+			/* Try to squeeze key on this page */
+			if (FREESPACE(bp) > PAIRSIZE(key, val)) {
+				squeeze_key(bp, key, val);
+				return (0);
+			} else {
+				bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+				if (!bufp)
+					return (-1);
+				bp = (u_int16_t *)bufp->page;
+			}
+
+	if (PAIRFITS(bp, key, val))
+		putpair(bufp->page, key, val);
+	else {
+		do_expand = 1;
+		bufp = __add_ovflpage(hashp, bufp);
+		if (!bufp)
+			return (-1);
+		sop = (u_int16_t *)bufp->page;
+
+		if (PAIRFITS(sop, key, val))
+			putpair((char *)sop, key, val);
+		else
+			if (__big_insert(hashp, bufp, key, val))
+				return (-1);
+	}
+	bufp->flags |= BUF_MOD;
+	/*
+	 * If the average number of keys per bucket exceeds the fill factor,
+	 * expand the table.
+	 */
+	hashp->NKEYS++;
+	if (do_expand ||
+	    (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
+		return (__expand_table(hashp));
+	return (0);
+}
+
+/*
+ *
+ * Returns:
+ *	pointer on success
+ *	NULL on error
+ */
+extern BUFHEAD *
+__add_ovflpage(hashp, bufp)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+{
+	u_int16_t *sp;
+	u_int16_t ndx, ovfl_num;
+#ifdef DEBUG1
+	int tmp1, tmp2;
+#endif
+	sp = (u_int16_t *)bufp->page;
+
+	/* Check if we are dynamically determining the fill factor */
+	if (hashp->FFACTOR == DEF_FFACTOR) {
+		hashp->FFACTOR = sp[0] >> 1;
+		if (hashp->FFACTOR < MIN_FFACTOR)
+			hashp->FFACTOR = MIN_FFACTOR;
+	}
+	bufp->flags |= BUF_MOD;
+	ovfl_num = overflow_page(hashp);
+#ifdef DEBUG1
+	tmp1 = bufp->addr;
+	tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
+#endif
+	if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
+		return (NULL);
+	bufp->ovfl->flags |= BUF_MOD;
+#ifdef DEBUG1
+	(void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
+	    tmp1, tmp2, bufp->ovfl->addr);
+#endif
+	ndx = sp[0];
+	/*
+	 * Since a pair is allocated on a page only if there's room to add
+	 * an overflow page, we know that the OVFL information will fit on
+	 * the page.
+	 */
+	sp[ndx + 4] = OFFSET(sp);
+	sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
+	sp[ndx + 1] = ovfl_num;
+	sp[ndx + 2] = OVFLPAGE;
+	sp[0] = ndx + 2;
+#ifdef HASH_STATISTICS
+	hash_overflows++;
+#endif
+	return (bufp->ovfl);
+}
+
+/*
+ * Returns:
+ *	 0 indicates SUCCESS
+ *	-1 indicates FAILURE
+ */
+extern int
+__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
+	HTAB *hashp;
+	char *p;
+	u_int32_t bucket;
+	int is_bucket, is_disk, is_bitmap;
+{
+	int fd, page, size;
+	int rsize;
+	u_int16_t *bp;
+
+	fd = hashp->fp;
+	size = hashp->BSIZE;
+
+	if ((fd == -1) || !is_disk) {
+		PAGE_INIT(p);
+		return (0);
+	}
+	if (is_bucket)
+		page = BUCKET_TO_PAGE(bucket);
+	else
+		page = OADDR_TO_PAGE(bucket);
+	if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
+	    ((rsize = _read(fd, p, size)) == -1))
+		return (-1);
+	bp = (u_int16_t *)p;
+	if (!rsize)
+		bp[0] = 0;	/* We hit the EOF, so initialize a new page */
+	else
+		if (rsize != size) {
+			errno = EFTYPE;
+			return (-1);
+		}
+	if (!is_bitmap && !bp[0]) {
+		PAGE_INIT(p);
+	} else
+		if (hashp->LORDER != BYTE_ORDER) {
+			int i, max;
+
+			if (is_bitmap) {
+				max = hashp->BSIZE >> 2; /* divide by 4 */
+				for (i = 0; i < max; i++)
+					M_32_SWAP(((int *)p)[i]);
+			} else {
+				M_16_SWAP(bp[0]);
+				max = bp[0] + 2;
+				for (i = 1; i <= max; i++)
+					M_16_SWAP(bp[i]);
+			}
+		}
+	return (0);
+}
+
+/*
+ * Write page p to disk
+ *
+ * Returns:
+ *	 0 ==> OK
+ *	-1 ==>failure
+ */
+extern int
+__put_page(hashp, p, bucket, is_bucket, is_bitmap)
+	HTAB *hashp;
+	char *p;
+	u_int32_t bucket;
+	int is_bucket, is_bitmap;
+{
+	int fd, page, size;
+	int wsize;
+
+	size = hashp->BSIZE;
+	if ((hashp->fp == -1) && open_temp(hashp))
+		return (-1);
+	fd = hashp->fp;
+
+	if (hashp->LORDER != BYTE_ORDER) {
+		int i;
+		int max;
+
+		if (is_bitmap) {
+			max = hashp->BSIZE >> 2;	/* divide by 4 */
+			for (i = 0; i < max; i++)
+				M_32_SWAP(((int *)p)[i]);
+		} else {
+			max = ((u_int16_t *)p)[0] + 2;
+			for (i = 0; i <= max; i++)
+				M_16_SWAP(((u_int16_t *)p)[i]);
+		}
+	}
+	if (is_bucket)
+		page = BUCKET_TO_PAGE(bucket);
+	else
+		page = OADDR_TO_PAGE(bucket);
+	if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
+	    ((wsize = _write(fd, p, size)) == -1))
+		/* Errno is set */
+		return (-1);
+	if (wsize != size) {
+		errno = EFTYPE;
+		return (-1);
+	}
+	return (0);
+}
+
+#define BYTE_MASK	((1 << INT_BYTE_SHIFT) -1)
+/*
+ * Initialize a new bitmap page.  Bitmap pages are left in memory
+ * once they are read in.
+ */
+extern int
+__ibitmap(hashp, pnum, nbits, ndx)
+	HTAB *hashp;
+	int pnum, nbits, ndx;
+{
+	u_int32_t *ip;
+	int clearbytes, clearints;
+
+	if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
+		return (1);
+	hashp->nmaps++;
+	clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
+	clearbytes = clearints << INT_TO_BYTE;
+	(void)memset((char *)ip, 0, clearbytes);
+	(void)memset(((char *)ip) + clearbytes, 0xFF,
+	    hashp->BSIZE - clearbytes);
+	ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
+	SETBIT(ip, 0);
+	hashp->BITMAPS[ndx] = (u_int16_t)pnum;
+	hashp->mapp[ndx] = ip;
+	return (0);
+}
+
+static u_int32_t
+first_free(map)
+	u_int32_t map;
+{
+	u_int32_t i, mask;
+
+	mask = 0x1;
+	for (i = 0; i < BITS_PER_MAP; i++) {
+		if (!(mask & map))
+			return (i);
+		mask = mask << 1;
+	}
+	return (i);
+}
+
+static u_int16_t
+overflow_page(hashp)
+	HTAB *hashp;
+{
+	u_int32_t *freep;
+	int max_free, offset, splitnum;
+	u_int16_t addr;
+	int bit, first_page, free_bit, free_page, i, in_use_bits, j;
+#ifdef DEBUG2
+	int tmp1, tmp2;
+#endif
+	splitnum = hashp->OVFL_POINT;
+	max_free = hashp->SPARES[splitnum];
+
+	free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
+	free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
+
+	/* Look through all the free maps to find the first free block */
+	first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
+	for ( i = first_page; i <= free_page; i++ ) {
+		if (!(freep = (u_int32_t *)hashp->mapp[i]) &&
+		    !(freep = fetch_bitmap(hashp, i)))
+			return (0);
+		if (i == free_page)
+			in_use_bits = free_bit;
+		else
+			in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
+
+		if (i == first_page) {
+			bit = hashp->LAST_FREED &
+			    ((hashp->BSIZE << BYTE_SHIFT) - 1);
+			j = bit / BITS_PER_MAP;
+			bit = bit & ~(BITS_PER_MAP - 1);
+		} else {
+			bit = 0;
+			j = 0;
+		}
+		for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
+			if (freep[j] != ALL_SET)
+				goto found;
+	}
+
+	/* No Free Page Found */
+	hashp->LAST_FREED = hashp->SPARES[splitnum];
+	hashp->SPARES[splitnum]++;
+	offset = hashp->SPARES[splitnum] -
+	    (splitnum ? hashp->SPARES[splitnum - 1] : 0);
+
+#define	OVMSG	"HASH: Out of overflow pages.  Increase page size\n"
+	if (offset > SPLITMASK) {
+		if (++splitnum >= NCACHED) {
+			(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+			return (0);
+		}
+		hashp->OVFL_POINT = splitnum;
+		hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
+		hashp->SPARES[splitnum-1]--;
+		offset = 1;
+	}
+
+	/* Check if we need to allocate a new bitmap page */
+	if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
+		free_page++;
+		if (free_page >= NCACHED) {
+			(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+			return (0);
+		}
+		/*
+		 * This is tricky.  The 1 indicates that you want the new page
+		 * allocated with 1 clear bit.  Actually, you are going to
+		 * allocate 2 pages from this map.  The first is going to be
+		 * the map page, the second is the overflow page we were
+		 * looking for.  The init_bitmap routine automatically, sets
+		 * the first bit of itself to indicate that the bitmap itself
+		 * is in use.  We would explicitly set the second bit, but
+		 * don't have to if we tell init_bitmap not to leave it clear
+		 * in the first place.
+		 */
+		if (__ibitmap(hashp,
+		    (int)OADDR_OF(splitnum, offset), 1, free_page))
+			return (0);
+		hashp->SPARES[splitnum]++;
+#ifdef DEBUG2
+		free_bit = 2;
+#endif
+		offset++;
+		if (offset > SPLITMASK) {
+			if (++splitnum >= NCACHED) {
+				(void)_write(STDERR_FILENO, OVMSG,
+				    sizeof(OVMSG) - 1);
+				return (0);
+			}
+			hashp->OVFL_POINT = splitnum;
+			hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
+			hashp->SPARES[splitnum-1]--;
+			offset = 0;
+		}
+	} else {
+		/*
+		 * Free_bit addresses the last used bit.  Bump it to address
+		 * the first available bit.
+		 */
+		free_bit++;
+		SETBIT(freep, free_bit);
+	}
+
+	/* Calculate address of the new overflow page */
+	addr = OADDR_OF(splitnum, offset);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    addr, free_bit, free_page);
+#endif
+	return (addr);
+
+found:
+	bit = bit + first_free(freep[j]);
+	SETBIT(freep, bit);
+#ifdef DEBUG2
+	tmp1 = bit;
+	tmp2 = i;
+#endif
+	/*
+	 * Bits are addressed starting with 0, but overflow pages are addressed
+	 * beginning at 1. Bit is a bit addressnumber, so we need to increment
+	 * it to convert it to a page number.
+	 */
+	bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
+	if (bit >= hashp->LAST_FREED)
+		hashp->LAST_FREED = bit - 1;
+
+	/* Calculate the split number for this page */
+	for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
+	offset = (i ? bit - hashp->SPARES[i - 1] : bit);
+	if (offset >= SPLITMASK)
+		return (0);	/* Out of overflow pages */
+	addr = OADDR_OF(i, offset);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    addr, tmp1, tmp2);
+#endif
+
+	/* Allocate and return the overflow page */
+	return (addr);
+}
+
+/*
+ * Mark this overflow page as free.
+ */
+extern void
+__free_ovflpage(hashp, obufp)
+	HTAB *hashp;
+	BUFHEAD *obufp;
+{
+	u_int16_t addr;
+	u_int32_t *freep;
+	int bit_address, free_page, free_bit;
+	u_int16_t ndx;
+
+	addr = obufp->addr;
+#ifdef DEBUG1
+	(void)fprintf(stderr, "Freeing %d\n", addr);
+#endif
+	ndx = (((u_int16_t)addr) >> SPLITSHIFT);
+	bit_address =
+	    (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
+	 if (bit_address < hashp->LAST_FREED)
+		hashp->LAST_FREED = bit_address;
+	free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
+	free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
+
+	if (!(freep = hashp->mapp[free_page]))
+		freep = fetch_bitmap(hashp, free_page);
+#ifdef DEBUG
+	/*
+	 * This had better never happen.  It means we tried to read a bitmap
+	 * that has already had overflow pages allocated off it, and we
+	 * failed to read it from the file.
+	 */
+	if (!freep)
+		assert(0);
+#endif
+	CLRBIT(freep, free_bit);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    obufp->addr, free_bit, free_page);
+#endif
+	__reclaim_buf(hashp, obufp);
+}
+
+/*
+ * Returns:
+ *	 0 success
+ *	-1 failure
+ */
+static int
+open_temp(hashp)
+	HTAB *hashp;
+{
+	sigset_t set, oset;
+#ifdef __EMX__
+	char namestr[] = "hsXXXXXX";
+#else /* not __EMX__ */
+	static char namestr[] = "_hashXXXXXX";
+#endif /* not __EMX__ */
+
+	/* Block signals; make sure file goes away at process exit. */
+	(void)sigfillset(&set);
+	(void)_sigprocmask(SIG_BLOCK, &set, &oset);
+	if ((hashp->fp = mkstemp(namestr)) != -1) {
+#ifdef __EMX__
+		char absname[_MAX_PATH];
+		setmode (hashp->fp, O_BINARY);
+		if (_abspath (absname, namestr, sizeof (absname)) == 0)
+			hashp->tempname = strdup (absname);
+#else /* not __EMX__ */
+		(void)unlink(namestr);
+#endif /* not __EMX__ */
+		(void)_fcntl(hashp->fp, F_SETFD, 1);
+	}
+	(void)_sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
+	return (hashp->fp != -1 ? 0 : -1);
+}
+
+/*
+ * We have to know that the key will fit, but the last entry on the page is
+ * an overflow pair, so we need to shift things.
+ */
+static void
+squeeze_key(sp, key, val)
+	u_int16_t *sp;
+	const DBT *key, *val;
+{
+	char *p;
+	u_int16_t free_space, n, off, pageno;
+
+	p = (char *)sp;
+	n = sp[0];
+	free_space = FREESPACE(sp);
+	off = OFFSET(sp);
+
+	pageno = sp[n - 1];
+	off -= key->size;
+	sp[n - 1] = off;
+	memmove(p + off, key->data, key->size);
+	off -= val->size;
+	sp[n] = off;
+	memmove(p + off, val->data, val->size);
+	sp[0] = n + 2;
+	sp[n + 1] = pageno;
+	sp[n + 2] = OVFLPAGE;
+	FREESPACE(sp) = free_space - PAIRSIZE(key, val);
+	OFFSET(sp) = off;
+}
+
+static u_int32_t *
+fetch_bitmap(hashp, ndx)
+	HTAB *hashp;
+	int ndx;
+{
+	if (ndx >= hashp->nmaps)
+		return (NULL);
+	if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
+		return (NULL);
+	if (__get_page(hashp,
+	    (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {
+		free(hashp->mapp[ndx]);
+		return (NULL);
+	}
+	return (hashp->mapp[ndx]);
+}
+
+#ifdef DEBUG4
+int
+print_chain(addr)
+	int addr;
+{
+	BUFHEAD *bufp;
+	short *bp, oaddr;
+
+	(void)fprintf(stderr, "%d ", addr);
+	bufp = __get_buf(hashp, addr, NULL, 0);
+	bp = (short *)bufp->page;
+	while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
+		((bp[0] > 2) && bp[2] < REAL_KEY))) {
+		oaddr = bp[bp[0] - 1];
+		(void)fprintf(stderr, "%d ", (int)oaddr);
+		bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
+		bp = (short *)bufp->page;
+	}
+	(void)fprintf(stderr, "\n");
+}
+#endif
Index: /trunk/libc/src/fbsdlibc/db/hash/ndbm.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/ndbm.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/ndbm.c	(revision 2448)
@@ -0,0 +1,232 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ndbm.c	8.4 (Berkeley) 7/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/ndbm.c,v 1.6 2002/03/22 21:52:01 obrien Exp $");
+
+/*
+ * This package provides a dbm compatible interface to the new hashing
+ * package described in db(3).
+ */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <ndbm.h>
+#include "hash.h"
+
+/*
+ * Returns:
+ * 	*DBM on success
+ *	 NULL on failure
+ */
+extern DBM *
+dbm_open(file, flags, mode)
+	const char *file;
+	int flags, mode;
+{
+	HASHINFO info;
+	char path[MAXPATHLEN];
+
+	info.bsize = 4096;
+	info.ffactor = 40;
+	info.nelem = 1;
+	info.cachesize = 0;
+	info.hash = NULL;
+	info.lorder = 0;
+
+	if( strlen(file) >= sizeof(path) - strlen(DBM_SUFFIX)) {
+		errno = ENAMETOOLONG;
+		return(NULL);
+	}
+	(void)strcpy(path, file);
+	(void)strcat(path, DBM_SUFFIX);
+	return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+}
+
+extern void
+dbm_close(db)
+	DBM *db;
+{
+	(void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+extern datum
+dbm_fetch(db, key)
+	DBM *db;
+	datum key;
+{
+	datum retdata;
+	int status;
+	DBT dbtkey, dbtretdata;
+
+	dbtkey.data = key.dptr;
+	dbtkey.size = key.dsize;
+	status = (db->get)(db, &dbtkey, &dbtretdata, 0);
+	if (status) {
+		dbtretdata.data = NULL;
+		dbtretdata.size = 0;
+	}
+	retdata.dptr = dbtretdata.data;
+	retdata.dsize = dbtretdata.size;
+	return (retdata);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+extern datum
+dbm_firstkey(db)
+	DBM *db;
+{
+	int status;
+	datum retkey;
+	DBT dbtretkey, dbtretdata;
+
+	status = (db->seq)(db, &dbtretkey, &dbtretdata, R_FIRST);
+	if (status)
+		dbtretkey.data = NULL;
+	retkey.dptr = dbtretkey.data;
+	retkey.dsize = dbtretkey.size;
+	return (retkey);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+extern datum
+dbm_nextkey(db)
+	DBM *db;
+{
+	int status;
+	datum retkey;
+	DBT dbtretkey, dbtretdata;
+
+	status = (db->seq)(db, &dbtretkey, &dbtretdata, R_NEXT);
+	if (status)
+		dbtretkey.data = NULL;
+	retkey.dptr = dbtretkey.data;
+	retkey.dsize = dbtretkey.size;
+	return (retkey);
+}
+
+/*
+ * Returns:
+ *	 0 on success
+ *	<0 failure
+ */
+extern int
+dbm_delete(db, key)
+	DBM *db;
+	datum key;
+{
+	int status;
+	DBT dbtkey;
+
+	dbtkey.data = key.dptr;
+	dbtkey.size = key.dsize;
+	status = (db->del)(db, &dbtkey, 0);
+	if (status)
+		return (-1);
+	else
+		return (0);
+}
+
+/*
+ * Returns:
+ *	 0 on success
+ *	<0 failure
+ *	 1 if DBM_INSERT and entry exists
+ */
+extern int
+dbm_store(db, key, data, flags)
+	DBM *db;
+	datum key, data;
+	int flags;
+{
+	DBT dbtkey, dbtdata;
+
+	dbtkey.data = key.dptr;
+	dbtkey.size = key.dsize;
+	dbtdata.data = data.dptr;
+	dbtdata.size = data.dsize;
+	return ((db->put)(db, &dbtkey, &dbtdata,
+	    (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
+}
+
+extern int
+dbm_error(db)
+	DBM *db;
+{
+	HTAB *hp;
+
+	hp = (HTAB *)db->internal;
+	return (hp->dbmerrno);          /* bird: errno */
+}
+
+extern int
+dbm_clearerr(db)
+	DBM *db;
+{
+	HTAB *hp;
+
+	hp = (HTAB *)db->internal;
+	hp->dbmerrno = 0;               /* bird: errno */
+	return (0);
+}
+
+extern int
+dbm_dirfno(db)
+	DBM *db;
+{
+	return(((HTAB *)db->internal)->fp);
+}
Index: /trunk/libc/src/fbsdlibc/db/hash/page.h
===================================================================
--- /trunk/libc/src/fbsdlibc/db/hash/page.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/hash/page.h	(revision 2448)
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ *
+ *	@(#)page.h	8.2 (Berkeley) 5/31/94
+ * $FreeBSD: src/lib/libc/db/hash/page.h,v 1.2 2002/03/22 23:41:40 obrien Exp $
+ */
+
+/*
+ * Definitions for hashing page file format.
+ */
+
+/*
+ * routines dealing with a data page
+ *
+ * page format:
+ *	+------------------------------+
+ * p	| n | keyoff | datoff | keyoff |
+ * 	+------------+--------+--------+
+ *	| datoff | free  |  ptr  | --> |
+ *	+--------+---------------------+
+ *	|	 F R E E A R E A       |
+ *	+--------------+---------------+
+ *	|  <---- - - - | data          |
+ *	+--------+-----+----+----------+
+ *	|  key   | data     | key      |
+ *	+--------+----------+----------+
+ *
+ * Pointer to the free space is always:  p[p[0] + 2]
+ * Amount of free space on the page is:  p[p[0] + 1]
+ */
+
+/*
+ * How many bytes required for this pair?
+ *	2 shorts in the table at the top of the page + room for the
+ *	key and room for the data
+ *
+ * We prohibit entering a pair on a page unless there is also room to append
+ * an overflow page. The reason for this it that you can get in a situation
+ * where a single key/data pair fits on a page, but you can't append an
+ * overflow page and later you'd have to split the key/data and handle like
+ * a big pair.
+ * You might as well do this up front.
+ */
+
+#define	PAIRSIZE(K,D)	(2*sizeof(u_int16_t) + (K)->size + (D)->size)
+#define BIGOVERHEAD	(4*sizeof(u_int16_t))
+#define KEYSIZE(K)	(4*sizeof(u_int16_t) + (K)->size);
+#define OVFLSIZE	(2*sizeof(u_int16_t))
+#define FREESPACE(P)	((P)[(P)[0]+1])
+#define	OFFSET(P)	((P)[(P)[0]+2])
+#define PAIRFITS(P,K,D) \
+	(((P)[2] >= REAL_KEY) && \
+	    (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P)))
+#define PAGE_META(N)	(((N)+3) * sizeof(u_int16_t))
+
+typedef struct {
+	BUFHEAD *newp;
+	BUFHEAD *oldp;
+	BUFHEAD *nextp;
+	u_int16_t next_addr;
+}       SPLIT_RETURN;
Index: /trunk/libc/src/fbsdlibc/db/man/Makefile.inc
===================================================================
--- /trunk/libc/src/fbsdlibc/db/man/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/man/Makefile.inc	(revision 2448)
@@ -0,0 +1,18 @@
+#       from @(#)Makefile.inc	8.1 (Berkeley) 6/4/93
+# $FreeBSD: src/lib/libc/db/man/Makefile.inc,v 1.11 2002/11/18 09:50:54 ru Exp $
+
+.PATH: ${.CURDIR}/db/man
+
+MAN+=	btree.3 dbm.3 dbopen.3 hash.3 mpool.3 recno.3
+
+MLINKS+= dbm.3 dbm_clearerr.3
+MLINKS+= dbm.3 dbm_close.3
+MLINKS+= dbm.3 dbm_delete.3
+MLINKS+= dbm.3 dbm_dirnfo.3
+MLINKS+= dbm.3 dbm_error.3
+MLINKS+= dbm.3 dbm_fetch.3
+MLINKS+= dbm.3 dbm_firstkey.3
+MLINKS+= dbm.3 dbm_nextkey.3
+MLINKS+= dbm.3 dbm_open.3
+MLINKS+= dbm.3 dbm_store.3
+MLINKS+= dbopen.3 db.3
Index: /trunk/libc/src/fbsdlibc/db/man/btree.3
===================================================================
--- /trunk/libc/src/fbsdlibc/db/man/btree.3	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/man/btree.3	(revision 2448)
@@ -0,0 +1,275 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.\"	@(#)btree.3	8.4 (Berkeley) 8/18/94
+.\" $FreeBSD: src/lib/libc/db/man/btree.3,v 1.6 2002/12/19 09:40:21 ru Exp $
+.\"
+.Dd August 18, 1994
+.Dt BTREE 3
+.Os
+.Sh NAME
+.Nm btree
+.Nd "btree database access method"
+.Sh SYNOPSIS
+.In sys/types.h
+.In db.h
+.Sh DESCRIPTION
+The routine
+.Fn dbopen
+is the library interface to database files.
+One of the supported file formats is
+.Nm
+files.
+The general description of the database access methods is in
+.Xr dbopen 3 ,
+this manual page describes only the
+.Nm
+specific information.
+.Pp
+The
+.Nm
+data structure is a sorted, balanced tree structure storing
+associated key/data pairs.
+.Pp
+The
+.Nm
+access method specific data structure provided to
+.Fn dbopen
+is defined in the
+.Aq Pa db.h
+include file as follows:
+.Bd -literal
+typedef struct {
+	u_long flags;
+	u_int cachesize;
+	int maxkeypage;
+	int minkeypage;
+	u_int psize;
+	int (*compare)(const DBT *key1, const DBT *key2);
+	size_t (*prefix)(const DBT *key1, const DBT *key2);
+	int lorder;
+} BTREEINFO;
+.Ed
+.Pp
+The elements of this structure are as follows:
+.Bl -tag -width indent
+.It Va flags
+The flag value is specified by
+.Em or Ns 'ing
+any of the following values:
+.Bl -tag -width indent
+.It Dv R_DUP
+Permit duplicate keys in the tree, i.e. permit insertion if the key to be
+inserted already exists in the tree.
+The default behavior, as described in
+.Xr dbopen 3 ,
+is to overwrite a matching key when inserting a new key or to fail if
+the
+.Dv R_NOOVERWRITE
+flag is specified.
+The
+.Dv R_DUP
+flag is overridden by the
+.Dv R_NOOVERWRITE
+flag, and if the
+.Dv R_NOOVERWRITE
+flag is specified, attempts to insert duplicate keys into
+the tree will fail.
+.Pp
+If the database contains duplicate keys, the order of retrieval of
+key/data pairs is undefined if the
+.Va get
+routine is used, however,
+.Va seq
+routine calls with the
+.Dv R_CURSOR
+flag set will always return the logical
+.Dq first
+of any group of duplicate keys.
+.El
+.It Va cachesize
+A suggested maximum size (in bytes) of the memory cache.
+This value is
+.Em only
+advisory, and the access method will allocate more memory rather than fail.
+Since every search examines the root page of the tree, caching the most
+recently used pages substantially improves access time.
+In addition, physical writes are delayed as long as possible, so a moderate
+cache can reduce the number of I/O operations significantly.
+Obviously, using a cache increases (but only increases) the likelihood of
+corruption or lost data if the system crashes while a tree is being modified.
+If
+.Va cachesize
+is 0 (no size is specified) a default cache is used.
+.It Va maxkeypage
+The maximum number of keys which will be stored on any single page.
+Not currently implemented.
+.\" The maximum number of keys which will be stored on any single page.
+.\" Because of the way the
+.\" .Nm
+.\" data structure works,
+.\" .Va maxkeypage
+.\" must always be greater than or equal to 2.
+.\" If
+.\" .Va maxkeypage
+.\" is 0 (no maximum number of keys is specified) the page fill factor is
+.\" made as large as possible (which is almost invariably what is wanted).
+.It Va minkeypage
+The minimum number of keys which will be stored on any single page.
+This value is used to determine which keys will be stored on overflow
+pages, i.e. if a key or data item is longer than the pagesize divided
+by the minkeypage value, it will be stored on overflow pages instead
+of in the page itself.
+If
+.Va minkeypage
+is 0 (no minimum number of keys is specified) a value of 2 is used.
+.It Va psize
+Page size is the size (in bytes) of the pages used for nodes in the tree.
+The minimum page size is 512 bytes and the maximum page size is 64K.
+If
+.Va psize
+is 0 (no page size is specified) a page size is chosen based on the
+underlying file system I/O block size.
+.It Va compare
+Compare is the key comparison function.
+It must return an integer less than, equal to, or greater than zero if the
+first key argument is considered to be respectively less than, equal to,
+or greater than the second key argument.
+The same comparison function must be used on a given tree every time it
+is opened.
+If
+.Va compare
+is
+.Dv NULL
+(no comparison function is specified), the keys are compared
+lexically, with shorter keys considered less than longer keys.
+.It Va prefix
+The
+.Va prefix
+element
+is the prefix comparison function.
+If specified, this routine must return the number of bytes of the second key
+argument which are necessary to determine that it is greater than the first
+key argument.
+If the keys are equal, the key length should be returned.
+Note, the usefulness of this routine is very data dependent, but, in some
+data sets can produce significantly reduced tree sizes and search times.
+If
+.Va prefix
+is
+.Dv NULL
+(no prefix function is specified),
+.Em and
+no comparison function is specified, a default lexical comparison routine
+is used.
+If
+.Va prefix
+is
+.Dv NULL
+and a comparison routine is specified, no prefix comparison is
+done.
+.It Va lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example,
+big endian order would be the number 4,321.
+If
+.Va lorder
+is 0 (no order is specified) the current host order is used.
+.El
+.Pp
+If the file already exists (and the
+.Dv O_TRUNC
+flag is not specified), the
+values specified for the
+.Va flags , lorder
+and
+.Va psize
+arguments
+are ignored
+in favor of the values used when the tree was created.
+.Pp
+Forward sequential scans of a tree are from the least key to the greatest.
+.Pp
+Space freed up by deleting key/data pairs from the tree is never reclaimed,
+although it is normally made available for reuse.
+This means that the
+.Nm
+storage structure is grow-only.
+The only solutions are to avoid excessive deletions, or to create a fresh
+tree periodically from a scan of an existing one.
+.Pp
+Searches, insertions, and deletions in a
+.Nm
+will all complete in
+O lg base N where base is the average fill factor.
+Often, inserting ordered data into
+.Nm Ns s
+results in a low fill factor.
+This implementation has been modified to make ordered insertion the best
+case, resulting in a much better than normal page fill factor.
+.Sh ERRORS
+The
+.Nm
+access method routines may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr dbopen 3 .
+.Sh SEE ALSO
+.Xr dbopen 3 ,
+.Xr hash 3 ,
+.Xr mpool 3 ,
+.Xr recno 3
+.Rs
+.%T "The Ubiquitous B-tree"
+.%A Douglas Comer
+.%J "ACM Comput. Surv. 11"
+.%N 2
+.%D June 1979
+.%P 121-138
+.Re
+.Rs
+.%A Bayer
+.%A Unterauer
+.%T "Prefix B-trees"
+.%J "ACM Transactions on Database Systems"
+.%N 1
+.%V Vol. 2
+.%D March 1977
+.%P 11-26
+.Re
+.Rs
+.%B "The Art of Computer Programming Vol. 3: Sorting and Searching"
+.%A D. E. Knuth
+.%D 1968
+.%P 471-480
+.Re
+.Sh BUGS
+Only big and little endian byte order is supported.
Index: /trunk/libc/src/fbsdlibc/db/man/dbm.3
===================================================================
--- /trunk/libc/src/fbsdlibc/db/man/dbm.3	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/man/dbm.3	(revision 2448)
@@ -0,0 +1,234 @@
+.\" Copyright (c) 1999 Tim Singletary
+.\" No copyright is claimed.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD: src/lib/libc/db/man/dbm.3,v 1.7 2002/12/19 09:40:21 ru Exp $
+.\"
+.\" Note: The date here should be updated whenever a non-trivial
+.\" change is made to the manual page.
+.Dd July 7, 1999
+.Dt DBM 3
+.Os
+.Sh NAME
+.Nm dbm_clearerr ,
+.Nm dbm_close ,
+.Nm dbm_delete ,
+.Nm dbm_dirfno ,
+.Nm dbm_error ,
+.Nm dbm_fetch ,
+.Nm dbm_firstkey ,
+.Nm dbm_nextkey ,
+.Nm dbm_open ,
+.Nm dbm_store
+.Nd database access functions
+.Sh SYNOPSIS
+.In fcntl.h
+.In ndbm.h
+.Ft DBM *
+.Fn dbm_open "const char *base" "int flags" "int mode"
+.Ft void
+.Fn dbm_close "DBM *db"
+.Ft int
+.Fn dbm_store "DBM *db" "datum key" "datum data" "int flags"
+.Ft datum
+.Fn dbm_fetch "DBM *db" "datum key"
+.Ft int
+.Fn dbm_delete "DBM *db" "datum key"
+.Ft datum
+.Fn dbm_firstkey "DBM *db"
+.Ft datum
+.Fn dbm_nextkey "DBM *db"
+.Ft int
+.Fn dbm_error "DBM *db"
+.Ft int
+.Fn dbm_clearerr "DBM *db"
+.Ft int
+.Fn dbm_dirfno "DBM *db"
+.Sh DESCRIPTION
+Database access functions.
+These functions are implemented using
+.Xr dbopen 3
+with a
+.Xr hash 3
+database.
+.Pp
+.Vt datum
+is declared in
+.Aq Pa ndbm.h :
+.Bd -literal
+typedef struct {
+	char *dptr;
+	int dsize;
+} datum;
+.Ed
+.Pp
+The
+.Fn dbm_open base flags mode
+function
+opens or creates a database.
+The
+.Fa base
+argument
+is the basename of the file containing
+the database; the actual database has a
+.Pa .db
+suffix.
+I.e., if
+.Fa base
+is
+.Qq Li /home/me/mystuff
+then the actual database is in the file
+.Pa /home/me/mystuff.db .
+The
+.Fa flags
+and
+.Fa mode
+arguments
+are passed to
+.Xr open 2 .
+.Pq Dv O_RDWR | O_CREAT
+is a typical value for
+.Fa flags ;
+.Li 0660
+is a typical value for
+.Fa mode .
+.Dv O_WRONLY
+is not allowed in
+.Fa flags .
+The pointer returned by
+.Fn dbm_open
+identifies the database and is the
+.Fa db
+argument to the other functions.
+The
+.Fn dbm_open
+function
+returns
+.Dv NULL
+and sets
+.Va errno
+if there were any errors.
+.Pp
+The
+.Fn dbm_close db
+function
+closes the database.
+The
+.Fn dbm_close
+function
+normally returns zero.
+.Pp
+The
+.Fn dbm_store db key data flags
+function
+inserts or replaces an entry in the database.
+The
+.Fa flags
+argument
+is either
+.Dv DBM_INSERT
+or
+.Dv DBM_REPLACE .
+If
+.Fa flags
+is
+.Dv DBM_INSERT
+and the database already contains an entry for
+.Fa key ,
+that entry is not replaced.
+Otherwise the entry is replaced or inserted.
+The
+.Fn dbm_store
+function
+normally returns zero but returns 1 if the entry could not be
+inserted (because
+.Fa flags
+is
+.Dv DBM_INSERT ,
+and an entry with
+.Fa key
+already exists) or returns -1 and sets
+.Va errno
+if there were any errors.
+.Pp
+The
+.Fn dbm_fetch db key
+function
+returns
+.Dv NULL
+or the
+.Fa data
+corresponding to
+.Fa key .
+.Pp
+The
+.Fn dbm_delete db key
+function
+deletes the entry for
+.Fa key .
+The
+.Fn dbm_delete
+function
+normally returns zero but returns 1 if there was no entry with
+.Fa key
+in the database or returns -1 and sets
+.Va errno
+if there were any errors.
+.Pp
+The
+.Fn dbm_firstkey db
+function
+returns the first key in the database.
+The
+.Fn dbm_nextkey db
+function
+returns subsequent keys.
+The
+.Fn db_firstkey
+function
+must be called before
+.Fn dbm_nextkey .
+The order in which keys are returned is unspecified and may appear
+random.
+The
+.Fn dbm_nextkey
+function
+returns
+.Dv NULL
+after all keys have been returned.
+.Pp
+The
+.Fn dbm_error db
+function
+returns the
+.Va errno
+value of the most recent error.
+The
+.Fn dbm_clearerr db
+function
+resets this value to 0 and returns 0.
+.Pp
+The
+.Fn dbm_dirfno db
+function
+returns the file descriptor to the database.
+.Sh SEE ALSO
+.Xr open 2 ,
+.Xr dbopen 3 ,
+.Xr hash 3
+.Sh STANDARDS
+These functions (except
+.Fn dbm_dirfno )
+are included in the
+.St -susv2 .
Index: /trunk/libc/src/fbsdlibc/db/man/dbopen.3
===================================================================
--- /trunk/libc/src/fbsdlibc/db/man/dbopen.3	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/man/dbopen.3	(revision 2448)
@@ -0,0 +1,550 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.\"	@(#)dbopen.3	8.5 (Berkeley) 1/2/94
+.\" $FreeBSD: src/lib/libc/db/man/dbopen.3,v 1.8 2002/12/19 09:40:21 ru Exp $
+.\"
+.Dd January 2, 1994
+.Dt DBOPEN 3
+.Os
+.Sh NAME
+.Nm dbopen
+.Nd "database access methods"
+.Sh SYNOPSIS
+.In sys/types.h
+.In db.h
+.In fcntl.h
+.In limits.h
+.Ft DB *
+.Fn dbopen "const char *file" "int flags" "int mode" "DBTYPE type" "const void *openinfo"
+.Sh DESCRIPTION
+The
+.Fn dbopen
+function
+is the library interface to database files.
+The supported file formats are btree, hashed and UNIX file oriented.
+The btree format is a representation of a sorted, balanced tree structure.
+The hashed format is an extensible, dynamic hashing scheme.
+The flat-file format is a byte stream file with fixed or variable length
+records.
+The formats and file format specific information are described in detail
+in their respective manual pages
+.Xr btree 3 ,
+.Xr hash 3
+and
+.Xr recno 3 .
+.Pp
+The
+.Fn dbopen
+function
+opens
+.Fa file
+for reading and/or writing.
+Files never intended to be preserved on disk may be created by setting
+the
+.Fa file
+argument to
+.Dv NULL .
+.Pp
+The
+.Fa flags
+and
+.Fa mode
+arguments
+are as specified to the
+.Xr open 2
+routine, however, only the
+.Dv O_CREAT , O_EXCL , O_EXLOCK , O_NONBLOCK ,
+.Dv O_RDONLY , O_RDWR , O_SHLOCK
+and
+.Dv O_TRUNC
+flags are meaningful.
+(Note, opening a database file
+.Dv O_WRONLY
+is not possible.)
+.\"Three additional options may be specified by
+.\".Em or Ns 'ing
+.\"them into the
+.\".Fa flags
+.\"argument.
+.\".Bl -tag -width indent
+.\".It Dv DB_LOCK
+.\"Do the necessary locking in the database to support concurrent access.
+.\"If concurrent access isn't needed or the database is read-only this
+.\"flag should not be set, as it tends to have an associated performance
+.\"penalty.
+.\".It Dv DB_SHMEM
+.\"Place the underlying memory pool used by the database in shared
+.\"memory.
+.\"Necessary for concurrent access.
+.\".It Dv DB_TXN
+.\"Support transactions in the database.
+.\"The
+.\".Dv DB_LOCK
+.\"and
+.\".Dv DB_SHMEM
+.\"flags must be set as well.
+.\".El
+.Pp
+The
+.Fa type
+argument is of type
+.Ft DBTYPE
+(as defined in the
+.Aq Pa db.h
+include file) and
+may be set to
+.Dv DB_BTREE , DB_HASH
+or
+.Dv DB_RECNO .
+.Pp
+The
+.Fa openinfo
+argument is a pointer to an access method specific structure described
+in the access method's manual page.
+If
+.Fa openinfo
+is
+.Dv NULL ,
+each access method will use defaults appropriate for the system
+and the access method.
+.Pp
+The
+.Fn dbopen
+function
+returns a pointer to a
+.Ft DB
+structure on success and
+.Dv NULL
+on error.
+The
+.Ft DB
+structure is defined in the
+.Aq Pa db.h
+include file, and contains at
+least the following fields:
+.Bd -literal
+typedef struct {
+	DBTYPE type;
+	int (*close)(const DB *db);
+	int (*del)(const DB *db, const DBT *key, u_int flags);
+	int (*fd)(const DB *db);
+	int (*get)(const DB *db, DBT *key, DBT *data, u_int flags);
+	int (*put)(const DB *db, DBT *key, const DBT *data,
+	     u_int flags);
+	int (*sync)(const DB *db, u_int flags);
+	int (*seq)(const DB *db, DBT *key, DBT *data, u_int flags);
+} DB;
+.Ed
+.Pp
+These elements describe a database type and a set of functions performing
+various actions.
+These functions take a pointer to a structure as returned by
+.Fn dbopen ,
+and sometimes one or more pointers to key/data structures and a flag value.
+.Bl -tag -width indent
+.It Va type
+The type of the underlying access method (and file format).
+.It Va close
+A pointer to a routine to flush any cached information to disk, free any
+allocated resources, and close the underlying file(s).
+Since key/data pairs may be cached in memory, failing to sync the file
+with a
+.Va close
+or
+.Va sync
+function may result in inconsistent or lost information.
+.Va close
+routines return -1 on error (setting
+.Va errno )
+and 0 on success.
+.It Va del
+A pointer to a routine to remove key/data pairs from the database.
+.Pp
+The
+.Fa flags
+argument
+may be set to the following value:
+.Bl -tag -width indent
+.It Dv R_CURSOR
+Delete the record referenced by the cursor.
+The cursor must have previously been initialized.
+.El
+.Pp
+.Va delete
+routines return -1 on error (setting
+.Va errno ) ,
+0 on success, and 1 if the specified
+.Fa key
+was not in the file.
+.It Va fd
+A pointer to a routine which returns a file descriptor representative
+of the underlying database.
+A file descriptor referencing the same file will be returned to all
+processes which call
+.Fn dbopen
+with the same
+.Fa file
+name.
+This file descriptor may be safely used as an argument to the
+.Xr fcntl 2
+and
+.Xr flock 2
+locking functions.
+The file descriptor is not necessarily associated with any of the
+underlying files used by the access method.
+No file descriptor is available for in memory databases.
+.Va \&Fd
+routines return -1 on error (setting
+.Va errno ) ,
+and the file descriptor on success.
+.It Va get
+A pointer to a routine which is the interface for keyed retrieval from
+the database.
+The address and length of the data associated with the specified
+.Fa key
+are returned in the structure referenced by
+.Fa data .
+.Va get
+routines return -1 on error (setting
+.Va errno ) ,
+0 on success, and 1 if the
+.Fa key
+was not in the file.
+.It Va put
+A pointer to a routine to store key/data pairs in the database.
+.Pp
+The
+.Fa flags
+argument
+may be set to one of the following values:
+.Bl -tag -width indent
+.It Dv R_CURSOR
+Replace the key/data pair referenced by the cursor.
+The cursor must have previously been initialized.
+.It Dv R_IAFTER
+Append the data immediately after the data referenced by
+.Fa key ,
+creating a new key/data pair.
+The record number of the appended key/data pair is returned in the
+.Fa key
+structure.
+(Applicable only to the
+.Dv DB_RECNO
+access method.)
+.It Dv R_IBEFORE
+Insert the data immediately before the data referenced by
+.Fa key ,
+creating a new key/data pair.
+The record number of the inserted key/data pair is returned in the
+.Fa key
+structure.
+(Applicable only to the
+.Dv DB_RECNO
+access method.)
+.It Dv R_NOOVERWRITE
+Enter the new key/data pair only if the key does not previously exist.
+.It Dv R_SETCURSOR
+Store the key/data pair, setting or initializing the position of the
+cursor to reference it.
+(Applicable only to the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access methods.)
+.El
+.Pp
+.Dv R_SETCURSOR
+is available only for the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access
+methods because it implies that the keys have an inherent order
+which does not change.
+.Pp
+.Dv R_IAFTER
+and
+.Dv R_IBEFORE
+are available only for the
+.Dv DB_RECNO
+access method because they each imply that the access method is able to
+create new keys.
+This is only true if the keys are ordered and independent, record numbers
+for example.
+.Pp
+The default behavior of the
+.Va put
+routines is to enter the new key/data pair, replacing any previously
+existing key.
+.Pp
+.Va put
+routines return -1 on error (setting
+.Va errno ) ,
+0 on success, and 1 if the
+.Dv R_NOOVERWRITE
+flag
+was set and the key already exists in the file.
+.It Va seq
+A pointer to a routine which is the interface for sequential
+retrieval from the database.
+The address and length of the key are returned in the structure
+referenced by
+.Fa key ,
+and the address and length of the data are returned in the
+structure referenced
+by
+.Fa data .
+.Pp
+Sequential key/data pair retrieval may begin at any time, and the
+position of the
+.Dq cursor
+is not affected by calls to the
+.Va del ,
+.Va get ,
+.Va put ,
+or
+.Va sync
+routines.
+Modifications to the database during a sequential scan will be reflected
+in the scan, i.e. records inserted behind the cursor will not be returned
+while records inserted in front of the cursor will be returned.
+.Pp
+The
+.Fa flags
+argument
+.Em must
+be set to one of the following values:
+.Bl -tag -width indent
+.It Dv R_CURSOR
+The data associated with the specified key is returned.
+This differs from the
+.Va get
+routines in that it sets or initializes the cursor to the location of
+the key as well.
+(Note, for the
+.Dv DB_BTREE
+access method, the returned key is not necessarily an
+exact match for the specified key.
+The returned key is the smallest key greater than or equal to the specified
+key, permitting partial key matches and range searches.)
+.It Dv R_FIRST
+The first key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+.It Dv R_LAST
+The last key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+(Applicable only to the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access methods.)
+.It Dv R_NEXT
+Retrieve the key/data pair immediately after the cursor.
+If the cursor is not yet set, this is the same as the
+.Dv R_FIRST
+flag.
+.It Dv R_PREV
+Retrieve the key/data pair immediately before the cursor.
+If the cursor is not yet set, this is the same as the
+.Dv R_LAST
+flag.
+(Applicable only to the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access methods.)
+.El
+.Pp
+.Dv R_LAST
+and
+.Dv R_PREV
+are available only for the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access methods because they each imply that the keys have an inherent
+order which does not change.
+.Pp
+.Va seq
+routines return -1 on error (setting
+.Va errno ) ,
+0 on success and 1 if there are no key/data pairs less than or greater
+than the specified or current key.
+If the
+.Dv DB_RECNO
+access method is being used, and if the database file
+is a character special file and no complete key/data pairs are currently
+available, the
+.Va seq
+routines return 2.
+.It Va sync
+A pointer to a routine to flush any cached information to disk.
+If the database is in memory only, the
+.Va sync
+routine has no effect and will always succeed.
+.Pp
+The
+.Fa flags
+argument may be set to the following value:
+.Bl -tag -width indent
+.It Dv R_RECNOSYNC
+If the
+.Dv DB_RECNO
+access method is being used, this flag causes
+the
+.Va sync
+routine to apply to the btree file which underlies the
+recno file, not the recno file itself.
+(See the
+.Va bfname
+field of the
+.Xr recno 3
+manual page for more information.)
+.El
+.Pp
+.Va sync
+routines return -1 on error (setting
+.Va errno )
+and 0 on success.
+.El
+.Sh "KEY/DATA PAIRS"
+Access to all file types is based on key/data pairs.
+Both keys and data are represented by the following data structure:
+.Bd -literal
+typedef struct {
+	void *data;
+	size_t size;
+} DBT;
+.Ed
+.Pp
+The elements of the
+.Ft DBT
+structure are defined as follows:
+.Bl -tag -width "data"
+.It Va data
+A pointer to a byte string.
+.It Va size
+The length of the byte string.
+.El
+.Pp
+Key and data byte strings may reference strings of essentially unlimited
+length although any two of them must fit into available memory at the same
+time.
+It should be noted that the access methods provide no guarantees about
+byte string alignment.
+.Sh ERRORS
+The
+.Fn dbopen
+routine may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr open 2
+and
+.Xr malloc 3
+or the following:
+.Bl -tag -width Er
+.It Bq Er EFTYPE
+A file is incorrectly formatted.
+.It Bq Er EINVAL
+An argument has been specified (hash function, pad byte etc.) that is
+incompatible with the current file specification or which is not
+meaningful for the function (for example, use of the cursor without
+prior initialization) or there is a mismatch between the version
+number of file and the software.
+.El
+.Pp
+The
+.Va close
+routines may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr close 2 ,
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr free 3 ,
+or
+.Xr fsync 2 .
+.Pp
+The
+.Va del ,
+.Va get ,
+.Va put
+and
+.Va seq
+routines may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr free 3
+or
+.Xr malloc 3 .
+.Pp
+The
+.Va fd
+routines will fail and set
+.Va errno
+to
+.Er ENOENT
+for in memory databases.
+.Pp
+The
+.Va sync
+routines may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr fsync 2 .
+.Sh SEE ALSO
+.Xr btree 3 ,
+.Xr hash 3 ,
+.Xr mpool 3 ,
+.Xr recno 3
+.Rs
+.%T "LIBTP: Portable, Modular Transactions for UNIX"
+.%A Margo Seltzer
+.%A Michael Olson
+.%R "USENIX proceedings"
+.%D Winter 1992
+.Re
+.Sh BUGS
+The typedef
+.Ft DBT
+is a mnemonic for
+.Dq "data base thang" ,
+and was used
+because noone could think of a reasonable name that wasn't already used.
+.Pp
+The file descriptor interface is a kluge and will be deleted in a
+future version of the interface.
+.Pp
+None of the access methods provide any form of concurrent access,
+locking, or transactions.
Index: /trunk/libc/src/fbsdlibc/db/man/hash.3
===================================================================
--- /trunk/libc/src/fbsdlibc/db/man/hash.3	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/man/hash.3	(revision 2448)
@@ -0,0 +1,200 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.\"	@(#)hash.3	8.6 (Berkeley) 8/18/94
+.\" $FreeBSD: src/lib/libc/db/man/hash.3,v 1.7 2002/12/19 09:40:21 ru Exp $
+.\"
+.Dd August 18, 1994
+.Dt HASH 3
+.Os
+.Sh NAME
+.Nm hash
+.Nd "hash database access method"
+.Sh SYNOPSIS
+.In sys/types.h
+.In db.h
+.Sh DESCRIPTION
+The routine
+.Fn dbopen
+is the library interface to database files.
+One of the supported file formats is
+.Nm
+files.
+The general description of the database access methods is in
+.Xr dbopen 3 ,
+this manual page describes only the
+.Nm
+specific information.
+.Pp
+The
+.Nm
+data structure is an extensible, dynamic hashing scheme.
+.Pp
+The access method specific data structure provided to
+.Fn dbopen
+is defined in the
+.Aq Pa db.h
+include file as follows:
+.Bd -literal
+typedef struct {
+	u_int bsize;
+	u_int ffactor;
+	u_int nelem;
+	u_int cachesize;
+	u_int32_t (*hash)(const void *, size_t);
+	int lorder;
+} HASHINFO;
+.Ed
+.Pp
+The elements of this structure are as follows:
+.Bl -tag -width indent
+.It Va bsize
+The
+.Va bsize
+element
+defines the
+.Nm
+table bucket size, and is, by default, 256 bytes.
+It may be preferable to increase the page size for disk-resident tables
+and tables with large data items.
+.It Va ffactor
+The
+.Va ffactor
+element
+indicates a desired density within the
+.Nm
+table.
+It is an approximation of the number of keys allowed to accumulate in any
+one bucket, determining when the
+.Nm
+table grows or shrinks.
+The default value is 8.
+.It Va nelem
+The
+.Va nelem
+element
+is an estimate of the final size of the
+.Nm
+table.
+If not set or set too low,
+.Nm
+tables will expand gracefully as keys
+are entered, although a slight performance degradation may be noticed.
+The default value is 1.
+.It Va cachesize
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.Em only
+advisory, and the access method will allocate more memory rather
+than fail.
+.It Va hash
+The
+.Va hash
+element
+is a user defined
+.Nm
+function.
+Since no
+.Nm
+function performs equally well on all possible data, the
+user may find that the built-in
+.Nm
+function does poorly on a particular
+data set.
+User specified
+.Nm
+functions must take two arguments (a pointer to a byte
+string and a length) and return a 32-bit quantity to be used as the
+.Nm
+value.
+.It Va lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example,
+big endian order would be the number 4,321.
+If
+.Va lorder
+is 0 (no order is specified) the current host order is used.
+If the file already exists, the specified value is ignored and the
+value specified when the tree was created is used.
+.El
+.Pp
+If the file already exists (and the
+.Dv O_TRUNC
+flag is not specified), the
+values specified for the
+.Va bsize , ffactor , lorder
+and
+.Va nelem
+arguments
+are
+ignored and the values specified when the tree was created are used.
+.Pp
+If a
+.Nm
+function is specified,
+.Fn hash_open
+will attempt to determine if the
+.Nm
+function specified is the same as
+the one with which the database was created, and will fail if it is not.
+.Pp
+Backward compatible interfaces to the older
+.Em dbm
+and
+.Em ndbm
+routines are provided, however these interfaces are not compatible with
+previous file formats.
+.Sh ERRORS
+The
+.Nm
+access method routines may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr dbopen 3 .
+.Sh SEE ALSO
+.Xr btree 3 ,
+.Xr dbopen 3 ,
+.Xr mpool 3 ,
+.Xr recno 3
+.Rs
+.%T "Dynamic Hash Tables"
+.%A Per-Ake Larson
+.%R "Communications of the ACM"
+.%D April 1988
+.Re
+.Rs
+.%T "A New Hash Package for UNIX"
+.%A Margo Seltzer
+.%R "USENIX Proceedings"
+.%D Winter 1991
+.Re
+.Sh BUGS
+Only big and little endian byte order is supported.
Index: /trunk/libc/src/fbsdlibc/db/man/mpool.3
===================================================================
--- /trunk/libc/src/fbsdlibc/db/man/mpool.3	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/man/mpool.3	(revision 2448)
@@ -0,0 +1,247 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.\"	@(#)mpool.3	8.1 (Berkeley) 6/4/93
+.\" $FreeBSD: src/lib/libc/db/man/mpool.3,v 1.12 2003/02/06 11:04:46 charnier Exp $
+.\"
+.Dd June 4, 1993
+.Dt MPOOL 3
+.Os
+.Sh NAME
+.Nm mpool
+.Nd "shared memory buffer pool"
+.Sh SYNOPSIS
+.In db.h
+.In mpool.h
+.Ft MPOOL *
+.Fn mpool_open "void *key" "int fd" "pgno_t pagesize" "pgno_t maxcache"
+.Ft void
+.Fo mpool_filter
+.Fa "MPOOL *mp"
+.Fa "void (*pgin)(void *, pgno_t, void *)"
+.Fa "void (*pgout)(void *, pgno_t, void *)"
+.Fa "void *pgcookie"
+.Fc
+.Ft void *
+.Fn mpool_new "MPOOL *mp" "pgno_t *pgnoaddr"
+.Ft void *
+.Fn mpool_get "MPOOL *mp" "pgno_t pgno" "u_int flags"
+.Ft int
+.Fn mpool_put "MPOOL *mp" "void *pgaddr" "u_int flags"
+.Ft int
+.Fn mpool_sync "MPOOL *mp"
+.Ft int
+.Fn mpool_close "MPOOL *mp"
+.Sh DESCRIPTION
+The
+.Nm mpool
+library interface is intended to provide page oriented buffer management
+of files.
+The buffers may be shared between processes.
+.Pp
+The
+.Fn mpool_open
+function initializes a memory pool.
+The
+.Fa key
+argument is the byte string used to negotiate between multiple
+processes wishing to share buffers.
+If the file buffers are mapped in shared memory, all processes using
+the same key will share the buffers.
+If
+.Fa key
+is
+.Dv NULL ,
+the buffers are mapped into private memory.
+The
+.Fa fd
+argument is a file descriptor for the underlying file, which must be seekable.
+If
+.Fa key
+is
+.No non\- Ns Dv NULL
+and matches a file already being mapped, the
+.Fa fd
+argument is ignored.
+.Pp
+The
+.Fa pagesize
+argument is the size, in bytes, of the pages into which the file is broken up.
+The
+.Fa maxcache
+argument is the maximum number of pages from the underlying file to cache
+at any one time.
+This value is not relative to the number of processes which share a file's
+buffers, but will be the largest value specified by any of the processes
+sharing the file.
+.Pp
+The
+.Fn mpool_filter
+function is intended to make transparent input and output processing of the
+pages possible.
+If the
+.Fa pgin
+function is specified, it is called each time a buffer is read into the memory
+pool from the backing file.
+If the
+.Fa pgout
+function is specified, it is called each time a buffer is written into the
+backing file.
+Both functions are called with the
+.Fa pgcookie
+pointer, the page number and a pointer to the page to being read or written.
+.Pp
+The
+.Fn mpool_new
+function takes an
+.Ft MPOOL
+pointer and an address as arguments.
+If a new page can be allocated, a pointer to the page is returned and
+the page number is stored into the
+.Fa pgnoaddr
+address.
+Otherwise,
+.Dv NULL
+is returned and
+.Va errno
+is set.
+.Pp
+The
+.Fn mpool_get
+function takes a
+.Ft MPOOL
+pointer and a page number as arguments.
+If the page exists, a pointer to the page is returned.
+Otherwise,
+.Dv NULL
+is returned and
+.Va errno
+is set.
+The
+.Fa flags
+argument is not currently used.
+.Pp
+The
+.Fn mpool_put
+function unpins the page referenced by
+.Fa pgaddr .
+The
+.Fa pgaddr
+argument
+must be an address previously returned by
+.Fn mpool_get
+or
+.Fn mpool_new .
+The
+.Fa flags
+argument is specified by
+.Em or Ns 'ing
+any of the following values:
+.Bl -tag -width indent
+.It Dv MPOOL_DIRTY
+The page has been modified and needs to be written to the backing file.
+.El
+.Pp
+The
+.Fn mpool_put
+function
+returns 0 on success and -1 if an error occurs.
+.Pp
+The
+.Fn mpool_sync
+function writes all modified pages associated with the
+.Ft MPOOL
+pointer to the
+backing file.
+The
+.Fn mpool_sync
+function
+returns 0 on success and -1 if an error occurs.
+.Pp
+The
+.Fn mpool_close
+function free's up any allocated memory associated with the memory pool
+cookie.
+Modified pages are
+.Em not
+written to the backing file.
+The
+.Fn mpool_close
+function
+returns 0 on success and -1 if an error occurs.
+.Sh ERRORS
+The
+.Fn mpool_open
+function may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr malloc 3 .
+.Pp
+The
+.Fn mpool_get
+function may fail and set
+.Va errno
+for the following:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The requested record doesn't exist.
+.El
+.Pp
+The
+.Fn mpool_new
+and
+.Fn mpool_get
+functions may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr read 2 ,
+.Xr write 2 ,
+and
+.Xr malloc 3 .
+.Pp
+The
+.Fn mpool_sync
+function may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr write 2 .
+.Pp
+The
+.Fn mpool_close
+function may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr free 3 .
+.Sh SEE ALSO
+.Xr btree 3 ,
+.Xr dbopen 3 ,
+.Xr hash 3 ,
+.Xr recno 3
Index: /trunk/libc/src/fbsdlibc/db/man/recno.3
===================================================================
--- /trunk/libc/src/fbsdlibc/db/man/recno.3	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/man/recno.3	(revision 2448)
@@ -0,0 +1,232 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.\"	@(#)recno.3	8.5 (Berkeley) 8/18/94
+.\" $FreeBSD: src/lib/libc/db/man/recno.3,v 1.6 2001/10/01 16:08:50 ru Exp $
+.\"
+.Dd August 18, 1994
+.Dt RECNO 3
+.Os
+.Sh NAME
+.Nm recno
+.Nd "record number database access method"
+.Sh SYNOPSIS
+.In sys/types.h
+.In db.h
+.Sh DESCRIPTION
+The routine
+.Fn dbopen
+is the library interface to database files.
+One of the supported file formats is record number files.
+The general description of the database access methods is in
+.Xr dbopen 3 ,
+this manual page describes only the
+.Nm
+specific information.
+.Pp
+The record number data structure is either variable or fixed-length
+records stored in a flat-file format, accessed by the logical record
+number.
+The existence of record number five implies the existence of records
+one through four, and the deletion of record number one causes
+record number five to be renumbered to record number four, as well
+as the cursor, if positioned after record number one, to shift down
+one record.
+.Pp
+The
+.Nm
+access method specific data structure provided to
+.Fn dbopen
+is defined in the
+.Aq Pa db.h
+include file as follows:
+.Bd -literal
+typedef struct {
+	u_long flags;
+	u_int cachesize;
+	u_int psize;
+	int lorder;
+	size_t reclen;
+	u_char bval;
+	char *bfname;
+} RECNOINFO;
+.Ed
+.Pp
+The elements of this structure are defined as follows:
+.Bl -tag -width indent
+.It Va flags
+The flag value is specified by
+.Em or Ns 'ing
+any of the following values:
+.Bl -tag -width indent
+.It Dv R_FIXEDLEN
+The records are fixed-length, not byte delimited.
+The structure element
+.Va reclen
+specifies the length of the record, and the structure element
+.Va bval
+is used as the pad character.
+Any records, inserted into the database, that are less than
+.Va reclen
+bytes long are automatically padded.
+.It Dv R_NOKEY
+In the interface specified by
+.Fn dbopen ,
+the sequential record retrieval fills in both the caller's key and
+data structures.
+If the
+.Dv R_NOKEY
+flag is specified, the
+.Em cursor
+routines are not required to fill in the key structure.
+This permits applications to retrieve records at the end of files without
+reading all of the intervening records.
+.It Dv R_SNAPSHOT
+This flag requires that a snapshot of the file be taken when
+.Fn dbopen
+is called, instead of permitting any unmodified records to be read from
+the original file.
+.El
+.It Va cachesize
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.Em only
+advisory, and the access method will allocate more memory rather than fail.
+If
+.Va cachesize
+is 0 (no size is specified) a default cache is used.
+.It Va psize
+The
+.Nm
+access method stores the in-memory copies of its records
+in a btree.
+This value is the size (in bytes) of the pages used for nodes in that tree.
+If
+.Va psize
+is 0 (no page size is specified) a page size is chosen based on the
+underlying file system I/O block size.
+See
+.Xr btree 3
+for more information.
+.It Va lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example,
+big endian order would be the number 4,321.
+If
+.Va lorder
+is 0 (no order is specified) the current host order is used.
+.It Va reclen
+The length of a fixed-length record.
+.It Va bval
+The delimiting byte to be used to mark the end of a record for
+variable-length records, and the pad character for fixed-length
+records.
+If no value is specified, newlines
+.Pq Dq \en
+are used to mark the end
+of variable-length records and fixed-length records are padded with
+spaces.
+.It Va bfname
+The
+.Nm
+access method stores the in-memory copies of its records
+in a btree.
+If
+.Va bfname
+is
+.No non\- Ns Dv NULL ,
+it specifies the name of the btree file,
+as if specified as the file name for a
+.Fn dbopen
+of a btree file.
+.El
+.Pp
+The data part of the key/data pair used by the
+.Nm
+access method
+is the same as other access methods.
+The key is different.
+The
+.Va data
+field of the key should be a pointer to a memory location of type
+.Ft recno_t ,
+as defined in the
+.Aq Pa db.h
+include file.
+This type is normally the largest unsigned integral type available to
+the implementation.
+The
+.Va size
+field of the key should be the size of that type.
+.Pp
+Because there can be no meta-data associated with the underlying
+.Nm
+access method files, any changes made to the default values
+(e.g. fixed record length or byte separator value) must be explicitly
+specified each time the file is opened.
+.Pp
+In the interface specified by
+.Fn dbopen ,
+using the
+.Va put
+interface to create a new record will cause the creation of multiple,
+empty records if the record number is more than one greater than the
+largest record currently in the database.
+.Sh ERRORS
+The
+.Nm
+access method routines may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr dbopen 3
+or the following:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+An attempt was made to add a record to a fixed-length database that
+was too large to fit.
+.El
+.Sh SEE ALSO
+.Xr btree 3 ,
+.Xr dbopen 3 ,
+.Xr hash 3 ,
+.Xr mpool 3
+.Rs
+.%T "Document Processing in a Relational Database System"
+.%A Michael Stonebraker
+.%A Heidi Stettner
+.%A Joseph Kalash
+.%A Antonin Guttman
+.%A Nadene Lynn
+.%R "Memorandum No. UCB/ERL M82/32"
+.%D May 1982
+.Re
+.Sh BUGS
+Only big and little endian byte order is supported.
Index: /trunk/libc/src/fbsdlibc/db/mpool/Makefile.inc
===================================================================
--- /trunk/libc/src/fbsdlibc/db/mpool/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/mpool/Makefile.inc	(revision 2448)
@@ -0,0 +1,6 @@
+#	from @(#)Makefile.inc	8.1 (Berkeley) 6/4/93
+# $FreeBSD: src/lib/libc/db/mpool/Makefile.inc,v 1.4 2002/11/18 09:50:55 ru Exp $
+
+.PATH: ${.CURDIR}/db/mpool
+
+SRCS+=	mpool.c
Index: /trunk/libc/src/fbsdlibc/db/mpool/README
===================================================================
--- /trunk/libc/src/fbsdlibc/db/mpool/README	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/mpool/README	(revision 2448)
@@ -0,0 +1,7 @@
+#	@(#)README	8.1 (Berkeley) 6/4/93
+
+These are the current memory pool routines.
+They aren't ready for prime time, yet, and
+the interface is expected to change.
+
+--keith
Index: /trunk/libc/src/fbsdlibc/db/mpool/mpool.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/mpool/mpool.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/mpool/mpool.c	(revision 2448)
@@ -0,0 +1,462 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mpool.c	8.5 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/mpool/mpool.c,v 1.11 2004/01/20 00:40:35 das Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+
+#define	__MPOOLINTERFACE_PRIVATE
+#include <mpool.h>
+
+static BKT *mpool_bkt(MPOOL *);
+static BKT *mpool_look(MPOOL *, pgno_t);
+static int  mpool_write(MPOOL *, BKT *);
+
+/*
+ * mpool_open --
+ *	Initialize a memory pool.
+ */
+MPOOL *
+mpool_open(key, fd, pagesize, maxcache)
+	void *key;
+	int fd;
+	pgno_t pagesize, maxcache;
+{
+	struct stat sb;
+	MPOOL *mp;
+	int entry;
+
+	/*
+	 * Get information about the file.
+	 *
+	 * XXX
+	 * We don't currently handle pipes, although we should.
+	 */
+	if (_fstat(fd, &sb))
+		return (NULL);
+	if (!S_ISREG(sb.st_mode)) {
+		errno = ESPIPE;
+		return (NULL);
+	}
+
+	/* Allocate and initialize the MPOOL cookie. */
+	if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL)
+		return (NULL);
+	TAILQ_INIT(&mp->lqh);
+	for (entry = 0; entry < HASHSIZE; ++entry)
+		TAILQ_INIT(&mp->hqh[entry]);
+	mp->maxcache = maxcache;
+	mp->npages = sb.st_size / pagesize;
+	mp->pagesize = pagesize;
+	mp->fd = fd;
+	return (mp);
+}
+
+/*
+ * mpool_filter --
+ *	Initialize input/output filters.
+ */
+void
+mpool_filter(mp, pgin, pgout, pgcookie)
+	MPOOL *mp;
+	void (*pgin)(void *, pgno_t, void *);
+	void (*pgout)(void *, pgno_t, void *);
+	void *pgcookie;
+{
+	mp->pgin = pgin;
+	mp->pgout = pgout;
+	mp->pgcookie = pgcookie;
+}
+	
+/*
+ * mpool_new --
+ *	Get a new page of memory.
+ */
+void *
+mpool_new(mp, pgnoaddr)
+	MPOOL *mp;
+	pgno_t *pgnoaddr;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	if (mp->npages == MAX_PAGE_NUMBER) {
+		(void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
+		abort();
+	}
+#ifdef STATISTICS
+	++mp->pagenew;
+#endif
+	/*
+	 * Get a BKT from the cache.  Assign a new page number, attach
+	 * it to the head of the hash chain, the tail of the lru chain,
+	 * and return.
+	 */
+	if ((bp = mpool_bkt(mp)) == NULL)
+		return (NULL);
+	*pgnoaddr = bp->pgno = mp->npages++;
+	bp->flags = MPOOL_PINNED;
+
+	head = &mp->hqh[HASHKEY(bp->pgno)];
+	TAILQ_INSERT_HEAD(head, bp, hq);
+	TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+	return (bp->page);
+}
+
+/*
+ * mpool_get
+ *	Get a page.
+ */
+void *
+mpool_get(mp, pgno, flags)
+	MPOOL *mp;
+	pgno_t pgno;
+	u_int flags;				/* XXX not used? */
+{
+	struct _hqh *head;
+	BKT *bp;
+	off_t off;
+	int nr;
+
+	/* Check for attempt to retrieve a non-existent page. */
+	if (pgno >= mp->npages) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+#ifdef STATISTICS
+	++mp->pageget;
+#endif
+
+	/* Check for a page that is cached. */
+	if ((bp = mpool_look(mp, pgno)) != NULL) {
+#ifdef DEBUG
+		if (bp->flags & MPOOL_PINNED) {
+			(void)fprintf(stderr,
+			    "mpool_get: page %d already pinned\n", bp->pgno);
+			abort();
+		}
+#endif
+		/*
+		 * Move the page to the head of the hash chain and the tail
+		 * of the lru chain.
+		 */
+		head = &mp->hqh[HASHKEY(bp->pgno)];
+		TAILQ_REMOVE(head, bp, hq);
+		TAILQ_INSERT_HEAD(head, bp, hq);
+		TAILQ_REMOVE(&mp->lqh, bp, q);
+		TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+		/* Return a pinned page. */
+		bp->flags |= MPOOL_PINNED;
+		return (bp->page);
+	}
+
+	/* Get a page from the cache. */
+	if ((bp = mpool_bkt(mp)) == NULL)
+		return (NULL);
+
+	/* Read in the contents. */
+#ifdef STATISTICS
+	++mp->pageread;
+#endif
+	off = mp->pagesize * pgno;
+	nr = pread(mp->fd, bp->page, mp->pagesize, off);
+	if (nr != mp->pagesize) {
+		if (nr >= 0)
+			errno = EFTYPE;
+		return (NULL);
+	}
+
+	/* Set the page number, pin the page. */
+	bp->pgno = pgno;
+	bp->flags = MPOOL_PINNED;
+
+	/*
+	 * Add the page to the head of the hash chain and the tail
+	 * of the lru chain.
+	 */
+	head = &mp->hqh[HASHKEY(bp->pgno)];
+	TAILQ_INSERT_HEAD(head, bp, hq);
+	TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+	/* Run through the user's filter. */
+	if (mp->pgin != NULL)
+		(mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
+
+	return (bp->page);
+}
+
+/*
+ * mpool_put
+ *	Return a page.
+ */
+int
+mpool_put(mp, page, flags)
+	MPOOL *mp;
+	void *page;
+	u_int flags;
+{
+	BKT *bp;
+
+#ifdef STATISTICS
+	++mp->pageput;
+#endif
+	bp = (BKT *)((char *)page - sizeof(BKT));
+#ifdef DEBUG
+	if (!(bp->flags & MPOOL_PINNED)) {
+		(void)fprintf(stderr,
+		    "mpool_put: page %d not pinned\n", bp->pgno);
+		abort();
+	}
+#endif
+	bp->flags &= ~MPOOL_PINNED;
+	bp->flags |= flags & MPOOL_DIRTY;
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_close
+ *	Close the buffer pool.
+ */
+int
+mpool_close(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+
+	/* Free up any space allocated to the lru pages. */
+	while (!TAILQ_EMPTY(&mp->lqh)) {
+		bp = TAILQ_FIRST(&mp->lqh);
+		TAILQ_REMOVE(&mp->lqh, bp, q);
+		free(bp);
+	}
+
+	/* Free the MPOOL cookie. */
+	free(mp);
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_sync
+ *	Sync the pool to disk.
+ */
+int
+mpool_sync(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+
+	/* Walk the lru chain, flushing any dirty pages to disk. */
+	TAILQ_FOREACH(bp, &mp->lqh, q)
+		if (bp->flags & MPOOL_DIRTY &&
+		    mpool_write(mp, bp) == RET_ERROR)
+			return (RET_ERROR);
+
+	/* Sync the file descriptor. */
+	return (_fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
+}
+
+/*
+ * mpool_bkt
+ *	Get a page from the cache (or create one).
+ */
+static BKT *
+mpool_bkt(mp)
+	MPOOL *mp;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	/* If under the max cached, always create a new page. */
+	if (mp->curcache < mp->maxcache)
+		goto new;
+
+	/*
+	 * If the cache is max'd out, walk the lru list for a buffer we
+	 * can flush.  If we find one, write it (if necessary) and take it
+	 * off any lists.  If we don't find anything we grow the cache anyway.
+	 * The cache never shrinks.
+	 */
+	TAILQ_FOREACH(bp, &mp->lqh, q)
+		if (!(bp->flags & MPOOL_PINNED)) {
+			/* Flush if dirty. */
+			if (bp->flags & MPOOL_DIRTY &&
+			    mpool_write(mp, bp) == RET_ERROR)
+				return (NULL);
+#ifdef STATISTICS
+			++mp->pageflush;
+#endif
+			/* Remove from the hash and lru queues. */
+			head = &mp->hqh[HASHKEY(bp->pgno)];
+			TAILQ_REMOVE(head, bp, hq);
+			TAILQ_REMOVE(&mp->lqh, bp, q);
+#ifdef DEBUG
+			{ void *spage;
+				spage = bp->page;
+				memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+				bp->page = spage;
+			}
+#endif
+			return (bp);
+		}
+
+new:	if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
+		return (NULL);
+#ifdef STATISTICS
+	++mp->pagealloc;
+#endif
+#if defined(DEBUG) || defined(PURIFY)
+	memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+#endif
+	bp->page = (char *)bp + sizeof(BKT);
+	++mp->curcache;
+	return (bp);
+}
+
+/*
+ * mpool_write
+ *	Write a page to disk.
+ */
+static int
+mpool_write(mp, bp)
+	MPOOL *mp;
+	BKT *bp;
+{
+	off_t off;
+
+#ifdef STATISTICS
+	++mp->pagewrite;
+#endif
+
+	/* Run through the user's filter. */
+	if (mp->pgout)
+		(mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
+
+	off = mp->pagesize * bp->pgno;
+	if (pwrite(mp->fd, bp->page, mp->pagesize, off) != mp->pagesize)
+		return (RET_ERROR);
+
+	bp->flags &= ~MPOOL_DIRTY;
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_look
+ *	Lookup a page in the cache.
+ */
+static BKT *
+mpool_look(mp, pgno)
+	MPOOL *mp;
+	pgno_t pgno;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	head = &mp->hqh[HASHKEY(pgno)];
+	TAILQ_FOREACH(bp, head, hq)
+		if (bp->pgno == pgno) {
+#ifdef STATISTICS
+			++mp->cachehit;
+#endif
+			return (bp);
+		}
+#ifdef STATISTICS
+	++mp->cachemiss;
+#endif
+	return (NULL);
+}
+
+#ifdef STATISTICS
+/*
+ * mpool_stat
+ *	Print out cache statistics.
+ */
+void
+mpool_stat(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+	int cnt;
+	char *sep;
+
+	(void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
+	(void)fprintf(stderr,
+	    "page size %lu, cacheing %lu pages of %lu page max cache\n",
+	    mp->pagesize, mp->curcache, mp->maxcache);
+	(void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
+	    mp->pageput, mp->pageget, mp->pagenew);
+	(void)fprintf(stderr, "%lu page allocs, %lu page flushes\n",
+	    mp->pagealloc, mp->pageflush);
+	if (mp->cachehit + mp->cachemiss)
+		(void)fprintf(stderr,
+		    "%.0f%% cache hit rate (%lu hits, %lu misses)\n", 
+		    ((double)mp->cachehit / (mp->cachehit + mp->cachemiss))
+		    * 100, mp->cachehit, mp->cachemiss);
+	(void)fprintf(stderr, "%lu page reads, %lu page writes\n",
+	    mp->pageread, mp->pagewrite);
+
+	sep = "";
+	cnt = 0;
+	TAILQ_FOREACH(bp, &mp->lqh, q) {
+		(void)fprintf(stderr, "%s%d", sep, bp->pgno);
+		if (bp->flags & MPOOL_DIRTY)
+			(void)fprintf(stderr, "d");
+		if (bp->flags & MPOOL_PINNED)
+			(void)fprintf(stderr, "P");
+		if (++cnt == 10) {
+			sep = "\n";
+			cnt = 0;
+		} else
+			sep = ", ";
+			
+	}
+	(void)fprintf(stderr, "\n");
+}
+#endif
Index: /trunk/libc/src/fbsdlibc/db/mpool/mpool.libtp
===================================================================
--- /trunk/libc/src/fbsdlibc/db/mpool/mpool.libtp	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/mpool/mpool.libtp	(revision 2448)
@@ -0,0 +1,746 @@
+/******************************************************************************
+
+VERSION $FreeBSD: src/lib/libc/db/mpool/mpool.libtp,v 1.4 1999/08/27 23:58:23 peter Exp $
+PACKAGE: 	User Level Shared Memory Manager
+
+DESCRIPTION: 	
+	This package provides a buffer pool interface implemented as
+	a collection of file pages mapped into shared memory.
+
+	Based on Mark's buffer manager
+
+ROUTINES: 
+    External
+	buf_alloc
+	buf_flags
+	buf_get
+	buf_init
+	buf_last
+	buf_open
+	buf_pin
+	buf_sync
+	buf_unpin
+    Internal
+	bf_assign_buf
+	bf_fid_to_fd
+	bf_newbuf
+	bf_put_page
+	
+
+******************************************************************************/
+#include	<sys/types.h>
+#include	<assert.h>
+#include	<sys/file.h>
+#include	<sys/stat.h>
+#include	<stdio.h>
+#include	<errno.h>
+#include	"list.h"
+#include	"user.h"
+#include	"txn_sys.h"
+#include	"buf.h"
+#include	"semkeys.h"
+#include	"error.h"
+
+/*
+    we need to translate between some type of file id that the user 
+    process passes and a file descriptor.  For now, it's a nop.
+*/
+#define GET_MASTER      get_sem ( buf_spinlock )
+#define RELEASE_MASTER  release_sem ( buf_spinlock )
+
+#define	LRUID	*buf_lru
+#define	LRUP	(bufhdr_table+*buf_lru)
+#define	MRU	bufhdr_table[*buf_lru].lru.prev
+
+/* Global indicator that you have started reusing buffers */
+int	do_statistics = 0;
+/*
+    Process Statics (pointers into shared memory)
+*/
+static	BUF_T	*buf_table = 0;
+static	BUFHDR_T	*bufhdr_table;
+static	int	*buf_hash_table;
+static	int	*buf_lru;		/* LRU is the free list */
+static	int	buf_spinlock;
+static	FINFO_T	*buf_fids;
+static	int	*buf_sp;		/* Pointer to string free space */
+static	char	*buf_strings;
+
+/* Process Local FID->FD table */
+static	int	fds[NUM_FILE_ENTRIES];
+
+/* Static routines */
+static	BUFHDR_T	*bf_assign_buf();
+static	int		bf_fid_to_fd();
+static	BUFHDR_T	*bf_newbuf();
+static	int		bf_put_page();
+
+/*
+    Return  0 on success
+	    1 on failure
+*/
+extern int
+buf_init ( )
+{
+    ADDR_T	buf_region;
+    BUFHDR_T	*bhp;
+    int		i;
+    int		ref_count;
+    int		*spinlockp;
+
+    /*
+	Initialize Process local structures
+    */
+    for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+	fds[i] = -1;
+    }
+
+    buf_region = attach_region ( BUF_REGION_NAME, BUF_REGION_NUM,
+				 BUF_REGION_SIZE, &ref_count );
+    if ( !buf_region ) {
+	return (1);
+    }
+    error_log3 ( "Buf Region: ADDR: %d ID: %d SIZE: %d\n", buf_region,
+		    BUF_REGION_NUM, BUF_REGION_SIZE );
+
+    buf_table = (BUF_T *)buf_region;
+    bufhdr_table = (BUFHDR_T *)(buf_table + NUM_BUFS);
+    buf_hash_table = (int *)(bufhdr_table + NUM_BUFS);
+    buf_lru = buf_hash_table + NUMTABLE_ENTRIES;
+    spinlockp = buf_lru + 1;
+    buf_fids = (FINFO_T *)(spinlockp+1);
+    buf_sp = (int *)(buf_fids + NUM_FILE_ENTRIES);
+    buf_strings = (char *)(buf_sp + 1);
+
+    /* Create locking spinlock (gets creating holding the lock) */
+    buf_spinlock = create_sem ( BUF_SPIN_NAME, BUF_SPIN_NUM, ref_count <= 1 );
+    if ( buf_spinlock < 0 )  {
+	return(1);
+    }
+    if ( ref_count <= 1 ) {
+	*spinlockp = buf_spinlock;
+
+	/* Now initialize the buffer manager */
+
+	/* 1. Free list */
+	*buf_lru = 0;
+
+	/* 2. Buffer headers */
+	for ( i = 0, bhp = bufhdr_table; i < NUM_BUFS; bhp++, i++ ) {
+		bhp->lru.next = i+1;
+		bhp->lru.prev = i-1;
+		bhp->flags = 0;				/* All Flags off */
+		bhp->refcount = 0;
+		bhp->wait_proc = -1;			/* No sleepers */
+		LISTPE_INIT ( hash, bhp, i );		/* Hash chains */
+	}
+	bufhdr_table[0].lru.prev = NUM_BUFS-1;
+	bufhdr_table[NUM_BUFS-1].lru.next = 0;
+
+	/* 3. Hash Table */
+	for ( i = 0; i < NUMTABLE_ENTRIES; i++ ) {
+		buf_hash_table[i] = NUM_BUFS;
+	}
+
+	/* 4. File ID Table */
+	for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+		buf_fids[i].offset = -1;
+		buf_fids[i].npages = -1;
+		buf_fids[i].refcount = 0;
+	}
+
+	/* 5. Free String Pointer */
+	*buf_sp = (FILE_NAME_LEN*NUM_FILE_ENTRIES);
+	if (RELEASE_MASTER) {
+		return(1);
+	}
+	error_log0 ( "Initialized buffer region\n" );
+    } 
+    return (0);
+}
+
+extern	void
+buf_exit()
+{
+    int	ref;
+    int	i;
+
+    /* Flush Buffer Pool on Exit */
+    for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+	if ( fds[i] != -1 ) {
+		close ( fds[i] );
+	}
+    }
+    if ( buf_table ) {
+	detach_region ( buf_table, BUF_REGION_NUM, BUF_REGION_SIZE, &ref );
+    }
+    return;
+}
+
+/*
+	We need an empty buffer.  Find the LRU unpinned NON-Dirty page.
+*/
+static BUFHDR_T	*
+bf_newbuf()
+{
+    int		fd;
+    int		lruid;
+    int		nbytes;
+    int		ndx;
+    BUFHDR_T	*bhp;
+
+    lruid = LRUID;
+    for ( bhp = LRUP; 
+	  bhp->flags & (BUF_PINNED|BUF_IO_IN_PROGRESS); 
+	  bhp = LISTP_NEXTP (bufhdr_table, lru, bhp ) ) {
+
+	if ( bhp->lru.next == lruid ) {
+		/* OUT OF BUFFERS */
+		error_log1 ( "All buffers are pinned.  %s\n",
+				"Unable to grant buffer request" );
+		return(NULL);
+	}
+    }
+    /* BHP can be used */
+    if ( bhp->flags & BUF_DIRTY ) {
+	do_statistics = 1;
+	/* 
+	    MIS  Check for log flushed appropriately
+	*/
+	fd = bf_fid_to_fd(bhp->id.file_id);
+	if ( fd == -1 ) {
+	    error_log1 ("Invalid fid %d\n", bhp->id.file_id);
+	    return(NULL);
+	}
+	if ( bf_put_page(fd, bhp) < 0 ) {
+	    return(NULL);
+	}
+    }
+    /* Update Hash Pointers */
+    ndx = BUF_HASH ( bhp->id.file_id, bhp->id.obj_id );
+    LISTP_REMOVE(bufhdr_table, hash, bhp);
+    if ( buf_hash_table[ndx] == (bhp-bufhdr_table) ) {
+	if ( bhp->hash.next != (bhp-bufhdr_table) ) {
+		buf_hash_table[ndx] = bhp->hash.next;
+	} else {
+		buf_hash_table[ndx] = NUM_BUFS;
+	}
+    }
+    INIT_BUF(bhp); 
+
+    return(bhp);
+}
+/*
+    buf_alloc
+
+    Add a page to a file and return a buffer for it.
+
+*/
+ADDR_T
+buf_alloc ( fid, new_pageno )
+int	fid;
+int	*new_pageno;
+{
+	BUFHDR_T	*bhp;
+	int	fd;
+	int	len;
+	int	ndx;
+	OBJ_T	fobj;
+
+	if (GET_MASTER) {
+		return(NULL);
+	}
+	if ( buf_fids[fid].npages == -1 ) {
+	    /* initialize npages field */
+	    fd = bf_fid_to_fd ( fid );
+	}
+	assert (fid < NUM_FILE_ENTRIES);
+
+	*new_pageno = buf_fids[fid].npages;
+	if ( *new_pageno == -1 ) {
+	    RELEASE_MASTER;
+	    return ( NULL );
+	}
+	buf_fids[fid].npages++;
+	ndx = BUF_HASH ( fid, *new_pageno );
+	fobj.file_id = fid;
+	fobj.obj_id  = *new_pageno;
+	bhp = bf_assign_buf ( ndx, &fobj, BF_PIN|BF_DIRTY|BF_EMPTY, &len );
+	if ( RELEASE_MASTER ) {
+		/* Memory leak */
+		return(NULL);
+	}
+	if ( bhp ) {
+	    return ((ADDR_T)(buf_table+(bhp-bufhdr_table)));
+	} else {
+	    return ( NULL );
+	}
+}
+
+
+/*
+	Buffer Flags
+	BF_DIRTY		Mark page as dirty
+	BF_EMPTY		Don't initialize page, just get buffer
+	BF_PIN			Retrieve with pin 
+
+MIS
+Might want to add a flag that sets an LSN for this buffer is the
+DIRTY flag is set
+
+Eventually, you may want a flag that indicates the I/O and lock
+request should be shipped off together, but not for now.
+*/
+extern ADDR_T
+buf_get ( file_id, page_id, flags, len )
+int	file_id;
+int	page_id;
+u_long	flags;
+int	*len;		/* Number of bytes read into buffer */
+{
+	BUFHDR_T	*bhp;
+	int		bufid;
+	int		fd;
+	int		ndx;
+	int		next_bufid;
+	int		stat;
+	OBJ_T		fobj;	
+
+	ndx = BUF_HASH ( file_id, page_id );
+	fobj.file_id = (long) file_id;
+	fobj.obj_id = (long) page_id;
+	if ( GET_MASTER ) {
+		return(NULL);
+	}
+	/*
+		This could be a for loop, but we lose speed
+		by making all the cases general purpose so we
+		optimize for the no-collision case. 
+	*/
+	bufid = buf_hash_table[ndx]; 
+	if ( bufid < NUM_BUFS ) {
+	    for ( bhp = bufhdr_table+bufid; 
+		  !OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID);
+		  bhp = LISTP_NEXTP ( bufhdr_table, hash, bhp ) ) {
+
+		if ( bhp->hash.next == bufid ) {
+		    goto not_found;
+		}
+	    }
+/* found */
+	    if ( flags & BF_PIN ) {
+		    bhp->flags |= BUF_PINNED;
+		    bhp->refcount++;
+#ifdef PIN_DEBUG
+	fprintf(stderr, "buf_get: %X PINNED (%d)\n", 
+			buf_table + (bhp-bufhdr_table), bhp->refcount);
+#endif
+	    }
+	    if ( flags & BF_DIRTY ) {
+		    bhp->flags |= BUF_DIRTY;
+	    }
+
+	    while ( bhp->flags & BUF_IO_IN_PROGRESS ) {
+		/* MIS -- eventually err check here */
+#ifdef DEBUG
+		printf("About to sleep on %d (me: %d\n)\n", bhp->wait_proc,
+			my_txnp - txn_table);
+#endif
+#ifdef WAIT_STATS
+		buf_waits++;
+#endif
+		stat = proc_sleep_on ( &(bhp->wait_proc), buf_spinlock );
+		if ( stat ) {
+			/* Memory leak */
+			return(NULL);
+		}
+		if (!( bhp->flags & BUF_IO_IN_PROGRESS) &&
+		    (!OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID))) {
+			if (RELEASE_MASTER)
+				return(NULL);
+			return(buf_get ( file_id, page_id, flags, len ));
+		}
+	    }
+	    MAKE_MRU( bhp );
+	    *len = BUFSIZE;
+	} else {
+not_found:
+	    /* If you get here, the page isn't in the hash table */
+	    bhp = bf_assign_buf ( ndx, &fobj, flags, len );
+	}
+	/* Common code between found and not found */
+
+	if ( bhp && bhp->flags & BUF_NEWPAGE ) {
+	    *len = 0;
+	}
+	if (RELEASE_MASTER){
+		/* Memory leak */
+		return(NULL);
+	}
+	if ( bhp ) {
+	    return ((ADDR_T)(buf_table+(bhp-bufhdr_table)));
+	} else {
+	    return ( NULL );
+	}
+}
+
+/*
+	MIS - do I want to add file links to buffer pool?
+*/
+extern int
+buf_sync ( fid, close )
+int	fid;
+int	close;		/* should we dec refcount and possibly
+			   invalidate all the buffers */
+{
+    int	i;
+    int	fd;
+    int	invalidate;
+    BUFHDR_T	*bhp;
+
+    if ( (fd = bf_fid_to_fd ( fid )) < 0 ) {
+	return(1);
+    }
+    if (GET_MASTER) {
+	return(1);
+    }
+    invalidate = (buf_fids[fid].refcount == 1 && close);
+    if ( invalidate )
+	for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) {
+	    if (bhp->id.file_id == fid) {
+		if ((bhp->flags & BF_DIRTY) && (bf_put_page( fd, bhp ) < 0)) {
+			return(1);
+		}
+		bhp->id.file_id = -1;
+	    }
+	}
+    if (invalidate || close)
+	buf_fids[fid].refcount--;
+
+    if (RELEASE_MASTER) {
+	return(1);
+    }
+    return(0);
+
+
+}
+
+extern int
+buf_flags ( addr, set_flags, unset_flags )
+ADDR_T	addr;
+u_long	set_flags;
+u_long	unset_flags;
+{
+    int		bufid;
+    BUFHDR_T	*bhp;
+
+#ifdef PIN_DEBUG
+	fprintf(stderr, "buf_flags: %X setting %s%s%s%s%s releasing %s%s%s%s%s\n",
+	    addr, 
+	    set_flags&BUF_DIRTY ? "DIRTY " : "", 
+	    set_flags&BUF_VALID ? "VALID " : "", 
+	    set_flags&BUF_PINNED ? "PINNED " : "", 
+	    set_flags&BUF_IO_ERROR ? "IO_ERROR " : "", 
+	    set_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "", 
+	    set_flags&BUF_NEWPAGE ? "NEWPAGE " : "", 
+	    unset_flags&BUF_DIRTY ? "DIRTY " : "", 
+	    unset_flags&BUF_VALID ? "VALID " : "", 
+	    unset_flags&BUF_PINNED ? "PINNED " : "", 
+	    unset_flags&BUF_IO_ERROR ? "IO_ERROR " : "", 
+	    unset_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "", 
+	    unset_flags&BUF_NEWPAGE ? "NEWPAGE " : "" );
+#endif
+    if (!ADDR_OK(addr)) {
+	error_log1 ( "buf_pin: Invalid Buffer Address %x\n", addr );
+	return(1);
+    }
+    bufid = ((BUF_T *)addr) - buf_table;
+    assert ( bufid < NUM_BUFS);
+    bhp = &bufhdr_table[bufid];
+    if (GET_MASTER) {
+	return(1);
+    }
+    bhp->flags |= set_flags;
+    if ( set_flags & BUF_PINNED ) {
+	bhp->refcount++;
+    }
+    if ( set_flags & BUF_DIRTY ) {
+	unset_flags |= BUF_NEWPAGE;
+    }
+
+    if ( unset_flags & BUF_PINNED ) {
+	bhp->refcount--;
+	if ( bhp->refcount ) {
+		/* Turn off pin bit so it doesn't get unset */
+		unset_flags &= ~BUF_PINNED;
+	}
+    }
+    bhp->flags &= ~unset_flags;
+    MAKE_MRU(bhp);
+    if (RELEASE_MASTER) {
+	return(1);
+    }
+    return(0);
+}
+
+/*
+	Take a string name and produce an fid.
+
+	returns -1 on error
+
+	MIS -- this is a potential problem -- you keep actual names
+		here -- what if people run from different directories?
+*/
+extern	int
+buf_name_lookup ( fname )
+char	*fname;
+{
+    int	i;
+    int	fid;
+    int	ndx;
+
+    fid = -1;
+    if (GET_MASTER) {
+	    return(-1);
+    }
+    for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+	if ( buf_fids[i].offset == -1 ) {
+		fid = i;
+	} else {
+		if (!strcmp (fname, buf_strings+buf_fids[i].offset)) {
+			if (RELEASE_MASTER) {
+				return(-1);
+			}
+			buf_fids[i].refcount++;
+			return(i);
+		}
+	}
+    }
+    if ( fid == -1 ) {
+	error_log0 ( "No more file ID's\n" );
+    } else {
+	ndx = *buf_sp - strlen(fname) - 1;
+	if ( ndx < 0 ) {
+	    error_log0 ( "Out of string space\n" );
+	    fid = -1;
+	} else {
+	    *buf_sp = ndx;
+	    strcpy ( buf_strings+ndx, fname );
+	    buf_fids[fid].offset = ndx;
+	}
+	buf_fids[fid].refcount = 1;
+    }
+    if (RELEASE_MASTER) {
+	return(-1);
+    }
+    return(fid);
+}
+
+static	int
+bf_fid_to_fd ( fid ) 
+int	fid;
+{
+	struct stat sbuf;
+
+	assert ( (fid < NUM_FILE_ENTRIES) && (buf_fids[fid].offset != -1) );
+	if ( fds[fid] != -1 ) {
+	    return(fds[fid]);
+
+	}
+	fds[fid] = open ( buf_strings+buf_fids[fid].offset, O_RDWR|O_CREAT, 
+			  0666 );
+	if ( fds[fid] < 0 ) {
+	    error_log3 ( "Error Opening File %s FID: %d FD: %d.  Errno = %d\n", 
+			    buf_strings+buf_fids[fid].offset, fid, fds[fid], 
+			    errno );
+	    return(-1);
+	}
+	error_log3 ( "Opening File %s FID: %d FD: %d\n", 
+			buf_strings+buf_fids[fid].offset, fid, fds[fid] );
+	if ( buf_fids[fid].npages == -1 ) {
+		/* Initialize the npages field */
+		if ( fstat ( fds[fid], &sbuf ) ) {
+		    error_log3 ( "Error Fstating %s FID: %d.  Errno = %d\n", 
+				buf_strings+buf_fids[fid].offset, fid, errno );
+		} else {
+		    buf_fids[fid].npages = ( sbuf.st_size / BUFSIZE );
+		}
+	}
+
+	return ( fds[fid] );
+}
+
+static int
+bf_put_page ( fd, bhp ) 
+int	fd;
+BUFHDR_T	*bhp;
+{
+	int	nbytes;
+
+	assert ( (bhp-bufhdr_table) < NUM_BUFS );
+	if ( lseek ( fd, bhp->id.obj_id << BUFSHIFT, L_SET ) < 0 ) {
+	    return(-1);
+	}
+	bhp->flags |= BUF_IO_IN_PROGRESS;
+	if (RELEASE_MASTER) {
+	    return(-1);
+	}
+	nbytes = write(fd, buf_table[bhp-bufhdr_table], BUFSIZE);
+	if (GET_MASTER) {
+	    return(-2);
+	}
+	if ( nbytes < 0 ) {
+		error_log1 ("Write failed with error code %d\n", errno);
+		return(-1);
+	} else if ( nbytes != BUFSIZE ) {
+		error_log1 ("Short write: %d bytes of %d\n", nbytes, BUFSIZE );
+	}
+	bhp->flags &= ~(BUF_DIRTY|BUF_IO_IN_PROGRESS);
+	return (0);
+}
+
+static BUFHDR_T	*
+bf_assign_buf ( ndx, obj, flags, len )
+int	ndx;
+OBJ_T	*obj;
+u_long	flags;
+int	*len;		/* Number of bytes read */
+{
+    BUFHDR_T	*bhp;
+    int		fd;
+
+    assert ( obj->file_id < NUM_FILE_ENTRIES );
+    bhp = bf_newbuf();
+    if ( !bhp ) {
+	return(NULL);
+    }
+    OBJ_ASSIGN ( (*obj), bhp->id );
+    if ( buf_hash_table[ndx] >= NUM_BUFS ) {
+	buf_hash_table[ndx] = bhp-bufhdr_table;
+    } else {
+	LISTPE_INSERT ( bufhdr_table, hash, bhp, buf_hash_table[ndx] );
+    }
+
+    bhp->flags |= BUF_VALID;
+    if ( flags & BF_PIN ) {
+	bhp->flags |= BUF_PINNED;
+	bhp->refcount++;
+#ifdef PIN_DEBUG
+	fprintf(stderr, "bf_assign_buf: %X PINNED (%d)\n", 
+		buf_table + (bhp-bufhdr_table), bhp->refcount);
+#endif
+    }
+    fd = bf_fid_to_fd(obj->file_id);
+    if ( fd == -1 ) {
+	error_log1 ("Invalid fid %d\n", obj->file_id);
+	bhp->flags |= ~BUF_IO_ERROR;
+	return(NULL);
+    }
+    if ( obj->obj_id >= buf_fids[obj->file_id].npages) {
+	buf_fids[obj->file_id].npages = obj->obj_id+1;
+	*len = 0;
+    } else if ( flags & BF_EMPTY ) {
+	*len = 0;
+    } else {
+	bhp->flags |= BUF_IO_IN_PROGRESS;
+	if (RELEASE_MASTER) {
+		return(NULL);
+	}
+	if ( lseek ( fd, obj->obj_id << BUFSHIFT, L_SET ) < -1 ) {
+	    error_log2 ("Unable to perform seek on file: %d  to page %d",
+			obj->file_id, obj->obj_id );
+	    bhp->flags &= ~BUF_IO_IN_PROGRESS;
+	    bhp->flags |= ~BUF_IO_ERROR;
+	    return(NULL);
+	}
+	*len = read(fd, buf_table[bhp-bufhdr_table], BUFSIZE);
+	if ( *len < 0 ) {
+	    error_log2 ("Unable to perform read on file: %d  to page %d",
+			obj->file_id, obj->obj_id );
+	    bhp->flags &= ~BUF_IO_IN_PROGRESS;
+	    bhp->flags |= ~BUF_IO_ERROR;
+	    return(NULL);
+	} 
+	if (GET_MASTER) {
+		return(NULL);
+	}
+	bhp->flags &= ~BUF_IO_IN_PROGRESS;
+	if ( bhp->wait_proc != -1 ) {
+	    /* wake up waiter and anyone waiting on it */
+#ifdef DEBUG
+	    printf("Waking transaction %d due to completed I/O\n", 
+		bhp->wait_proc);
+#endif
+	    proc_wake_id ( bhp->wait_proc );
+	    bhp->wait_proc = -1;
+	}
+	MAKE_MRU(bhp);
+    }
+
+    if ( flags & BF_DIRTY ) {
+	bhp->flags |= BUF_DIRTY;
+    } else if ( *len < BUFSIZE ) {
+	bhp->flags |= BUF_NEWPAGE;
+    }
+    return ( bhp );
+}
+
+int
+buf_last ( fid )
+int	fid;
+{
+	int	val;
+
+	if (GET_MASTER) {
+		return(-1);
+	}
+	assert ( fid < NUM_FILE_ENTRIES );
+	if ( buf_fids[fid].npages == -1 ) {
+	    /* initialize npages field */
+	    (void) bf_fid_to_fd ( fid );
+	}
+	val = buf_fids[fid].npages;	
+	if ( val ) {
+		val--;			/* Convert to page number */
+	}
+	if (RELEASE_MASTER) {
+		return(-1);
+	}
+	return(val);
+}
+
+#ifdef DEBUG
+extern void
+buf_dump ( id, all )
+int	id;
+int	all;
+{
+	int i;
+	BUFHDR_T	*bhp;
+
+	printf ( "LRU + %d\n", *buf_lru );
+	if ( all ) {
+	    printf("ID\tFID\tPID\tLNEXT\tLPREV\tHNEXT\tHPREV\tSLEEP\tFLAG\tREFS\n");
+	    for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) {
+		    printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i,
+			bhp->id.file_id, bhp->id.obj_id,
+			bhp->lru.next, bhp->lru.prev,
+			bhp->hash.next, bhp->hash.prev,
+			bhp->wait_proc, bhp->flags, bhp->refcount );
+	    }
+	} else {
+		if ( id >= NUM_BUFS ) {
+			printf ( "Buffer ID (%d) too high\n", id );
+			return;
+		}
+		bhp = bufhdr_table+id;
+		printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i,
+		    bhp->id.file_id, bhp->id.obj_id,
+		    bhp->lru.next, bhp->lru.prev,
+		    bhp->hash.next, bhp->hash.prev,
+		    bhp->wait_proc, bhp->flags, bhp->refcount );
+	}
+	return;
+}
+#endif
+
Index: /trunk/libc/src/fbsdlibc/db/recno/Makefile.inc
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/Makefile.inc	(revision 2448)
@@ -0,0 +1,7 @@
+#       from @(#)Makefile.inc	8.1 (Berkeley) 6/4/93
+# $FreeBSD: src/lib/libc/db/recno/Makefile.inc,v 1.4 2002/11/18 09:50:55 ru Exp $
+
+.PATH: ${.CURDIR}/db/recno
+
+SRCS+=	rec_close.c rec_delete.c rec_get.c rec_open.c rec_put.c rec_search.c \
+	rec_seq.c rec_utils.c
Index: /trunk/libc/src/fbsdlibc/db/recno/extern.h
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/extern.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/extern.h	(revision 2448)
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1991, 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.
+ *
+ *	@(#)extern.h	8.3 (Berkeley) 6/4/94
+ * $FreeBSD: src/lib/libc/db/recno/extern.h,v 1.2 2002/03/21 22:46:28 obrien Exp $
+ */
+
+#include "../btree/extern.h"
+
+int	 __rec_close(DB *);
+int	 __rec_delete(const DB *, const DBT *, u_int);
+int	 __rec_dleaf(BTREE *, PAGE *, u_int32_t);
+int	 __rec_fd(const DB *);
+int	 __rec_fmap(BTREE *, recno_t);
+int	 __rec_fout(BTREE *);
+int	 __rec_fpipe(BTREE *, recno_t);
+int	 __rec_get(const DB *, const DBT *, DBT *, u_int);
+int	 __rec_iput(BTREE *, recno_t, const DBT *, u_int);
+int	 __rec_put(const DB *dbp, DBT *, const DBT *, u_int);
+int	 __rec_ret(BTREE *, EPG *, recno_t, DBT *, DBT *);
+EPG	*__rec_search(BTREE *, recno_t, enum SRCHOP);
+int	 __rec_seq(const DB *, DBT *, DBT *, u_int);
+int	 __rec_sync(const DB *, u_int);
+int	 __rec_vmap(BTREE *, recno_t);
+int	 __rec_vout(BTREE *);
+int	 __rec_vpipe(BTREE *, recno_t);
Index: /trunk/libc/src/fbsdlibc/db/recno/rec_close.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/rec_close.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/rec_close.c	(revision 2448)
@@ -0,0 +1,192 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_close.c	8.6 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_close.c,v 1.7 2003/02/16 17:29:09 nectar Exp $");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/uio.h>
+#ifndef __EMX__
+#include <sys/mman.h>
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_CLOSE -- Close a recno tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_close(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	if (__rec_sync(dbp, 0) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Committed to closing. */
+	status = RET_SUCCESS;
+#ifndef __EMX__
+	if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
+		status = RET_ERROR;
+#endif
+
+	if (!F_ISSET(t, R_INMEM)) {
+		if (F_ISSET(t, R_CLOSEFP)) {
+			if (fclose(t->bt_rfp))
+				status = RET_ERROR;
+		} else
+			if (_close(t->bt_rfd))
+				status = RET_ERROR;
+	}
+
+	if (__bt_close(dbp) == RET_ERROR)
+		status = RET_ERROR;
+
+	return (status);
+}
+
+/*
+ * __REC_SYNC -- sync the recno tree to disk.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_sync(dbp, flags)
+	const DB *dbp;
+	u_int flags;
+{
+	struct iovec iov[2];
+	BTREE *t;
+	DBT data, key;
+	off_t off;
+	recno_t scursor, trec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	if (flags == R_RECNOSYNC)
+		return (__bt_sync(dbp, 0));
+
+	if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
+		return (RET_SUCCESS);
+
+	/* Read any remaining records into the tree. */
+	if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Rewind the file descriptor. */
+	if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
+		return (RET_ERROR);
+
+	/* Save the cursor. */
+	scursor = t->bt_cursor.rcursor;
+
+	key.size = sizeof(recno_t);
+	key.data = &trec;
+
+	if (F_ISSET(t, R_FIXLEN)) {
+		/*
+		 * We assume that fixed length records are all fixed length.
+		 * Any that aren't are either EINVAL'd or corrected by the
+		 * record put code.
+		 */
+		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+		while (status == RET_SUCCESS) {
+			if (_write(t->bt_rfd, data.data, data.size) !=
+			    data.size)
+				return (RET_ERROR);
+			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+		}
+	} else {
+		iov[1].iov_base = (char *)&t->bt_bval;
+		iov[1].iov_len = 1;
+
+		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+		while (status == RET_SUCCESS) {
+			iov[0].iov_base = data.data;
+			iov[0].iov_len = data.size;
+			if (_writev(t->bt_rfd, iov, 2) != data.size + 1)
+				return (RET_ERROR);
+			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+		}
+	}
+
+	/* Restore the cursor. */
+	t->bt_cursor.rcursor = scursor;
+
+	if (status == RET_ERROR)
+		return (RET_ERROR);
+	if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
+		return (RET_ERROR);
+	if (ftruncate(t->bt_rfd, off))
+		return (RET_ERROR);
+	F_CLR(t, R_MODIFIED);
+	return (RET_SUCCESS);
+}
Index: /trunk/libc/src/fbsdlibc/db/recno/rec_delete.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/rec_delete.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/rec_delete.c	(revision 2448)
@@ -0,0 +1,200 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_delete.c	8.7 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_delete.c,v 1.2 2002/03/21 22:46:28 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+static int rec_rdelete(BTREE *, recno_t);
+
+/*
+ * __REC_DELETE -- Delete the item(s) referenced by a key.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to delete
+ *	flags:	R_CURSOR if deleting what the cursor references
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_delete(dbp, key, flags)
+	const DB *dbp;
+	const DBT *key;
+	u_int flags;
+{
+	BTREE *t;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	switch(flags) {
+	case 0:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		if (nrec > t->bt_nrecs)
+			return (RET_SPECIAL);
+		--nrec;
+		status = rec_rdelete(t, nrec);
+		break;
+	case R_CURSOR:
+		if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+			goto einval;
+		if (t->bt_nrecs == 0)
+			return (RET_SPECIAL);
+		status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
+		if (status == RET_SUCCESS)
+			--t->bt_cursor.rcursor;
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (status == RET_SUCCESS)
+		F_SET(t, B_MODIFIED | R_MODIFIED);
+	return (status);
+}
+
+/*
+ * REC_RDELETE -- Delete the data matching the specified key.
+ *
+ * Parameters:
+ *	tree:	tree
+ *	nrec:	record to delete
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+rec_rdelete(t, nrec)
+	BTREE *t;
+	recno_t nrec;
+{
+	EPG *e;
+	PAGE *h;
+	int status;
+
+	/* Find the record; __rec_search pins the page. */
+	if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
+		return (RET_ERROR);
+
+	/* Delete the record. */
+	h = e->page;
+	status = __rec_dleaf(t, h, e->index);
+	if (status != RET_SUCCESS) {
+		mpool_put(t->bt_mp, h, 0);
+		return (status);
+	}
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_DLEAF -- Delete a single record from a recno leaf page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	index:	index on current page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_dleaf(t, h, index)
+	BTREE *t;
+	PAGE *h;
+	u_int32_t index;
+{
+	RLEAF *rl;
+	indx_t *ip, cnt, offset;
+	u_int32_t nbytes;
+	char *from;
+	void *to;
+
+	/*
+	 * Delete a record from a recno leaf page.  Internal records are never
+	 * deleted from internal pages, regardless of the records that caused
+	 * them to be added being deleted.  Pages made empty by deletion are
+	 * not reclaimed.  They are, however, made available for reuse.
+	 *
+	 * Pack the remaining entries at the end of the page, shift the indices
+	 * down, overwriting the deleted record and its index.  If the record
+	 * uses overflow pages, make them available for reuse.
+	 */
+	to = rl = GETRLEAF(h, index);
+	if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
+		return (RET_ERROR);
+	nbytes = NRLEAF(rl);
+
+	/*
+	 * Compress the key/data pairs.  Compress and adjust the [BR]LEAF
+	 * offsets.  Reset the headers.
+	 */
+	from = (char *)h + h->upper;
+	memmove(from + nbytes, from, (char *)to - from);
+	h->upper += nbytes;
+
+	offset = h->linp[index];
+	for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip)
+		if (ip[0] < offset)
+			ip[0] += nbytes;
+	for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
+		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+	h->lower -= sizeof(indx_t);
+	--t->bt_nrecs;
+	return (RET_SUCCESS);
+}
Index: /trunk/libc/src/fbsdlibc/db/recno/rec_get.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/rec_get.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/rec_get.c	(revision 2448)
@@ -0,0 +1,314 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_get.c	8.9 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_get.c,v 1.5 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to find
+ *	data:	data to return
+ *	flag:	currently unused
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_get(dbp, key, data, flags)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Get currently doesn't take any flags, and keys of 0 are illegal. */
+	if (flags || (nrec = *(recno_t *)key->data) == 0) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * If we haven't seen this record yet, try to find it in the
+	 * original file.
+	 */
+	if (nrec > t->bt_nrecs) {
+		if (F_ISSET(t, R_EOF | R_INMEM))
+			return (RET_SPECIAL);
+		if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+			return (status);
+	}
+
+	--nrec;
+	if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	status = __rec_ret(t, e, 0, NULL, data);
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
+
+/*
+ * __REC_FPIPE -- Get fixed length records from a pipe.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fpipe(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	size_t len;
+	int ch;
+	u_char *p;
+
+	if (t->bt_rdata.size < t->bt_reclen) {
+		t->bt_rdata.data = t->bt_rdata.data == NULL ?
+		    malloc(t->bt_reclen) :
+		    reallocf(t->bt_rdata.data, t->bt_reclen);
+		if (t->bt_rdata.data == NULL)
+			return (RET_ERROR);
+		t->bt_rdata.size = t->bt_reclen;
+	}
+	data.data = t->bt_rdata.data;
+	data.size = t->bt_reclen;
+
+	for (nrec = t->bt_nrecs; nrec < top;) {
+		len = t->bt_reclen;
+		for (p = t->bt_rdata.data;; *p++ = ch)
+			if ((ch = getc(t->bt_rfp)) == EOF || !--len) {
+				if (ch != EOF)
+					*p = ch;
+				if (len != 0)
+					memset(p, t->bt_bval, len);
+				if (__rec_iput(t,
+				    nrec, &data, 0) != RET_SUCCESS)
+					return (RET_ERROR);
+				++nrec;
+				break;
+			}
+		if (ch == EOF)
+			break;
+	}
+	if (nrec < top) {
+		F_SET(t, R_EOF);
+		return (RET_SPECIAL);
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VPIPE -- Get variable length records from a pipe.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vpipe(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	size_t len;
+	size_t sz;
+	int bval, ch;
+	u_char *p;
+
+	bval = t->bt_bval;
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		for (p = t->bt_rdata.data,
+		    sz = t->bt_rdata.size;; *p++ = ch, --sz) {
+			if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {
+				data.data = t->bt_rdata.data;
+				data.size = p - (u_char *)t->bt_rdata.data;
+				if (ch == EOF && data.size == 0)
+					break;
+				if (__rec_iput(t, nrec, &data, 0)
+				    != RET_SUCCESS)
+					return (RET_ERROR);
+				break;
+			}
+			if (sz == 0) {
+				len = p - (u_char *)t->bt_rdata.data;
+				t->bt_rdata.size += (sz = 256);
+				t->bt_rdata.data = t->bt_rdata.data == NULL ?
+				    malloc(t->bt_rdata.size) :
+				    reallocf(t->bt_rdata.data, t->bt_rdata.size);
+				if (t->bt_rdata.data == NULL)
+					return (RET_ERROR);
+				p = (u_char *)t->bt_rdata.data + len;
+			}
+		}
+		if (ch == EOF)
+			break;
+	}
+	if (nrec < top) {
+		F_SET(t, R_EOF);
+		return (RET_SPECIAL);
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_FMAP -- Get fixed length records from a file.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fmap(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	u_char *sp, *ep, *p;
+	size_t len;
+
+	if (t->bt_rdata.size < t->bt_reclen) {
+		t->bt_rdata.data = t->bt_rdata.data == NULL ?
+		    malloc(t->bt_reclen) :
+		    reallocf(t->bt_rdata.data, t->bt_reclen);
+		if (t->bt_rdata.data == NULL)
+			return (RET_ERROR);
+		t->bt_rdata.size = t->bt_reclen;
+	}
+	data.data = t->bt_rdata.data;
+	data.size = t->bt_reclen;
+
+	sp = (u_char *)t->bt_cmap;
+	ep = (u_char *)t->bt_emap;
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		if (sp >= ep) {
+			F_SET(t, R_EOF);
+			return (RET_SPECIAL);
+		}
+		len = t->bt_reclen;
+		for (p = t->bt_rdata.data;
+		    sp < ep && len > 0; *p++ = *sp++, --len);
+		if (len != 0)
+			memset(p, t->bt_bval, len);
+		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+			return (RET_ERROR);
+	}
+	t->bt_cmap = (caddr_t)sp;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VMAP -- Get variable length records from a file.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vmap(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	u_char *sp, *ep;
+	recno_t nrec;
+	int bval;
+
+	sp = (u_char *)t->bt_cmap;
+	ep = (u_char *)t->bt_emap;
+	bval = t->bt_bval;
+
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		if (sp >= ep) {
+			F_SET(t, R_EOF);
+			return (RET_SPECIAL);
+		}
+		for (data.data = sp; sp < ep && *sp != bval; ++sp);
+		data.size = sp - (u_char *)data.data;
+		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+			return (RET_ERROR);
+		++sp;
+	}
+	t->bt_cmap = (caddr_t)sp;
+	return (RET_SUCCESS);
+}
Index: /trunk/libc/src/fbsdlibc/db/recno/rec_open.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/rec_open.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/rec_open.c	(revision 2448)
@@ -0,0 +1,249 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_open.c	8.10 (Berkeley) 9/1/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_open.c,v 1.6 2002/03/22 21:52:02 obrien Exp $");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "recno.h"
+
+DB *
+__rec_open(fname, flags, mode, openinfo, dflags)
+	const char *fname;
+	int flags, mode, dflags;
+	const RECNOINFO *openinfo;
+{
+	BTREE *t;
+	BTREEINFO btopeninfo;
+	DB *dbp;
+	PAGE *h;
+	struct stat sb;
+	int rfd, sverrno;
+
+	/* Open the user's file -- if this fails, we're done. */
+#ifdef __EMX__
+	if (fname != NULL && (rfd = _open(fname, flags | O_BINARY, mode)) < 0)
+#else
+	if (fname != NULL && (rfd = _open(fname, flags, mode)) < 0)
+#endif
+		return (NULL);
+
+	/* Create a btree in memory (backed by disk). */
+	dbp = NULL;
+	if (openinfo) {
+		if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
+			goto einval;
+		btopeninfo.flags = 0;
+		btopeninfo.cachesize = openinfo->cachesize;
+		btopeninfo.maxkeypage = 0;
+		btopeninfo.minkeypage = 0;
+		btopeninfo.psize = openinfo->psize;
+		btopeninfo.compare = NULL;
+		btopeninfo.prefix = NULL;
+		btopeninfo.lorder = openinfo->lorder;
+		dbp = __bt_open(openinfo->bfname,
+		    O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
+	} else
+		dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
+	if (dbp == NULL)
+		goto err;
+
+	/*
+	 * Some fields in the tree structure are recno specific.  Fill them
+	 * in and make the btree structure look like a recno structure.  We
+	 * don't change the bt_ovflsize value, it's close enough and slightly
+	 * bigger.
+	 */
+	t = dbp->internal;
+	if (openinfo) {
+		if (openinfo->flags & R_FIXEDLEN) {
+			F_SET(t, R_FIXLEN);
+			t->bt_reclen = openinfo->reclen;
+			if (t->bt_reclen == 0)
+				goto einval;
+		}
+		t->bt_bval = openinfo->bval;
+	} else
+		t->bt_bval = '\n';
+
+	F_SET(t, R_RECNO);
+	if (fname == NULL)
+		F_SET(t, R_EOF | R_INMEM);
+	else
+		t->bt_rfd = rfd;
+
+	if (fname != NULL) {
+		/*
+		 * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
+		 * Unfortunately, that's not portable, so we use lseek
+		 * and check the errno values.
+		 */
+		errno = 0;
+		if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
+			switch (flags & O_ACCMODE) {
+			case O_RDONLY:
+				F_SET(t, R_RDONLY);
+				break;
+			default:
+				goto einval;
+			}
+slow:			if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
+				goto err;
+			F_SET(t, R_CLOSEFP);
+			t->bt_irec =
+			    F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
+		} else {
+			switch (flags & O_ACCMODE) {
+			case O_RDONLY:
+				F_SET(t, R_RDONLY);
+				break;
+			case O_RDWR:
+				break;
+			default:
+				goto einval;
+			}
+
+			if (_fstat(rfd, &sb))
+				goto err;
+			/*
+			 * Kluge -- we'd like to test to see if the file is too
+			 * big to mmap.  Since, we don't know what size or type
+			 * off_t's or size_t's are, what the largest unsigned
+			 * integral type is, or what random insanity the local
+			 * C compiler will perpetrate, doing the comparison in
+			 * a portable way is flatly impossible.  Hope that mmap
+			 * fails if the file is too large.
+			 */
+			if (sb.st_size == 0)
+				F_SET(t, R_EOF);
+			else {
+#ifdef MMAP_NOT_AVAILABLE
+				/*
+				 * XXX
+				 * Mmap doesn't work correctly on many current
+				 * systems.  In particular, it can fail subtly,
+				 * with cache coherency problems.  Don't use it
+				 * for now.
+				 */
+				t->bt_msize = sb.st_size;
+				if ((t->bt_smap = mmap(NULL, t->bt_msize,
+				    PROT_READ, MAP_PRIVATE, rfd,
+				    (off_t)0)) == MAP_FAILED)
+					goto slow;
+				t->bt_cmap = t->bt_smap;
+				t->bt_emap = t->bt_smap + sb.st_size;
+				t->bt_irec = F_ISSET(t, R_FIXLEN) ?
+				    __rec_fmap : __rec_vmap;
+				F_SET(t, R_MEMMAPPED);
+#else
+				goto slow;
+#endif
+			}
+		}
+	}
+
+	/* Use the recno routines. */
+	dbp->close = __rec_close;
+	dbp->del = __rec_delete;
+	dbp->fd = __rec_fd;
+	dbp->get = __rec_get;
+	dbp->put = __rec_put;
+	dbp->seq = __rec_seq;
+	dbp->sync = __rec_sync;
+
+	/* If the root page was created, reset the flags. */
+	if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
+		goto err;
+	if ((h->flags & P_TYPE) == P_BLEAF) {
+		F_CLR(h, P_TYPE);
+		F_SET(h, P_RLEAF);
+		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	} else
+		mpool_put(t->bt_mp, h, 0);
+
+	if (openinfo && openinfo->flags & R_SNAPSHOT &&
+	    !F_ISSET(t, R_EOF | R_INMEM) &&
+	    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+                goto err;
+	return (dbp);
+
+einval:	errno = EINVAL;
+err:	sverrno = errno;
+	if (dbp != NULL)
+		(void)__bt_close(dbp);
+	if (fname != NULL)
+		(void)_close(rfd);
+	errno = sverrno;
+	return (NULL);
+}
+
+int
+__rec_fd(dbp)
+	const DB *dbp;
+{
+	BTREE *t;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* In-memory database can't have a file descriptor. */
+	if (F_ISSET(t, R_INMEM)) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (t->bt_rfd);
+}
Index: /trunk/libc/src/fbsdlibc/db/recno/rec_put.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/rec_put.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/rec_put.c	(revision 2448)
@@ -0,0 +1,288 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_put.c	8.7 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_put.c,v 1.6 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_PUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key
+ *	data:	data
+ *	flag:	R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is
+ *	already in the tree and R_NOOVERWRITE specified.
+ */
+int
+__rec_put(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	DBT fdata, tdata;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/*
+	 * If using fixed-length records, and the record is long, return
+	 * EINVAL.  If it's short, pad it out.  Use the record data return
+	 * memory, it's only short-term.
+	 */
+	if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) {
+		if (data->size > t->bt_reclen)
+			goto einval;
+
+		if (t->bt_rdata.size < t->bt_reclen) {
+			t->bt_rdata.data =
+			    reallocf(t->bt_rdata.data, t->bt_reclen);
+			if (t->bt_rdata.data == NULL)
+				return (RET_ERROR);
+			t->bt_rdata.size = t->bt_reclen;
+		}
+		memmove(t->bt_rdata.data, data->data, data->size);
+		memset((char *)t->bt_rdata.data + data->size,
+		    t->bt_bval, t->bt_reclen - data->size);
+		fdata.data = t->bt_rdata.data;
+		fdata.size = t->bt_reclen;
+	} else {
+		fdata.data = data->data;
+		fdata.size = data->size;
+	}
+
+	switch (flags) {
+	case R_CURSOR:
+		if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+			goto einval;
+		nrec = t->bt_cursor.rcursor;
+		break;
+	case R_SETCURSOR:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_IAFTER:
+		if ((nrec = *(recno_t *)key->data) == 0) {
+			nrec = 1;
+			flags = R_IBEFORE;
+		}
+		break;
+	case 0:
+	case R_IBEFORE:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_NOOVERWRITE:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		if (nrec <= t->bt_nrecs)
+			return (RET_SPECIAL);
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * Make sure that records up to and including the put record are
+	 * already in the database.  If skipping records, create empty ones.
+	 */
+	if (nrec > t->bt_nrecs) {
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    t->bt_irec(t, nrec) == RET_ERROR)
+			return (RET_ERROR);
+		if (nrec > t->bt_nrecs + 1) {
+			if (F_ISSET(t, R_FIXLEN)) {
+				if ((tdata.data =
+				    (void *)malloc(t->bt_reclen)) == NULL)
+					return (RET_ERROR);
+				tdata.size = t->bt_reclen;
+				memset(tdata.data, t->bt_bval, tdata.size);
+			} else {
+				tdata.data = NULL;
+				tdata.size = 0;
+			}
+			while (nrec > t->bt_nrecs + 1)
+				if (__rec_iput(t,
+				    t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
+					return (RET_ERROR);
+			if (F_ISSET(t, R_FIXLEN))
+				free(tdata.data);
+		}
+	}
+
+	if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS)
+		return (status);
+
+	switch (flags) {
+	case R_IAFTER:
+		nrec++;
+		break;
+	case R_SETCURSOR:
+		t->bt_cursor.rcursor = nrec;
+		break;
+	}
+	
+	F_SET(t, R_MODIFIED);
+	return (__rec_ret(t, NULL, nrec, key, NULL));
+}
+
+/*
+ * __REC_IPUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	nrec:	record number
+ *	data:	data
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_iput(t, nrec, data, flags)
+	BTREE *t;
+	recno_t nrec;
+	const DBT *data;
+	u_int flags;
+{
+	DBT tdata;
+	EPG *e;
+	PAGE *h;
+	indx_t index, nxtindex;
+	pgno_t pg;
+	u_int32_t nbytes;
+	int dflags, status;
+	char *dest, db[NOVFLSIZE];
+
+	/*
+	 * If the data won't fit on a page, store it on indirect pages.
+	 *
+	 * XXX
+	 * If the insert fails later on, these pages aren't recovered.
+	 */
+	if (data->size > t->bt_ovflsize) {
+		if (__ovfl_put(t, data, &pg) == RET_ERROR)
+			return (RET_ERROR);
+		tdata.data = db;
+		tdata.size = NOVFLSIZE;
+		*(pgno_t *)db = pg;
+		*(u_int32_t *)(db + sizeof(pgno_t)) = data->size;
+		dflags = P_BIGDATA;
+		data = &tdata;
+	} else
+		dflags = 0;
+
+	/* __rec_search pins the returned page. */
+	if ((e = __rec_search(t, nrec,
+	    nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
+	    SINSERT : SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	h = e->page;
+	index = e->index;
+
+	/*
+	 * Add the specified key/data pair to the tree.  The R_IAFTER and
+	 * R_IBEFORE flags insert the key after/before the specified key.
+	 *
+	 * Pages are split as required.
+	 */
+	switch (flags) {
+	case R_IAFTER:
+		++index;
+		break;
+	case R_IBEFORE:
+		break;
+	default:
+		if (nrec < t->bt_nrecs &&
+		    __rec_dleaf(t, h, index) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		break;
+	}
+
+	/*
+	 * If not enough room, split the page.  The split code will insert
+	 * the key and data and unpin the current page.  If inserting into
+	 * the offset array, shift the pointers up.
+	 */
+	nbytes = NRLEAFDBT(data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+		status = __bt_split(t, h, NULL, data, dflags, nbytes, index);
+		if (status == RET_SUCCESS)
+			++t->bt_nrecs;
+		return (status);
+	}
+
+	if (index < (nxtindex = NEXTINDEX(h)))
+		memmove(h->linp + index + 1, h->linp + index,
+		    (nxtindex - index) * sizeof(indx_t));
+	h->lower += sizeof(indx_t);
+
+	h->linp[index] = h->upper -= nbytes;
+	dest = (char *)h + h->upper;
+	WR_RLEAF(dest, data, dflags);
+
+	++t->bt_nrecs;
+	F_SET(t, B_MODIFIED);
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
Index: /trunk/libc/src/fbsdlibc/db/recno/rec_search.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/rec_search.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/rec_search.c	(revision 2448)
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1990, 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_search.c	8.4 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_search.c,v 1.4 2002/03/21 18:47:38 obrien Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_SEARCH -- Search a btree for a key.
+ *
+ * Parameters:
+ *	t:	tree to search
+ *	recno:	key to find
+ *	op: 	search operation
+ *
+ * Returns:
+ *	EPG for matching record, if any, or the EPG for the location of the
+ *	key, if it were inserted into the tree.
+ *
+ * Returns:
+ *	The EPG for matching record, if any, or the EPG for the location
+ *	of the key, if it were inserted into the tree, is entered into
+ *	the bt_cur field of the tree.  A pointer to the field is returned.
+ */
+EPG *
+__rec_search(t, recno, op)
+	BTREE *t;
+	recno_t recno;
+	enum SRCHOP op;
+{
+	indx_t index;
+	PAGE *h;
+	EPGNO *parent;
+	RINTERNAL *r;
+	pgno_t pg;
+	indx_t top;
+	recno_t total;
+	int sverrno;
+
+	BT_CLR(t);
+	for (pg = P_ROOT, total = 0;;) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			goto err;
+		if (h->flags & P_RLEAF) {
+			t->bt_cur.page = h;
+			t->bt_cur.index = recno - total;
+			return (&t->bt_cur);
+		}
+		for (index = 0, top = NEXTINDEX(h);;) {
+			r = GETRINTERNAL(h, index);
+			if (++index == top || total + r->nrecs > recno)
+				break;
+			total += r->nrecs;
+		}
+
+		BT_PUSH(t, pg, index - 1);
+		
+		pg = r->pgno;
+		switch (op) {
+		case SDELETE:
+			--GETRINTERNAL(h, (index - 1))->nrecs;
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		case SINSERT:
+			++GETRINTERNAL(h, (index - 1))->nrecs;
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		case SEARCH:
+			mpool_put(t->bt_mp, h, 0);
+			break;
+		}
+
+	}
+	/* Try and recover the tree. */
+err:	sverrno = errno;
+	if (op != SEARCH)
+		while  ((parent = BT_POP(t)) != NULL) {
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				break;
+			if (op == SINSERT)
+				--GETRINTERNAL(h, parent->index)->nrecs;
+			else
+				++GETRINTERNAL(h, parent->index)->nrecs;
+                        mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+                }
+	errno = sverrno;
+	return (NULL);
+}
Index: /trunk/libc/src/fbsdlibc/db/recno/rec_seq.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/rec_seq.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/rec_seq.c	(revision 2448)
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 1991, 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.
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+#ifndef lint
+/* XXX use __SCCSID */
+static char sccsid[] __unused = "@(#)rec_seq.c	8.3 (Berkeley) 7/14/94";
+#endif /* not lint */
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_seq.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_SEQ -- Recno sequential scan interface.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key for positioning and return value
+ *	data:	data return value
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__rec_seq(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key, *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	switch(flags) {
+	case R_CURSOR:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_NEXT:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			nrec = t->bt_cursor.rcursor + 1;
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_FIRST:
+		nrec = 1;
+		break;
+	case R_PREV:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			if ((nrec = t->bt_cursor.rcursor - 1) == 0)
+				return (RET_SPECIAL);
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_LAST:
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+			return (RET_ERROR);
+		nrec = t->bt_nrecs;
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+	
+	if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    (status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+			return (status);
+		if (t->bt_nrecs == 0 || nrec > t->bt_nrecs)
+			return (RET_SPECIAL);
+	}
+
+	if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	F_SET(&t->bt_cursor, CURS_INIT);
+	t->bt_cursor.rcursor = nrec;
+
+	status = __rec_ret(t, e, nrec, key, data);
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
Index: /trunk/libc/src/fbsdlibc/db/recno/rec_utils.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/rec_utils.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/rec_utils.c	(revision 2448)
@@ -0,0 +1,125 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_utils.c	8.6 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_utils.c,v 1.2 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __rec_ret --
+ *	Build return data.
+ *
+ * Parameters:
+ *	t:	tree
+ *	e:	key/data pair to be returned
+ *   nrec:	record number
+ *    key:	user's key structure
+ *	data:	user's data structure
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_ret(t, e, nrec, key, data)
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	DBT *key, *data;
+{
+	RLEAF *rl;
+	void *p;
+
+	if (key == NULL)
+		goto dataonly;
+
+	/* We have to copy the key, it's not on the page. */
+	if (sizeof(recno_t) > t->bt_rkey.size) {
+		p = (void *)(t->bt_rkey.data == NULL ?
+		    malloc(sizeof(recno_t)) :
+		    realloc(t->bt_rkey.data, sizeof(recno_t)));
+		if (p == NULL)
+			return (RET_ERROR);
+		t->bt_rkey.data = p;
+		t->bt_rkey.size = sizeof(recno_t);
+	}
+	memmove(t->bt_rkey.data, &nrec, sizeof(recno_t));
+	key->size = sizeof(recno_t);
+	key->data = t->bt_rkey.data;
+
+dataonly:
+	if (data == NULL)
+		return (RET_SUCCESS);
+
+	/*
+	 * We must copy big keys/data to make them contigous.  Otherwise,
+	 * leave the page pinned and don't copy unless the user specified
+	 * concurrent access.
+	 */
+	rl = GETRLEAF(e->page, e->index);
+	if (rl->flags & P_BIGDATA) {
+		if (__ovfl_get(t, rl->bytes,
+		    &data->size, &t->bt_rdata.data, &t->bt_rdata.size))
+			return (RET_ERROR);
+		data->data = t->bt_rdata.data;
+	} else if (F_ISSET(t, B_DB_LOCK)) {
+		/* Use +1 in case the first record retrieved is 0 length. */
+		if (rl->dsize + 1 > t->bt_rdata.size) {
+			p = (void *)(t->bt_rdata.data == NULL ?
+			    malloc(rl->dsize + 1) :
+			    realloc(t->bt_rdata.data, rl->dsize + 1));
+			if (p == NULL)
+				return (RET_ERROR);
+			t->bt_rdata.data = p;
+			t->bt_rdata.size = rl->dsize + 1;
+		}
+		memmove(t->bt_rdata.data, rl->bytes, rl->dsize);
+		data->size = rl->dsize;
+		data->data = t->bt_rdata.data;
+	} else {
+		data->size = rl->dsize;
+		data->data = rl->bytes;
+	}
+	return (RET_SUCCESS);
+}
Index: /trunk/libc/src/fbsdlibc/db/recno/recno.h
===================================================================
--- /trunk/libc/src/fbsdlibc/db/recno/recno.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/recno/recno.h	(revision 2448)
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 1991, 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.
+ *
+ *	@(#)recno.h	8.1 (Berkeley) 6/4/93
+ * $FreeBSD: src/lib/libc/db/recno/recno.h,v 1.2 2002/03/22 23:41:40 obrien Exp $
+ */
+
+enum SRCHOP { SDELETE, SINSERT, SEARCH};	/* Rec_search operation. */
+
+#include "../btree/btree.h"
+#include "extern.h"
Index: /trunk/libc/src/fbsdlibc/db/test/Makefile
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/Makefile	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/Makefile	(revision 2448)
@@ -0,0 +1,24 @@
+#	@(#)Makefile	8.15 (Berkeley) 7/28/94
+# $FreeBSD: src/lib/libc/db/test/Makefile,v 1.3 2001/08/03 21:43:26 bde Exp $
+
+PROG=	dbtest
+OBJS=	dbtest.o strerror.o
+
+# Uncomment the STAT line get hash and btree statistical use info.  This
+# also forces ld to load the btree debug functions for use by gdb, which
+# is useful.  The db library has to be compiled with -DSTATISTICS as well.
+INC=	-I${PORTDIR}/include -I${PORTDIR}
+OORG=	-g
+#STAT=	-DSTATISTICS
+CFLAGS+=-D__DBINTERFACE_PRIVATE -DDEBUG ${STAT} ${OORG} ${INC}
+
+dbtest: ${OBJS} ${PORTDIR}/libdb.a
+	${CC} -o ${.TARGET} ${OBJS} ${PORTDIR}/libdb.a
+
+strerror.o: ${PORTDIR}/clib/strerror.c
+	${CC} -c ${PORTDIR}/clib/strerror.c
+
+clean:
+	rm -f dbtest.core gmon.out ${OBJS} ${PROG} t1 t2 t3
+
+${OBJS}: Makefile
Index: /trunk/libc/src/fbsdlibc/db/test/README
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/README	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/README	(revision 2448)
@@ -0,0 +1,74 @@
+#	@(#)README	8.8 (Berkeley) 7/31/94
+
+To build this portably, try something like:
+
+    make PORTDIR="../PORT/MACH"
+
+where MACH is the machine, i.e. "sunos.4.1.1".
+
+To run the tests, enter "sh run.test".  If your system dictionary isn't
+in /usr/share/dict/words, edit run.test to reflect the correct place.
+
+Fairly large files (the command files) are built in this directory during
+the test runs, and even larger files (the database files) are created in
+"/var/tmp".  If the latter directory doesn't exist, set the environmental
+variable TMPDIR to a directory where the files can be built.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+The script file consists of lines with an initial character which is
+the command for that line, or an initial character indicating a key
+or data entry for a previous command.
+
+Legal command characters are as follows:
+
+c: compare a record
+	+ must be followed by [kK][dD]; the data value in the database
+	  associated with the specified key is compared to the specified
+	  data value.
+e: echo a string
+	+ writes out the rest of the line into the output file; if the
+	  last character is not a carriage-return, a newline is appended.
+f: set the flags for the next command
+	+ no value zero's the flags
+g: do a get command
+	+ must be followed by [kK]
+	+ writes out the retrieved data DBT.
+o [r]: dump [reverse]
+	+ dump the database out, if 'r' is set, in reverse order.
+p: do a put command
+	+ must be followed by [kK][dD]
+r: do a del command
+	+ must be followed by [kK] unless R_CURSOR flag set.
+S: sync the database
+s: do a seq command
+	+ must be followed by [kK] if R_CURSOR flag set.
+	+ writes out the retrieved data DBT.
+
+Legal key/data characters are as follows:
+
+D [file]: data file
+	+ set the current data value to the contents of the file
+d [data]:
+	+ set the current key value to the contents of the line.
+K [file]: key file
+	+ set the current key value to the contents of the file
+k [data]:
+	+ set the current key value to the contents of the line.
+
+Blank lines, lines with leading white space, and lines with leading
+hash marks (#) are ignored.
+
+Options to dbtest are as follows:
+
+	-d: Set the DB_LOCK flag.
+	-f: Use the file argument as the database file.
+	-i: Use the rest of the argument to set elements in the info
+	    structure.  If the type is btree, then "-i cachesize=10240"
+	    will set BTREEINFO.cachesize to 10240.
+	-o: The rest of the argument is the output file instead of
+	    using stdout.
+	-s: Don't delete the database file before opening it, i.e.
+	    use the database file from a previous run.
+
+Dbtest requires two arguments, the type of access "hash", "recno"
+or "btree", and the script name or "-" to indicate stdin.
Index: /trunk/libc/src/fbsdlibc/db/test/btree.tests/main.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/btree.tests/main.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/btree.tests/main.c	(revision 2448)
@@ -0,0 +1,767 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/btree.tests/main.c,v 1.4 2002/03/21 22:46:29 obrien Exp $");
+
+#include <sys/param.h>
+#include <fcntl.h>
+#include <db.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "btree.h"
+
+typedef struct cmd_table {
+	char *cmd;
+	int nargs;
+	int rconv;
+	void (*func)(DB *, char **);
+	char *usage, *descrip;
+} cmd_table;
+
+int stopstop;
+DB *globaldb;
+
+void append(DB *, char **);
+void bstat(DB *, char **);
+void cursor(DB *, char **);
+void delcur(DB *, char **);
+void delete(DB *, char **);
+void dump(DB *, char **);
+void first(DB *, char **);
+void get(DB *, char **);
+void help(DB *, char **);
+void iafter(DB *, char **);
+void ibefore(DB *, char **);
+void icursor(DB *, char **);
+void insert(DB *, char **);
+void keydata(DBT *, DBT *);
+void last(DB *, char **);
+void list(DB *, char **);
+void load(DB *, char **);
+void mstat(DB *, char **);
+void next(DB *, char **);
+int  parse(char *, char **, int);
+void previous(DB *, char **);
+void show(DB *, char **);
+void usage(void);
+void user(DB *);
+
+cmd_table commands[] = {
+	"?",	0, 0, help, "help", NULL,
+	"a",	2, 1, append, "append key def", "append key with data def",
+	"b",	0, 0, bstat, "bstat", "stat btree",
+	"c",	1, 1, cursor,  "cursor word", "move cursor to word",
+	"delc",	0, 0, delcur, "delcur", "delete key the cursor references",
+	"dele",	1, 1, delete, "delete word", "delete word",
+	"d",	0, 0, dump, "dump", "dump database",
+	"f",	0, 0, first, "first", "move cursor to first record",
+	"g",	1, 1, get, "get key", "locate key",
+	"h",	0, 0, help, "help", "print command summary",
+	"ia",	2, 1, iafter, "iafter key data", "insert data after key",
+	"ib",	2, 1, ibefore, "ibefore key data", "insert data before key",
+	"ic",	2, 1, icursor, "icursor key data", "replace cursor",
+	"in",	2, 1, insert, "insert key def", "insert key with data def",
+	"la",	0, 0, last, "last", "move cursor to last record",
+	"li",	1, 1, list, "list file", "list to a file",
+	"loa",	1, 0, load, "load file", NULL,
+	"loc",	1, 1, get, "get key", NULL,
+	"m",	0, 0, mstat, "mstat", "stat memory pool",
+	"n",	0, 0, next, "next", "move cursor forward one record",
+	"p",	0, 0, previous, "previous", "move cursor back one record",
+	"q",	0, 0, NULL, "quit", "quit",
+	"sh",	1, 0, show, "show page", "dump a page",
+	{ NULL },
+};
+
+int recno;					/* use record numbers */
+char *dict = "words";				/* default dictionary */
+char *progname;
+
+int
+main(argc, argv)
+	int argc;
+	char **argv;
+{
+	int c;
+	DB *db;
+	BTREEINFO b;
+
+	progname = *argv;
+
+	b.flags = 0;
+	b.cachesize = 0;
+	b.maxkeypage = 0;
+	b.minkeypage = 0;
+	b.psize = 0;
+	b.compare = NULL;
+	b.prefix = NULL;
+	b.lorder = 0;
+
+	while ((c = getopt(argc, argv, "bc:di:lp:ru")) != EOF) {
+		switch (c) {
+		case 'b':
+			b.lorder = BIG_ENDIAN;
+			break;
+		case 'c':
+			b.cachesize = atoi(optarg);
+			break;
+		case 'd':
+			b.flags |= R_DUP;
+			break;
+		case 'i':
+			dict = optarg;
+			break;
+		case 'l':
+			b.lorder = LITTLE_ENDIAN;
+			break;
+		case 'p':
+			b.psize = atoi(optarg);
+			break;
+		case 'r':
+			recno = 1;
+			break;
+		case 'u':
+			b.flags = 0;
+			break;
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (recno)
+		db = dbopen(*argv == NULL ? NULL : *argv, O_RDWR,
+		    0, DB_RECNO, NULL);
+	else
+		db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|O_RDWR,
+		    0600, DB_BTREE, &b);
+
+	if (db == NULL) {
+		(void)fprintf(stderr, "dbopen: %s\n", strerror(errno));
+		exit(1);
+	}
+	globaldb = db;
+	user(db);
+	exit(0);
+	/* NOTREACHED */
+}
+
+void
+user(db)
+	DB *db;
+{
+	FILE *ifp;
+	int argc, i, last;
+	char *lbuf, *argv[4], buf[512];
+
+	if ((ifp = fopen("/dev/tty", "r")) == NULL) {
+		(void)fprintf(stderr,
+		    "/dev/tty: %s\n", strerror(errno));
+		exit(1);
+	}
+	for (last = 0;;) {
+		(void)printf("> ");
+		(void)fflush(stdout);
+		if ((lbuf = fgets(&buf[0], 512, ifp)) == NULL)
+			break;
+		if (lbuf[0] == '\n') {
+			i = last;
+			goto uselast;
+		}
+		lbuf[strlen(lbuf) - 1] = '\0';
+
+		if (lbuf[0] == 'q')
+			break;
+
+		argc = parse(lbuf, &argv[0], 3);
+		if (argc == 0)
+			continue;
+
+		for (i = 0; commands[i].cmd != NULL; i++)
+			if (strncmp(commands[i].cmd, argv[0],
+			    strlen(commands[i].cmd)) == 0)
+				break;
+
+		if (commands[i].cmd == NULL) {
+			(void)fprintf(stderr,
+			    "%s: command unknown ('help' for help)\n", lbuf);
+			continue;
+		}
+
+		if (commands[i].nargs != argc - 1) {
+			(void)fprintf(stderr, "usage: %s\n", commands[i].usage);
+			continue;
+		}
+
+		if (recno && commands[i].rconv) {
+			static recno_t nlong;
+			nlong = atoi(argv[1]);
+			argv[1] = (char *)&nlong;
+		}
+uselast:	last = i;
+		(*commands[i].func)(db, argv);
+	}
+	if ((db->sync)(db) == RET_ERROR)
+		perror("dbsync");
+	else if ((db->close)(db) == RET_ERROR)
+		perror("dbclose");
+}
+
+int
+parse(lbuf, argv, maxargc)
+	char *lbuf, **argv;
+	int maxargc;
+{
+	int argc = 0;
+	char *c;
+
+	c = lbuf;
+	while (isspace(*c))
+		c++;
+	while (*c != '\0' && argc < maxargc) {
+		*argv++ = c;
+		argc++;
+		while (!isspace(*c) && *c != '\0') {
+			c++;
+		}
+		while (isspace(*c))
+			*c++ = '\0';
+	}
+	return (argc);
+}
+
+void
+append(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT key, data;
+	int status;
+
+	if (!recno) {
+		(void)fprintf(stderr,
+		    "append only available for recno db's.\n");
+		return;
+	}
+	key.data = argv[1];
+	key.size = sizeof(recno_t);
+	data.data = argv[2];
+	data.size = strlen(data.data);
+	status = (db->put)(db, &key, &data, R_APPEND);
+	switch (status) {
+	case RET_ERROR:
+		perror("append/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+cursor(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+	status = (*db->seq)(db, &key, &data, R_CURSOR);
+	switch (status) {
+	case RET_ERROR:
+		perror("cursor/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("key not found\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+delcur(db, argv)
+	DB *db;
+	char **argv;
+{
+	int status;
+
+	status = (*db->del)(db, NULL, R_CURSOR);
+
+	if (status == RET_ERROR)
+		perror("delcur/del");
+}
+
+void
+delete(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT key;
+	int status;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+
+	status = (*db->del)(db, &key, 0);
+	switch (status) {
+	case RET_ERROR:
+		perror("delete/del");
+		break;
+	case RET_SPECIAL:
+		(void)printf("key not found\n");
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+dump(db, argv)
+	DB *db;
+	char **argv;
+{
+	__bt_dump(db);
+}
+
+void
+first(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	status = (*db->seq)(db, &key, &data, R_FIRST);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("first/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("no more keys\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+get(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+
+	status = (*db->get)(db, &key, &data, 0);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("get/get");
+		break;
+	case RET_SPECIAL:
+		(void)printf("key not found\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+help(db, argv)
+	DB *db;
+	char **argv;
+{
+	int i;
+
+	for (i = 0; commands[i].cmd; i++)
+		if (commands[i].descrip)
+			(void)printf("%s: %s\n",
+			    commands[i].usage, commands[i].descrip);
+}
+
+void
+iafter(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT key, data;
+	int status;
+
+	if (!recno) {
+		(void)fprintf(stderr,
+		    "iafter only available for recno db's.\n");
+		return;
+	}
+	key.data = argv[1];
+	key.size = sizeof(recno_t);
+	data.data = argv[2];
+	data.size = strlen(data.data);
+	status = (db->put)(db, &key, &data, R_IAFTER);
+	switch (status) {
+	case RET_ERROR:
+		perror("iafter/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+ibefore(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT key, data;
+	int status;
+
+	if (!recno) {
+		(void)fprintf(stderr,
+		    "ibefore only available for recno db's.\n");
+		return;
+	}
+	key.data = argv[1];
+	key.size = sizeof(recno_t);
+	data.data = argv[2];
+	data.size = strlen(data.data);
+	status = (db->put)(db, &key, &data, R_IBEFORE);
+	switch (status) {
+	case RET_ERROR:
+		perror("ibefore/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+icursor(db, argv)
+	DB *db;
+	char **argv;
+{
+	int status;
+	DBT data, key;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+	data.data = argv[2];
+	data.size = strlen(argv[2]) + 1;
+
+	status = (*db->put)(db, &key, &data, R_CURSOR);
+	switch (status) {
+	case RET_ERROR:
+		perror("icursor/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+insert(db, argv)
+	DB *db;
+	char **argv;
+{
+	int status;
+	DBT data, key;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+	data.data = argv[2];
+	data.size = strlen(argv[2]) + 1;
+
+	status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
+	switch (status) {
+	case RET_ERROR:
+		perror("insert/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+last(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	status = (*db->seq)(db, &key, &data, R_LAST);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("last/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("no more keys\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+list(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	FILE *fp;
+	int status;
+
+	if ((fp = fopen(argv[1], "w")) == NULL) {
+		(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+		return;
+	}
+	status = (*db->seq)(db, &key, &data, R_FIRST);
+	while (status == RET_SUCCESS) {
+		(void)fprintf(fp, "%s\n", key.data);
+		status = (*db->seq)(db, &key, &data, R_NEXT);
+	}
+	if (status == RET_ERROR)
+		perror("list/seq");
+}
+
+DB *BUGdb;
+void
+load(db, argv)
+	DB *db;
+	char **argv;
+{
+	char *p, *t;
+	FILE *fp;
+	DBT data, key;
+	recno_t cnt;
+	size_t len;
+	int status;
+	char *lp, buf[16 * 1024];
+
+	BUGdb = db;
+	if ((fp = fopen(argv[1], "r")) == NULL) {
+		(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+		return;
+	}
+	(void)printf("loading %s...\n", argv[1]);
+
+	for (cnt = 1; (lp = fgetline(fp, &len)) != NULL; ++cnt) {
+		if (recno) {
+			key.data = &cnt;
+			key.size = sizeof(recno_t);
+			data.data = lp;
+			data.size = len + 1;
+		} else {
+			key.data = lp;
+			key.size = len + 1;
+			for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--);
+			*t = '\0';
+			data.data = buf;
+			data.size = len + 1;
+		}
+
+		status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
+		switch (status) {
+		case RET_ERROR:
+			perror("load/put");
+			exit(1);
+		case RET_SPECIAL:
+			if (recno)
+				(void)fprintf(stderr,
+				    "duplicate: %ld {%s}\n", cnt, data.data);
+			else
+				(void)fprintf(stderr,
+				    "duplicate: %ld {%s}\n", cnt, key.data);
+			exit(1);
+		case RET_SUCCESS:
+			break;
+		}
+	}
+	(void)fclose(fp);
+}
+
+void
+next(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	status = (*db->seq)(db, &key, &data, R_NEXT);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("next/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("no more keys\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+previous(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	status = (*db->seq)(db, &key, &data, R_PREV);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("previous/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("no more keys\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+show(db, argv)
+	DB *db;
+	char **argv;
+{
+	BTREE *t;
+	PAGE *h;
+	pgno_t pg;
+
+	pg = atoi(argv[1]);
+	t = db->internal;
+	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {
+		(void)printf("getpage of %ld failed\n", pg);
+		return;
+	}
+	if (pg == 0)
+		__bt_dmpage(h);
+	else
+		__bt_dpage(h);
+	mpool_put(t->bt_mp, h, 0);
+}
+
+void
+bstat(db, argv)
+	DB *db;
+	char **argv;
+{
+	(void)printf("BTREE\n");
+	__bt_stat(db);
+}
+
+void
+mstat(db, argv)
+	DB *db;
+	char **argv;
+{
+	(void)printf("MPOOL\n");
+	mpool_stat(((BTREE *)db->internal)->bt_mp);
+}
+
+void
+keydata(key, data)
+	DBT *key, *data;
+{
+	if (!recno && key->size > 0)
+		(void)printf("%s/", key->data);
+	if (data->size > 0)
+		(void)printf("%s", data->data);
+	(void)printf("\n");
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr,
+	    "usage: %s [-bdlu] [-c cache] [-i file] [-p page] [file]\n",
+	    progname);
+	exit (1);
+}
Index: /trunk/libc/src/fbsdlibc/db/test/dbtest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/dbtest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/dbtest.c	(revision 2448)
@@ -0,0 +1,742 @@
+/*-
+ * Copyright (c) 1992, 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.
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)dbtest.c	8.17 (Berkeley) 9/1/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/dbtest.c,v 1.10 2002/05/28 16:59:38 alfred Exp $");
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
+
+void	 compare(DBT *, DBT *);
+DBTYPE	 dbtype(char *);
+void	 dump(DB *, int);
+void	 err(const char *, ...) __printflike(1, 2);
+void	 get(DB *, DBT *);
+void	 getdata(DB *, DBT *, DBT *);
+void	 put(DB *, DBT *, DBT *);
+void	 rem(DB *, DBT *);
+char	*sflags(int);
+void	 synk(DB *);
+void	*rfile(char *, size_t *);
+void	 seq(DB *, DBT *);
+u_int	 setflags(char *);
+void	*setinfo(DBTYPE, char *);
+void	 usage(void);
+void	*xmalloc(char *, size_t);
+
+DBTYPE type;				/* Database type. */
+void *infop;				/* Iflags. */
+u_long lineno;				/* Current line in test script. */
+u_int flags;				/* Current DB flags. */
+int ofd = STDOUT_FILENO;		/* Standard output fd. */
+
+DB *XXdbp;				/* Global for gdb. */
+int XXlineno;				/* Fast breakpoint for gdb. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern int optind;
+	extern char *optarg;
+	enum S command, state;
+	DB *dbp;
+	DBT data, key, keydata;
+	size_t len;
+	int ch, oflags, sflag;
+	char *fname, *infoarg, *p, *t, buf[8 * 1024];
+
+	infoarg = NULL;
+	fname = NULL;
+	oflags = O_CREAT | O_RDWR;
+	sflag = 0;
+	while ((ch = getopt(argc, argv, "f:i:lo:s")) != EOF)
+		switch (ch) {
+		case 'f':
+			fname = optarg;
+			break;
+		case 'i':
+			infoarg = optarg;
+			break;
+		case 'l':
+			oflags |= DB_LOCK;
+			break;
+		case 'o':
+			if ((ofd = open(optarg,
+			    O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+				err("%s: %s", optarg, strerror(errno));
+			break;
+		case 's':
+			sflag = 1;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 2)
+		usage();
+
+	/* Set the type. */
+	type = dbtype(*argv++);
+
+	/* Open the descriptor file. */
+        if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
+	    err("%s: %s", *argv, strerror(errno));
+
+	/* Set up the db structure as necessary. */
+	if (infoarg == NULL)
+		infop = NULL;
+	else
+		for (p = strtok(infoarg, ",\t "); p != NULL;
+		    p = strtok(0, ",\t "))
+			if (*p != '\0')
+				infop = setinfo(type, p);
+
+	/*
+	 * Open the DB.  Delete any preexisting copy, you almost never
+	 * want it around, and it often screws up tests.
+	 */
+	if (fname == NULL) {
+		p = getenv("TMPDIR");
+		if (p == NULL)
+			p = "/var/tmp";
+		(void)snprintf(buf, sizeof(buf), "%s/__dbtest", p);
+		fname = buf;
+		(void)unlink(buf);
+	} else  if (!sflag)
+		(void)unlink(fname);
+
+	if ((dbp = dbopen(fname,
+	    oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
+		err("dbopen: %s", strerror(errno));
+	XXdbp = dbp;
+
+	state = COMMAND;
+	for (lineno = 1;
+	    (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
+		/* Delete the newline, displaying the key/data is easier. */
+		if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
+			*t = '\0';
+		if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#')
+			continue;
+
+		/* Convenient gdb break point. */
+		if (XXlineno == lineno)
+			XXlineno = 1;
+		switch (*p) {
+		case 'c':			/* compare */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = COMPARE;
+			break;
+		case 'e':			/* echo */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			/* Don't display the newline, if CR at EOL. */
+			if (p[len - 2] == '\r')
+				--len;
+			if (write(ofd, p + 1, len - 1) != len - 1 ||
+			    write(ofd, "\n", 1) != 1)
+				err("write: %s", strerror(errno));
+			break;
+		case 'g':			/* get */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = GET;
+			break;
+		case 'p':			/* put */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = PUT;
+			break;
+		case 'r':			/* remove */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+                        if (flags == R_CURSOR) {
+				rem(dbp, &key);
+				state = COMMAND;
+                        } else {
+				state = KEY;
+				command = REMOVE;
+			}
+			break;
+		case 'S':			/* sync */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			synk(dbp);
+			state = COMMAND;
+			break;
+		case 's':			/* seq */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			if (flags == R_CURSOR) {
+				state = KEY;
+				command = SEQ;
+			} else
+				seq(dbp, &key);
+			break;
+		case 'f':
+			flags = setflags(p + 1);
+			break;
+		case 'D':			/* data file */
+			if (state != DATA)
+				err("line %lu: not expecting data", lineno);
+			data.data = rfile(p + 1, &data.size);
+			goto ldata;
+		case 'd':			/* data */
+			if (state != DATA)
+				err("line %lu: not expecting data", lineno);
+			data.data = xmalloc(p + 1, len - 1);
+			data.size = len - 1;
+ldata:			switch (command) {
+			case COMPARE:
+				compare(&keydata, &data);
+				break;
+			case PUT:
+				put(dbp, &key, &data);
+				break;
+			default:
+				err("line %lu: command doesn't take data",
+				    lineno);
+			}
+			if (type != DB_RECNO)
+				free(key.data);
+			free(data.data);
+			state = COMMAND;
+			break;
+		case 'K':			/* key file */
+			if (state != KEY)
+				err("line %lu: not expecting a key", lineno);
+			if (type == DB_RECNO)
+				err("line %lu: 'K' not available for recno",
+				    lineno);
+			key.data = rfile(p + 1, &key.size);
+			goto lkey;
+		case 'k':			/* key */
+			if (state != KEY)
+				err("line %lu: not expecting a key", lineno);
+			if (type == DB_RECNO) {
+				static recno_t recno;
+				recno = atoi(p + 1);
+				key.data = &recno;
+				key.size = sizeof(recno);
+			} else {
+				key.data = xmalloc(p + 1, len - 1);
+				key.size = len - 1;
+			}
+lkey:			switch (command) {
+			case COMPARE:
+				getdata(dbp, &key, &keydata);
+				state = DATA;
+				break;
+			case GET:
+				get(dbp, &key);
+				if (type != DB_RECNO)
+					free(key.data);
+				state = COMMAND;
+				break;
+			case PUT:
+				state = DATA;
+				break;
+			case REMOVE:
+				rem(dbp, &key);
+				if ((type != DB_RECNO) && (flags != R_CURSOR))
+					free(key.data);
+				state = COMMAND;
+				break;
+			case SEQ:
+				seq(dbp, &key);
+				if ((type != DB_RECNO) && (flags != R_CURSOR))
+					free(key.data);
+				state = COMMAND;
+				break;
+			default:
+				err("line %lu: command doesn't take a key",
+				    lineno);
+			}
+			break;
+		case 'o':
+			dump(dbp, p[1] == 'r');
+			break;
+		default:
+			err("line %lu: %s: unknown command character",
+			    lineno, p);
+		}
+	}
+#ifdef STATISTICS
+	/*
+	 * -l must be used (DB_LOCK must be set) for this to be
+	 * used, otherwise a page will be locked and it will fail.
+	 */
+	if (type == DB_BTREE && oflags & DB_LOCK)
+		__bt_stat(dbp);
+#endif
+	if (dbp->close(dbp))
+		err("db->close: %s", strerror(errno));
+	(void)close(ofd);
+	exit(0);
+}
+
+#define	NOOVERWRITE	"put failed, would overwrite key\n"
+
+void
+compare(db1, db2)
+	DBT *db1, *db2;
+{
+	size_t len;
+	u_char *p1, *p2;
+
+	if (db1->size != db2->size)
+		printf("compare failed: key->data len %lu != data len %lu\n",
+		    db1->size, db2->size);
+
+	len = MIN(db1->size, db2->size);
+	for (p1 = db1->data, p2 = db2->data; len--;)
+		if (*p1++ != *p2++) {
+			printf("compare failed at offset %d\n",
+			    p1 - (u_char *)db1->data);
+			break;
+		}
+}
+
+void
+get(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	DBT data;
+
+	switch (dbp->get(dbp, kp, &data, flags)) {
+	case 0:
+		(void)write(ofd, data.data, data.size);
+		if (ofd == STDOUT_FILENO)
+			(void)write(ofd, "\n", 1);
+		break;
+	case -1:
+		err("line %lu: get: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"get failed, no such key\n"
+		if (ofd != STDOUT_FILENO)
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+		else
+			(void)fprintf(stderr, "%d: %.*s: %s",
+			    lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+getdata(dbp, kp, dp)
+	DB *dbp;
+	DBT *kp, *dp;
+{
+	switch (dbp->get(dbp, kp, dp, flags)) {
+	case 0:
+		return;
+	case -1:
+		err("line %lu: getdata: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+		err("line %lu: getdata failed, no such key", lineno);
+		/* NOTREACHED */
+	}
+}
+
+void
+put(dbp, kp, dp)
+	DB *dbp;
+	DBT *kp, *dp;
+{
+	switch (dbp->put(dbp, kp, dp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: put: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+		(void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1);
+		break;
+	}
+}
+
+void
+rem(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	switch (dbp->del(dbp, kp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: rem: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"rem failed, no such key\n"
+		if (ofd != STDOUT_FILENO)
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+		else if (flags != R_CURSOR)
+			(void)fprintf(stderr, "%d: %.*s: %s", 
+			    lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+		else
+			(void)fprintf(stderr,
+			    "%d: rem of cursor failed\n", lineno);
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+synk(dbp)
+	DB *dbp;
+{
+	switch (dbp->sync(dbp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: synk: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	}
+}
+
+void
+seq(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	DBT data;
+
+	switch (dbp->seq(dbp, kp, &data, flags)) {
+	case 0:
+		(void)write(ofd, data.data, data.size);
+		if (ofd == STDOUT_FILENO)
+			(void)write(ofd, "\n", 1);
+		break;
+	case -1:
+		err("line %lu: seq: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"seq failed, no such key\n"
+		if (ofd != STDOUT_FILENO)
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+		else if (flags == R_CURSOR)
+			(void)fprintf(stderr, "%d: %.*s: %s", 
+			    lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+		else
+			(void)fprintf(stderr,
+			    "%d: seq (%s) failed\n", lineno, sflags(flags));
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+dump(dbp, rev)
+	DB *dbp;
+	int rev;
+{
+	DBT key, data;
+	int flags, nflags;
+
+	if (rev) {
+		flags = R_LAST;
+		nflags = R_PREV;
+	} else {
+		flags = R_FIRST;
+		nflags = R_NEXT;
+	}
+	for (;; flags = nflags)
+		switch (dbp->seq(dbp, &key, &data, flags)) {
+		case 0:
+			(void)write(ofd, data.data, data.size);
+			if (ofd == STDOUT_FILENO)
+				(void)write(ofd, "\n", 1);
+			break;
+		case 1:
+			goto done;
+		case -1:
+			err("line %lu: (dump) seq: %s",
+			    lineno, strerror(errno));
+			/* NOTREACHED */
+		}
+done:	return;
+}
+	
+u_int
+setflags(s)
+	char *s;
+{
+	char *p, *index();
+
+	for (; isspace(*s); ++s);
+	if (*s == '\n' || *s == '\0')
+		return (0);
+	if ((p = index(s, '\n')) != NULL)
+		*p = '\0';
+	if (!strcmp(s, "R_CURSOR"))		return (R_CURSOR);
+	if (!strcmp(s, "R_FIRST"))		return (R_FIRST);
+	if (!strcmp(s, "R_IAFTER")) 		return (R_IAFTER);
+	if (!strcmp(s, "R_IBEFORE")) 		return (R_IBEFORE);
+	if (!strcmp(s, "R_LAST")) 		return (R_LAST);
+	if (!strcmp(s, "R_NEXT")) 		return (R_NEXT);
+	if (!strcmp(s, "R_NOOVERWRITE"))	return (R_NOOVERWRITE);
+	if (!strcmp(s, "R_PREV"))		return (R_PREV);
+	if (!strcmp(s, "R_SETCURSOR"))		return (R_SETCURSOR);
+
+	err("line %lu: %s: unknown flag", lineno, s);
+	/* NOTREACHED */
+}
+
+char *
+sflags(flags)
+	int flags;
+{
+	switch (flags) {
+	case R_CURSOR:		return ("R_CURSOR");
+	case R_FIRST:		return ("R_FIRST");
+	case R_IAFTER:		return ("R_IAFTER");
+	case R_IBEFORE:		return ("R_IBEFORE");
+	case R_LAST:		return ("R_LAST");
+	case R_NEXT:		return ("R_NEXT");
+	case R_NOOVERWRITE:	return ("R_NOOVERWRITE");
+	case R_PREV:		return ("R_PREV");
+	case R_SETCURSOR:	return ("R_SETCURSOR");
+	}
+
+	return ("UNKNOWN!");
+}
+	
+DBTYPE
+dbtype(s)
+	char *s;
+{
+	if (!strcmp(s, "btree"))
+		return (DB_BTREE);
+	if (!strcmp(s, "hash"))
+		return (DB_HASH);
+	if (!strcmp(s, "recno"))
+		return (DB_RECNO);
+	err("%s: unknown type (use btree, hash or recno)", s);
+	/* NOTREACHED */
+}
+
+void *
+setinfo(type, s)
+	DBTYPE type;
+	char *s;
+{
+	static BTREEINFO ib;
+	static HASHINFO ih;
+	static RECNOINFO rh;
+	char *eq, *index();
+
+	if ((eq = index(s, '=')) == NULL)
+		err("%s: illegal structure set statement", s);
+	*eq++ = '\0';
+	if (!isdigit(*eq))
+		err("%s: structure set statement must be a number", s);
+		
+	switch (type) {
+	case DB_BTREE:
+		if (!strcmp("flags", s)) {
+			ib.flags = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("cachesize", s)) {
+			ib.cachesize = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("maxkeypage", s)) {
+			ib.maxkeypage = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("minkeypage", s)) {
+			ib.minkeypage = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("lorder", s)) {
+			ib.lorder = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("psize", s)) {
+			ib.psize = atoi(eq);
+			return (&ib);
+		}
+		break;
+	case DB_HASH:
+		if (!strcmp("bsize", s)) {
+			ih.bsize = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("ffactor", s)) {
+			ih.ffactor = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("nelem", s)) {
+			ih.nelem = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("cachesize", s)) {
+			ih.cachesize = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("lorder", s)) {
+			ih.lorder = atoi(eq);
+			return (&ih);
+		}
+		break;
+	case DB_RECNO:
+		if (!strcmp("flags", s)) {
+			rh.flags = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("cachesize", s)) {
+			rh.cachesize = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("lorder", s)) {
+			rh.lorder = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("reclen", s)) {
+			rh.reclen = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("bval", s)) {
+			rh.bval = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("psize", s)) {
+			rh.psize = atoi(eq);
+			return (&rh);
+		}
+		break;
+	}
+	err("%s: unknown structure value", s);
+	/* NOTREACHED */
+}
+
+void *
+rfile(name, lenp)
+	char *name;
+	size_t *lenp;
+{
+	struct stat sb;
+	void *p;
+	int fd;
+	char *np, *index();
+
+	for (; isspace(*name); ++name);
+	if ((np = index(name, '\n')) != NULL)
+		*np = '\0';
+	if ((fd = open(name, O_RDONLY, 0)) < 0 ||
+	    fstat(fd, &sb))
+		err("%s: %s\n", name, strerror(errno));
+#ifdef NOT_PORTABLE
+	if (sb.st_size > (off_t)SIZE_T_MAX)
+		err("%s: %s\n", name, strerror(E2BIG));
+#endif
+	if ((p = (void *)malloc((u_int)sb.st_size)) == NULL)
+		err("%s", strerror(errno));
+	(void)read(fd, p, (int)sb.st_size);
+	*lenp = sb.st_size;
+	(void)close(fd);
+	return (p);
+}
+
+void *
+xmalloc(text, len)
+	char *text;
+	size_t len;
+{
+	void *p;
+
+	if ((p = (void *)malloc(len)) == NULL)
+		err("%s", strerror(errno));
+	memmove(p, text, len);
+	return (p);
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr,
+	    "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n");
+	exit(1);
+}
+
+#include <stdarg.h>
+
+void
+err(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	(void)fprintf(stderr, "dbtest: ");
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	(void)fprintf(stderr, "\n");
+	exit(1);
+	/* NOTREACHED */
+}
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/driver2.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/driver2.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/driver2.c	(revision 2448)
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)driver2.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/hash.tests/driver2.c,v 1.3 2002/03/22 21:52:02 obrien Exp $");
+
+/*
+ * Test driver, to try to tackle the large ugly-split problem.
+ */
+
+#include <sys/file.h>
+#include <stdio.h>
+#include "ndbm.h"
+
+int my_hash(key, len)
+	char	*key;
+	int	len;
+{
+	return(17);		/* So I'm cruel... */
+}
+
+main(argc, argv)
+	int	argc;
+{
+	DB	*db;
+	DBT	key, content;
+	char	keybuf[2049];
+	char	contentbuf[2049];
+	char	buf[256];
+	int	i;
+	HASHINFO	info;
+
+	info.bsize = 1024;
+	info.ffactor = 5;
+	info.nelem = 1;
+	info.cachesize = NULL;
+#ifdef HASH_ID_PROGRAM_SPECIFIED
+	info.hash_id = HASH_ID_PROGRAM_SPECIFIED;
+	info.hash_func = my_hash;
+#else
+	info.hash = my_hash;
+#endif
+	info.lorder = 0;
+	if (!(db = dbopen("bigtest", O_RDWR | O_CREAT, 0644, DB_HASH, &info))) {
+		sprintf(buf, "dbopen: failed on file bigtest");
+		perror(buf);
+		exit(1);
+	}
+	srandom(17);
+	key.data = keybuf;
+	content.data = contentbuf;
+	bzero(keybuf, sizeof(keybuf));
+	bzero(contentbuf, sizeof(contentbuf));
+	for (i=1; i <= 500; i++) {
+		key.size = 128 + (random()&1023);
+		content.size = 128 + (random()&1023);
+/*		printf("%d: Key size %d, data size %d\n", i, key.size,
+		       content.size); */
+		sprintf(keybuf, "Key #%d", i);
+		sprintf(contentbuf, "Contents #%d", i);
+		if ((db->put)(db, &key, &content, R_NOOVERWRITE)) {
+			sprintf(buf, "dbm_store #%d", i);
+			perror(buf);
+		}
+	}
+	if ((db->close)(db)) {
+		perror("closing hash file");
+		exit(1);
+	}
+	exit(0);
+}
+
+
+
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/makedb.sh
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/makedb.sh	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/makedb.sh	(revision 2448)
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+#	@(#)makedb.sh	8.1 (Berkeley) 6/4/93
+
+awk '{i++; print $0; print i;}' /usr/share/dict/words > WORDS
+ls /bin /usr/bin /usr/ucb /etc | egrep '^(...|....|.....|......)$' | \
+sort | uniq | \
+awk '{
+	printf "%s\n", $0
+	for (i = 0; i < 1000; i++)
+		printf "%s+", $0
+	printf "\n"
+}' > LONG.DATA
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/tcreat3.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/tcreat3.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/tcreat3.c	(revision 2448)
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tcreat3.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/hash.tests/tcreat3.c,v 1.3 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key;
+	DB	*dbp;
+	HASHINFO ctl;
+	FILE *fp;
+	int	trash;
+
+	int i = 0;
+
+	argv++;
+	ctl.hash = NULL;
+	ctl.bsize = atoi(*argv++);
+	ctl.ffactor = atoi(*argv++);
+	ctl.nelem = atoi(*argv++);
+	ctl.lorder = 0;
+	if (!(dbp = dbopen( "hashtest",
+	    O_CREAT|O_TRUNC|O_RDWR, 0600, DB_HASH, &ctl))){
+		/* create table */
+		fprintf(stderr, "cannot create: hash table (size %d)\n",
+			INITIAL);
+		exit(1);
+	}
+
+	key.data = wp1;
+	item.data = wp2;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+		item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+		if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+			fprintf(stderr, "cannot enter: key %s\n",
+				item.data);
+			exit(1);
+		}
+	}
+
+	(dbp->close)(dbp);
+	exit(0);
+}
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/tdel.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/tdel.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/tdel.c	(revision 2448)
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tdel.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/hash.tests/tdel.c,v 1.3 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <db.h>
+#include <stdio.h>
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+/* Usage: thash pagesize fillfactor file */
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key;
+	DB	*dbp;
+	HASHINFO ctl;
+	FILE *fp;
+	int	stat;
+
+	int i = 0;
+
+	argv++;
+	ctl.nelem = INITIAL;
+	ctl.hash = NULL;
+	ctl.bsize = atoi(*argv++);
+	ctl.ffactor = atoi(*argv++);
+	ctl.cachesize = 1024 * 1024;	/* 1 MEG */
+	ctl.lorder = 0;
+	argc -= 2;
+	if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR, 0400, DB_HASH, &ctl))) {
+		/* create table */
+		fprintf(stderr, "cannot create: hash table size %d)\n",
+			INITIAL);
+		exit(1);
+	}
+
+	key.data = wp1;
+	item.data = wp2;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+		item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+		if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+			fprintf(stderr, "cannot enter: key %s\n",
+				item.data);
+			exit(1);
+		}
+	}
+
+	if ( --argc ) {
+		fp = fopen ( argv[0], "r");
+		i = 0;
+		while ( fgets(wp1, 8192, fp) &&
+			fgets(wp2, 8192, fp) &&
+			i++ < MAXWORDS) {
+		    key.size = strlen(wp1);
+		    stat = (dbp->del)(dbp, &key, 0);
+		    if (stat) {
+			fprintf ( stderr, "Error retrieving %s\n", key.data );
+			exit(1);
+		    }
+		}
+		fclose(fp);
+	}
+	(dbp->close)(dbp);
+	exit(0);
+}
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/testit
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/testit	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/testit	(revision 2448)
@@ -0,0 +1,147 @@
+#!/bin/csh -f
+#
+#	@(#)testit	8.1 (Berkeley) 6/4/93
+#
+
+echo ""
+echo "PAGE FILL "
+set name=WORDS
+	set i = 256
+	foreach j ( 11 14 21 )
+	    thash4 $i $j 25000 65536 $name < $name
+	end
+	set i = 512
+	foreach j ( 21 28 43 )
+	    thash4 $i $j 25000 65536  $name < $name
+	end
+	set i = 1024
+	foreach j ( 43 57 85 )
+	    thash4 $i $j 25000 65536 $name < $name
+	end
+	set i = 2048
+	foreach j ( 85 114 171 )
+	    thash4 $i $j 25000 65536 $name < $name
+	end
+	set i = 4096
+	foreach j ( 171 228 341 )
+	    thash4 $i $j 25000 65536 $name < $name
+	end
+	set i = 8192
+	foreach j ( 341 455 683 )
+	    thash4 $i $j 25000 65536 $name < $name
+	end
+	echo "PAGE FILL "
+	set i = 256
+	foreach j ( 11 14 21 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 25000 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+	set i = 512
+	foreach j ( 21 28 43 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 25000 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+	set i = 1024
+	foreach j ( 43 57 85 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 25000 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+	set i = 2048
+	foreach j ( 85 114 171 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 25000 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+	set i = 4096
+	foreach j ( 171 228 341 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 25000 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+	set i = 8192
+	foreach j ( 341 455 683 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 25000 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+set name=LONG.DATA
+	set i = 1024
+	foreach j ( 1 2 4 )
+	    echo thash4 $i $j 600 65536 $name 
+	    thash4 $i $j 600 65536 $name < $name
+	end
+
+	set i = 2048
+	foreach j ( 1 2 4 )
+	    echo thash4 $i $j 600 65536 $name 
+	    thash4 $i $j 600 65536 $name < $name
+	end
+	set i = 4096
+	foreach j ( 1 2 4 )
+	    echo thash4 $i $j 600 65536 $name 
+	    thash4 $i $j 600 65536 $name < $name
+	end
+	set i = 8192
+	foreach j ( 2 4 8 )
+	    echo thash4 $i $j 600 65536 $name 
+	    thash4 $i $j 600 65536 $name < $name
+	end
+	echo "PAGE FILL "
+	set i = 1024
+	foreach j ( 1 2 4 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 600 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+	set i = 2048
+	foreach j ( 1 2 4 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 600 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+	set i = 4096
+	foreach j ( 1 2 4 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 600 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+	set i = 8192
+	foreach j ( 2 4 8 )
+	    echo "$i"_"$j"
+	    tcreat3 $i $j 600 $name < $name
+	    tread2 65536 < $name
+	    tverify $name < $name
+	    tseq > /dev/null
+	    tdel $i $j  $name < $name
+	end
+driver2
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/thash4.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/thash4.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/thash4.c	(revision 2448)
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)thash4.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/hash.tests/thash4.c,v 1.3 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/timeb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <db.h>
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+/* Usage: thash pagesize fillfactor file */
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key, res;
+	DB *dbp;
+	HASHINFO ctl;
+	FILE *fp;
+	int	stat;
+	time_t	t;
+
+	int i = 0;
+
+	argv++;
+	ctl.hash = NULL;
+	ctl.bsize = atoi(*argv++);
+	ctl.ffactor = atoi(*argv++);
+	ctl.nelem = atoi(*argv++);
+	ctl.cachesize = atoi(*argv++);
+	ctl.lorder = 0;
+	if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR, 0400, DB_HASH, &ctl))) {
+		/* create table */
+		fprintf(stderr, "cannot create: hash table size %d)\n",
+			INITIAL);
+		fprintf(stderr, "\terrno: %d\n", errno);
+		exit(1);
+	}
+
+	key.data = wp1;
+	item.data = wp2;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+		item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+		if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+			fprintf(stderr, "cannot enter: key %s\n",
+				item.data);
+			fprintf(stderr, "\terrno: %d\n", errno);
+			exit(1);
+		}
+	}
+
+	if ( --argc ) {
+		fp = fopen ( argv[0], "r");
+		i = 0;
+		while ( fgets(wp1, 256, fp) &&
+			fgets(wp2, 8192, fp) &&
+			i++ < MAXWORDS) {
+
+		    key.size = strlen(wp1);
+		    stat = (dbp->get)(dbp, &key, &res, 0);
+		    if (stat < 0 ) {
+			fprintf ( stderr, "Error retrieving %s\n", key.data );
+			fprintf(stderr, "\terrno: %d\n", errno);
+			exit(1);
+		    } else if ( stat > 0 ) {
+			fprintf ( stderr, "%s not found\n", key.data );
+			fprintf(stderr, "\terrno: %d\n", errno);
+			exit(1);
+		    }
+		}
+		fclose(fp);
+	}
+	dbp->close(dbp);
+	exit(0);
+}
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/tread2.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/tread2.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/tread2.c	(revision 2448)
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tread2.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/hash.tests/tread2.c,v 1.2 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+typedef struct {		       /* info to be stored */
+	int num, siz;
+} info;
+
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key, res;
+	DB	*dbp;
+	HASHINFO ctl;
+	int	stat;
+
+	int i = 0;
+
+	ctl.nelem = INITIAL;
+	ctl.hash = NULL;
+	ctl.bsize = 64;
+	ctl.ffactor = 1;
+	ctl.cachesize = atoi(*argv++);
+	ctl.lorder = 0;
+	if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, &ctl))) {
+		/* create table */
+		fprintf(stderr, "cannot open: hash table\n" );
+		exit(1);
+	}
+
+	key.data = wp1;
+	item.data = wp2;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+		item.size = strlen(wp2);
+
+		stat = (dbp->get)(dbp, &key, &res,0);
+		if (stat < 0) {
+		    fprintf ( stderr, "Error retrieving %s\n", key.data );
+		    exit(1);
+		} else if ( stat > 0 ) {
+		    fprintf ( stderr, "%s not found\n", key.data );
+		    exit(1);
+		}
+	}
+	(dbp->close)(dbp);
+	exit(0);
+}
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/tseq.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/tseq.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/tseq.c	(revision 2448)
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tseq.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/hash.tests/tseq.c,v 1.3 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+
+char	wp[8192];
+char	cp[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key, res;
+	DB	*dbp;
+	FILE *fp;
+	int	stat;
+
+	if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, NULL))) {
+		/* create table */
+		fprintf(stderr, "cannot open: hash table\n" );
+		exit(1);
+	}
+
+/*
+* put info in structure, and structure in the item
+*/
+	for ( stat = (dbp->seq) (dbp, &res, &item, 1 );
+	      stat == 0;
+	      stat = (dbp->seq) (dbp, &res, &item, 0 ) ) {
+
+	      bcopy ( res.data, wp, res.size );
+	      wp[res.size] = 0;
+	      bcopy ( item.data, cp, item.size );
+	      cp[item.size] = 0;
+
+	      printf ( "%s %s\n", wp, cp );
+	}
+	(dbp->close)(dbp);
+	exit(0);
+}
Index: /trunk/libc/src/fbsdlibc/db/test/hash.tests/tverify.c
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/hash.tests/tverify.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/hash.tests/tverify.c	(revision 2448)
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tverify.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/test/hash.tests/tverify.c,v 1.2 2002/03/22 21:52:02 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+typedef struct {		       /* info to be stored */
+	int num, siz;
+} info;
+
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT key, res;
+	DB	*dbp;
+	HASHINFO ctl;
+	int	trash;
+	int	stat;
+
+	int i = 0;
+
+	ctl.nelem = INITIAL;
+	ctl.hash = NULL;
+	ctl.bsize = 64;
+	ctl.ffactor = 1;
+	ctl.cachesize = 1024 * 1024;	/* 1 MEG */
+	ctl.lorder = 0;
+	if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, &ctl))) {
+		/* create table */
+		fprintf(stderr, "cannot open: hash table\n" );
+		exit(1);
+	}
+
+	key.data = wp1;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+
+		stat = (dbp->get)(dbp, &key, &res,0);
+		if (stat < 0) {
+		    fprintf ( stderr, "Error retrieving %s\n", key.data );
+		    exit(1);
+		} else if ( stat > 0 ) {
+		    fprintf ( stderr, "%s not found\n", key.data );
+		    exit(1);
+		}
+		if ( memcmp ( res.data, wp2, res.size ) ) {
+		    fprintf ( stderr, "data for %s is incorrect.  Data was %s.  Should have been %s\n", key.data, res.data, wp2 );
+		}
+	}
+	(dbp->close)(dbp);
+	exit(0);
+}
Index: /trunk/libc/src/fbsdlibc/db/test/run.test
===================================================================
--- /trunk/libc/src/fbsdlibc/db/test/run.test	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/db/test/run.test	(revision 2448)
@@ -0,0 +1,705 @@
+#!/bin/sh -
+#
+#	@(#)run.test	8.10 (Berkeley) 7/26/94
+#
+
+# db regression tests
+main()
+{
+
+	PROG=./dbtest
+	TMP1=t1
+	TMP2=t2
+	TMP3=t3
+
+	if [ -f /usr/share/dict/words ]; then
+		DICT=/usr/share/dict/words
+	elif [ -f /usr/dict/words ]; then
+		DICT=/usr/dict/words
+	else
+		echo 'run.test: no dictionary'
+		exit 1
+	fi
+	
+	if [ $# -eq 0 ]; then
+		for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
+			test$t
+		done
+	else
+		while [ $# -gt 0 ]
+			do case "$1" in
+			test*)
+				$1;;
+			[0-9]*)
+				test$1;;
+			btree)
+				for t in 1 2 3 7 8 9 10 12 13; do
+					test$t
+				done;;
+			hash)
+				for t in 1 2 3 8 13 20; do
+					test$t
+				done;;
+			recno)
+				for t in 1 2 3 4 5 6 7 10 11; do
+					test$t
+				done;;
+			*)
+				echo "run.test: unknown test $1"
+				echo "usage: run.test test# | type"
+				exit 1
+			esac
+			shift
+		done
+	fi
+	rm -f $TMP1 $TMP2 $TMP3
+	exit 0
+}
+
+# Take the first hundred entries in the dictionary, and make them
+# be key/data pairs.
+test1()
+{
+	echo "Test 1: btree, hash: small key, small data pairs"
+	sed 200q $DICT > $TMP1
+	for type in btree hash; do
+		rm -f $TMP2 $TMP3
+		for i in `sed 200q $DICT`; do
+			echo p
+			echo k$i
+			echo d$i
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test1: type $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 1: recno: small key, small data pairs"
+	rm -f $TMP2 $TMP3
+	sed 200q $DICT |
+	awk '{ 
+		++i;
+		printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+	}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test1: type recno: failed"
+		exit 1
+	fi
+}
+
+# Take the first 200 entries in the dictionary, and give them
+# each a medium size data entry.
+test2()
+{
+	echo "Test 2: btree, hash: small key, medium data pairs"
+	mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+	echo $mdata |
+	awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1
+	for type in hash btree; do
+		rm -f $TMP2 $TMP3
+		for i in `sed 200q $DICT`; do
+			echo p
+			echo k$i
+			echo d$mdata
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test2: type $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 2: recno: small key, medium data pairs"
+	rm -f $TMP2 $TMP3
+	echo $mdata | 
+	awk '{  for (i = 1; i < 201; ++i)
+		printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+	}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test2: type recno: failed"
+		exit 1
+	fi
+}
+
+# Insert the programs in /bin with their paths as their keys.
+test3()
+{
+	echo "Test 3: hash: small key, big data pairs"
+	rm -f $TMP1
+	(find /bin -type f -print | xargs cat) > $TMP1
+	for type in hash; do
+		rm -f $TMP2 $TMP3
+		for i in `find /bin -type f -print`; do
+			echo p
+			echo k$i
+			echo D$i
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test3: $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 3: btree: small key, big data pairs"
+	for psize in 512 16384 65536; do
+		echo "    page size $psize"
+		for type in btree; do
+			rm -f $TMP2 $TMP3
+			for i in `find /bin -type f -print`; do
+				echo p
+				echo k$i
+				echo D$i
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -i psize=$psize -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test3: $type: page size $psize: failed"
+				exit 1
+			fi
+		done
+	done
+	echo "Test 3: recno: big data pairs"
+	rm -f $TMP2 $TMP3
+	find /bin -type f -print | 
+	awk '{
+		++i;
+		printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
+	}' > $TMP2
+	for psize in 512 16384 65536; do
+		echo "    page size $psize"
+		$PROG -i psize=$psize -o $TMP3 recno $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test3: recno: page size $psize: failed"
+			exit 1
+		fi
+	done
+}
+
+# Do random recno entries.
+test4()
+{
+	echo "Test 4: recno: random entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 37; i <= 37 + 88 * 17; i += 17) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 1; i <= 15; ++i) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 19234; i <= 19234 + 61 * 27; i += 27) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 37;
+			incr = 17;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			if (i == 19234 + 61 * 27)
+				exit;
+			if (i == 37 + 88 * 17) {
+				i = 1;
+				incr = 1;
+			} else if (i == 15) {
+				i = 19234;
+				incr = 27;
+			} else
+				i += incr;
+		}
+		END {
+			for (i = 37; i <= 37 + 88 * 17; i += 17)
+				printf("g\nk%d\n", i);
+			for (i = 1; i <= 15; ++i)
+				printf("g\nk%d\n", i);
+			for (i = 19234; i <= 19234 + 61 * 27; i += 27)
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test4: type recno: failed"
+		exit 1
+	fi
+}
+
+# Do reverse order recno entries.
+test5()
+{
+	echo "Test 5: recno: reverse order entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk ' {
+		for (i = 1500; i; --i) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 1500;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			--i;
+		}
+		END {
+			for (i = 1500; i; --i) 
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test5: type recno: failed"
+		exit 1
+	fi
+}
+		
+# Do alternating order recno entries.
+test6()
+{
+	echo "Test 6: recno: alternating order entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk ' {
+		for (i = 1; i < 1200; i += 2) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 2; i < 1200; i += 2) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 1;
+			even = 0;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			i += 2;
+			if (i >= 1200) {
+				if (even == 1)
+					exit;
+				even = 1;
+				i = 2;
+			}
+		}
+		END {
+			for (i = 1; i < 1200; ++i) 
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	sort -o $TMP1 $TMP1
+	sort -o $TMP3 $TMP3
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test6: type recno: failed"
+		exit 1
+	fi
+}
+
+# Delete cursor record
+test7()
+{
+	echo "Test 7: btree, recno: delete cursor record"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 120; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		printf("%05d: input key %d: %s\n", 120, 120, $0);
+		printf("seq failed, no such key\n");
+		printf("%05d: input key %d: %s\n", 1, 1, $0);
+		printf("%05d: input key %d: %s\n", 2, 2, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 120)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_NEXT\n");
+			for (i = 1; i <= 120; ++i)
+				printf("s\n");
+			printf("fR_CURSOR\ns\nk120\n");
+			printf("r\n");
+			printf("fR_NEXT\ns\n");
+			printf("fR_CURSOR\ns\nk1\n");
+			printf("r\n");
+			printf("fR_FIRST\ns\n");
+		}' > $TMP2
+		$PROG -o $TMP3 recno $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test7: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Make sure that overflow pages are reused.
+test8()
+{
+	echo "Test 8: btree, hash: repeated small key, big data pairs"
+	rm -f $TMP1
+	echo "" | 
+	awk 'BEGIN {
+		for (i = 1; i <= 10; ++i) {
+			printf("p\nkkey1\nD/bin/sh\n");
+			printf("p\nkkey2\nD/bin/csh\n");
+			if (i % 8 == 0) {
+				printf("c\nkkey2\nD/bin/csh\n");
+				printf("c\nkkey1\nD/bin/sh\n");
+				printf("e\t%d of 10 (comparison)\n", i);
+			} else
+				printf("e\t%d of 10             \n", i);
+			printf("r\nkkey1\nr\nkkey2\n");
+		}
+	}' > $TMP1
+	$PROG btree $TMP1
+#	$PROG hash $TMP1
+	# No explicit test for success.
+}
+
+# Test btree duplicate keys
+test9()
+{
+	echo "Test 9: btree: duplicate keys"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 543; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in btree; do
+		cat $TMP1 | 
+		awk '{
+			if (i++ % 2)
+				printf("p\nkduplicatekey\nd%s\n", $0);
+			else
+				printf("p\nkunique%dkey\nd%s\n", i, $0);
+		}
+		END {
+				printf("o\n");
+		}' > $TMP2
+		$PROG -iflags=1 -o $TMP3 $type $TMP2
+		sort -o $TMP3 $TMP3
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test9: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Test use of cursor flags without initialization
+test10()
+{
+	echo "Test 10: btree, recno: test cursor flag use"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 20; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	# Test that R_CURSOR doesn't succeed before cursor initialized
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 10)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_CURSOR\nr\n");
+			printf("eR_CURSOR SHOULD HAVE FAILED\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+		if [ -s $TMP3 ] ; then
+			echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED"
+			exit 1
+		fi
+	done
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 10)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_CURSOR\np\nk1\ndsome data\n");
+			printf("eR_CURSOR SHOULD HAVE FAILED\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+		if [ -s $TMP3 ] ; then
+			echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED"
+			exit 1
+		fi
+	done
+}
+
+# Test insert in reverse order.
+test11()
+{
+	echo "Test 11: recno: reverse order insert"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 779; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 0) {
+				i = 1;
+				printf("p\nk1\nd%s\n", $0);
+				printf("%s\n", "fR_IBEFORE");
+			} else
+				printf("p\nk1\nd%s\n", $0);
+		}
+		END {
+				printf("or\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test11: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Take the first 20000 entries in the dictionary, reverse them, and give
+# them each a small size data entry.  Use a small page size to make sure
+# the btree split code gets hammered.
+test12()
+{
+	echo "Test 12: btree: lots of keys, small page size"
+	mdata=abcdefghijklmnopqrstuvwxy
+	echo $mdata |
+	awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1
+	for type in btree; do
+		rm -f $TMP2 $TMP3
+		for i in `sed 20000q $DICT | rev`; do
+			echo p
+			echo k$i
+			echo d$mdata
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -i psize=512 -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test12: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Test different byte orders.
+test13()
+{
+	echo "Test 13: btree, hash: differing byte orders"
+	sed 50q $DICT > $TMP1
+	for order in 1234 4321; do
+		for type in btree hash; do
+			rm -f byte.file $TMP2 $TMP3
+			for i in `sed 50q $DICT`; do
+				echo p
+				echo k$i
+				echo d$i
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test13: $type/$order put failed"
+				exit 1
+			fi
+			for i in `sed 50q $DICT`; do
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -s \
+			    -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test13: $type/$order get failed"
+				exit 1
+			fi
+		done
+	done
+	rm -f byte.file
+}
+
+# Try a variety of bucketsizes and fill factors for hashing
+test20()
+{
+	echo\
+    "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 10000; ++i) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("%s\n", s);
+		}
+		exit;
+	}' > $TMP1
+	sed 10000q $DICT |
+	awk 'BEGIN {
+		ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg"
+	}
+	{
+		if (++i % 34)
+			s = substr(ds, 1, i % 34);
+		else
+			s = substr(ds, 1);
+		printf("p\nk%s\nd%s\n", $0, s);
+	}' > $TMP2
+	sed 10000q $DICT |
+	awk '{
+		++i;
+		printf("g\nk%s\n", $0);
+	}' >> $TMP2
+	bsize=256
+	for ffactor in 11 14 21; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=512
+	for ffactor in 21 28 43; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=1024
+	for ffactor in 43 57 85; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=2048
+	for ffactor in 85 114 171; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=4096
+	for ffactor in 171 228 341; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=8192
+	for ffactor in 341 455 683; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+}
+
+main $*
Index: /trunk/libc/src/fbsdlibc/gdtoa/README
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/README	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/README	(revision 2448)
@@ -0,0 +1,323 @@
+This directory contains source for a library of binary -> decimal
+and decimal -> binary conversion routines, for single-, double-,
+and extended-precision IEEE binary floating-point arithmetic, and
+other IEEE-like binary floating-point, including "double double",
+as in
+
+	T. J. Dekker, "A Floating-Point Technique for Extending the
+	Available Precision", Numer. Math. 18 (1971), pp. 224-242
+
+and
+
+	"Inside Macintosh: PowerPC Numerics", Addison-Wesley, 1994
+
+The conversion routines use double-precision floating-point arithmetic
+and, where necessary, high precision integer arithmetic.  The routines
+are generalizations of the strtod and dtoa routines described in
+
+	David M. Gay, "Correctly Rounded Binary-Decimal and
+	Decimal-Binary Conversions", Numerical Analysis Manuscript
+	No. 90-10, Bell Labs, Murray Hill, 1990;
+	http://cm.bell-labs.com/cm/cs/what/ampl/REFS/rounding.ps.gz
+
+(based in part on papers by Clinger and Steele & White: see the
+references in the above paper).
+
+The present conversion routines should be able to use any of IEEE binary,
+VAX, or IBM-mainframe double-precision arithmetic internally, but I (dmg)
+have so far only had a chance to test them with IEEE double precision
+arithmetic.
+
+The core conversion routines are strtodg for decimal -> binary conversions
+and gdtoa for binary -> decimal conversions.  These routines operate
+on arrays of unsigned 32-bit integers of type ULong, a signed 32-bit
+exponent of type Long, and arithmetic characteristics described in
+struct FPI; FPI, Long, and ULong are defined in gdtoa.h.  File arith.h
+is supposed to provide #defines that cause gdtoa.h to define its
+types correctly.  File arithchk.c is source for a program that
+generates a suitable arith.h on all systems where I've been able to
+test it.
+
+The core conversion routines are meant to be called by helper routines
+that know details of the particular binary arithmetic of interest and
+convert.  The present directory provides helper routines for 5 variants
+of IEEE binary floating-point arithmetic, each indicated by one or
+two letters:
+
+	f	IEEE single precision
+	d	IEEE double precision
+	x	IEEE extended precision, as on Intel 80x87
+		and software emulations of Motorola 68xxx chips
+		that do not pad the way the 68xxx does, but
+		only store 80 bits
+	xL	IEEE extended precision, as on Motorola 68xxx chips
+	Q	quad precision, as on Sun Sparc chips
+	dd	double double, pairs of IEEE double numbers
+		whose sum is the desired value
+
+For decimal -> binary conversions, there are three families of
+helper routines: one for round-nearest:
+
+	strtof
+	strtod
+	strtodd
+	strtopd
+	strtopf
+	strtopx
+	strtopxL
+	strtopQ
+
+one with rounding direction specified:
+
+	strtorf
+	strtord
+	strtordd
+	strtorx
+	strtorxL
+	strtorQ
+
+and one for computing an interval (at most one bit wide) that contains
+the decimal number:
+
+	strtoIf
+	strtoId
+	strtoIdd
+	strtoIx
+	strtoIxL
+	strtoIQ
+
+The latter call strtoIg, which makes one call on strtodg and adjusts
+the result to provide the desired interval.  On systems where native
+arithmetic can easily make one-ulp adjustments on values in the
+desired floating-point format, it might be more efficient to use the
+native arithmetic.  Routine strtodI is a variant of strtoId that
+illustrates one way to do this for IEEE binary double-precision
+arithmetic -- but whether this is more efficient remains to be seen.
+
+Functions strtod and strtof have "natural" return types, float and
+double -- strtod is specified by the C standard, and strtof appears
+in the stdlib.h of some systems, such as (at least some) Linux systems.
+The other functions write their results to their final argument(s):
+to the final two argument for the strtoI... (interval) functions,
+and to the final argument for the others (strtop... and strtor...).
+Where possible, these arguments have "natural" return types (double*
+or float*), to permit at least some type checking.  In reality, they
+are viewed as arrays of ULong (or, for the "x" functions, UShort)
+values. On systems where long double is the appropriate type, one can
+pass long double* final argument(s) to these routines.  The int value
+that these routines return is the return value from the call they make
+on strtodg; see the enum of possible return values in gdtoa.h.
+
+Source files g_ddfmt.c, misc.c, smisc.c, strtod.c, strtodg.c, and ulp.c
+should use true IEEE double arithmetic (not, e.g., double extended),
+at least for storing (and viewing the bits of) the variables declared
+"double" within them.
+
+One detail indicated in struct FPI is whether the target binary
+arithmetic departs from the IEEE standard by flushing denormalized
+numbers to 0.  On systems that do this, the helper routines for
+conversion to double-double format (when compiled with
+Sudden_Underflow #defined) penalize the bottom of the exponent
+range so that they return a nonzero result only when the least
+significant bit of the less significant member of the pair of
+double values returned can be expressed as a normalized double
+value.  An alternative would be to drop to 53-bit precision near
+the bottom of the exponent range.  To get correct rounding, this
+would (in general) require two calls on strtodg (one specifying
+126-bit arithmetic, then, if necessary, one specifying 53-bit
+arithmetic).
+
+By default, the core routine strtodg and strtod set errno to ERANGE
+if the result overflows to +Infinity or underflows to 0.  Compile
+these routines with NO_ERRNO #defined to inhibit errno assignments.
+
+Routine strtod is based on netlib's "dtoa.c from fp", and
+(f = strtod(s,se)) is more efficient for some conversions than, say,
+strtord(s,se,1,&f).  Parts of strtod require true IEEE double
+arithmetic with the default rounding mode (round-to-nearest) and, on
+systems with IEEE extended-precision registers, double-precision
+(53-bit) rounding precision.  If the machine uses (the equivalent of)
+Intel 80x87 arithmetic, the call
+	_control87(PC_53, MCW_PC);
+does this with many compilers.  Whether this or another call is
+appropriate depends on the compiler; for this to work, it may be
+necessary to #include "float.h" or another system-dependent header
+file.
+
+The values returned for NaNs may be signaling NaNs on some systems,
+since the rules for distinguishing signaling from quiet NaNs are
+system-dependent.  You can easily fix this by suitably modifying the
+ULto* routines in strtor*.c.
+
+C99's hexadecimal floating-point constants are recognized by the
+strto* routines (but this feature has not yet been heavily tested).
+Compiling with NO_HEX_FP #defined disables this feature.
+
+The strto* routines do not (yet) recognize C99's NaN(...) syntax; the
+strto* routines simply regard '(' as the first unprocessed input
+character.
+
+For binary -> decimal conversions, I've provided just one family
+of helper routines:
+
+	g_ffmt
+	g_dfmt
+	g_ddfmt
+	g_xfmt
+	g_xLfmt
+	g_Qfmt
+
+which do a "%g" style conversion either to a specified number of decimal
+places (if their ndig argument is positive), or to the shortest
+decimal string that rounds to the given binary floating-point value
+(if ndig <= 0).  They write into a buffer supplied as an argument
+and return either a pointer to the end of the string (a null character)
+in the buffer, if the buffer was long enough, or 0.  Other forms of
+conversion are easily done with the help of gdtoa(), such as %e or %f
+style and conversions with direction of rounding specified (so that, if
+desired, the decimal value is either >= or <= the binary value).
+
+For an example of more general conversions based on dtoa(), see
+netlib's "printf.c from ampl/solvers".
+
+For double-double -> decimal, g_ddfmt() assumes IEEE-like arithmetic
+of precision max(126, #bits(input)) bits, where #bits(input) is the
+number of mantissa bits needed to represent the sum of the two double
+values in the input.
+
+The makefile creates a library, gdtoa.a.  To use the helper
+routines, a program only needs to include gdtoa.h.  All the
+source files for gdtoa.a include a more extensive gdtoaimp.h;
+among other things, gdtoaimp.h has #defines that make "internal"
+names end in _D2A.  To make a "system" library, one could modify
+these #defines to make the names start with __.
+
+Various comments about possible #defines appear in gdtoaimp.h,
+but for most purposes, arith.h should set suitable #defines.
+
+Systems with preemptive scheduling of multiple threads require some
+manual intervention.  On such systems, it's necessary to compile
+dmisc.c, dtoa.c gdota.c, and misc.c with MULTIPLE_THREADS #defined,
+and to provide (or suitably #define) two locks, acquired by
+ACQUIRE_DTOA_LOCK(n) and freed by FREE_DTOA_LOCK(n) for n = 0 or 1.
+(The second lock, accessed in pow5mult, ensures lazy evaluation of
+only one copy of high powers of 5; omitting this lock would introduce
+a small probability of wasting memory, but would otherwise be harmless.)
+Routines that call dtoa or gdtoa directly must also invoke freedtoa(s)
+to free the value s returned by dtoa or gdtoa.  It's OK to do so whether
+or not MULTIPLE_THREADS is #defined, and the helper g_*fmt routines
+listed above all do this indirectly (in gfmt_D2A(), which they all call).
+
+By default, there is a private pool of memory of length 2000 bytes
+for intermediate quantities, and MALLOC (see gdtoaimp.h) is called only
+if the private pool does not suffice.   2000 is large enough that MALLOC
+is called only under very unusual circumstances (decimal -> binary
+conversion of very long strings) for conversions to and from double
+precision.  For systems with preemptivaly scheduled multiple threads
+or for conversions to extended or quad, it may be appropriate to
+#define PRIVATE_MEM nnnn, where nnnn is a suitable value > 2000.
+For extended and quad precisions, -DPRIVATE_MEM=20000 is probably
+plenty even for many digits at the ends of the exponent range.
+Use of the private pool avoids some overhead.
+
+Directory test provides some test routines.  See its README.
+I've also tested this stuff (except double double conversions)
+with Vern Paxson's testbase program: see
+
+	V. Paxson and W. Kahan, "A Program for Testing IEEE Binary-Decimal
+	Conversion", manuscript, May 1991,
+	ftp://ftp.ee.lbl.gov/testbase-report.ps.Z .
+
+(The same ftp directory has source for testbase.)
+
+Some system-dependent additions to CFLAGS in the makefile:
+
+	HU-UX: -Aa -Ae
+	OSF (DEC Unix): -ieee_with_no_inexact
+	SunOS 4.1x: -DKR_headers -DBad_float_h
+
+If you want to put this stuff into a shared library and your
+operating system requires export lists for shared libraries,
+the following would be an appropriate export list:
+
+	dtoa
+	freedtoa
+	g_Qfmt
+	g_ddfmt
+	g_dfmt
+	g_ffmt
+	g_xLfmt
+	g_xfmt
+	gdtoa
+	strtoIQ
+	strtoId
+	strtoIdd
+	strtoIf
+	strtoIx
+	strtoIxL
+	strtod
+	strtodI
+	strtodg
+	strtof
+	strtopQ
+	strtopd
+	strtopdd
+	strtopf
+	strtopx
+	strtopxL
+	strtorQ
+	strtord
+	strtordd
+	strtorf
+	strtorx
+	strtorxL
+
+When time permits, I (dmg) hope to write in more detail about the
+present conversion routines; for now, this README file must suffice.
+Meanwhile, if you wish to write helper functions for other kinds of
+IEEE-like arithmetic, some explanation of struct FPI and the bits
+array may be helpful.  Both gdtoa and strtodg operate on a bits array
+described by FPI *fpi.  The bits array is of type ULong, a 32-bit
+unsigned integer type.  Floating-point numbers have fpi->nbits bits,
+with the least significant 32 bits in bits[0], the next 32 bits in
+bits[1], etc.  These numbers are regarded as integers multiplied by
+2^e (i.e., 2 to the power of the exponent e), where e is the second
+argument (be) to gdtoa and is stored in *exp by strtodg.  The minimum
+and maximum exponent values fpi->emin and fpi->emax for normalized
+floating-point numbers reflect this arrangement.  For example, the
+P754 standard for binary IEEE arithmetic specifies doubles as having
+53 bits, with normalized values of the form 1.xxxxx... times 2^(b-1023),
+with 52 bits (the x's) and the biased exponent b represented explicitly;
+b is an unsigned integer in the range 1 <= b <= 2046 for normalized
+finite doubles, b = 0 for denormals, and b = 2047 for Infinities and NaNs.
+To turn an IEEE double into the representation used by strtodg and gdtoa,
+we multiply 1.xxxx... by 2^52 (to make it an integer) and reduce the
+exponent e = (b-1023) by 52:
+
+	fpi->emin = 1 - 1023 - 52
+	fpi->emax = 1046 - 1023 - 52
+
+In various wrappers for IEEE double, we actually write -53 + 1 rather
+than -52, to emphasize that there are 53 bits including one implicit bit.
+Field fpi->rounding indicates the desired rounding direction, with
+possible values
+	FPI_Round_zero = toward 0,
+	FPI_Round_near = unbiased rounding -- the IEEE default,
+	FPI_Round_up = toward +Infinity, and
+	FPI_Round_down = toward -Infinity
+given in gdtoa.h.
+
+Field fpi->sudden_underflow indicates whether strtodg should return
+denormals or flush them to zero.  Normal floating-point numbers have
+bit fpi->nbits in the bits array on.  Denormals have it off, with
+exponent = fpi->emin.  Strtodg provides distinct return values for normals
+and denormals; see gdtoa.h.
+
+Compiling g__fmt.c, strtod.c, and strtodg.c with -DUSE_LOCALE causes
+the decimal-point character to be taken from the current locale; otherwise
+it is '.'.
+
+Please send comments to
+
+	David M. Gay
+	dmg@acm.org
Index: /trunk/libc/src/fbsdlibc/gdtoa/arithchk.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/arithchk.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/arithchk.c	(revision 2448)
@@ -0,0 +1,182 @@
+/****************************************************************
+Copyright (C) 1997, 1998 Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+/* Try to deduce arith.h from arithmetic properties. */
+
+#include <stdio.h>
+
+ static int dalign;
+ typedef struct
+Akind {
+	char *name;
+	int   kind;
+	} Akind;
+
+ static Akind
+IEEE_8087	= { "IEEE_8087", 1 },
+IEEE_MC68k	= { "IEEE_MC68k", 2 },
+IBM		= { "IBM", 3 },
+VAX		= { "VAX", 4 },
+CRAY		= { "CRAY", 5};
+
+ static Akind *
+Lcheck()
+{
+	union {
+		double d;
+		long L[2];
+		} u;
+	struct {
+		double d;
+		long L;
+		} x[2];
+
+	if (sizeof(x) > 2*(sizeof(double) + sizeof(long)))
+		dalign = 1;
+	u.L[0] = u.L[1] = 0;
+	u.d = 1e13;
+	if (u.L[0] == 1117925532 && u.L[1] == -448790528)
+		return &IEEE_MC68k;
+	if (u.L[1] == 1117925532 && u.L[0] == -448790528)
+		return &IEEE_8087;
+	if (u.L[0] == -2065213935 && u.L[1] == 10752)
+		return &VAX;
+	if (u.L[0] == 1267827943 && u.L[1] == 704643072)
+		return &IBM;
+	return 0;
+	}
+
+ static Akind *
+icheck()
+{
+	union {
+		double d;
+		int L[2];
+		} u;
+	struct {
+		double d;
+		int L;
+		} x[2];
+
+	if (sizeof(x) > 2*(sizeof(double) + sizeof(int)))
+		dalign = 1;
+	u.L[0] = u.L[1] = 0;
+	u.d = 1e13;
+	if (u.L[0] == 1117925532 && u.L[1] == -448790528)
+		return &IEEE_MC68k;
+	if (u.L[1] == 1117925532 && u.L[0] == -448790528)
+		return &IEEE_8087;
+	if (u.L[0] == -2065213935 && u.L[1] == 10752)
+		return &VAX;
+	if (u.L[0] == 1267827943 && u.L[1] == 704643072)
+		return &IBM;
+	return 0;
+	}
+
+char *emptyfmt = "";	/* avoid possible warning message with printf("") */
+
+ static Akind *
+ccheck()
+{
+	union {
+		double d;
+		long L;
+		} u;
+	long Cray1;
+
+	/* Cray1 = 4617762693716115456 -- without overflow on non-Crays */
+	Cray1 = printf(emptyfmt) < 0 ? 0 : 4617762;
+	if (printf(emptyfmt, Cray1) >= 0)
+		Cray1 = 1000000*Cray1 + 693716;
+	if (printf(emptyfmt, Cray1) >= 0)
+		Cray1 = 1000000*Cray1 + 115456;
+	u.d = 1e13;
+	if (u.L == Cray1)
+		return &CRAY;
+	return 0;
+	}
+
+ static int
+fzcheck()
+{
+	double a, b;
+	int i;
+
+	a = 1.;
+	b = .1;
+	for(i = 155;; b *= b, i >>= 1) {
+		if (i & 1) {
+			a *= b;
+			if (i == 1)
+				break;
+			}
+		}
+	b = a * a;
+	return b == 0.;
+	}
+
+int main()
+{
+	Akind *a = 0;
+	int Ldef = 0;
+	FILE *f;
+
+#ifdef WRITE_ARITH_H	/* for Symantec's buggy "make" */
+	f = fopen("arith.h", "w");
+	if (!f) {
+		printf("Cannot open arith.h\n");
+		return 1;
+		}
+#else
+	f = stdout;
+#endif
+
+	if (sizeof(double) == 2*sizeof(long))
+		a = Lcheck();
+	else if (sizeof(double) == 2*sizeof(int)) {
+		Ldef = 1;
+		a = icheck();
+		}
+	else if (sizeof(double) == sizeof(long))
+		a = ccheck();
+	if (a) {
+		fprintf(f, "#define %s\n#define Arith_Kind_ASL %d\n",
+			a->name, a->kind);
+		if (Ldef)
+			fprintf(f, "#define Long int\n#define Intcast (int)(long)\n");
+		if (dalign)
+			fprintf(f, "#define Double_Align\n");
+		if (sizeof(char*) == 8)
+			fprintf(f, "#define X64_bit_pointers\n");
+#ifndef NO_LONG_LONG
+		if (sizeof(long long) < 8)
+#endif
+			fprintf(f, "#define NO_LONG_LONG\n");
+		if (a->kind <= 2 && fzcheck())
+			fprintf(f, "#define Sudden_Underflow\n");
+		return 0;
+		}
+	fprintf(f, "/* Unknown arithmetic */\n");
+	return 1;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/dmisc.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/dmisc.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/dmisc.c	(revision 2448)
@@ -0,0 +1,222 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#ifndef MULTIPLE_THREADS
+ char *dtoa_result;
+#endif
+
+ char *
+#ifdef KR_headers
+rv_alloc(i) int i;
+#else
+rv_alloc(int i)
+#endif
+{
+	int j, k, *r;
+
+	j = sizeof(ULong);
+	for(k = 0;
+		sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
+		j <<= 1)
+			k++;
+	r = (int*)Balloc(k);
+	*r = k;
+	return
+#ifndef MULTIPLE_THREADS
+	dtoa_result =
+#endif
+		(char *)(r+1);
+	}
+
+ char *
+#ifdef KR_headers
+nrv_alloc(s, rve, n) char *s, **rve; int n;
+#else
+nrv_alloc(char *s, char **rve, int n)
+#endif
+{
+	char *rv, *t;
+
+	t = rv = rv_alloc(n);
+	while((*t = *s++) !=0)
+		t++;
+	if (rve)
+		*rve = t;
+	return rv;
+	}
+
+/* freedtoa(s) must be used to free values s returned by dtoa
+ * when MULTIPLE_THREADS is #defined.  It should be used in all cases,
+ * but for consistency with earlier versions of dtoa, it is optional
+ * when MULTIPLE_THREADS is not defined.
+ */
+
+ void
+#ifdef KR_headers
+freedtoa(s) char *s;
+#else
+freedtoa(char *s)
+#endif
+{
+	Bigint *b = (Bigint *)((int *)s - 1);
+	b->maxwds = 1 << (b->k = *(int*)b);
+	Bfree(b);
+#ifndef MULTIPLE_THREADS
+	if (s == dtoa_result)
+		dtoa_result = 0;
+#endif
+	}
+
+ int
+quorem
+#ifdef KR_headers
+	(b, S) Bigint *b, *S;
+#else
+	(Bigint *b, Bigint *S)
+#endif
+{
+	int n;
+	ULong *bx, *bxe, q, *sx, *sxe;
+#ifdef ULLong
+	ULLong borrow, carry, y, ys;
+#else
+	ULong borrow, carry, y, ys;
+#ifdef Pack_32
+	ULong si, z, zs;
+#endif
+#endif
+
+	n = S->wds;
+#ifdef DEBUG
+	/*debug*/ if (b->wds > n)
+	/*debug*/	Bug("oversize b in quorem");
+#endif
+	if (b->wds < n)
+		return 0;
+	sx = S->x;
+	sxe = sx + --n;
+	bx = b->x;
+	bxe = bx + n;
+	q = *bxe / (*sxe + 1);	/* ensure q <= true quotient */
+#ifdef DEBUG
+	/*debug*/ if (q > 9)
+	/*debug*/	Bug("oversized quotient in quorem");
+#endif
+	if (q) {
+		borrow = 0;
+		carry = 0;
+		do {
+#ifdef ULLong
+			ys = *sx++ * (ULLong)q + carry;
+			carry = ys >> 32;
+			y = *bx - (ys & 0xffffffffUL) - borrow;
+			borrow = y >> 32 & 1UL;
+			*bx++ = y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+			si = *sx++;
+			ys = (si & 0xffff) * q + carry;
+			zs = (si >> 16) * q + (ys >> 16);
+			carry = zs >> 16;
+			y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+			borrow = (y & 0x10000) >> 16;
+			z = (*bx >> 16) - (zs & 0xffff) - borrow;
+			borrow = (z & 0x10000) >> 16;
+			Storeinc(bx, z, y);
+#else
+			ys = *sx++ * q + carry;
+			carry = ys >> 16;
+			y = *bx - (ys & 0xffff) - borrow;
+			borrow = (y & 0x10000) >> 16;
+			*bx++ = y & 0xffff;
+#endif
+#endif
+			}
+			while(sx <= sxe);
+		if (!*bxe) {
+			bx = b->x;
+			while(--bxe > bx && !*bxe)
+				--n;
+			b->wds = n;
+			}
+		}
+	if (cmp(b, S) >= 0) {
+		q++;
+		borrow = 0;
+		carry = 0;
+		bx = b->x;
+		sx = S->x;
+		do {
+#ifdef ULLong
+			ys = *sx++ + carry;
+			carry = ys >> 32;
+			y = *bx - (ys & 0xffffffffUL) - borrow;
+			borrow = y >> 32 & 1UL;
+			*bx++ = y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+			si = *sx++;
+			ys = (si & 0xffff) + carry;
+			zs = (si >> 16) + (ys >> 16);
+			carry = zs >> 16;
+			y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+			borrow = (y & 0x10000) >> 16;
+			z = (*bx >> 16) - (zs & 0xffff) - borrow;
+			borrow = (z & 0x10000) >> 16;
+			Storeinc(bx, z, y);
+#else
+			ys = *sx++ + carry;
+			carry = ys >> 16;
+			y = *bx - (ys & 0xffff) - borrow;
+			borrow = (y & 0x10000) >> 16;
+			*bx++ = y & 0xffff;
+#endif
+#endif
+			}
+			while(sx <= sxe);
+		bx = b->x;
+		bxe = bx + n;
+		if (!*bxe) {
+			while(--bxe > bx && !*bxe)
+				--n;
+			b->wds = n;
+			}
+		}
+	return q;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/dtoa.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/dtoa.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/dtoa.c	(revision 2448)
@@ -0,0 +1,759 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *	1. Rather than iterating, we use a simple numeric overestimate
+ *	   to determine k = floor(log10(d)).  We scale relevant
+ *	   quantities using O(log2(k)) rather than O(k) multiplications.
+ *	2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ *	   try to generate digits strictly left to right.  Instead, we
+ *	   compute with fewer bits and propagate the carry if necessary
+ *	   when rounding the final digit up.  This is often faster.
+ *	3. Under the assumption that input will be rounded nearest,
+ *	   mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ *	   That is, we allow equality in stopping tests when the
+ *	   round-nearest rule will give the same floating-point value
+ *	   as would satisfaction of the stopping test with strict
+ *	   inequality.
+ *	4. We remove common factors of powers of 2 from relevant
+ *	   quantities.
+ *	5. When converting floating-point integers less than 1e16,
+ *	   we use floating-point arithmetic rather than resorting
+ *	   to multiple-precision integers.
+ *	6. When asked to produce fewer than 15 digits, we first try
+ *	   to get by with floating-point arithmetic; we resort to
+ *	   multiple-precision integer arithmetic only if we cannot
+ *	   guarantee that the floating-point calculation has given
+ *	   the correctly rounded result.  For k requested digits and
+ *	   "uniformly" distributed input, the probability is
+ *	   something like 10^(k-15) that we must resort to the Long
+ *	   calculation.
+ */
+
+#ifdef Honor_FLT_ROUNDS
+#define Rounding rounding
+#undef Check_FLT_ROUNDS
+#define Check_FLT_ROUNDS
+#else
+#define Rounding Flt_Rounds
+#endif
+
+ char *
+dtoa
+#ifdef KR_headers
+	(d, mode, ndigits, decpt, sign, rve)
+	double d; int mode, ndigits, *decpt, *sign; char **rve;
+#else
+	(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+#endif
+{
+ /*	Arguments ndigits, decpt, sign are similar to those
+	of ecvt and fcvt; trailing zeros are suppressed from
+	the returned string.  If not null, *rve is set to point
+	to the end of the return value.  If d is +-Infinity or NaN,
+	then *decpt is set to 9999.
+
+	mode:
+		0 ==> shortest string that yields d when read in
+			and rounded to nearest.
+		1 ==> like 0, but with Steele & White stopping rule;
+			e.g. with IEEE P754 arithmetic , mode 0 gives
+			1e23 whereas mode 1 gives 9.999999999999999e22.
+		2 ==> max(1,ndigits) significant digits.  This gives a
+			return value similar to that of ecvt, except
+			that trailing zeros are suppressed.
+		3 ==> through ndigits past the decimal point.  This
+			gives a return value similar to that from fcvt,
+			except that trailing zeros are suppressed, and
+			ndigits can be negative.
+		4,5 ==> similar to 2 and 3, respectively, but (in
+			round-nearest mode) with the tests of mode 0 to
+			possibly return a shorter string that rounds to d.
+			With IEEE arithmetic and compilation with
+			-DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
+			as modes 2 and 3 when FLT_ROUNDS != 1.
+		6-9 ==> Debugging modes similar to mode - 4:  don't try
+			fast floating-point estimate (if applicable).
+
+		Values of mode other than 0-9 are treated as mode 0.
+
+		Sufficient space is allocated to the return value
+		to hold the suppressed trailing zeros.
+	*/
+
+	int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
+		j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+		spec_case, try_quick;
+	Long L;
+#ifndef Sudden_Underflow
+	int denorm;
+	ULong x;
+#endif
+	Bigint *b, *b1, *delta, *mlo, *mhi, *S;
+	double d2, ds, eps;
+	char *s, *s0;
+#ifdef Honor_FLT_ROUNDS
+	int rounding;
+#endif
+#ifdef SET_INEXACT
+	int inexact, oldinexact;
+#endif
+
+#ifndef MULTIPLE_THREADS
+	if (dtoa_result) {
+		freedtoa(dtoa_result);
+		dtoa_result = 0;
+		}
+#endif
+
+	if (word0(d) & Sign_bit) {
+		/* set sign for everything, including 0's and NaNs */
+		*sign = 1;
+		word0(d) &= ~Sign_bit;	/* clear sign bit */
+		}
+	else
+		*sign = 0;
+
+#if defined(IEEE_Arith) + defined(VAX)
+#ifdef IEEE_Arith
+	if ((word0(d) & Exp_mask) == Exp_mask)
+#else
+	if (word0(d)  == 0x8000)
+#endif
+		{
+		/* Infinity or NaN */
+		*decpt = 9999;
+#ifdef IEEE_Arith
+		if (!word1(d) && !(word0(d) & 0xfffff))
+			return nrv_alloc("Infinity", rve, 8);
+#endif
+		return nrv_alloc("NaN", rve, 3);
+		}
+#endif
+#ifdef IBM
+	dval(d) += 0; /* normalize */
+#endif
+	if (!dval(d)) {
+		*decpt = 1;
+		return nrv_alloc("0", rve, 1);
+		}
+
+#ifdef SET_INEXACT
+	try_quick = oldinexact = get_inexact();
+	inexact = 1;
+#endif
+#ifdef Honor_FLT_ROUNDS
+	if ((rounding = Flt_Rounds) >= 2) {
+		if (*sign)
+			rounding = rounding == 2 ? 0 : 2;
+		else
+			if (rounding != 2)
+				rounding = 0;
+		}
+#endif
+
+	b = d2b(dval(d), &be, &bbits);
+#ifdef Sudden_Underflow
+	i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+#else
+	if (( i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) {
+#endif
+		dval(d2) = dval(d);
+		word0(d2) &= Frac_mask1;
+		word0(d2) |= Exp_11;
+#ifdef IBM
+		if (( j = 11 - hi0bits(word0(d2) & Frac_mask) )!=0)
+			dval(d2) /= 1 << j;
+#endif
+
+		/* log(x)	~=~ log(1.5) + (x-1.5)/1.5
+		 * log10(x)	 =  log(x) / log(10)
+		 *		~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+		 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+		 *
+		 * This suggests computing an approximation k to log10(d) by
+		 *
+		 * k = (i - Bias)*0.301029995663981
+		 *	+ ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+		 *
+		 * We want k to be too large rather than too small.
+		 * The error in the first-order Taylor series approximation
+		 * is in our favor, so we just round up the constant enough
+		 * to compensate for any error in the multiplication of
+		 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+		 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+		 * adding 1e-13 to the constant term more than suffices.
+		 * Hence we adjust the constant term to 0.1760912590558.
+		 * (We could get a more accurate k by invoking log10,
+		 *  but this is probably not worthwhile.)
+		 */
+
+		i -= Bias;
+#ifdef IBM
+		i <<= 2;
+		i += j;
+#endif
+#ifndef Sudden_Underflow
+		denorm = 0;
+		}
+	else {
+		/* d is denormalized */
+
+		i = bbits + be + (Bias + (P-1) - 1);
+		x = i > 32  ? word0(d) << 64 - i | word1(d) >> i - 32
+			    : word1(d) << 32 - i;
+		dval(d2) = x;
+		word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+		i -= (Bias + (P-1) - 1) + 1;
+		denorm = 1;
+		}
+#endif
+	ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+	k = (int)ds;
+	if (ds < 0. && ds != k)
+		k--;	/* want k = floor(ds) */
+	k_check = 1;
+	if (k >= 0 && k <= Ten_pmax) {
+		if (dval(d) < tens[k])
+			k--;
+		k_check = 0;
+		}
+	j = bbits - i - 1;
+	if (j >= 0) {
+		b2 = 0;
+		s2 = j;
+		}
+	else {
+		b2 = -j;
+		s2 = 0;
+		}
+	if (k >= 0) {
+		b5 = 0;
+		s5 = k;
+		s2 += k;
+		}
+	else {
+		b2 -= k;
+		b5 = -k;
+		s5 = 0;
+		}
+	if (mode < 0 || mode > 9)
+		mode = 0;
+
+#ifndef SET_INEXACT
+#ifdef Check_FLT_ROUNDS
+	try_quick = Rounding == 1;
+#else
+	try_quick = 1;
+#endif
+#endif /*SET_INEXACT*/
+
+	if (mode > 5) {
+		mode -= 4;
+		try_quick = 0;
+		}
+	leftright = 1;
+	switch(mode) {
+		case 0:
+		case 1:
+			ilim = ilim1 = -1;
+			i = 18;
+			ndigits = 0;
+			break;
+		case 2:
+			leftright = 0;
+			/* no break */
+		case 4:
+			if (ndigits <= 0)
+				ndigits = 1;
+			ilim = ilim1 = i = ndigits;
+			break;
+		case 3:
+			leftright = 0;
+			/* no break */
+		case 5:
+			i = ndigits + k + 1;
+			ilim = i;
+			ilim1 = i - 1;
+			if (i <= 0)
+				i = 1;
+		}
+	s = s0 = rv_alloc(i);
+
+#ifdef Honor_FLT_ROUNDS
+	if (mode > 1 && rounding != 1)
+		leftright = 0;
+#endif
+
+	if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+		/* Try to get by with floating-point arithmetic. */
+
+		i = 0;
+		dval(d2) = dval(d);
+		k0 = k;
+		ilim0 = ilim;
+		ieps = 2; /* conservative */
+		if (k > 0) {
+			ds = tens[k&0xf];
+			j = k >> 4;
+			if (j & Bletch) {
+				/* prevent overflows */
+				j &= Bletch - 1;
+				dval(d) /= bigtens[n_bigtens-1];
+				ieps++;
+				}
+			for(; j; j >>= 1, i++)
+				if (j & 1) {
+					ieps++;
+					ds *= bigtens[i];
+					}
+			dval(d) /= ds;
+			}
+		else if (( j1 = -k )!=0) {
+			dval(d) *= tens[j1 & 0xf];
+			for(j = j1 >> 4; j; j >>= 1, i++)
+				if (j & 1) {
+					ieps++;
+					dval(d) *= bigtens[i];
+					}
+			}
+		if (k_check && dval(d) < 1. && ilim > 0) {
+			if (ilim1 <= 0)
+				goto fast_failed;
+			ilim = ilim1;
+			k--;
+			dval(d) *= 10.;
+			ieps++;
+			}
+		dval(eps) = ieps*dval(d) + 7.;
+		word0(eps) -= (P-1)*Exp_msk1;
+		if (ilim == 0) {
+			S = mhi = 0;
+			dval(d) -= 5.;
+			if (dval(d) > dval(eps))
+				goto one_digit;
+			if (dval(d) < -dval(eps))
+				goto no_digits;
+			goto fast_failed;
+			}
+#ifndef No_leftright
+		if (leftright) {
+			/* Use Steele & White method of only
+			 * generating digits needed.
+			 */
+			dval(eps) = 0.5/tens[ilim-1] - dval(eps);
+			for(i = 0;;) {
+				L = dval(d);
+				dval(d) -= L;
+				*s++ = '0' + (int)L;
+				if (dval(d) < dval(eps))
+					goto ret1;
+				if (1. - dval(d) < dval(eps))
+					goto bump_up;
+				if (++i >= ilim)
+					break;
+				dval(eps) *= 10.;
+				dval(d) *= 10.;
+				}
+			}
+		else {
+#endif
+			/* Generate ilim digits, then fix them up. */
+			dval(eps) *= tens[ilim-1];
+			for(i = 1;; i++, dval(d) *= 10.) {
+				L = (Long)(dval(d));
+				if (!(dval(d) -= L))
+					ilim = i;
+				*s++ = '0' + (int)L;
+				if (i == ilim) {
+					if (dval(d) > 0.5 + dval(eps))
+						goto bump_up;
+					else if (dval(d) < 0.5 - dval(eps)) {
+						while(*--s == '0');
+						s++;
+						goto ret1;
+						}
+					break;
+					}
+				}
+#ifndef No_leftright
+			}
+#endif
+ fast_failed:
+		s = s0;
+		dval(d) = dval(d2);
+		k = k0;
+		ilim = ilim0;
+		}
+
+	/* Do we have a "small" integer? */
+
+	if (be >= 0 && k <= Int_max) {
+		/* Yes. */
+		ds = tens[k];
+		if (ndigits < 0 && ilim <= 0) {
+			S = mhi = 0;
+			if (ilim < 0 || dval(d) <= 5*ds)
+				goto no_digits;
+			goto one_digit;
+			}
+		for(i = 1;; i++, dval(d) *= 10.) {
+			L = (Long)(dval(d) / ds);
+			dval(d) -= L*ds;
+#ifdef Check_FLT_ROUNDS
+			/* If FLT_ROUNDS == 2, L will usually be high by 1 */
+			if (dval(d) < 0) {
+				L--;
+				dval(d) += ds;
+				}
+#endif
+			*s++ = '0' + (int)L;
+			if (!dval(d)) {
+#ifdef SET_INEXACT
+				inexact = 0;
+#endif
+				break;
+				}
+			if (i == ilim) {
+#ifdef Honor_FLT_ROUNDS
+				if (mode > 1)
+				switch(rounding) {
+				  case 0: goto ret1;
+				  case 2: goto bump_up;
+				  }
+#endif
+				dval(d) += dval(d);
+				if (dval(d) > ds || dval(d) == ds && L & 1) {
+ bump_up:
+					while(*--s == '9')
+						if (s == s0) {
+							k++;
+							*s = '0';
+							break;
+							}
+					++*s++;
+					}
+				break;
+				}
+			}
+		goto ret1;
+		}
+
+	m2 = b2;
+	m5 = b5;
+	mhi = mlo = 0;
+	if (leftright) {
+		i =
+#ifndef Sudden_Underflow
+			denorm ? be + (Bias + (P-1) - 1 + 1) :
+#endif
+#ifdef IBM
+			1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
+#else
+			1 + P - bbits;
+#endif
+		b2 += i;
+		s2 += i;
+		mhi = i2b(1);
+		}
+	if (m2 > 0 && s2 > 0) {
+		i = m2 < s2 ? m2 : s2;
+		b2 -= i;
+		m2 -= i;
+		s2 -= i;
+		}
+	if (b5 > 0) {
+		if (leftright) {
+			if (m5 > 0) {
+				mhi = pow5mult(mhi, m5);
+				b1 = mult(mhi, b);
+				Bfree(b);
+				b = b1;
+				}
+			if (( j = b5 - m5 )!=0)
+				b = pow5mult(b, j);
+			}
+		else
+			b = pow5mult(b, b5);
+		}
+	S = i2b(1);
+	if (s5 > 0)
+		S = pow5mult(S, s5);
+
+	/* Check for special case that d is a normalized power of 2. */
+
+	spec_case = 0;
+	if ((mode < 2 || leftright)
+#ifdef Honor_FLT_ROUNDS
+			&& rounding == 1
+#endif
+				) {
+		if (!word1(d) && !(word0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+		 && word0(d) & (Exp_mask & ~Exp_msk1)
+#endif
+				) {
+			/* The special case */
+			b2 += Log2P;
+			s2 += Log2P;
+			spec_case = 1;
+			}
+		}
+
+	/* Arrange for convenient computation of quotients:
+	 * shift left if necessary so divisor has 4 leading 0 bits.
+	 *
+	 * Perhaps we should just compute leading 28 bits of S once
+	 * and for all and pass them and a shift to quorem, so it
+	 * can do shifts and ors to compute the numerator for q.
+	 */
+#ifdef Pack_32
+	if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f )!=0)
+		i = 32 - i;
+#else
+	if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf )!=0)
+		i = 16 - i;
+#endif
+	if (i > 4) {
+		i -= 4;
+		b2 += i;
+		m2 += i;
+		s2 += i;
+		}
+	else if (i < 4) {
+		i += 28;
+		b2 += i;
+		m2 += i;
+		s2 += i;
+		}
+	if (b2 > 0)
+		b = lshift(b, b2);
+	if (s2 > 0)
+		S = lshift(S, s2);
+	if (k_check) {
+		if (cmp(b,S) < 0) {
+			k--;
+			b = multadd(b, 10, 0);	/* we botched the k estimate */
+			if (leftright)
+				mhi = multadd(mhi, 10, 0);
+			ilim = ilim1;
+			}
+		}
+	if (ilim <= 0 && (mode == 3 || mode == 5)) {
+		if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
+			/* no digits, fcvt style */
+ no_digits:
+			k = -1 - ndigits;
+			goto ret;
+			}
+ one_digit:
+		*s++ = '1';
+		k++;
+		goto ret;
+		}
+	if (leftright) {
+		if (m2 > 0)
+			mhi = lshift(mhi, m2);
+
+		/* Compute mlo -- check for special case
+		 * that d is a normalized power of 2.
+		 */
+
+		mlo = mhi;
+		if (spec_case) {
+			mhi = Balloc(mhi->k);
+			Bcopy(mhi, mlo);
+			mhi = lshift(mhi, Log2P);
+			}
+
+		for(i = 1;;i++) {
+			dig = quorem(b,S) + '0';
+			/* Do we yet have the shortest decimal string
+			 * that will round to d?
+			 */
+			j = cmp(b, mlo);
+			delta = diff(S, mhi);
+			j1 = delta->sign ? 1 : cmp(b, delta);
+			Bfree(delta);
+#ifndef ROUND_BIASED
+			if (j1 == 0 && mode != 1 && !(word1(d) & 1)
+#ifdef Honor_FLT_ROUNDS
+				&& rounding >= 1
+#endif
+								   ) {
+				if (dig == '9')
+					goto round_9_up;
+				if (j > 0)
+					dig++;
+#ifdef SET_INEXACT
+				else if (!b->x[0] && b->wds <= 1)
+					inexact = 0;
+#endif
+				*s++ = dig;
+				goto ret;
+				}
+#endif
+			if (j < 0 || j == 0 && mode != 1
+#ifndef ROUND_BIASED
+							&& !(word1(d) & 1)
+#endif
+					) {
+				if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+					inexact = 0;
+#endif
+					goto accept_dig;
+					}
+#ifdef Honor_FLT_ROUNDS
+				if (mode > 1)
+				 switch(rounding) {
+				  case 0: goto accept_dig;
+				  case 2: goto keep_dig;
+				  }
+#endif /*Honor_FLT_ROUNDS*/
+				if (j1 > 0) {
+					b = lshift(b, 1);
+					j1 = cmp(b, S);
+					if ((j1 > 0 || j1 == 0 && dig & 1)
+					&& dig++ == '9')
+						goto round_9_up;
+					}
+ accept_dig:
+				*s++ = dig;
+				goto ret;
+				}
+			if (j1 > 0) {
+#ifdef Honor_FLT_ROUNDS
+				if (!rounding)
+					goto accept_dig;
+#endif
+				if (dig == '9') { /* possible if i == 1 */
+ round_9_up:
+					*s++ = '9';
+					goto roundoff;
+					}
+				*s++ = dig + 1;
+				goto ret;
+				}
+#ifdef Honor_FLT_ROUNDS
+ keep_dig:
+#endif
+			*s++ = dig;
+			if (i == ilim)
+				break;
+			b = multadd(b, 10, 0);
+			if (mlo == mhi)
+				mlo = mhi = multadd(mhi, 10, 0);
+			else {
+				mlo = multadd(mlo, 10, 0);
+				mhi = multadd(mhi, 10, 0);
+				}
+			}
+		}
+	else
+		for(i = 1;; i++) {
+			*s++ = dig = quorem(b,S) + '0';
+			if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+				inexact = 0;
+#endif
+				goto ret;
+				}
+			if (i >= ilim)
+				break;
+			b = multadd(b, 10, 0);
+			}
+
+	/* Round off last digit */
+
+#ifdef Honor_FLT_ROUNDS
+	switch(rounding) {
+	  case 0: goto trimzeros;
+	  case 2: goto roundoff;
+	  }
+#endif
+	b = lshift(b, 1);
+	j = cmp(b, S);
+	if (j > 0 || j == 0 && dig & 1) {
+ roundoff:
+		while(*--s == '9')
+			if (s == s0) {
+				k++;
+				*s++ = '1';
+				goto ret;
+				}
+		++*s++;
+		}
+	else {
+ trimzeros:
+		while(*--s == '0');
+		s++;
+		}
+ ret:
+	Bfree(S);
+	if (mhi) {
+		if (mlo && mlo != mhi)
+			Bfree(mlo);
+		Bfree(mhi);
+		}
+ ret1:
+#ifdef SET_INEXACT
+	if (inexact) {
+		if (!oldinexact) {
+			word0(d) = Exp_1 + (70 << Exp_shift);
+			word1(d) = 0;
+			dval(d) += 1.;
+			}
+		}
+	else if (!oldinexact)
+		clear_inexact();
+#endif
+	Bfree(b);
+	*s = 0;
+	*decpt = k + 1;
+	if (rve)
+		*rve = s;
+	return s0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/g_Qfmt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/g_Qfmt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/g_Qfmt.c	(revision 2448)
@@ -0,0 +1,120 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#endif
+#ifdef IEEE_8087
+#define _0 3
+#define _1 2
+#define _2 1
+#define _3 0
+#endif
+
+ char*
+#ifdef KR_headers
+g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
+#else
+g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize)
+#endif
+{
+	static FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 };
+	char *b, *s, *se;
+	ULong bits[4], *L, sign;
+	int decpt, ex, i, mode;
+
+	if (ndig < 0)
+		ndig = 0;
+	if (bufsize < ndig + 10)
+		return 0;
+
+	L = (ULong*)V;
+	sign = L[_0] & 0x80000000L;
+	bits[3] = L[_0] & 0xffff;
+	bits[2] = L[_1];
+	bits[1] = L[_2];
+	bits[0] = L[_3];
+	b = buf;
+	if ( (ex = (L[_0] & 0x7fff0000L) >> 16) !=0) {
+		if (ex == 0x7fff) {
+			/* Infinity or NaN */
+			if (bits[0] | bits[1] | bits[2] | bits[3])
+				b = strcpy(b, "NaN");
+			else {
+				b = buf;
+				if (sign)
+					*b++ = '-';
+				b = strcp(b, "Infinity");
+				}
+			return b;
+			}
+		i = STRTOG_Normal;
+		bits[3] |= 0x10000;
+		}
+	else if (bits[0] | bits[1] | bits[2] | bits[3]) {
+		i = STRTOG_Denormal;
+		ex = 1;
+		}
+	else {
+#ifndef IGNORE_ZERO_SIGN
+		if (sign)
+			*b++ = '-';
+#endif
+		*b++ = '0';
+		*b = 0;
+		return b;
+		}
+	ex -= 0x3fff + 112;
+	mode = 2;
+	if (ndig <= 0) {
+		if (bufsize < 48)
+			return 0;
+		mode = 0;
+		}
+	s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+	return g__fmt(buf, s, se, decpt, sign);
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/g__fmt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/g__fmt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/g__fmt.c	(revision 2448)
@@ -0,0 +1,101 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	dmg@acm.org
+ */
+
+#include "gdtoaimp.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+ char *
+#ifdef KR_headers
+g__fmt(b, s, se, decpt, sign) char *b; char *s; char *se; int decpt; ULong sign;
+#else
+g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
+#endif
+{
+	int i, j, k;
+	char *s0 = s;
+#ifdef USE_LOCALE
+	char decimalpoint = *localeconv()->decimal_point;
+#else
+#define decimalpoint '.'
+#endif
+	if (sign)
+		*b++ = '-';
+	if (decpt <= -4 || decpt > se - s + 5) {
+		*b++ = *s++;
+		if (*s) {
+			*b++ = decimalpoint;
+			while((*b = *s++) !=0)
+				b++;
+			}
+		*b++ = 'e';
+		/* sprintf(b, "%+.2d", decpt - 1); */
+		if (--decpt < 0) {
+			*b++ = '-';
+			decpt = -decpt;
+			}
+		else
+			*b++ = '+';
+		for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){}
+		for(;;) {
+			i = decpt / k;
+			*b++ = i + '0';
+			if (--j <= 0)
+				break;
+			decpt -= i*k;
+			decpt *= 10;
+			}
+		*b = 0;
+		}
+	else if (decpt <= 0) {
+		*b++ = decimalpoint;
+		for(; decpt < 0; decpt++)
+			*b++ = '0';
+		while((*b = *s++) !=0)
+			b++;
+		}
+	else {
+		while((*b = *s++) !=0) {
+			b++;
+			if (--decpt == 0 && *s)
+				*b++ = decimalpoint;
+			}
+		for(; decpt > 0; decpt--)
+			*b++ = '0';
+		*b = 0;
+		}
+	freedtoa(s0);
+	return b;
+ 	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/g_ddfmt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/g_ddfmt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/g_ddfmt.c	(revision 2448)
@@ -0,0 +1,161 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+#include <string.h>
+
+ char *
+#ifdef KR_headers
+g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; unsigned bufsize;
+#else
+g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
+#endif
+{
+	FPI fpi;
+	char *b, *s, *se;
+	ULong *L, bits0[4], *bits, *zx;
+	int bx, by, decpt, ex, ey, i, j, mode;
+	Bigint *x, *y, *z;
+	double ddx[2];
+
+	if (bufsize < 10 || bufsize < ndig + 8)
+		return 0;
+
+	L = (ULong*)dd;
+	if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) {
+		/* Infinity or NaN */
+		if (L[_0] & 0xfffff || L[_1]) {
+ nanret:
+			return strcp(buf, "NaN");
+			}
+		if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) {
+			if (L[2+_0] & 0xfffff || L[2+_1])
+				goto nanret;
+			if ((L[_0] ^ L[2+_0]) & 0x80000000L)
+				goto nanret;	/* Infinity - Infinity */
+			}
+ infret:
+		b = buf;
+		if (L[_0] & 0x80000000L)
+			*b++ = '-';
+		return strcp(b, "Infinity");
+		}
+	if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) {
+		L += 2;
+		if (L[_0] & 0xfffff || L[_1])
+			goto nanret;
+		goto infret;
+		}
+	if (dd[0] + dd[1] == 0.) {
+		b = buf;
+#ifndef IGNORE_ZERO_SIGN
+		if (L[_0] & L[2+_0] & 0x80000000L)
+			*b++ = '-';
+#endif
+		*b++ = '0';
+		*b = 0;
+		return b;
+		}
+	if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) {
+		ddx[1] = dd[0];
+		ddx[0] = dd[1];
+		dd = ddx;
+		L = (ULong*)dd;
+		}
+	z = d2b(dd[0], &ex, &bx);
+	if (dd[1] == 0.)
+		goto no_y;
+	x = z;
+	y = d2b(dd[1], &ey, &by);
+	if ( (i = ex - ey) !=0) {
+		if (i > 0) {
+			x = lshift(x, i);
+			ex = ey;
+			}
+		else
+			y = lshift(y, -i);
+		}
+	if ((L[_0] ^ L[2+_0]) & 0x80000000L) {
+		z = diff(x, y);
+		if (L[_0] & 0x80000000L)
+			z->sign = 1 - z->sign;
+		}
+	else {
+		z = sum(x, y);
+		if (L[_0] & 0x80000000L)
+			z->sign = 1;
+		}
+	Bfree(x);
+	Bfree(y);
+ no_y:
+	bits = zx = z->x;
+	for(i = 0; !*zx; zx++)
+		i += 32;
+	i += lo0bits(zx);
+	if (i) {
+		rshift(z, i);
+		ex += i;
+		}
+	fpi.nbits = z->wds * 32 - hi0bits(z->x[j = z->wds-1]);
+	if (fpi.nbits < 106) {
+		fpi.nbits = 106;
+		if (j < 3) {
+			for(i = 0; i <= j; i++)
+				bits0[i] = bits[i];
+			while(i < 4)
+				bits0[i++] = 0;
+			bits = bits0;
+			}
+		}
+	mode = 2;
+	if (ndig <= 0) {
+		if (bufsize < (int)(fpi.nbits * .301029995664) + 10) {
+			Bfree(z);
+			return 0;
+			}
+		mode = 0;
+		}
+	fpi.emin = 1-1023-53+1;
+	fpi.emax = 2046-1023-106+1;
+	fpi.rounding = FPI_Round_near;
+	fpi.sudden_underflow = 0;
+	i = STRTOG_Normal;
+	s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+	b = g__fmt(buf, s, se, decpt, z->sign);
+	Bfree(z);
+	return b;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/g_dfmt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/g_dfmt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/g_dfmt.c	(revision 2448)
@@ -0,0 +1,95 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ char*
+#ifdef KR_headers
+g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; unsigned bufsize;
+#else
+g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
+#endif
+{
+	static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
+	char *b, *s, *se;
+	ULong bits[2], *L, sign;
+	int decpt, ex, i, mode;
+
+	if (ndig < 0)
+		ndig = 0;
+	if (bufsize < ndig + 10)
+		return 0;
+
+	L = (ULong*)d;
+	sign = L[_0] & 0x80000000L;
+	if ((L[_0] & 0x7ff00000) == 0x7ff00000) {
+		/* Infinity or NaN */
+		if (L[_0] & 0xfffff || L[_1]) {
+			return strcp(buf, "NaN");
+			}
+		b = buf;
+		if (sign)
+			*b++ = '-';
+		return strcp(b, "Infinity");
+		}
+	if (L[_1] == 0 && (L[_0] ^ sign) == 0 /*d == 0.*/) {
+		b = buf;
+#ifndef IGNORE_ZERO_SIGN
+		if (L[_0] & 0x80000000L)
+			*b++ = '-';
+#endif
+		*b++ = '0';
+		*b = 0;
+		return b;
+		}
+	bits[0] = L[_1];
+	bits[1] = L[_0] & 0xfffff;
+	if ( (ex = (L[_0] >> 20) & 0x7ff) !=0)
+		bits[1] |= 0x100000;
+	else
+		ex = 1;
+	ex -= 0x3ff + 52;
+	mode = 2;
+	if (ndig <= 0) {
+		if (bufsize < 25)
+			return 0;
+		mode = 0;
+		}
+	i = STRTOG_Normal;
+	s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+	return g__fmt(buf, s, se, decpt, sign);
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/g_ffmt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/g_ffmt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/g_ffmt.c	(revision 2448)
@@ -0,0 +1,94 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ char*
+#ifdef KR_headers
+g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; unsigned bufsize;
+#else
+g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
+#endif
+{
+	static FPI fpi = { 24, 1-127-24+1,  254-127-24+1, 1, 0 };
+	char *b, *s, *se;
+	ULong bits[1], *L, sign;
+	int decpt, ex, i, mode;
+
+	if (ndig < 0)
+		ndig = 0;
+	if (bufsize < ndig + 10)
+		return 0;
+
+	L = (ULong*)f;
+	sign = L[0] & 0x80000000L;
+	if ((L[0] & 0x7f800000) == 0x7f800000) {
+		/* Infinity or NaN */
+		if (L[0] & 0x7fffff) {
+			return strcp(buf, "NaN");
+			}
+		b = buf;
+		if (sign)
+			*b++ = '-';
+		return strcp(b, "Infinity");
+		}
+	if (*f == 0.) {
+		b = buf;
+#ifndef IGNORE_ZERO_SIGN
+		if (L[0] & 0x80000000L)
+			*b++ = '-';
+#endif
+		*b++ = '0';
+		*b = 0;
+		return b;
+		}
+	bits[0] = L[0] & 0x7fffff;
+	if ( (ex = (L[0] >> 23) & 0xff) !=0)
+		bits[0] |= 0x800000;
+	else
+		ex = 1;
+	ex -= 0x7f + 23;
+	mode = 2;
+	if (ndig <= 0) {
+		if (bufsize < 16)
+			return 0;
+		mode = 0;
+		}
+	i = STRTOG_Normal;
+	s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+	return g__fmt(buf, s, se, decpt, sign);
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/g_xLfmt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/g_xLfmt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/g_xLfmt.c	(revision 2448)
@@ -0,0 +1,114 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#endif
+#ifdef IEEE_8087
+#define _0 2
+#define _1 1
+#define _2 0
+#endif
+
+ char*
+#ifdef KR_headers
+g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
+#else
+g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize)
+#endif
+{
+	static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
+	char *b, *s, *se;
+	ULong bits[2], *L, sign;
+	int decpt, ex, i, mode;
+
+	if (ndig < 0)
+		ndig = 0;
+	if (bufsize < ndig + 10)
+		return 0;
+
+	L = (ULong*)V;
+	sign = L[_0] & 0x80000000L;
+	bits[1] = L[_1];
+	bits[0] = L[_2];
+	if ( (ex = (L[_0] >> 16) & 0x7fff) !=0) {
+		if (ex == 0x7fff) {
+			/* Infinity or NaN */
+			if (bits[0] | bits[1])
+				b = strcp(buf, "NaN");
+			else {
+				b = buf;
+				if (sign)
+					*b++ = '-';
+				b = strcp(b, "Infinity");
+				}
+			return b;
+			}
+		i = STRTOG_Normal;
+		}
+	else if (bits[0] | bits[1]) {
+		i = STRTOG_Denormal;
+		}
+	else {
+		b = buf;
+#ifndef IGNORE_ZERO_SIGN
+		if (sign)
+			*b++ = '-';
+#endif
+		*b++ = '0';
+		*b = 0;
+		return b;
+		}
+	ex -= 0x3fff + 63;
+	mode = 2;
+	if (ndig <= 0) {
+		if (bufsize < 32)
+			return 0;
+		mode = 0;
+		}
+	s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+	return g__fmt(buf, s, se, decpt, sign);
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/g_xfmt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/g_xfmt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/g_xfmt.c	(revision 2448)
@@ -0,0 +1,119 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#define _4 4
+#endif
+#ifdef IEEE_8087
+#define _0 4
+#define _1 3
+#define _2 2
+#define _3 1
+#define _4 0
+#endif
+
+ char*
+#ifdef KR_headers
+g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
+#else
+g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
+#endif
+{
+	static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
+	char *b, *s, *se;
+	ULong bits[2], sign;
+	UShort *L;
+	int decpt, ex, i, mode;
+
+	if (ndig < 0)
+		ndig = 0;
+	if (bufsize < ndig + 10)
+		return 0;
+
+	L = (UShort *)V;
+	sign = L[_0] & 0x8000;
+	bits[1] = (L[_1] << 16) | L[_2];
+	bits[0] = (L[_3] << 16) | L[_4];
+	if ( (ex = L[_0] & 0x7fff) !=0) {
+		if (ex == 0x7fff) {
+			/* Infinity or NaN */
+			if (bits[0] | bits[1])
+				b = strcp(buf, "NaN");
+			else {
+				b = buf;
+				if (sign)
+					*b++ = '-';
+				b = strcp(b, "Infinity");
+				}
+			return b;
+			}
+		i = STRTOG_Normal;
+		}
+	else if (bits[0] | bits[1]) {
+		i = STRTOG_Denormal;
+		}
+	else {
+		b = buf;
+#ifndef IGNORE_ZERO_SIGN
+		if (sign)
+			*b++ = '-';
+#endif
+		*b++ = '0';
+		*b = 0;
+		return b;
+		}
+	ex -= 0x3fff + 63;
+	mode = 2;
+	if (ndig <= 0) {
+		if (bufsize < 32)
+			return 0;
+		mode = 0;
+		}
+	s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+	return g__fmt(buf, s, se, decpt, sign);
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.c	(revision 2448)
@@ -0,0 +1,764 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ static Bigint *
+#ifdef KR_headers
+bitstob(bits, nbits, bbits) ULong *bits; int nbits; int *bbits;
+#else
+bitstob(ULong *bits, int nbits, int *bbits)
+#endif
+{
+	int i, k;
+	Bigint *b;
+	ULong *be, *x, *x0;
+
+	i = ULbits;
+	k = 0;
+	while(i < nbits) {
+		i <<= 1;
+		k++;
+		}
+#ifndef Pack_32
+	if (!k)
+		k = 1;
+#endif
+	b = Balloc(k);
+	be = bits + ((nbits - 1) >> kshift);
+	x = x0 = b->x;
+	do {
+		*x++ = *bits & ALL_ON;
+#ifdef Pack_16
+		*x++ = (*bits >> 16) & ALL_ON;
+#endif
+		} while(++bits <= be);
+	i = x - x0;
+	while(!x0[--i])
+		if (!i) {
+			b->wds = 0;
+			*bbits = 0;
+			goto ret;
+			}
+	b->wds = i + 1;
+	*bbits = i*ULbits + 32 - hi0bits(b->x[i]);
+ ret:
+	return b;
+	}
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *	1. Rather than iterating, we use a simple numeric overestimate
+ *	   to determine k = floor(log10(d)).  We scale relevant
+ *	   quantities using O(log2(k)) rather than O(k) multiplications.
+ *	2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ *	   try to generate digits strictly left to right.  Instead, we
+ *	   compute with fewer bits and propagate the carry if necessary
+ *	   when rounding the final digit up.  This is often faster.
+ *	3. Under the assumption that input will be rounded nearest,
+ *	   mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ *	   That is, we allow equality in stopping tests when the
+ *	   round-nearest rule will give the same floating-point value
+ *	   as would satisfaction of the stopping test with strict
+ *	   inequality.
+ *	4. We remove common factors of powers of 2 from relevant
+ *	   quantities.
+ *	5. When converting floating-point integers less than 1e16,
+ *	   we use floating-point arithmetic rather than resorting
+ *	   to multiple-precision integers.
+ *	6. When asked to produce fewer than 15 digits, we first try
+ *	   to get by with floating-point arithmetic; we resort to
+ *	   multiple-precision integer arithmetic only if we cannot
+ *	   guarantee that the floating-point calculation has given
+ *	   the correctly rounded result.  For k requested digits and
+ *	   "uniformly" distributed input, the probability is
+ *	   something like 10^(k-15) that we must resort to the Long
+ *	   calculation.
+ */
+
+ char *
+gdtoa
+#ifdef KR_headers
+	(fpi, be, bits, kindp, mode, ndigits, decpt, rve)
+	FPI *fpi; int be; ULong *bits;
+	int *kindp, mode, ndigits, *decpt; char **rve;
+#else
+	(FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)
+#endif
+{
+ /*	Arguments ndigits and decpt are similar to the second and third
+	arguments of ecvt and fcvt; trailing zeros are suppressed from
+	the returned string.  If not null, *rve is set to point
+	to the end of the return value.  If d is +-Infinity or NaN,
+	then *decpt is set to 9999.
+
+	mode:
+		0 ==> shortest string that yields d when read in
+			and rounded to nearest.
+		1 ==> like 0, but with Steele & White stopping rule;
+			e.g. with IEEE P754 arithmetic , mode 0 gives
+			1e23 whereas mode 1 gives 9.999999999999999e22.
+		2 ==> max(1,ndigits) significant digits.  This gives a
+			return value similar to that of ecvt, except
+			that trailing zeros are suppressed.
+		3 ==> through ndigits past the decimal point.  This
+			gives a return value similar to that from fcvt,
+			except that trailing zeros are suppressed, and
+			ndigits can be negative.
+		4-9 should give the same return values as 2-3, i.e.,
+			4 <= mode <= 9 ==> same return as mode
+			2 + (mode & 1).  These modes are mainly for
+			debugging; often they run slower but sometimes
+			faster than modes 2-3.
+		4,5,8,9 ==> left-to-right digit generation.
+		6-9 ==> don't try fast floating-point estimate
+			(if applicable).
+
+		Values of mode other than 0-9 are treated as mode 0.
+
+		Sufficient space is allocated to the return value
+		to hold the suppressed trailing zeros.
+	*/
+
+	int bbits, b2, b5, be0, dig, i, ieps, ilim, ilim0, ilim1, inex;
+	int j, j1, k, k0, k_check, kind, leftright, m2, m5, nbits;
+	int rdir, s2, s5, spec_case, try_quick;
+	Long L;
+	Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
+	double d, d2, ds, eps;
+	char *s, *s0;
+
+#ifndef MULTIPLE_THREADS
+	if (dtoa_result) {
+		freedtoa(dtoa_result);
+		dtoa_result = 0;
+		}
+#endif
+	inex = 0;
+	kind = *kindp &= ~STRTOG_Inexact;
+	switch(kind & STRTOG_Retmask) {
+	  case STRTOG_Zero:
+		goto ret_zero;
+	  case STRTOG_Normal:
+	  case STRTOG_Denormal:
+		break;
+	  case STRTOG_Infinite:
+		*decpt = -32768;
+		return nrv_alloc("Infinity", rve, 8);
+	  case STRTOG_NaN:
+		*decpt = -32768;
+		return nrv_alloc("NaN", rve, 3);
+	  default:
+		return 0;
+	  }
+	b = bitstob(bits, nbits = fpi->nbits, &bbits);
+	be0 = be;
+	if ( (i = trailz(b)) !=0) {
+		rshift(b, i);
+		be += i;
+		bbits -= i;
+		}
+	if (!b->wds) {
+		Bfree(b);
+ ret_zero:
+		*decpt = 1;
+		return nrv_alloc("0", rve, 1);
+		}
+
+	dval(d) = b2d(b, &i);
+	i = be + bbits - 1;
+	word0(d) &= Frac_mask1;
+	word0(d) |= Exp_11;
+#ifdef IBM
+	if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
+		dval(d) /= 1 << j;
+#endif
+
+	/* log(x)	~=~ log(1.5) + (x-1.5)/1.5
+	 * log10(x)	 =  log(x) / log(10)
+	 *		~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+	 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+	 *
+	 * This suggests computing an approximation k to log10(d) by
+	 *
+	 * k = (i - Bias)*0.301029995663981
+	 *	+ ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+	 *
+	 * We want k to be too large rather than too small.
+	 * The error in the first-order Taylor series approximation
+	 * is in our favor, so we just round up the constant enough
+	 * to compensate for any error in the multiplication of
+	 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+	 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+	 * adding 1e-13 to the constant term more than suffices.
+	 * Hence we adjust the constant term to 0.1760912590558.
+	 * (We could get a more accurate k by invoking log10,
+	 *  but this is probably not worthwhile.)
+	 */
+#ifdef IBM
+	i <<= 2;
+	i += j;
+#endif
+	ds = (dval(d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+
+	/* correct assumption about exponent range */
+	if ((j = i) < 0)
+		j = -j;
+	if ((j -= 1077) > 0)
+		ds += j * 7e-17;
+
+	k = (int)ds;
+	if (ds < 0. && ds != k)
+		k--;	/* want k = floor(ds) */
+	k_check = 1;
+#ifdef IBM
+	j = be + bbits - 1;
+	if ( (j1 = j & 3) !=0)
+		dval(d) *= 1 << j1;
+	word0(d) += j << Exp_shift - 2 & Exp_mask;
+#else
+	word0(d) += (be + bbits - 1) << Exp_shift;
+#endif
+	if (k >= 0 && k <= Ten_pmax) {
+		if (dval(d) < tens[k])
+			k--;
+		k_check = 0;
+		}
+	j = bbits - i - 1;
+	if (j >= 0) {
+		b2 = 0;
+		s2 = j;
+		}
+	else {
+		b2 = -j;
+		s2 = 0;
+		}
+	if (k >= 0) {
+		b5 = 0;
+		s5 = k;
+		s2 += k;
+		}
+	else {
+		b2 -= k;
+		b5 = -k;
+		s5 = 0;
+		}
+	if (mode < 0 || mode > 9)
+		mode = 0;
+	try_quick = 1;
+	if (mode > 5) {
+		mode -= 4;
+		try_quick = 0;
+		}
+	leftright = 1;
+	switch(mode) {
+		case 0:
+		case 1:
+			ilim = ilim1 = -1;
+			i = (int)(nbits * .30103) + 3;
+			ndigits = 0;
+			break;
+		case 2:
+			leftright = 0;
+			/* no break */
+		case 4:
+			if (ndigits <= 0)
+				ndigits = 1;
+			ilim = ilim1 = i = ndigits;
+			break;
+		case 3:
+			leftright = 0;
+			/* no break */
+		case 5:
+			i = ndigits + k + 1;
+			ilim = i;
+			ilim1 = i - 1;
+			if (i <= 0)
+				i = 1;
+		}
+	s = s0 = rv_alloc(i);
+
+	if ( (rdir = fpi->rounding - 1) !=0) {
+		if (rdir < 0)
+			rdir = 2;
+		if (kind & STRTOG_Neg)
+			rdir = 3 - rdir;
+		}
+
+	/* Now rdir = 0 ==> round near, 1 ==> round up, 2 ==> round down. */
+
+	if (ilim >= 0 && ilim <= Quick_max && try_quick && !rdir
+#ifndef IMPRECISE_INEXACT
+		&& k == 0
+#endif
+								) {
+
+		/* Try to get by with floating-point arithmetic. */
+
+		i = 0;
+		d2 = dval(d);
+#ifdef IBM
+		if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
+			dval(d) /= 1 << j;
+#endif
+		k0 = k;
+		ilim0 = ilim;
+		ieps = 2; /* conservative */
+		if (k > 0) {
+			ds = tens[k&0xf];
+			j = k >> 4;
+			if (j & Bletch) {
+				/* prevent overflows */
+				j &= Bletch - 1;
+				dval(d) /= bigtens[n_bigtens-1];
+				ieps++;
+				}
+			for(; j; j >>= 1, i++)
+				if (j & 1) {
+					ieps++;
+					ds *= bigtens[i];
+					}
+			}
+		else  {
+			ds = 1.;
+			if ( (j1 = -k) !=0) {
+				dval(d) *= tens[j1 & 0xf];
+				for(j = j1 >> 4; j; j >>= 1, i++)
+					if (j & 1) {
+						ieps++;
+						dval(d) *= bigtens[i];
+						}
+				}
+			}
+		if (k_check && dval(d) < 1. && ilim > 0) {
+			if (ilim1 <= 0)
+				goto fast_failed;
+			ilim = ilim1;
+			k--;
+			dval(d) *= 10.;
+			ieps++;
+			}
+		dval(eps) = ieps*dval(d) + 7.;
+		word0(eps) -= (P-1)*Exp_msk1;
+		if (ilim == 0) {
+			S = mhi = 0;
+			dval(d) -= 5.;
+			if (dval(d) > dval(eps))
+				goto one_digit;
+			if (dval(d) < -dval(eps))
+				goto no_digits;
+			goto fast_failed;
+			}
+#ifndef No_leftright
+		if (leftright) {
+			/* Use Steele & White method of only
+			 * generating digits needed.
+			 */
+			dval(eps) = ds*0.5/tens[ilim-1] - dval(eps);
+			for(i = 0;;) {
+				L = (Long)(dval(d)/ds);
+				dval(d) -= L*ds;
+				*s++ = '0' + (int)L;
+				if (dval(d) < dval(eps)) {
+					if (dval(d))
+						inex = STRTOG_Inexlo;
+					goto ret1;
+					}
+				if (ds - dval(d) < dval(eps))
+					goto bump_up;
+				if (++i >= ilim)
+					break;
+				dval(eps) *= 10.;
+				dval(d) *= 10.;
+				}
+			}
+		else {
+#endif
+			/* Generate ilim digits, then fix them up. */
+			dval(eps) *= tens[ilim-1];
+			for(i = 1;; i++, dval(d) *= 10.) {
+				if ( (L = (Long)(dval(d)/ds)) !=0)
+					dval(d) -= L*ds;
+				*s++ = '0' + (int)L;
+				if (i == ilim) {
+					ds *= 0.5;
+					if (dval(d) > ds + dval(eps))
+						goto bump_up;
+					else if (dval(d) < ds - dval(eps)) {
+						while(*--s == '0'){}
+						s++;
+						if (dval(d))
+							inex = STRTOG_Inexlo;
+						goto ret1;
+						}
+					break;
+					}
+				}
+#ifndef No_leftright
+			}
+#endif
+ fast_failed:
+		s = s0;
+		dval(d) = d2;
+		k = k0;
+		ilim = ilim0;
+		}
+
+	/* Do we have a "small" integer? */
+
+	if (be >= 0 && k <= Int_max) {
+		/* Yes. */
+		ds = tens[k];
+		if (ndigits < 0 && ilim <= 0) {
+			S = mhi = 0;
+			if (ilim < 0 || dval(d) <= 5*ds)
+				goto no_digits;
+			goto one_digit;
+			}
+		for(i = 1;; i++, dval(d) *= 10.) {
+			L = dval(d) / ds;
+			dval(d) -= L*ds;
+#ifdef Check_FLT_ROUNDS
+			/* If FLT_ROUNDS == 2, L will usually be high by 1 */
+			if (dval(d) < 0) {
+				L--;
+				dval(d) += ds;
+				}
+#endif
+			*s++ = '0' + (int)L;
+			if (dval(d) == 0.)
+				break;
+			if (i == ilim) {
+				if (rdir) {
+					if (rdir == 1)
+						goto bump_up;
+					inex = STRTOG_Inexlo;
+					goto ret1;
+					}
+				dval(d) += dval(d);
+				if (dval(d) > ds || dval(d) == ds && L & 1) {
+ bump_up:
+					inex = STRTOG_Inexhi;
+					while(*--s == '9')
+						if (s == s0) {
+							k++;
+							*s = '0';
+							break;
+							}
+					++*s++;
+					}
+				else
+					inex = STRTOG_Inexlo;
+				break;
+				}
+			}
+		goto ret1;
+		}
+
+	m2 = b2;
+	m5 = b5;
+	mhi = mlo = 0;
+	if (leftright) {
+		if (mode < 2) {
+			i = nbits - bbits;
+			if (be - i++ < fpi->emin)
+				/* denormal */
+				i = be - fpi->emin + 1;
+			}
+		else {
+			j = ilim - 1;
+			if (m5 >= j)
+				m5 -= j;
+			else {
+				s5 += j -= m5;
+				b5 += j;
+				m5 = 0;
+				}
+			if ((i = ilim) < 0) {
+				m2 -= i;
+				i = 0;
+				}
+			}
+		b2 += i;
+		s2 += i;
+		mhi = i2b(1);
+		}
+	if (m2 > 0 && s2 > 0) {
+		i = m2 < s2 ? m2 : s2;
+		b2 -= i;
+		m2 -= i;
+		s2 -= i;
+		}
+	if (b5 > 0) {
+		if (leftright) {
+			if (m5 > 0) {
+				mhi = pow5mult(mhi, m5);
+				b1 = mult(mhi, b);
+				Bfree(b);
+				b = b1;
+				}
+			if ( (j = b5 - m5) !=0)
+				b = pow5mult(b, j);
+			}
+		else
+			b = pow5mult(b, b5);
+		}
+	S = i2b(1);
+	if (s5 > 0)
+		S = pow5mult(S, s5);
+
+	/* Check for special case that d is a normalized power of 2. */
+
+	spec_case = 0;
+	if (mode < 2) {
+		if (bbits == 1 && be0 > fpi->emin + 1) {
+			/* The special case */
+			b2++;
+			s2++;
+			spec_case = 1;
+			}
+		}
+
+	/* Arrange for convenient computation of quotients:
+	 * shift left if necessary so divisor has 4 leading 0 bits.
+	 *
+	 * Perhaps we should just compute leading 28 bits of S once
+	 * and for all and pass them and a shift to quorem, so it
+	 * can do shifts and ors to compute the numerator for q.
+	 */
+#ifdef Pack_32
+	if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) !=0)
+		i = 32 - i;
+#else
+	if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) !=0)
+		i = 16 - i;
+#endif
+	if (i > 4) {
+		i -= 4;
+		b2 += i;
+		m2 += i;
+		s2 += i;
+		}
+	else if (i < 4) {
+		i += 28;
+		b2 += i;
+		m2 += i;
+		s2 += i;
+		}
+	if (b2 > 0)
+		b = lshift(b, b2);
+	if (s2 > 0)
+		S = lshift(S, s2);
+	if (k_check) {
+		if (cmp(b,S) < 0) {
+			k--;
+			b = multadd(b, 10, 0);	/* we botched the k estimate */
+			if (leftright)
+				mhi = multadd(mhi, 10, 0);
+			ilim = ilim1;
+			}
+		}
+	if (ilim <= 0 && mode > 2) {
+		if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
+			/* no digits, fcvt style */
+ no_digits:
+			k = -1 - ndigits;
+			inex = STRTOG_Inexlo;
+			goto ret;
+			}
+ one_digit:
+		inex = STRTOG_Inexhi;
+		*s++ = '1';
+		k++;
+		goto ret;
+		}
+	if (leftright) {
+		if (m2 > 0)
+			mhi = lshift(mhi, m2);
+
+		/* Compute mlo -- check for special case
+		 * that d is a normalized power of 2.
+		 */
+
+		mlo = mhi;
+		if (spec_case) {
+			mhi = Balloc(mhi->k);
+			Bcopy(mhi, mlo);
+			mhi = lshift(mhi, 1);
+			}
+
+		for(i = 1;;i++) {
+			dig = quorem(b,S) + '0';
+			/* Do we yet have the shortest decimal string
+			 * that will round to d?
+			 */
+			j = cmp(b, mlo);
+			delta = diff(S, mhi);
+			j1 = delta->sign ? 1 : cmp(b, delta);
+			Bfree(delta);
+#ifndef ROUND_BIASED
+			if (j1 == 0 && !mode && !(bits[0] & 1) && !rdir) {
+				if (dig == '9')
+					goto round_9_up;
+				if (j <= 0) {
+					if (b->wds > 1 || b->x[0])
+						inex = STRTOG_Inexlo;
+					}
+				else {
+					dig++;
+					inex = STRTOG_Inexhi;
+					}
+				*s++ = dig;
+				goto ret;
+				}
+#endif
+			if (j < 0 || j == 0 && !mode
+#ifndef ROUND_BIASED
+							&& !(bits[0] & 1)
+#endif
+					) {
+				if (rdir && (b->wds > 1 || b->x[0])) {
+					if (rdir == 2) {
+						inex = STRTOG_Inexlo;
+						goto accept;
+						}
+					while (cmp(S,mhi) > 0) {
+						*s++ = dig;
+						mhi1 = multadd(mhi, 10, 0);
+						if (mlo == mhi)
+							mlo = mhi1;
+						mhi = mhi1;
+						b = multadd(b, 10, 0);
+						dig = quorem(b,S) + '0';
+						}
+					if (dig++ == '9')
+						goto round_9_up;
+					inex = STRTOG_Inexhi;
+					goto accept;
+					}
+				if (j1 > 0) {
+					b = lshift(b, 1);
+					j1 = cmp(b, S);
+					if ((j1 > 0 || j1 == 0 && dig & 1)
+					&& dig++ == '9')
+						goto round_9_up;
+					inex = STRTOG_Inexhi;
+					}
+				if (b->wds > 1 || b->x[0])
+					inex = STRTOG_Inexlo;
+ accept:
+				*s++ = dig;
+				goto ret;
+				}
+			if (j1 > 0 && rdir != 2) {
+				if (dig == '9') { /* possible if i == 1 */
+ round_9_up:
+					*s++ = '9';
+					inex = STRTOG_Inexhi;
+					goto roundoff;
+					}
+				inex = STRTOG_Inexhi;
+				*s++ = dig + 1;
+				goto ret;
+				}
+			*s++ = dig;
+			if (i == ilim)
+				break;
+			b = multadd(b, 10, 0);
+			if (mlo == mhi)
+				mlo = mhi = multadd(mhi, 10, 0);
+			else {
+				mlo = multadd(mlo, 10, 0);
+				mhi = multadd(mhi, 10, 0);
+				}
+			}
+		}
+	else
+		for(i = 1;; i++) {
+			*s++ = dig = quorem(b,S) + '0';
+			if (i >= ilim)
+				break;
+			b = multadd(b, 10, 0);
+			}
+
+	/* Round off last digit */
+
+	if (rdir) {
+		if (rdir == 2 || b->wds <= 1 && !b->x[0])
+			goto chopzeros;
+		goto roundoff;
+		}
+	b = lshift(b, 1);
+	j = cmp(b, S);
+	if (j > 0 || j == 0 && dig & 1) {
+ roundoff:
+		inex = STRTOG_Inexhi;
+		while(*--s == '9')
+			if (s == s0) {
+				k++;
+				*s++ = '1';
+				goto ret;
+				}
+		++*s++;
+		}
+	else {
+ chopzeros:
+		if (b->wds > 1 || b->x[0])
+			inex = STRTOG_Inexlo;
+		while(*--s == '0'){}
+		s++;
+		}
+ ret:
+	Bfree(S);
+	if (mhi) {
+		if (mlo && mlo != mhi)
+			Bfree(mlo);
+		Bfree(mhi);
+		}
+ ret1:
+	Bfree(b);
+	*s = 0;
+	*decpt = k + 1;
+	if (rve)
+		*rve = s;
+	*kindp |= inex;
+	return s0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.h
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.h	(revision 2448)
@@ -0,0 +1,159 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#ifndef GDTOA_H_INCLUDED
+#define GDTOA_H_INCLUDED
+
+#include "arith.h"
+
+#ifndef Long
+#define Long long
+#endif
+#ifndef ULong
+typedef unsigned Long ULong;
+#endif
+#ifndef UShort
+typedef unsigned short UShort;
+#endif
+
+#ifndef ANSI
+#ifdef KR_headers
+#define ANSI(x) ()
+#define Void /*nothing*/
+#else
+#define ANSI(x) x
+#define Void void
+#endif
+#endif /* ANSI */
+
+#ifndef CONST
+#ifdef KR_headers
+#define CONST /* blank */
+#else
+#define CONST const
+#endif
+#endif /* CONST */
+
+ enum {	/* return values from strtodg */
+	STRTOG_Zero	= 0,
+	STRTOG_Normal	= 1,
+	STRTOG_Denormal	= 2,
+	STRTOG_Infinite	= 3,
+	STRTOG_NaN	= 4,
+	STRTOG_NaNbits	= 5,
+	STRTOG_NoNumber	= 6,
+	STRTOG_Retmask	= 7,
+
+	/* The following may be or-ed into one of the above values. */
+
+	STRTOG_Neg	= 0x08,
+	STRTOG_Inexlo	= 0x10,
+	STRTOG_Inexhi	= 0x20,
+	STRTOG_Inexact	= 0x30,
+	STRTOG_Underflow= 0x40,
+	STRTOG_Overflow	= 0x80
+	};
+
+ typedef struct
+FPI {
+	int nbits;
+	int emin;
+	int emax;
+	int rounding;
+	int sudden_underflow;
+	} FPI;
+
+enum {	/* FPI.rounding values: same as FLT_ROUNDS */
+	FPI_Round_zero = 0,
+	FPI_Round_near = 1,
+	FPI_Round_up = 2,
+	FPI_Round_down = 3
+	};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char* dtoa  ANSI((double d, int mode, int ndigits, int *decpt,
+			int *sign, char **rve));
+extern char* gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp,
+			int mode, int ndigits, int *decpt, char **rve));
+extern void freedtoa ANSI((char*));
+extern float  strtof ANSI((CONST char *, char **));
+extern double strtod ANSI((CONST char *, char **));
+extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
+
+extern char*	g_ddfmt  ANSI((char*, double*, int, unsigned));
+extern char*	g_dfmt   ANSI((char*, double*, int, unsigned));
+extern char*	g_ffmt   ANSI((char*, float*,  int, unsigned));
+extern char*	g_Qfmt   ANSI((char*, void*,   int, unsigned));
+extern char*	g_xfmt   ANSI((char*, void*,   int, unsigned));
+extern char*	g_xLfmt  ANSI((char*, void*,   int, unsigned));
+
+extern int	strtoId  ANSI((CONST char*, char**, double*, double*));
+extern int	strtoIdd ANSI((CONST char*, char**, double*, double*));
+extern int	strtoIf  ANSI((CONST char*, char**, float*, float*));
+extern int	strtoIQ  ANSI((CONST char*, char**, void*, void*));
+extern int	strtoIx  ANSI((CONST char*, char**, void*, void*));
+extern int	strtoIxL ANSI((CONST char*, char**, void*, void*));
+extern int	strtord  ANSI((CONST char*, char**, int, double*));
+extern int	strtordd ANSI((CONST char*, char**, int, double*));
+extern int	strtorf  ANSI((CONST char*, char**, int, float*));
+extern int	strtorQ  ANSI((CONST char*, char**, int, void*));
+extern int	strtorx  ANSI((CONST char*, char**, int, void*));
+extern int	strtorxL ANSI((CONST char*, char**, int, void*));
+#if 1
+extern int	strtodI  ANSI((CONST char*, char**, double*));
+extern int	strtopd  ANSI((CONST char*, char**, double*));
+extern int	strtopdd ANSI((CONST char*, char**, double*));
+extern int	strtopf  ANSI((CONST char*, char**, float*));
+extern int	strtopQ  ANSI((CONST char*, char**, void*));
+extern int	strtopx  ANSI((CONST char*, char**, void*));
+extern int	strtopxL ANSI((CONST char*, char**, void*));
+#else
+#define strtopd(s,se,x) strtord(s,se,1,x)
+#define strtopdd(s,se,x) strtordd(s,se,1,x)
+#define strtopf(s,se,x) strtorf(s,se,1,x)
+#define strtopQ(s,se,x) strtorQ(s,se,1,x)
+#define strtopx(s,se,x) strtorx(s,se,1,x)
+#define strtopxL(s,se,x) strtorxL(s,se,1,x)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* GDTOA_H_INCLUDED */
Index: /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/gdtoa.smak	(revision 2448)
@@ -0,0 +1,16 @@
+libc.TSRC += $(filter-out %arithchk.c,$(wildcard src/fbsdlibc/gdtoa/*.c)) \
+	$(addprefix src/fbsdlibc/gdtoa/glue/, machdep_ldisx.c _hdtoa.c _ldtoa.c glue.c)
+libc.TDEP +=
+
+# make everything depend on arith.h.
+$(filter-out %arithchk.c,$(wildcard src/fbsdlibc/gdtoa/*.c)): $.arith.h
+
+# generate arith.h.
+$.arith.h: $.arithchk.exe
+	$< > $@
+	
+# build arith.h generator.
+$.arithchk.exe: src/fbsdlibc/gdtoa/arithchk.c									
+	$(LD) $(CFLAGS:-Iinclude=) $(CFLAGS.dbg) $(LDFLAGS.dbg) $(LDFLAGS.aout) -o $@ $<
+
+include comend.smak
Index: /trunk/libc/src/fbsdlibc/gdtoa/gdtoaimp.h
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/gdtoaimp.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/gdtoaimp.h	(revision 2448)
@@ -0,0 +1,721 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* $FreeBSD: src/contrib/gdtoa/gdtoaimp.h,v 1.7 2005/01/18 18:56:18 das Exp $ */
+
+/* This is a variation on dtoa.c that converts arbitary binary
+   floating-point formats to and from decimal notation.  It uses
+   double-precision arithmetic internally, so there are still
+   various #ifdefs that adapt the calculations to the native
+   double-precision arithmetic (any of IEEE, VAX D_floating,
+   or IBM mainframe arithmetic).
+
+   Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* On a machine with IEEE extended-precision registers, it is
+ * necessary to specify double-precision (53-bit) rounding precision
+ * before invoking strtod or dtoa.  If the machine uses (the equivalent
+ * of) Intel 80x87 arithmetic, the call
+ *	_control87(PC_53, MCW_PC);
+ * does this with many compilers.  Whether this or another call is
+ * appropriate depends on the compiler; for this to work, it may be
+ * necessary to #include "float.h" or another system-dependent header
+ * file.
+ */
+
+/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE).  With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule.  Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *
+ *	1. We only require IEEE, IBM, or VAX double-precision
+ *		arithmetic (not IEEE double-extended).
+ *	2. We get by with floating-point arithmetic in a case that
+ *		Clinger missed -- when we're computing d * 10^n
+ *		for a small integer d and the integer n is not too
+ *		much larger than 22 (the maximum integer k for which
+ *		we can represent 10^k exactly), we may be able to
+ *		compute (d*10^k) * 10^(e-k) with just one roundoff.
+ *	3. Rather than a bit-at-a-time adjustment of the binary
+ *		result in the hard case, we use floating-point
+ *		arithmetic to determine the adjustment to within
+ *		one bit; only in really hard cases do we need to
+ *		compute a second residual.
+ *	4. Because of 3., we don't need a large table of powers of 10
+ *		for ten-to-e (just some small tables, e.g. of 10^k
+ *		for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_8087 for IEEE-arithmetic machines where the least
+ *	significant byte has the lowest address.
+ * #define IEEE_MC68k for IEEE-arithmetic machines where the most
+ *	significant byte has the lowest address.
+ * #define Long int on machines with 32-bit ints and 64-bit longs.
+ * #define Sudden_Underflow for IEEE-format machines without gradual
+ *	underflow (i.e., that flush to zero on underflow).
+ * #define IBM for IBM mainframe-style floating-point arithmetic.
+ * #define VAX for VAX-style floating-point arithmetic (D_floating).
+ * #define No_leftright to omit left-right logic in fast floating-point
+ *	computation of dtoa.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
+ * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
+ *	that use extended-precision instructions to compute rounded
+ *	products and quotients) with IBM.
+ * #define ROUND_BIASED for IEEE-format with biased rounding.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ *	products but inaccurate quotients, e.g., for Intel i860.
+ * #define NO_LONG_LONG on machines that do not have a "long long"
+ *	integer type (of >= 64 bits).  On such machines, you can
+ *	#define Just_16 to store 16 bits per 32-bit Long when doing
+ *	high-precision integer arithmetic.  Whether this speeds things
+ *	up or slows things down depends on the machine and the number
+ *	being converted.  If long long is available and the name is
+ *	something other than "long long", #define Llong to be the name,
+ *	and if "unsigned Llong" does not work as an unsigned version of
+ *	Llong, #define #ULLong to be the corresponding unsigned type.
+ * #define KR_headers for old-style C function headers.
+ * #define Bad_float_h if your system lacks a float.h or if it does not
+ *	define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
+ *	FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
+ * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
+ *	if memory is available and otherwise does something you deem
+ *	appropriate.  If MALLOC is undefined, malloc will be invoked
+ *	directly -- and assumed always to succeed.
+ * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
+ *	memory allocations from a private pool of memory when possible.
+ *	When used, the private pool is PRIVATE_MEM bytes long:  2304 bytes,
+ *	unless #defined to be a different length.  This default length
+ *	suffices to get rid of MALLOC calls except for unusual cases,
+ *	such as decimal-to-binary conversion of a very long string of
+ *	digits.  When converting IEEE double precision values, the
+ *	longest string gdtoa can return is about 751 bytes long.  For
+ *	conversions by strtod of strings of 800 digits and all gdtoa
+ *	conversions of IEEE doubles in single-threaded executions with
+ *	8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with
+ *	4-byte pointers, PRIVATE_MEM >= 7112 appears adequate.
+ * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
+ *	Infinity and NaN (case insensitively).  On some systems (e.g.,
+ *	some HP systems), it may be necessary to #define NAN_WORD0
+ *	appropriately -- to the most significant word of a quiet NaN.
+ *	(On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ *	When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
+ *	strtodg also accepts (case insensitively) strings of the form
+ *	NaN(x), where x is a string of hexadecimal digits and spaces;
+ *	if there is only one string of hexadecimal digits, it is taken
+ *	for the fraction bits of the resulting NaN; if there are two or
+ *	more strings of hexadecimal digits, each string is assigned
+ *	to the next available sequence of 32-bit words of fractions
+ *	bits (starting with the most significant), right-aligned in
+ *	each sequence.
+ * #define MULTIPLE_THREADS if the system offers preemptively scheduled
+ *	multiple threads.  In this case, you must provide (or suitably
+ *	#define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
+ *	by FREE_DTOA_LOCK(n) for n = 0 or 1.  (The second lock, accessed
+ *	in pow5mult, ensures lazy evaluation of only one copy of high
+ *	powers of 5; omitting this lock would introduce a small
+ *	probability of wasting memory, but would otherwise be harmless.)
+ *	You must also invoke freedtoa(s) to free the value s returned by
+ *	dtoa.  You may do so whether or not MULTIPLE_THREADS is #defined.
+ * #define IMPRECISE_INEXACT if you do not care about the setting of
+ *	the STRTOG_Inexact bits in the special case of doing IEEE double
+ *	precision conversions (which could also be done by the strtog in
+ *	dtoa.c).
+ * #define NO_HEX_FP to disable recognition of C9x's hexadecimal
+ *	floating-point constants.
+ * #define -DNO_ERRNO to suppress setting errno (in strtod.c and
+ *	strtodg.c).
+ * #define NO_STRING_H to use private versions of memcpy.
+ *	On some K&R systems, it may also be necessary to
+ *	#define DECLARE_SIZE_T in this case.
+ * #define YES_ALIAS to permit aliasing certain double values with
+ *	arrays of ULongs.  This leads to slightly better code with
+ *	some compilers and was always used prior to 19990916, but it
+ *	is not strictly legal and can cause trouble with aggressively
+ *	optimizing compilers (e.g., gcc 2.95.1 under -O2).
+ * #define USE_LOCALE to use the current locale's decimal_point value.
+ */
+
+#ifndef GDTOAIMP_H_INCLUDED
+#define GDTOAIMP_H_INCLUDED
+#ifdef __EMX__
+#include "namespace.h"
+#endif
+#include "gdtoa.h"
+
+#ifdef DEBUG
+#include "stdio.h"
+#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
+#endif
+
+#include "limits.h"
+#include "stdlib.h"
+#include "string.h"
+#include "libc_private.h"
+
+#include "namespace.h"
+#ifdef __EMX__
+#include <386/builtin.h>
+#include <sys/fmutex.h>
+#else /* !__EMX__ */
+#include <pthread.h>
+#endif /* !__EMX__ */
+#include "un-namespace.h"
+
+#ifdef KR_headers
+#define Char char
+#else
+#define Char void
+#endif
+
+#ifdef MALLOC
+extern Char *MALLOC ANSI((size_t));
+#else
+#define MALLOC malloc
+#endif
+
+#define INFNAN_CHECK
+#define USE_LOCALE
+#define Honor_FLT_ROUNDS
+
+#undef IEEE_Arith
+#undef Avoid_Underflow
+#ifdef IEEE_MC68k
+#define IEEE_Arith
+#endif
+#ifdef IEEE_8087
+#define IEEE_Arith
+#endif
+
+#include "errno.h"
+#ifdef Bad_float_h
+
+#ifdef IEEE_Arith
+#define DBL_DIG 15
+#define DBL_MAX_10_EXP 308
+#define DBL_MAX_EXP 1024
+#define FLT_RADIX 2
+#define DBL_MAX 1.7976931348623157e+308
+#endif
+
+#ifdef IBM
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 75
+#define DBL_MAX_EXP 63
+#define FLT_RADIX 16
+#define DBL_MAX 7.2370055773322621e+75
+#endif
+
+#ifdef VAX
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 38
+#define DBL_MAX_EXP 127
+#define FLT_RADIX 2
+#define DBL_MAX 1.7014118346046923e+38
+#define n_bigtens 2
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647
+#endif
+
+#else /* ifndef Bad_float_h */
+#include "float.h"
+#endif /* Bad_float_h */
+
+#ifdef IEEE_Arith
+#define Scale_Bit 0x10
+#define n_bigtens 5
+#endif
+
+#ifdef IBM
+#define n_bigtens 3
+#endif
+
+#ifdef VAX
+#define n_bigtens 2
+#endif
+
+#ifndef __MATH_H__
+#include "math.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
+Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
+#endif
+
+typedef union { double d; ULong L[2]; } U;
+
+#ifdef YES_ALIAS
+#define dval(x) x
+#ifdef IEEE_8087
+#define word0(x) ((ULong *)&x)[1]
+#define word1(x) ((ULong *)&x)[0]
+#else
+#define word0(x) ((ULong *)&x)[0]
+#define word1(x) ((ULong *)&x)[1]
+#endif
+#else /* !YES_ALIAS */
+#ifdef IEEE_8087
+#define word0(x) ((U*)&x)->L[1]
+#define word1(x) ((U*)&x)->L[0]
+#else
+#define word0(x) ((U*)&x)->L[0]
+#define word1(x) ((U*)&x)->L[1]
+#endif
+#define dval(x) ((U*)&x)->d
+#endif /* YES_ALIAS */
+
+/* The following definition of Storeinc is appropriate for MIPS processors.
+ * An alternative that might be better on some machines is
+ * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ */
+#if defined(IEEE_8087) + defined(VAX)
+#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
+((unsigned short *)a)[0] = (unsigned short)c, a++)
+#else
+#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
+((unsigned short *)a)[1] = (unsigned short)c, a++)
+#endif
+
+/* #define P DBL_MANT_DIG */
+/* Ten_pmax = floor(P*log(2)/log(5)) */
+/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
+/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
+/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
+
+#ifdef IEEE_Arith
+#define Exp_shift  20
+#define Exp_shift1 20
+#define Exp_msk1    0x100000
+#define Exp_msk11   0x100000
+#define Exp_mask  0x7ff00000
+#define P 53
+#define Bias 1023
+#define Emin (-1022)
+#define Exp_1  0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask  0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask  0xfffff
+#define Bndry_mask1 0xfffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+
+#ifndef Flt_Rounds
+#ifdef FLT_ROUNDS
+#define Flt_Rounds FLT_ROUNDS
+#else
+#define Flt_Rounds 1
+#endif
+#endif /*Flt_Rounds*/
+
+#else /* ifndef IEEE_Arith */
+#undef  Sudden_Underflow
+#define Sudden_Underflow
+#ifdef IBM
+#undef Flt_Rounds
+#define Flt_Rounds 0
+#define Exp_shift  24
+#define Exp_shift1 24
+#define Exp_msk1   0x1000000
+#define Exp_msk11  0x1000000
+#define Exp_mask  0x7f000000
+#define P 14
+#define Bias 65
+#define Exp_1  0x41000000
+#define Exp_11 0x41000000
+#define Ebits 8	/* exponent has 7 bits, but 8 is the right value in b2d */
+#define Frac_mask  0xffffff
+#define Frac_mask1 0xffffff
+#define Bletch 4
+#define Ten_pmax 22
+#define Bndry_mask  0xefffff
+#define Bndry_mask1 0xffffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 4
+#define Tiny0 0x100000
+#define Tiny1 0
+#define Quick_max 14
+#define Int_max 15
+#else /* VAX */
+#undef Flt_Rounds
+#define Flt_Rounds 1
+#define Exp_shift  23
+#define Exp_shift1 7
+#define Exp_msk1    0x80
+#define Exp_msk11   0x800000
+#define Exp_mask  0x7f80
+#define P 56
+#define Bias 129
+#define Exp_1  0x40800000
+#define Exp_11 0x4080
+#define Ebits 8
+#define Frac_mask  0x7fffff
+#define Frac_mask1 0xffff007f
+#define Ten_pmax 24
+#define Bletch 2
+#define Bndry_mask  0xffff007f
+#define Bndry_mask1 0xffff007f
+#define LSB 0x10000
+#define Sign_bit 0x8000
+#define Log2P 1
+#define Tiny0 0x80
+#define Tiny1 0
+#define Quick_max 15
+#define Int_max 15
+#endif /* IBM, VAX */
+#endif /* IEEE_Arith */
+
+#ifndef IEEE_Arith
+#define ROUND_BIASED
+#endif
+
+#ifdef RND_PRODQUOT
+#define rounded_product(a,b) a = rnd_prod(a, b)
+#define rounded_quotient(a,b) a = rnd_quot(a, b)
+#ifdef KR_headers
+extern double rnd_prod(), rnd_quot();
+#else
+extern double rnd_prod(double, double), rnd_quot(double, double);
+#endif
+#else
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+#endif
+
+#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
+#define Big1 0xffffffff
+
+#undef  Pack_16
+#ifndef Pack_32
+#define Pack_32
+#endif
+
+#ifdef NO_LONG_LONG
+#undef ULLong
+#ifdef Just_16
+#undef Pack_32
+#define Pack_16
+/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower.  Hence the default is now to store 32 bits per Long.
+ */
+#endif
+#else	/* long long available */
+#ifndef Llong
+#define Llong long long
+#endif
+#ifndef ULLong
+#define ULLong unsigned Llong
+#endif
+#endif /* NO_LONG_LONG */
+
+#ifdef Pack_32
+#define ULbits 32
+#define kshift 5
+#define kmask 31
+#define ALL_ON 0xffffffff
+#else
+#define ULbits 16
+#define kshift 4
+#define kmask 15
+#define ALL_ON 0xffff
+#endif
+
+#define MULTIPLE_THREADS
+#ifdef __EMX__
+extern _fmutex __libc_gdtoa_locks[2];
+#define ACQUIRE_DTOA_LOCK(n)	do {				\
+    if (__libc_gdtoa_locks[n].fs == _FMS_UNINIT)                     \
+        _fmutex_checked_create2(&__libc_gdtoa_locks[n], 0, "gdtoa lock no." #n); \
+    _fmutex_checked_request(&__libc_gdtoa_locks[n], 0);              \
+} while(0)
+#define FREE_DTOA_LOCK(n)	do {				\
+    _fmutex_checked_release(&__libc_gdtoa_locks[n]);                 \
+} while(0)
+#else /* !__EMX__ */
+extern pthread_mutex_t __gdtoa_locks[2];
+#define ACQUIRE_DTOA_LOCK(n)	do {				\
+	if (__isthreaded)					\
+		_pthread_mutex_lock(&__gdtoa_locks[n]);		\
+} while(0)
+#define FREE_DTOA_LOCK(n)	do {				\
+	if (__isthreaded)					\
+		_pthread_mutex_unlock(&__gdtoa_locks[n]);	\
+} while(0)
+#endif /* !__EMX__ */
+
+#define Kmax 15
+
+ struct
+Bigint {
+	struct Bigint *next;
+	int k, maxwds, sign, wds;
+	ULong x[1];
+	};
+
+ typedef struct Bigint Bigint;
+
+#ifdef NO_STRING_H
+#ifdef DECLARE_SIZE_T
+typedef unsigned int size_t;
+#endif
+extern void memcpy_D2A ANSI((void*, const void*, size_t));
+#define Bcopy(x,y) memcpy_D2A(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
+#else /* !NO_STRING_H */
+#define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
+#endif /* NO_STRING_H */
+
+/*
+ * Paranoia: Protect exported symbols, including ones in files we don't
+ * compile right now.  The standard strtof and strtod survive.
+ */
+#define	dtoa		__dtoa
+#define	gdtoa		__gdtoa
+#define	freedtoa	__freedtoa
+#define	strtodg		__strtodg
+#define	g_ddfmt		__g_ddfmt
+#define	g_dfmt		__g_dfmt
+#define	g_ffmt		__g_ffmt
+#define	g_Qfmt		__g_Qfmt
+#define	g_xfmt		__g_xfmt
+#define	g_xLfmt		__g_xLfmt
+#define	strtoId		__strtoId
+#define	strtoIdd	__strtoIdd
+#define	strtoIf		__strtoIf
+#define	strtoIQ		__strtoIQ
+#define	strtoIx		__strtoIx
+#define	strtoIxL	__strtoIxL
+#define	strtord		__strtord
+#define	strtordd	__strtordd
+#define	strtorf		__strtorf
+#define	strtorQ		__strtorQ
+#define	strtorx		__strtorx
+#define	strtorxL	__strtorxL
+#define	strtodI		__strtodI
+#define	strtopd		__strtopd
+#define	strtopdd	__strtopdd
+#define	strtopf		__strtopf
+#define	strtopQ		__strtopQ
+#define	strtopx		__strtopx
+#define	strtopxL	__strtopxL
+
+/* Protect gdtoa-internal symbols */
+#define	Balloc		__Balloc_D2A
+#define	Bfree		__Bfree_D2A
+#define	ULtoQ		__ULtoQ_D2A
+#define	ULtof		__ULtof_D2A
+#define	ULtod		__ULtod_D2A
+#define	ULtodd		__ULtodd_D2A
+#define	ULtox		__ULtox_D2A
+#define	ULtoxL		__ULtoxL_D2A
+#define	any_on		__any_on_D2A
+#define	b2d		__b2d_D2A
+#define	bigtens		__bigtens_D2A
+#define	cmp		__cmp_D2A
+#define	copybits	__copybits_D2A
+#define	d2b		__d2b_D2A
+#define	decrement	__decrement_D2A
+#define	diff		__diff_D2A
+#define	dtoa_result	__dtoa_result_D2A
+#define	g__fmt		__g__fmt_D2A
+#define	gethex		__gethex_D2A
+#define	hexdig		__hexdig_D2A
+#define	hexdig_init_D2A	__hexdig_init_D2A
+#define	hexnan		__hexnan_D2A
+#define	hi0bits		__hi0bits_D2A
+#define	i2b		__i2b_D2A
+#define	increment	__increment_D2A
+#define	lo0bits		__lo0bits_D2A
+#define	lshift		__lshift_D2A
+#define	match		__match_D2A
+#define	mult		__mult_D2A
+#define	multadd		__multadd_D2A
+#define	nrv_alloc	__nrv_alloc_D2A
+#define	pow5mult	__pow5mult_D2A
+#define	quorem		__quorem_D2A
+#define	ratio		__ratio_D2A
+#define	rshift		__rshift_D2A
+#define	rv_alloc	__rv_alloc_D2A
+#define	s2b		__s2b_D2A
+#define	set_ones	__set_ones_D2A
+#define	strcp		__strcp_D2A
+#define	strcp_D2A      	__strcp_D2A
+#define	strtoIg		__strtoIg_D2A
+#define	sum		__sum_D2A
+#define	tens		__tens_D2A
+#define	tinytens	__tinytens_D2A
+#define	tinytens	__tinytens_D2A
+#define	trailz		__trailz_D2A
+#define	ulp		__ulp_D2A
+
+ extern char *dtoa_result;
+ extern CONST double bigtens[], tens[], tinytens[];
+ extern unsigned char hexdig[];
+
+ extern Bigint *Balloc ANSI((int));
+ extern void Bfree ANSI((Bigint*));
+ extern void ULtof ANSI((ULong*, ULong*, Long, int));
+ extern void ULtod ANSI((ULong*, ULong*, Long, int));
+ extern void ULtodd ANSI((ULong*, ULong*, Long, int));
+ extern void ULtoQ ANSI((ULong*, ULong*, Long, int));
+ extern void ULtox ANSI((UShort*, ULong*, Long, int));
+ extern void ULtoxL ANSI((ULong*, ULong*, Long, int));
+ extern ULong any_on ANSI((Bigint*, int));
+ extern double b2d ANSI((Bigint*, int*));
+ extern int cmp ANSI((Bigint*, Bigint*));
+ extern void copybits ANSI((ULong*, int, Bigint*));
+ extern Bigint *d2b ANSI((double, int*, int*));
+ extern int decrement ANSI((Bigint*));
+ extern Bigint *diff ANSI((Bigint*, Bigint*));
+ extern char *dtoa ANSI((double d, int mode, int ndigits,
+			int *decpt, int *sign, char **rve));
+ extern void freedtoa ANSI((char*));
+ extern char *gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp,
+			  int mode, int ndigits, int *decpt, char **rve));
+ extern char *g__fmt ANSI((char*, char*, char*, int, ULong));
+ extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
+ extern void hexdig_init_D2A(Void);
+ extern int hexnan ANSI((CONST char**, FPI*, ULong*));
+ extern int hi0bits ANSI((ULong));
+ extern Bigint *i2b ANSI((int));
+ extern Bigint *increment ANSI((Bigint*));
+ extern int lo0bits ANSI((ULong*));
+ extern Bigint *lshift ANSI((Bigint*, int));
+ extern int match ANSI((CONST char**, char*));
+ extern Bigint *mult ANSI((Bigint*, Bigint*));
+ extern Bigint *multadd ANSI((Bigint*, int, int));
+ extern char *nrv_alloc ANSI((char*, char **, int));
+ extern Bigint *pow5mult ANSI((Bigint*, int));
+ extern int quorem ANSI((Bigint*, Bigint*));
+ extern double ratio ANSI((Bigint*, Bigint*));
+ extern void rshift ANSI((Bigint*, int));
+ extern char *rv_alloc ANSI((int));
+ extern Bigint *s2b ANSI((CONST char*, int, int, ULong));
+ extern Bigint *set_ones ANSI((Bigint*, int));
+ extern char *strcp ANSI((char*, const char*));
+ extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
+
+#ifdef __EMX__
+ extern char*	g_ddfmt  ANSI((char*, double*, int, unsigned));
+ extern char*	g_dfmt   ANSI((char*, double*, int, unsigned));
+ extern char*	g_ffmt   ANSI((char*, float*,  int, unsigned));
+ extern char*	g_Qfmt   ANSI((char*, void*,   int, unsigned));
+ extern char*	g_xfmt   ANSI((char*, void*,   int, unsigned));
+ extern char*	g_xLfmt  ANSI((char*, void*,   int, unsigned));
+#endif /* __EMX__ */
+
+ extern int strtoId ANSI((CONST char *, char **, double *, double *));
+ extern int strtoIdd ANSI((CONST char *, char **, double *, double *));
+ extern int strtoIf ANSI((CONST char *, char **, float *, float *));
+ extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
+ extern int strtoIQ ANSI((CONST char *, char **, void *, void *));
+ extern int strtoIx ANSI((CONST char *, char **, void *, void *));
+ extern int strtoIxL ANSI((CONST char *, char **, void *, void *));
+ extern double strtod ANSI((const char *s00, char **se));
+ extern int strtopQ ANSI((CONST char *, char **, Void *));
+ extern int strtopf ANSI((CONST char *, char **, float *));
+ extern int strtopd ANSI((CONST char *, char **, double *));
+ extern int strtopdd ANSI((CONST char *, char **, double *));
+ extern int strtopx ANSI((CONST char *, char **, Void *));
+ extern int strtopxL ANSI((CONST char *, char **, Void *));
+ extern int strtord ANSI((CONST char *, char **, int, double *));
+ extern int strtordd ANSI((CONST char *, char **, int, double *));
+ extern int strtorf ANSI((CONST char *, char **, int, float *));
+ extern int strtorQ ANSI((CONST char *, char **, int, void *));
+ extern int strtorx ANSI((CONST char *, char **, int, void *));
+ extern int strtorxL ANSI((CONST char *, char **, int, void *));
+ extern Bigint *sum ANSI((Bigint*, Bigint*));
+ extern int trailz ANSI((Bigint*));
+ extern double ulp ANSI((double));
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef IEEE_Arith
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#else
+#define _0 1
+#define _1 0
+#endif
+#else
+#undef INFNAN_CHECK
+#endif
+
+#ifdef INFNAN_CHECK
+
+#ifndef NAN_WORD0
+#define NAN_WORD0 0x7ff80000
+#endif
+
+#ifndef NAN_WORD1
+#define NAN_WORD1 0
+#endif
+#endif	/* INFNAN_CHECK */
+
+#undef SI
+#ifdef Sudden_Underflow
+#define SI 1
+#else
+#define SI 0
+#endif
+
+#endif /* GDTOAIMP_H_INCLUDED */
Index: /trunk/libc/src/fbsdlibc/gdtoa/gethex.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/gethex.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/gethex.c	(revision 2448)
@@ -0,0 +1,249 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	dmg@acm.org
+ */
+
+#include "gdtoaimp.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+ int
+#ifdef KR_headers
+gethex(sp, fpi, exp, bp, sign)
+	CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign;
+#else
+gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
+#endif
+{
+	Bigint *b;
+	CONST unsigned char *decpt, *s0, *s, *s1;
+	int esign, havedig, irv, k, n, nbits, up;
+	ULong L, lostbits, *x;
+	Long e, e1;
+#ifdef USE_LOCALE
+	unsigned char decimalpoint = *localeconv()->decimal_point;
+#else
+#define decimalpoint '.'
+#endif
+
+	if (!hexdig['0'])
+		hexdig_init_D2A();
+	havedig = 0;
+	s0 = *(CONST unsigned char **)sp + 2;
+	while(s0[havedig] == '0')
+		havedig++;
+	s0 += havedig;
+	s = s0;
+	decpt = 0;
+	if (!hexdig[*s]) {
+		if (*s == decimalpoint) {
+			decpt = ++s;
+			if (!hexdig[*s])
+				goto ret0;
+			}
+		else {
+ ret0:
+			*sp = (char*)s;
+			return havedig ? STRTOG_Zero : STRTOG_NoNumber;
+			}
+		while(*s == '0')
+			s++;
+		havedig = 1;
+		if (!hexdig[*s])
+			goto ret0;
+		s0 = s;
+		}
+	while(hexdig[*s])
+		s++;
+	if (*s == decimalpoint && !decpt) {
+		decpt = ++s;
+		while(hexdig[*s])
+			s++;
+		}
+	e = 0;
+	if (decpt)
+		e = -(((Long)(s-decpt)) << 2);
+	s1 = s;
+	switch(*s) {
+	  case 'p':
+	  case 'P':
+		esign = 0;
+		switch(*++s) {
+		  case '-':
+			esign = 1;
+			/* no break */
+		  case '+':
+			s++;
+		  }
+		if ((n = hexdig[*s]) == 0 || n > 0x19) {
+			s = s1;
+			break;
+			}
+		e1 = n - 0x10;
+		while((n = hexdig[*++s]) !=0 && n <= 0x19)
+			e1 = 10*e1 + n - 0x10;
+		if (esign)
+			e1 = -e1;
+		e += e1;
+	  }
+	*sp = (char*)s;
+	n = s1 - s0 - 1;
+	for(k = 0; n > 7; n >>= 1)
+		k++;
+	b = Balloc(k);
+	x = b->x;
+	n = 0;
+	L = 0;
+	while(s1 > s0) {
+		if (*--s1 == decimalpoint)
+			continue;
+		if (n == 32) {
+			*x++ = L;
+			L = 0;
+			n = 0;
+			}
+		L |= (hexdig[*s1] & 0x0f) << n;
+		n += 4;
+		}
+	*x++ = L;
+	b->wds = n = x - b->x;
+	n = 32*n - hi0bits(L);
+	nbits = fpi->nbits;
+	lostbits = 0;
+	x = b->x;
+	if (n > nbits) {
+		n -= nbits;
+		if (any_on(b,n)) {
+			lostbits = 1;
+			k = n - 1;
+			if (x[k>>kshift] & 1 << (k & kmask)) {
+				lostbits = 2;
+				if (k > 1 && any_on(b,k-1))
+					lostbits = 3;
+				}
+			}
+		rshift(b, n);
+		e += n;
+		}
+	else if (n < nbits) {
+		n = nbits - n;
+		b = lshift(b, n);
+		e -= n;
+		x = b->x;
+		}
+	if (e > fpi->emax) {
+ ovfl:
+		Bfree(b);
+		*bp = 0;
+		return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
+		}
+	irv = STRTOG_Normal;
+	if (e < fpi->emin) {
+		irv = STRTOG_Denormal;
+		n = fpi->emin - e;
+		if (n >= nbits) {
+			switch (fpi->rounding) {
+			  case FPI_Round_near:
+				if (n == nbits && (n < 2 || any_on(b,n-1)))
+					goto one_bit;
+				break;
+			  case FPI_Round_up:
+				if (!sign)
+					goto one_bit;
+				break;
+			  case FPI_Round_down:
+				if (sign) {
+ one_bit:
+					*exp = fpi->emin;
+					x[0] = b->wds = 1;
+					*bp = b;
+					return STRTOG_Denormal | STRTOG_Inexhi
+						| STRTOG_Underflow;
+					}
+			  }
+			Bfree(b);
+			*bp = 0;
+			return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
+			}
+		k = n - 1;
+		if (lostbits)
+			lostbits = 1;
+		else if (k > 0)
+			lostbits = any_on(b,k);
+		if (x[k>>kshift] & 1 << (k & kmask))
+			lostbits |= 2;
+		nbits -= n;
+		rshift(b,n);
+		e = fpi->emin;
+		}
+	if (lostbits) {
+		up = 0;
+		switch(fpi->rounding) {
+		  case FPI_Round_zero:
+			break;
+		  case FPI_Round_near:
+			if (lostbits & 2
+			 && (lostbits & 1) | x[0] & 1)
+				up = 1;
+			break;
+		  case FPI_Round_up:
+			up = 1 - sign;
+			break;
+		  case FPI_Round_down:
+			up = sign;
+		  }
+		if (up) {
+			k = b->wds;
+			b = increment(b);
+			x = b->x;
+			if (irv == STRTOG_Denormal) {
+				if (nbits == fpi->nbits - 1
+				 && x[nbits >> kshift] & 1 << (nbits & kmask))
+					irv =  STRTOG_Normal;
+				}
+			else if (b->wds > k
+			 || (n = nbits & kmask) !=0
+			     && hi0bits(x[k-1]) < 32-n) {
+				rshift(b,1);
+				if (++e > fpi->emax)
+					goto ovfl;
+				}
+			irv |= STRTOG_Inexhi;
+			}
+		else
+			irv |= STRTOG_Inexlo;
+		}
+	*bp = b;
+	*exp = e;
+	return irv;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/glue/Makefile.inc
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/glue/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/glue/Makefile.inc	(revision 2448)
@@ -0,0 +1,21 @@
+# $FreeBSD: src/lib/libc/gdtoa/Makefile.inc,v 1.6 2004/01/18 10:32:49 das Exp $
+
+# netlib gdtoa sources
+.PATH: ${.CURDIR}/gdtoa
+
+MISRCS+=_hdtoa.c _ldtoa.c glue.c
+GDTOASRCS=dmisc.c dtoa.c gdtoa.c gethex.c gmisc.c \
+	hd_init.c hexnan.c misc.c smisc.c \
+	strtoIg.c strtod.c strtodg.c strtof.c strtord.c sum.c ulp.c
+.if exists(${.CURDIR}/${MACHINE_ARCH}/stdlib/gdtoa.mk)
+.include "${.CURDIR}/${MACHINE_ARCH}/stdlib/gdtoa.mk"
+.endif
+
+CFLAGS+=-I${.CURDIR}/../../contrib/gdtoa
+
+.for src in ${GDTOASRCS}
+MISRCS+=gdtoa_${src}
+CLEANFILES+=gdtoa_${src}
+gdtoa_${src}:
+	ln -sf ${.CURDIR}/../../contrib/gdtoa/${src} ${.TARGET}
+.endfor
Index: /trunk/libc/src/fbsdlibc/gdtoa/glue/_hdtoa.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/glue/_hdtoa.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/glue/_hdtoa.c	(revision 2448)
@@ -0,0 +1,439 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gdtoa/_hdtoa.c,v 1.2 2004/01/21 04:51:50 grehan Exp $");
+
+#ifdef __EMX__
+#include "namespace.h"
+#endif
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include "fpmath.h"
+#ifdef __EMX__
+#include "../gdtoaimp.h"
+#else
+#include "gdtoaimp.h"
+#endif
+
+/* Strings values used by dtoa() */
+#define	INFSTR	"Infinity"
+#define	NANSTR	"NaN"
+
+#define	DBL_BIAS	(DBL_MAX_EXP - 1)
+#define	LDBL_BIAS	(LDBL_MAX_EXP - 1)
+
+#ifdef	LDBL_IMPLICIT_NBIT
+#define	LDBL_NBIT_ADJ	0
+#else
+#define	LDBL_NBIT_ADJ	1
+#endif
+
+/*
+ * Efficiently compute the log2 of an integer.  Uses a combination of
+ * arcane tricks found in fortune and arcane tricks not (yet) in
+ * fortune.  This routine behaves similarly to fls(9).
+ */
+static int
+log2_32(uint32_t n)
+{
+
+        n |= (n >> 1);
+        n |= (n >> 2);
+        n |= (n >> 4);
+        n |= (n >> 8);
+        n |= (n >> 16);
+
+	n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
+	n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
+	n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
+	n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
+	n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
+	return (n - 1);
+}
+
+#if (LDBL_MANH_SIZE > 32 || LDBL_MANL_SIZE > 32)
+
+static int
+log2_64(uint64_t n)
+{
+
+	if (n >> 32 != 0)
+		return (log2_32((uint32_t)(n >> 32)) + 32);
+	else
+		return (log2_32((uint32_t)n));
+}
+
+#endif	/* (LDBL_MANH_SIZE > 32 || LDBL_MANL_SIZE > 32) */
+
+/*
+ * Round up the given digit string.  If the digit string is fff...f,
+ * this procedure sets it to 100...0 and returns 1 to indicate that
+ * the exponent needs to be bumped.  Otherwise, 0 is returned.
+ */
+static int
+roundup(char *s0, int ndigits)
+{
+	char *s;
+
+	for (s = s0 + ndigits - 1; *s == 0xf; s--) {
+		if (s == s0) {
+			*s = 1;
+			return (1);
+		}
+		++*s;
+	}
+	++*s;
+	return (0);
+}
+
+/*
+ * Round the given digit string to ndigits digits according to the
+ * current rounding mode.  Note that this could produce a string whose
+ * value is not representable in the corresponding floating-point
+ * type.  The exponent pointed to by decpt is adjusted if necessary.
+ */
+static void
+dorounding(char *s0, int ndigits, int sign, int *decpt)
+{
+	int adjust = 0;	/* do we need to adjust the exponent? */
+
+	switch (FLT_ROUNDS) {
+	case 0:		/* toward zero */
+	default:	/* implementation-defined */
+		break;
+	case 1:		/* to nearest, halfway rounds to even */
+		if ((s0[ndigits] > 8) ||
+		    (s0[ndigits] == 8 && s0[ndigits - 1] & 1))
+			adjust = roundup(s0, ndigits);
+		break;
+	case 2:		/* toward +inf */
+		if (sign == 0)
+			adjust = roundup(s0, ndigits);
+		break;
+	case 3:		/* toward -inf */
+		if (sign != 0)
+			adjust = roundup(s0, ndigits);
+		break;
+	}
+
+	if (adjust)
+		*decpt += 4;
+}
+
+/*
+ * This procedure converts a double-precision number in IEEE format
+ * into a string of hexadecimal digits and an exponent of 2.  Its
+ * behavior is bug-for-bug compatible with dtoa() in mode 2, with the
+ * following exceptions:
+ *
+ * - An ndigits < 0 causes it to use as many digits as necessary to
+ *   represent the number exactly.
+ * - The additional xdigs argument should point to either the string
+ *   "0123456789ABCDEF" or the string "0123456789abcdef", depending on
+ *   which case is desired.
+ * - This routine does not repeat dtoa's mistake of setting decpt
+ *   to 9999 in the case of an infinity or NaN.  INT_MAX is used
+ *   for this purpose instead.
+ *
+ * Note that the C99 standard does not specify what the leading digit
+ * should be for non-zero numbers.  For instance, 0x1.3p3 is the same
+ * as 0x2.6p2 is the same as 0x4.cp3.  This implementation chooses the
+ * first digit so that subsequent digits are aligned on nibble
+ * boundaries (before rounding).
+ *
+ * Inputs:	d, xdigs, ndigits
+ * Outputs:	decpt, sign, rve
+ */
+char *
+__hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
+    char **rve)
+{
+	union IEEEd2bits u;
+	char *s, *s0;
+	int bufsize;
+	int impnbit;	/* implicit normalization bit */
+	int pos;
+	int shift;	/* for subnormals, # of shifts required to normalize */
+	int sigfigs;	/* number of significant hex figures in result */
+
+	u.d = d;
+	*sign = u.bits.sign;
+
+	switch (fpclassify(d)) {
+	case FP_NORMAL:
+		sigfigs = (DBL_MANT_DIG + 3) / 4;
+		impnbit = 1 << ((DBL_MANT_DIG - 1) % 4);
+		*decpt = u.bits.exp - DBL_BIAS + 1 -
+		    ((DBL_MANT_DIG - 1) % 4);
+		break;
+	case FP_ZERO:
+		*decpt = 1;
+		return (nrv_alloc("0", rve, 1));
+	case FP_SUBNORMAL:
+		/*
+		 * The position of the highest-order bit tells us by
+		 * how much to adjust the exponent (decpt).  The
+		 * adjustment is raised to the next nibble boundary
+		 * since we will later choose the leftmost hexadecimal
+		 * digit so that all subsequent digits align on nibble
+		 * boundaries.
+		 */
+		if (u.bits.manh != 0) {
+			pos = log2_32(u.bits.manh);
+			shift = DBL_MANH_SIZE - pos;
+		} else {
+			pos = log2_32(u.bits.manl);
+			shift = DBL_MANH_SIZE + DBL_MANL_SIZE - pos;
+		}
+		sigfigs = (3 + DBL_MANT_DIG - shift) / 4;
+		impnbit = 0;
+		*decpt = DBL_MIN_EXP - ((shift + 3) & ~(4 - 1));
+		break;
+	case FP_INFINITE:
+		*decpt = INT_MAX;
+		return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
+	case FP_NAN:
+		*decpt = INT_MAX;
+		return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
+	default:
+		abort();
+	}
+
+	/* FP_NORMAL or FP_SUBNORMAL */
+
+	if (ndigits == 0)		/* dtoa() compatibility */
+		ndigits = 1;
+
+	/*
+	 * For simplicity, we generate all the digits even if the
+	 * caller has requested fewer.
+	 */
+	bufsize = (sigfigs > ndigits) ? sigfigs : ndigits;
+	s0 = rv_alloc(bufsize);
+
+	/*
+	 * We work from right to left, first adding any requested zero
+	 * padding, then the least significant portion of the
+	 * mantissa, followed by the most significant.  The buffer is
+	 * filled with the byte values 0x0 through 0xf, which are
+	 * converted to xdigs[0x0] through xdigs[0xf] after the
+	 * rounding phase.
+	 */
+	for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
+		*s = 0;
+	for (; s > s0 + sigfigs - (DBL_MANL_SIZE / 4) - 1 && s > s0; s--) {
+		*s = u.bits.manl & 0xf;
+		u.bits.manl >>= 4;
+	}
+	for (; s > s0; s--) {
+		*s = u.bits.manh & 0xf;
+		u.bits.manh >>= 4;
+	}
+
+	/*
+	 * At this point, we have snarfed all the bits in the
+	 * mantissa, with the possible exception of the highest-order
+	 * (partial) nibble, which is dealt with by the next
+	 * statement.  That nibble is usually in manh, but it could be
+	 * in manl instead for small subnormals.  We also tack on the
+	 * implicit normalization bit if appropriate.
+	 */
+	*s = u.bits.manh | u.bits.manl | impnbit;
+
+	/* If ndigits < 0, we are expected to auto-size the precision. */
+	if (ndigits < 0) {
+		for (ndigits = sigfigs; s0[ndigits - 1] == 0; ndigits--)
+			;
+	}
+
+	if (sigfigs > ndigits && s0[ndigits] != 0)
+		dorounding(s0, ndigits, u.bits.sign, decpt);
+
+	s = s0 + ndigits;
+	if (rve != NULL)
+		*rve = s;
+	*s-- = '\0';
+	for (; s >= s0; s--)
+		*s = xdigs[(unsigned int)*s];
+
+	return (s0);
+}
+
+#if (LDBL_MANT_DIG > DBL_MANT_DIG)
+
+/*
+ * This is the long double version of __hdtoa().
+ *
+ * On architectures that have an explicit integer bit, unnormals and
+ * pseudo-denormals cause problems in the conversion routine, so they
+ * are ``fixed'' by effectively toggling the integer bit.  Although
+ * this is not correct behavior, the hardware will not produce these
+ * formats externally.
+ */
+char *
+__hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
+    char **rve)
+{
+	union IEEEl2bits u;
+	char *s, *s0;
+	int bufsize;
+	int impnbit;	/* implicit normalization bit */
+	int pos;
+	int shift;	/* for subnormals, # of shifts required to normalize */
+	int sigfigs;	/* number of significant hex figures in result */
+
+	u.e = e;
+	*sign = u.bits.sign;
+
+	switch (fpclassify(e)) {
+	case FP_NORMAL:
+		sigfigs = (LDBL_MANT_DIG + 3) / 4;
+		impnbit = 1 << ((LDBL_MANT_DIG - 1) % 4);
+		*decpt = u.bits.exp - LDBL_BIAS + 1 -
+		    ((LDBL_MANT_DIG - 1) % 4);
+		break;
+	case FP_ZERO:
+		*decpt = 1;
+		return (nrv_alloc("0", rve, 1));
+	case FP_SUBNORMAL:
+		/*
+		 * The position of the highest-order bit tells us by
+		 * how much to adjust the exponent (decpt).  The
+		 * adjustment is raised to the next nibble boundary
+		 * since we will later choose the leftmost hexadecimal
+		 * digit so that all subsequent digits align on nibble
+		 * boundaries.
+		 */
+#ifdef	LDBL_IMPLICIT_NBIT
+		/* Don't trust the normalization bit to be off. */
+		u.bits.manh &= ~(~0ULL << (LDBL_MANH_SIZE - 1));
+#endif
+		if (u.bits.manh != 0) {
+#if LDBL_MANH_SIZE > 32
+			pos = log2_64(u.bits.manh);
+#else
+			pos = log2_32(u.bits.manh);
+#endif
+			shift = LDBL_MANH_SIZE - LDBL_NBIT_ADJ - pos;
+		} else {
+#if LDBL_MANL_SIZE > 32
+			pos = log2_64(u.bits.manl);
+#else
+			pos = log2_32(u.bits.manl);
+#endif
+			shift = LDBL_MANH_SIZE + LDBL_MANL_SIZE -
+			    LDBL_NBIT_ADJ - pos;
+		}
+		sigfigs = (3 + LDBL_MANT_DIG - LDBL_NBIT_ADJ - shift) / 4;
+		*decpt = LDBL_MIN_EXP + LDBL_NBIT_ADJ -
+		    ((shift + 3) & ~(4 - 1));
+		impnbit = 0;
+		break;
+	case FP_INFINITE:
+		*decpt = INT_MAX;
+		return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
+	case FP_NAN:
+		*decpt = INT_MAX;
+		return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
+	default:
+		abort();
+	}
+
+	/* FP_NORMAL or FP_SUBNORMAL */
+
+	if (ndigits == 0)		/* dtoa() compatibility */
+		ndigits = 1;
+
+	/*
+	 * For simplicity, we generate all the digits even if the
+	 * caller has requested fewer.
+	 */
+	bufsize = (sigfigs > ndigits) ? sigfigs : ndigits;
+	s0 = rv_alloc(bufsize);
+
+	/*
+	 * We work from right to left, first adding any requested zero
+	 * padding, then the least significant portion of the
+	 * mantissa, followed by the most significant.  The buffer is
+	 * filled with the byte values 0x0 through 0xf, which are
+	 * converted to xdigs[0x0] through xdigs[0xf] after the
+	 * rounding phase.
+	 */
+	for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
+		*s = 0;
+	for (; s > s0 + sigfigs - (LDBL_MANL_SIZE / 4) - 1 && s > s0; s--) {
+		*s = u.bits.manl & 0xf;
+		u.bits.manl >>= 4;
+	}
+	for (; s > s0; s--) {
+		*s = u.bits.manh & 0xf;
+		u.bits.manh >>= 4;
+	}
+
+	/*
+	 * At this point, we have snarfed all the bits in the
+	 * mantissa, with the possible exception of the highest-order
+	 * (partial) nibble, which is dealt with by the next
+	 * statement.  That nibble is usually in manh, but it could be
+	 * in manl instead for small subnormals.  We also tack on the
+	 * implicit normalization bit if appropriate.
+	 */
+	*s = u.bits.manh | u.bits.manl | impnbit;
+
+	/* If ndigits < 0, we are expected to auto-size the precision. */
+	if (ndigits < 0) {
+		for (ndigits = sigfigs; s0[ndigits - 1] == 0; ndigits--)
+			;
+	}
+
+	if (sigfigs > ndigits && s0[ndigits] != 0)
+		dorounding(s0, ndigits, u.bits.sign, decpt);
+
+	s = s0 + ndigits;
+	if (rve != NULL)
+		*rve = s;
+	*s-- = '\0';
+	for (; s >= s0; s--)
+		*s = xdigs[(unsigned int)*s];
+
+	return (s0);
+}
+
+#else	/* (LDBL_MANT_DIG == DBL_MANT_DIG) */
+
+char *
+__hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
+    char **rve)
+{
+
+	return (__hdtoa((double)e, xdigs, ndigits, decpt, sign, rve));
+}
+
+#endif	/* (LDBL_MANT_DIG == DBL_MANT_DIG) */
Index: /trunk/libc/src/fbsdlibc/gdtoa/glue/_ldtoa.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/glue/_ldtoa.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/glue/_ldtoa.c	(revision 2448)
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gdtoa/_ldtoa.c,v 1.2 2004/01/18 07:53:49 das Exp $");
+
+#ifdef __EMX__
+#include "namespace.h"
+#endif
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include "fpmath.h"
+#ifdef __EMX__
+#include "../gdtoaimp.h"
+#else
+#include "gdtoaimp.h"
+#endif
+
+/*
+ * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(),
+ * except that the floating point argument is passed by reference.
+ * When dtoa() is passed a NaN or infinity, it sets expt to 9999.
+ * However, a long double could have a valid exponent of 9999, so we
+ * use INT_MAX in ldtoa() instead.
+ */
+char *
+__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
+    char **rve)
+{
+	static FPI fpi = {
+		LDBL_MANT_DIG,			/* nbits */
+		LDBL_MIN_EXP - LDBL_MANT_DIG,	/* emin */
+		LDBL_MAX_EXP - LDBL_MANT_DIG,	/* emax */
+		FPI_Round_near,	       		/* rounding */
+#ifdef Sudden_Underflow	/* unused, but correct anyway */
+		1
+#else
+		0
+#endif
+	};
+	int be, kind;
+	char *ret;
+	union IEEEl2bits u;
+	uint32_t bits[(LDBL_MANT_DIG + 31) / 32];
+
+	u.e = *ld;
+	*sign = u.bits.sign;
+	be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1);
+	LDBL_TO_ARRAY32(u, bits);
+
+	switch (fpclassify(u.e)) {
+	case FP_NORMAL:
+		kind = STRTOG_Normal;
+#ifdef	LDBL_IMPLICIT_NBIT
+		bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32);
+#endif /* LDBL_IMPLICIT_NBIT */
+		break;
+	case FP_ZERO:
+		kind = STRTOG_Zero;
+		break;
+	case FP_SUBNORMAL:
+		kind = STRTOG_Denormal;
+#ifdef	LDBL_IMPLICIT_NBIT
+		be++;
+#endif
+		break;
+	case FP_INFINITE:
+		kind = STRTOG_Infinite;
+		break;
+	case FP_NAN:
+		kind = STRTOG_NaN;
+		break;
+	default:
+		abort();
+	}
+
+	ret = gdtoa(&fpi, be, (ULong *)bits, &kind, mode, ndigits, decpt, rve);
+	if (*decpt == -32768)
+		*decpt = INT_MAX;
+	return ret;
+}
Index: /trunk/libc/src/fbsdlibc/gdtoa/glue/glue.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/glue/glue.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/glue/glue.c	(revision 2448)
@@ -0,0 +1,22 @@
+/*
+ * Machine-independent glue to integrate David Gay's gdtoa
+ * package into libc.
+ *
+ * $FreeBSD: src/lib/libc/gdtoa/glue.c,v 1.2 2003/06/21 08:20:14 das Exp $
+ */
+
+#ifdef __EMX__
+
+#include <386/builtin.h>
+#include <sys/fmutex.h>
+_fmutex __libc_gdtoa_locks[2] = {0};
+
+#else
+
+#include <pthread.h>
+
+pthread_mutex_t __gdtoa_locks[] = {
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER
+};
+#endif
Index: /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisQ.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisQ.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisQ.c	(revision 2448)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Machine-dependent glue to integrate David Gay's gdtoa
+ * package into libc for architectures where a long double
+ * uses quad precision, such as sparc64.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gdtoa/machdep_ldisQ.c,v 1.2 2003/04/09 05:58:43 das Exp $");
+
+#ifdef __EMX__
+#include "../gdtoaimp.h"
+#else
+#include "gdtoaimp.h"
+#endif
+
+long double
+strtold(const char * __restrict s, char ** __restrict sp)
+{
+	long double result;
+
+	strtopQ(s, sp, &result);
+	return result;
+}
Index: /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisd.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisd.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisd.c	(revision 2448)
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Machine-dependent glue to integrate David Gay's gdtoa
+ * package into libc for architectures where a long double
+ * is the same as a double, such as the Alpha.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gdtoa/machdep_ldisd.c,v 1.1 2003/03/12 20:29:58 das Exp $");
+
+#ifdef __EMX__
+#include "../gdtoaimp.h"
+#else
+#include "gdtoaimp.h"
+#endif
+
+long double
+strtold(const char * __restrict s, char ** __restrict sp)
+{
+
+	return strtod(s, sp);
+}
Index: /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisx.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisx.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/glue/machdep_ldisx.c	(revision 2448)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Machine-dependent glue to integrate David Gay's gdtoa
+ * package into libc for architectures where a long double
+ * is an IEEE extended precision number.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gdtoa/machdep_ldisx.c,v 1.2 2003/04/09 05:58:43 das Exp $");
+
+#ifdef __EMX__
+#include "../gdtoaimp.h"
+#else
+#include "gdtoaimp.h"
+#endif
+
+long double
+_STD(strtold)(const char * __restrict s, char ** __restrict sp)
+{
+	long double result;
+
+	strtopx(s, sp, &result);
+	return result;
+}
Index: /trunk/libc/src/fbsdlibc/gdtoa/gmisc.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/gmisc.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/gmisc.c	(revision 2448)
@@ -0,0 +1,92 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ void
+#ifdef KR_headers
+rshift(b, k) Bigint *b; int k;
+#else
+rshift(Bigint *b, int k)
+#endif
+{
+	ULong *x, *x1, *xe, y;
+	int n;
+
+	x = x1 = b->x;
+	n = k >> kshift;
+	if (n < b->wds) {
+		xe = x + b->wds;
+		x += n;
+		if (k &= kmask) {
+			n = ULbits - k;
+			y = *x++ >> k;
+			while(x < xe) {
+				*x1++ = (y | (*x << n)) & ALL_ON;
+				y = *x++ >> k;
+				}
+			if ((*x1 = y) !=0)
+				x1++;
+			}
+		else
+			while(x < xe)
+				*x1++ = *x++;
+		}
+	if ((b->wds = x1 - b->x) == 0)
+		b->x[0] = 0;
+	}
+
+ int
+#ifdef KR_headers
+trailz(b) Bigint *b;
+#else
+trailz(Bigint *b)
+#endif
+{
+	ULong L, *x, *xe;
+	int n = 0;
+
+	x = b->x;
+	xe = x + b->wds;
+	for(n = 0; x < xe && !*x; x++)
+		n += ULbits;
+	if (x < xe) {
+		L = *x;
+		n += lo0bits(&L);
+		}
+	return n;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/hd_init.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/hd_init.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/hd_init.c	(revision 2448)
@@ -0,0 +1,61 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ unsigned char hexdig[256];
+
+ static void
+#ifdef KR_headers
+htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc;
+#else
+htinit(unsigned char *h, unsigned char *s, int inc)
+#endif
+{
+	int i, j;
+	for(i = 0; (j = s[i]) !=0; i++)
+		h[j] = i + inc;
+	}
+
+ void
+hexdig_init_D2A(Void)
+{
+#define USC (unsigned char *)
+	htinit(hexdig, USC "0123456789", 0x10);
+	htinit(hexdig, USC "abcdef", 0x10 + 10);
+	htinit(hexdig, USC "ABCDEF", 0x10 + 10);
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/hexnan.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/hexnan.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/hexnan.c	(revision 2448)
@@ -0,0 +1,137 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ static void
+#ifdef KR_headers
+L_shift(x, x1, i) ULong *x; ULong *x1; int i;
+#else
+L_shift(ULong *x, ULong *x1, int i)
+#endif
+{
+	int j;
+
+	i = 8 - i;
+	i <<= 2;
+	j = ULbits - i;
+	do {
+		*x |= x[1] << j;
+		x[1] >>= i;
+		} while(++x < x1);
+	}
+
+ int
+#ifdef KR_headers
+hexnan(sp, fpi, x0)
+	CONST char **sp; FPI *fpi; ULong *x0;
+#else
+hexnan( CONST char **sp, FPI *fpi, ULong *x0)
+#endif
+{
+	ULong c, h, *x, *x1, *xe;
+	CONST char *s;
+	int havedig, hd0, i, nbits;
+
+	if (!hexdig['0'])
+		hexdig_init_D2A();
+	nbits = fpi->nbits;
+	x = x0 + (nbits >> kshift);
+	if (nbits & kmask)
+		x++;
+	*--x = 0;
+	x1 = xe = x;
+	havedig = hd0 = i = 0;
+	s = *sp;
+	while(c = *(CONST unsigned char*)++s) {
+		if (!(h = hexdig[c])) {
+			if (c <= ' ') {
+				if (hd0 < havedig) {
+					if (x < x1 && i < 8)
+						L_shift(x, x1, i);
+					if (x <= x0) {
+						i = 8;
+						continue;
+						}
+					hd0 = havedig;
+					*--x = 0;
+					x1 = x;
+					i = 0;
+					}
+				continue;
+				}
+			if (/*(*/ c == ')' && havedig) {
+				*sp = s + 1;
+				break;
+				}
+			return STRTOG_NaN;
+			}
+		havedig++;
+		if (++i > 8) {
+			if (x <= x0)
+				continue;
+			i = 1;
+			*--x = 0;
+			}
+		*x = (*x << 4) | h & 0xf;
+		}
+	if (!havedig)
+		return STRTOG_NaN;
+	if (x < x1 && i < 8)
+		L_shift(x, x1, i);
+	if (x > x0) {
+		x1 = x0;
+		do *x1++ = *x++;
+			while(x <= xe);
+		do *x1++ = 0;
+			while(x1 <= xe);
+		}
+	else {
+		/* truncate high-order word if necessary */
+		if ( (i = nbits & (ULbits-1)) !=0)
+			*xe &= ((ULong)0xffffffff) >> (ULbits - i);
+		}
+	for(x1 = xe;; --x1) {
+		if (*x1 != 0)
+			break;
+		if (x1 == x0) {
+			*x1 = 1;
+			break;
+			}
+		}
+	return STRTOG_NaNbits;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/makefile
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/makefile	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/makefile	(revision 2448)
@@ -0,0 +1,69 @@
+# /****************************************************************
+# Copyright (C) 1998 by Lucent Technologies
+# All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appear in all
+# copies and that both that the copyright notice and this
+# permission notice and warranty disclaimer appear in supporting
+# documentation, and that the name of Lucent or any of its entities
+# not be used in advertising or publicity pertaining to
+# distribution of the software without specific, written prior
+# permission.
+#
+# LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+# IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+# THIS SOFTWARE.
+#
+# ****************************************************************/
+
+.SUFFIXES: .c .o
+CC = cc
+CFLAGS = -g -DINFNAN_CHECK
+
+.c.o:
+	$(CC) -c $(CFLAGS) $*.c
+
+all: arith.h gdtoa.a
+
+arith.h: arithchk.c
+	$(CC) $(CFLAGS) arithchk.c || $(CC) -DNO_LONG_LONG $(CFLAGS) arithchk.c
+	./a.out >arith.h
+	rm -f a.out arithchk.o
+
+gdtoa.a: dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c g_ffmt.c\
+	 g_xLfmt.c g_xfmt.c gdtoa.c gethex.c gmisc.c hd_init.c hexnan.c\
+	 misc.c smisc.c strtoIQ.c strtoId.c strtoIdd.c strtoIf.c strtoIg.c\
+	 strtoIx.c strtoIxL.c strtod.c strtodI.c strtodg.c strtof.c strtopQ.c\
+	 strtopd.c strtopdd.c strtopf.c strtopx.c strtopxL.c strtorQ.c\
+	 strtord.c strtordd.c strtorf.c strtorx.c strtorxL.c sum.c ulp.c
+	$(CC) -c $(CFLAGS) $?
+	x=`echo $? | sed 's/\.c/.o/g'` && ar ruv gdtoa.a $$x && rm $$x
+	ranlib gdtoa.a || true
+
+# If your system lacks ranlib, you do not need it.
+
+xs0 = README arithchk.c dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c\
+	 g_ffmt.c g_xLfmt.c g_xfmt.c gdtoa.c gdtoa.h gdtoaimp.h gethex.c\
+	 gmisc.c hd_init.c hexnan.c makefile misc.c smisc.c strtoIQ.c\
+	 strtoId.c strtoIdd.c strtoIf.c strtoIg.c strtoIx.c strtoIxL.c\
+	 strtod.c strtodI.c strtodg.c strtof.c strtopQ.c strtopd.c strtopdd.c\
+	 strtopf.c strtopx.c strtopxL.c strtorQ.c strtord.c strtordd.c\
+	 strtorf.c strtorx.c strtorxL.c sum.c ulp.c
+
+# "make xsum.out" to check for transmission errors; source for xsum is
+# netlib's "xsum.c from f2c", e.g.,
+# ftp://netlib.bell-labs.com/netlib/f2c/xsum.c.gz
+
+xsum.out: xsum0.out $(xs0)
+	xsum $(xs0) >xsum1.out
+	cmp xsum0.out xsum1.out && mv xsum1.out xsum.out || diff xsum[01].out
+
+clean:
+	rm -f arith.h *.[ao] xsum.out xsum1.out
Index: /trunk/libc/src/fbsdlibc/gdtoa/misc.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/misc.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/misc.c	(revision 2448)
@@ -0,0 +1,862 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ static Bigint *freelist[Kmax+1];
+#ifndef Omit_Private_Memory
+#ifndef PRIVATE_MEM
+#define PRIVATE_MEM 2304
+#endif
+#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
+static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
+#endif
+
+ Bigint *
+Balloc
+#ifdef KR_headers
+	(k) int k;
+#else
+	(int k)
+#endif
+{
+	int x;
+	Bigint *rv;
+#ifndef Omit_Private_Memory
+	unsigned int len;
+#endif
+
+	ACQUIRE_DTOA_LOCK(0);
+	if ( (rv = freelist[k]) !=0) {
+		freelist[k] = rv->next;
+		}
+	else {
+		x = 1 << k;
+#ifdef Omit_Private_Memory
+		rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
+#else
+		len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
+			/sizeof(double);
+		if (pmem_next - private_mem + len <= PRIVATE_mem) {
+			rv = (Bigint*)pmem_next;
+			pmem_next += len;
+			}
+		else
+			rv = (Bigint*)MALLOC(len*sizeof(double));
+#endif
+		rv->k = k;
+		rv->maxwds = x;
+		}
+	FREE_DTOA_LOCK(0);
+	rv->sign = rv->wds = 0;
+	return rv;
+	}
+
+ void
+Bfree
+#ifdef KR_headers
+	(v) Bigint *v;
+#else
+	(Bigint *v)
+#endif
+{
+	if (v) {
+		ACQUIRE_DTOA_LOCK(0);
+		v->next = freelist[v->k];
+		freelist[v->k] = v;
+		FREE_DTOA_LOCK(0);
+		}
+	}
+
+ int
+lo0bits
+#ifdef KR_headers
+	(y) ULong *y;
+#else
+	(ULong *y)
+#endif
+{
+	register int k;
+	register ULong x = *y;
+
+	if (x & 7) {
+		if (x & 1)
+			return 0;
+		if (x & 2) {
+			*y = x >> 1;
+			return 1;
+			}
+		*y = x >> 2;
+		return 2;
+		}
+	k = 0;
+	if (!(x & 0xffff)) {
+		k = 16;
+		x >>= 16;
+		}
+	if (!(x & 0xff)) {
+		k += 8;
+		x >>= 8;
+		}
+	if (!(x & 0xf)) {
+		k += 4;
+		x >>= 4;
+		}
+	if (!(x & 0x3)) {
+		k += 2;
+		x >>= 2;
+		}
+	if (!(x & 1)) {
+		k++;
+		x >>= 1;
+		if (!x & 1)
+			return 32;
+		}
+	*y = x;
+	return k;
+	}
+
+ Bigint *
+multadd
+#ifdef KR_headers
+	(b, m, a) Bigint *b; int m, a;
+#else
+	(Bigint *b, int m, int a)	/* multiply by m and add a */
+#endif
+{
+	int i, wds;
+#ifdef ULLong
+	ULong *x;
+	ULLong carry, y;
+#else
+	ULong carry, *x, y;
+#ifdef Pack_32
+	ULong xi, z;
+#endif
+#endif
+	Bigint *b1;
+
+	wds = b->wds;
+	x = b->x;
+	i = 0;
+	carry = a;
+	do {
+#ifdef ULLong
+		y = *x * (ULLong)m + carry;
+		carry = y >> 32;
+		*x++ = y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+		xi = *x;
+		y = (xi & 0xffff) * m + carry;
+		z = (xi >> 16) * m + (y >> 16);
+		carry = z >> 16;
+		*x++ = (z << 16) + (y & 0xffff);
+#else
+		y = *x * m + carry;
+		carry = y >> 16;
+		*x++ = y & 0xffff;
+#endif
+#endif
+		}
+		while(++i < wds);
+	if (carry) {
+		if (wds >= b->maxwds) {
+			b1 = Balloc(b->k+1);
+			Bcopy(b1, b);
+			Bfree(b);
+			b = b1;
+			}
+		b->x[wds++] = carry;
+		b->wds = wds;
+		}
+	return b;
+	}
+
+ int
+hi0bits
+#ifdef KR_headers
+	(x) register ULong x;
+#else
+	(register ULong x)
+#endif
+{
+	register int k = 0;
+
+	if (!(x & 0xffff0000)) {
+		k = 16;
+		x <<= 16;
+		}
+	if (!(x & 0xff000000)) {
+		k += 8;
+		x <<= 8;
+		}
+	if (!(x & 0xf0000000)) {
+		k += 4;
+		x <<= 4;
+		}
+	if (!(x & 0xc0000000)) {
+		k += 2;
+		x <<= 2;
+		}
+	if (!(x & 0x80000000)) {
+		k++;
+		if (!(x & 0x40000000))
+			return 32;
+		}
+	return k;
+	}
+
+ Bigint *
+i2b
+#ifdef KR_headers
+	(i) int i;
+#else
+	(int i)
+#endif
+{
+	Bigint *b;
+
+	b = Balloc(1);
+	b->x[0] = i;
+	b->wds = 1;
+	return b;
+	}
+
+ Bigint *
+mult
+#ifdef KR_headers
+	(a, b) Bigint *a, *b;
+#else
+	(Bigint *a, Bigint *b)
+#endif
+{
+	Bigint *c;
+	int k, wa, wb, wc;
+	ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+	ULong y;
+#ifdef ULLong
+	ULLong carry, z;
+#else
+	ULong carry, z;
+#ifdef Pack_32
+	ULong z2;
+#endif
+#endif
+
+	if (a->wds < b->wds) {
+		c = a;
+		a = b;
+		b = c;
+		}
+	k = a->k;
+	wa = a->wds;
+	wb = b->wds;
+	wc = wa + wb;
+	if (wc > a->maxwds)
+		k++;
+	c = Balloc(k);
+	for(x = c->x, xa = x + wc; x < xa; x++)
+		*x = 0;
+	xa = a->x;
+	xae = xa + wa;
+	xb = b->x;
+	xbe = xb + wb;
+	xc0 = c->x;
+#ifdef ULLong
+	for(; xb < xbe; xc0++) {
+		if ( (y = *xb++) !=0) {
+			x = xa;
+			xc = xc0;
+			carry = 0;
+			do {
+				z = *x++ * (ULLong)y + *xc + carry;
+				carry = z >> 32;
+				*xc++ = z & 0xffffffffUL;
+				}
+				while(x < xae);
+			*xc = carry;
+			}
+		}
+#else
+#ifdef Pack_32
+	for(; xb < xbe; xb++, xc0++) {
+		if ( (y = *xb & 0xffff) !=0) {
+			x = xa;
+			xc = xc0;
+			carry = 0;
+			do {
+				z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+				carry = z >> 16;
+				z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+				carry = z2 >> 16;
+				Storeinc(xc, z2, z);
+				}
+				while(x < xae);
+			*xc = carry;
+			}
+		if ( (y = *xb >> 16) !=0) {
+			x = xa;
+			xc = xc0;
+			carry = 0;
+			z2 = *xc;
+			do {
+				z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+				carry = z >> 16;
+				Storeinc(xc, z, z2);
+				z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+				carry = z2 >> 16;
+				}
+				while(x < xae);
+			*xc = z2;
+			}
+		}
+#else
+	for(; xb < xbe; xc0++) {
+		if ( (y = *xb++) !=0) {
+			x = xa;
+			xc = xc0;
+			carry = 0;
+			do {
+				z = *x++ * y + *xc + carry;
+				carry = z >> 16;
+				*xc++ = z & 0xffff;
+				}
+				while(x < xae);
+			*xc = carry;
+			}
+		}
+#endif
+#endif
+	for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
+	c->wds = wc;
+	return c;
+	}
+
+ static Bigint *p5s;
+
+ Bigint *
+pow5mult
+#ifdef KR_headers
+	(b, k) Bigint *b; int k;
+#else
+	(Bigint *b, int k)
+#endif
+{
+	Bigint *b1, *p5, *p51;
+	int i;
+	static int p05[3] = { 5, 25, 125 };
+
+	if ( (i = k & 3) !=0)
+		b = multadd(b, p05[i-1], 0);
+
+	if (!(k >>= 2))
+		return b;
+	if ((p5 = p5s) == 0) {
+		/* first time */
+#ifdef MULTIPLE_THREADS
+		ACQUIRE_DTOA_LOCK(1);
+		if (!(p5 = p5s)) {
+			p5 = p5s = i2b(625);
+			p5->next = 0;
+			}
+		FREE_DTOA_LOCK(1);
+#else
+		p5 = p5s = i2b(625);
+		p5->next = 0;
+#endif
+		}
+	for(;;) {
+		if (k & 1) {
+			b1 = mult(b, p5);
+			Bfree(b);
+			b = b1;
+			}
+		if (!(k >>= 1))
+			break;
+		if ((p51 = p5->next) == 0) {
+#ifdef MULTIPLE_THREADS
+			ACQUIRE_DTOA_LOCK(1);
+			if (!(p51 = p5->next)) {
+				p51 = p5->next = mult(p5,p5);
+				p51->next = 0;
+				}
+			FREE_DTOA_LOCK(1);
+#else
+			p51 = p5->next = mult(p5,p5);
+			p51->next = 0;
+#endif
+			}
+		p5 = p51;
+		}
+	return b;
+	}
+
+ Bigint *
+lshift
+#ifdef KR_headers
+	(b, k) Bigint *b; int k;
+#else
+	(Bigint *b, int k)
+#endif
+{
+	int i, k1, n, n1;
+	Bigint *b1;
+	ULong *x, *x1, *xe, z;
+
+	n = k >> kshift;
+	k1 = b->k;
+	n1 = n + b->wds + 1;
+	for(i = b->maxwds; n1 > i; i <<= 1)
+		k1++;
+	b1 = Balloc(k1);
+	x1 = b1->x;
+	for(i = 0; i < n; i++)
+		*x1++ = 0;
+	x = b->x;
+	xe = x + b->wds;
+	if (k &= kmask) {
+#ifdef Pack_32
+		k1 = 32 - k;
+		z = 0;
+		do {
+			*x1++ = *x << k | z;
+			z = *x++ >> k1;
+			}
+			while(x < xe);
+		if ((*x1 = z) !=0)
+			++n1;
+#else
+		k1 = 16 - k;
+		z = 0;
+		do {
+			*x1++ = *x << k  & 0xffff | z;
+			z = *x++ >> k1;
+			}
+			while(x < xe);
+		if (*x1 = z)
+			++n1;
+#endif
+		}
+	else do
+		*x1++ = *x++;
+		while(x < xe);
+	b1->wds = n1 - 1;
+	Bfree(b);
+	return b1;
+	}
+
+ int
+cmp
+#ifdef KR_headers
+	(a, b) Bigint *a, *b;
+#else
+	(Bigint *a, Bigint *b)
+#endif
+{
+	ULong *xa, *xa0, *xb, *xb0;
+	int i, j;
+
+	i = a->wds;
+	j = b->wds;
+#ifdef DEBUG
+	if (i > 1 && !a->x[i-1])
+		Bug("cmp called with a->x[a->wds-1] == 0");
+	if (j > 1 && !b->x[j-1])
+		Bug("cmp called with b->x[b->wds-1] == 0");
+#endif
+	if (i -= j)
+		return i;
+	xa0 = a->x;
+	xa = xa0 + j;
+	xb0 = b->x;
+	xb = xb0 + j;
+	for(;;) {
+		if (*--xa != *--xb)
+			return *xa < *xb ? -1 : 1;
+		if (xa <= xa0)
+			break;
+		}
+	return 0;
+	}
+
+ Bigint *
+diff
+#ifdef KR_headers
+	(a, b) Bigint *a, *b;
+#else
+	(Bigint *a, Bigint *b)
+#endif
+{
+	Bigint *c;
+	int i, wa, wb;
+	ULong *xa, *xae, *xb, *xbe, *xc;
+#ifdef ULLong
+	ULLong borrow, y;
+#else
+	ULong borrow, y;
+#ifdef Pack_32
+	ULong z;
+#endif
+#endif
+
+	i = cmp(a,b);
+	if (!i) {
+		c = Balloc(0);
+		c->wds = 1;
+		c->x[0] = 0;
+		return c;
+		}
+	if (i < 0) {
+		c = a;
+		a = b;
+		b = c;
+		i = 1;
+		}
+	else
+		i = 0;
+	c = Balloc(a->k);
+	c->sign = i;
+	wa = a->wds;
+	xa = a->x;
+	xae = xa + wa;
+	wb = b->wds;
+	xb = b->x;
+	xbe = xb + wb;
+	xc = c->x;
+	borrow = 0;
+#ifdef ULLong
+	do {
+		y = (ULLong)*xa++ - *xb++ - borrow;
+		borrow = y >> 32 & 1UL;
+		*xc++ = y & 0xffffffffUL;
+		}
+		while(xb < xbe);
+	while(xa < xae) {
+		y = *xa++ - borrow;
+		borrow = y >> 32 & 1UL;
+		*xc++ = y & 0xffffffffUL;
+		}
+#else
+#ifdef Pack_32
+	do {
+		y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
+		borrow = (y & 0x10000) >> 16;
+		z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
+		borrow = (z & 0x10000) >> 16;
+		Storeinc(xc, z, y);
+		}
+		while(xb < xbe);
+	while(xa < xae) {
+		y = (*xa & 0xffff) - borrow;
+		borrow = (y & 0x10000) >> 16;
+		z = (*xa++ >> 16) - borrow;
+		borrow = (z & 0x10000) >> 16;
+		Storeinc(xc, z, y);
+		}
+#else
+	do {
+		y = *xa++ - *xb++ - borrow;
+		borrow = (y & 0x10000) >> 16;
+		*xc++ = y & 0xffff;
+		}
+		while(xb < xbe);
+	while(xa < xae) {
+		y = *xa++ - borrow;
+		borrow = (y & 0x10000) >> 16;
+		*xc++ = y & 0xffff;
+		}
+#endif
+#endif
+	while(!*--xc)
+		wa--;
+	c->wds = wa;
+	return c;
+	}
+
+ double
+b2d
+#ifdef KR_headers
+	(a, e) Bigint *a; int *e;
+#else
+	(Bigint *a, int *e)
+#endif
+{
+	ULong *xa, *xa0, w, y, z;
+	int k;
+	double d;
+#ifdef VAX
+	ULong d0, d1;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+	xa0 = a->x;
+	xa = xa0 + a->wds;
+	y = *--xa;
+#ifdef DEBUG
+	if (!y) Bug("zero y in b2d");
+#endif
+	k = hi0bits(y);
+	*e = 32 - k;
+#ifdef Pack_32
+	if (k < Ebits) {
+		d0 = Exp_1 | y >> Ebits - k;
+		w = xa > xa0 ? *--xa : 0;
+		d1 = y << (32-Ebits) + k | w >> Ebits - k;
+		goto ret_d;
+		}
+	z = xa > xa0 ? *--xa : 0;
+	if (k -= Ebits) {
+		d0 = Exp_1 | y << k | z >> 32 - k;
+		y = xa > xa0 ? *--xa : 0;
+		d1 = z << k | y >> 32 - k;
+		}
+	else {
+		d0 = Exp_1 | y;
+		d1 = z;
+		}
+#else
+	if (k < Ebits + 16) {
+		z = xa > xa0 ? *--xa : 0;
+		d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
+		w = xa > xa0 ? *--xa : 0;
+		y = xa > xa0 ? *--xa : 0;
+		d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
+		goto ret_d;
+		}
+	z = xa > xa0 ? *--xa : 0;
+	w = xa > xa0 ? *--xa : 0;
+	k -= Ebits + 16;
+	d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
+	y = xa > xa0 ? *--xa : 0;
+	d1 = w << k + 16 | y << k;
+#endif
+ ret_d:
+#ifdef VAX
+	word0(d) = d0 >> 16 | d0 << 16;
+	word1(d) = d1 >> 16 | d1 << 16;
+#endif
+	return dval(d);
+	}
+#undef d0
+#undef d1
+
+ Bigint *
+d2b
+#ifdef KR_headers
+	(d, e, bits) double d; int *e, *bits;
+#else
+	(double d, int *e, int *bits)
+#endif
+{
+	Bigint *b;
+	int de, i, k;
+	ULong *x, y, z;
+#ifdef VAX
+	ULong d0, d1;
+	d0 = word0(d) >> 16 | word0(d) << 16;
+	d1 = word1(d) >> 16 | word1(d) << 16;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+#ifdef Pack_32
+	b = Balloc(1);
+#else
+	b = Balloc(2);
+#endif
+	x = b->x;
+
+	z = d0 & Frac_mask;
+	d0 &= 0x7fffffff;	/* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+	de = (int)(d0 >> Exp_shift);
+#ifndef IBM
+	z |= Exp_msk11;
+#endif
+#else
+	if ( (de = (int)(d0 >> Exp_shift)) !=0)
+		z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+	if ( (y = d1) !=0) {
+		if ( (k = lo0bits(&y)) !=0) {
+			x[0] = y | z << 32 - k;
+			z >>= k;
+			}
+		else
+			x[0] = y;
+		i = b->wds = (x[1] = z) !=0 ? 2 : 1;
+		}
+	else {
+#ifdef DEBUG
+		if (!z)
+			Bug("Zero passed to d2b");
+#endif
+		k = lo0bits(&z);
+		x[0] = z;
+		i = b->wds = 1;
+		k += 32;
+		}
+#else
+	if ( (y = d1) !=0) {
+		if ( (k = lo0bits(&y)) !=0)
+			if (k >= 16) {
+				x[0] = y | z << 32 - k & 0xffff;
+				x[1] = z >> k - 16 & 0xffff;
+				x[2] = z >> k;
+				i = 2;
+				}
+			else {
+				x[0] = y & 0xffff;
+				x[1] = y >> 16 | z << 16 - k & 0xffff;
+				x[2] = z >> k & 0xffff;
+				x[3] = z >> k+16;
+				i = 3;
+				}
+		else {
+			x[0] = y & 0xffff;
+			x[1] = y >> 16;
+			x[2] = z & 0xffff;
+			x[3] = z >> 16;
+			i = 3;
+			}
+		}
+	else {
+#ifdef DEBUG
+		if (!z)
+			Bug("Zero passed to d2b");
+#endif
+		k = lo0bits(&z);
+		if (k >= 16) {
+			x[0] = z;
+			i = 0;
+			}
+		else {
+			x[0] = z & 0xffff;
+			x[1] = z >> 16;
+			i = 1;
+			}
+		k += 32;
+		}
+	while(!x[i])
+		--i;
+	b->wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+	if (de) {
+#endif
+#ifdef IBM
+		*e = (de - Bias - (P-1) << 2) + k;
+		*bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
+#else
+		*e = de - Bias - (P-1) + k;
+		*bits = P - k;
+#endif
+#ifndef Sudden_Underflow
+		}
+	else {
+		*e = de - Bias - (P-1) + 1 + k;
+#ifdef Pack_32
+		*bits = 32*i - hi0bits(x[i-1]);
+#else
+		*bits = (i+2)*16 - hi0bits(x[i]);
+#endif
+		}
+#endif
+	return b;
+	}
+#undef d0
+#undef d1
+
+ CONST double
+#ifdef IEEE_Arith
+bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
+		};
+#else
+#ifdef IBM
+bigtens[] = { 1e16, 1e32, 1e64 };
+CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
+#else
+bigtens[] = { 1e16, 1e32 };
+CONST double tinytens[] = { 1e-16, 1e-32 };
+#endif
+#endif
+
+ CONST double
+tens[] = {
+		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+		1e20, 1e21, 1e22
+#ifdef VAX
+		, 1e23, 1e24
+#endif
+		};
+
+ char *
+#ifdef KR_headers
+strcp_D2A(a, b) char *a; char *b;
+#else
+strcp_D2A(char *a, CONST char *b)
+#endif
+{
+	while(*a = *b++)
+		a++;
+	return a;
+	}
+
+#ifdef NO_STRING_H
+
+ Char *
+#ifdef KR_headers
+memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
+#else
+memcpy_D2A(void *a1, void *b1, size_t len)
+#endif
+{
+	register char *a = (char*)a1, *ae = a + len;
+	register char *b = (char*)b1, *a0 = a;
+	while(a < ae)
+		*a++ = *b++;
+	return a0;
+	}
+
+#endif /* NO_STRING_H */
Index: /trunk/libc/src/fbsdlibc/gdtoa/smisc.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/smisc.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/smisc.c	(revision 2448)
@@ -0,0 +1,197 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ Bigint *
+s2b
+#ifdef KR_headers
+	(s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
+#else
+	(CONST char *s, int nd0, int nd, ULong y9)
+#endif
+{
+	Bigint *b;
+	int i, k;
+	Long x, y;
+
+	x = (nd + 8) / 9;
+	for(k = 0, y = 1; x > y; y <<= 1, k++) ;
+#ifdef Pack_32
+	b = Balloc(k);
+	b->x[0] = y9;
+	b->wds = 1;
+#else
+	b = Balloc(k+1);
+	b->x[0] = y9 & 0xffff;
+	b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
+#endif
+
+	i = 9;
+	if (9 < nd0) {
+		s += 9;
+		do b = multadd(b, 10, *s++ - '0');
+			while(++i < nd0);
+		s++;
+		}
+	else
+		s += 10;
+	for(; i < nd; i++)
+		b = multadd(b, 10, *s++ - '0');
+	return b;
+	}
+
+ double
+ratio
+#ifdef KR_headers
+	(a, b) Bigint *a, *b;
+#else
+	(Bigint *a, Bigint *b)
+#endif
+{
+	double da, db;
+	int k, ka, kb;
+
+	dval(da) = b2d(a, &ka);
+	dval(db) = b2d(b, &kb);
+	k = ka - kb + ULbits*(a->wds - b->wds);
+#ifdef IBM
+	if (k > 0) {
+		word0(da) += (k >> 2)*Exp_msk1;
+		if (k &= 3)
+			dval(da) *= 1 << k;
+		}
+	else {
+		k = -k;
+		word0(db) += (k >> 2)*Exp_msk1;
+		if (k &= 3)
+			dval(db) *= 1 << k;
+		}
+#else
+	if (k > 0)
+		word0(da) += k*Exp_msk1;
+	else {
+		k = -k;
+		word0(db) += k*Exp_msk1;
+		}
+#endif
+	return dval(da) / dval(db);
+	}
+
+#ifdef INFNAN_CHECK
+
+ int
+match
+#ifdef KR_headers
+	(sp, t) char **sp, *t;
+#else
+	(CONST char **sp, char *t)
+#endif
+{
+	int c, d;
+	CONST char *s = *sp;
+
+	while( (d = *t++) !=0) {
+		if ((c = *++s) >= 'A' && c <= 'Z')
+			c += 'a' - 'A';
+		if (c != d)
+			return 0;
+		}
+	*sp = s + 1;
+	return 1;
+	}
+#endif /* INFNAN_CHECK */
+
+ void
+#ifdef KR_headers
+copybits(c, n, b) ULong *c; int n; Bigint *b;
+#else
+copybits(ULong *c, int n, Bigint *b)
+#endif
+{
+	ULong *ce, *x, *xe;
+#ifdef Pack_16
+	int nw, nw1;
+#endif
+
+	ce = c + ((n-1) >> kshift) + 1;
+	x = b->x;
+#ifdef Pack_32
+	xe = x + b->wds;
+	while(x < xe)
+		*c++ = *x++;
+#else
+	nw = b->wds;
+	nw1 = nw & 1;
+	for(xe = x + (nw - nw1); x < xe; x += 2)
+		Storeinc(c, x[1], x[0]);
+	if (nw1)
+		*c++ = *x;
+#endif
+	while(c < ce)
+		*c++ = 0;
+	}
+
+ ULong
+#ifdef KR_headers
+any_on(b, k) Bigint *b; int k;
+#else
+any_on(Bigint *b, int k)
+#endif
+{
+	int n, nwds;
+	ULong *x, *x0, x1, x2;
+
+	x = b->x;
+	nwds = b->wds;
+	n = k >> kshift;
+	if (n > nwds)
+		n = nwds;
+	else if (n < nwds && (k &= kmask)) {
+		x1 = x2 = x[n];
+		x1 >>= k;
+		x1 <<= k;
+		if (x1 != x2)
+			return 1;
+		}
+	x0 = x;
+	x += n;
+	while(x > x0)
+		if (*--x)
+			return 1;
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtoIQ.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtoIQ.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtoIQ.c	(revision 2448)
@@ -0,0 +1,69 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtoIQ(s, sp, a, b) CONST char *s; char **sp; void *a; void *b;
+#else
+strtoIQ(CONST char *s, char **sp, void *a, void *b)
+#endif
+{
+	static FPI fpi = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI };
+	Long exp[2];
+	Bigint *B[2];
+	int k, rv[2];
+	ULong *L = (ULong *)a, *M = (ULong *)b;
+
+	B[0] = Balloc(2);
+	B[0]->wds = 4;
+	k = strtoIg(s, sp, &fpi, exp, B, rv);
+	ULtoQ(L, B[0]->x, exp[0], rv[0]);
+	Bfree(B[0]);
+	if (B[1]) {
+		ULtoQ(M, B[1]->x, exp[1], rv[1]);
+		Bfree(B[1]);
+		}
+	else {
+		M[0] = L[0];
+		M[1] = L[1];
+		M[2] = L[2];
+		M[3] = L[3];
+		}
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtoId.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtoId.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtoId.c	(revision 2448)
@@ -0,0 +1,66 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtoId(s, sp, f0, f1) CONST char *s; char **sp; double *f0, *f1;
+#else
+strtoId(CONST char *s, char **sp, double *f0, double *f1)
+#endif
+{
+	static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
+	Long exp[2];
+	Bigint *B[2];
+	int k, rv[2];
+
+	B[0] = Balloc(1);
+	B[0]->wds = 2;
+	k = strtoIg(s, sp, &fpi, exp, B, rv);
+	ULtod((ULong*)f0, B[0]->x, exp[0], rv[0]);
+	Bfree(B[0]);
+	if (B[1]) {
+		ULtod((ULong*)f1, B[1]->x, exp[1], rv[1]);
+		Bfree(B[1]);
+		}
+	else {
+		((ULong*)f1)[0] = ((ULong*)f0)[0];
+		((ULong*)f1)[1] = ((ULong*)f0)[1];
+		}
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtoIdd.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtoIdd.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtoIdd.c	(revision 2448)
@@ -0,0 +1,72 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtoIdd(s, sp, f0, f1) CONST char *s; char **sp; double *f0, *f1;
+#else
+strtoIdd(CONST char *s, char **sp, double *f0, double *f1)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
+#else
+	static FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
+#endif
+	Long exp[2];
+	Bigint *B[2];
+	int k, rv[2];
+
+	B[0] = Balloc(2);
+	B[0]->wds = 4;
+	k = strtoIg(s, sp, &fpi, exp, B, rv);
+	ULtodd((ULong*)f0, B[0]->x, exp[0], rv[0]);
+	Bfree(B[0]);
+	if (B[1]) {
+		ULtodd((ULong*)f1, B[1]->x, exp[1], rv[1]);
+		Bfree(B[1]);
+		}
+	else {
+		((ULong*)f1)[0] = ((ULong*)f0)[0];
+		((ULong*)f1)[1] = ((ULong*)f0)[1];
+		((ULong*)f1)[2] = ((ULong*)f0)[2];
+		((ULong*)f1)[3] = ((ULong*)f0)[3];
+		}
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtoIf.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtoIf.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtoIf.c	(revision 2448)
@@ -0,0 +1,64 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtoIf(s, sp, f0, f1) CONST char *s; char **sp; float *f0, *f1;
+#else
+strtoIf(CONST char *s, char **sp, float *f0, float *f1)
+#endif
+{
+	static FPI fpi = { 24, 1-127-24+1,  254-127-24+1, 1, SI };
+	Long exp[2];
+	Bigint *B[2];
+	int k, rv[2];
+
+	B[0] = Balloc(0);
+	B[0]->wds = 1;
+	k = strtoIg(s, sp, &fpi, exp, B, rv);
+	ULtof((ULong*)f0, B[0]->x, exp[0], rv[0]);
+	Bfree(B[0]);
+	if (B[1]) {
+		ULtof((ULong*)f1, B[1]->x, exp[1], rv[1]);
+		Bfree(B[1]);
+		}
+	else
+		*(ULong*)f1 = *(ULong*)f0;
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtoIg.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtoIg.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtoIg.c	(revision 2448)
@@ -0,0 +1,139 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtoIg(s00, se, fpi, exp, B, rvp) CONST char *s00; char **se; FPI *fpi; Long *exp; Bigint **B; int *rvp;
+#else
+strtoIg(CONST char *s00, char **se, FPI *fpi, Long *exp, Bigint **B, int *rvp)
+#endif
+{
+	Bigint *b, *b1;
+	int i, nb, nw, nw1, rv, rv1, swap;
+	unsigned int nb1, nb11;
+	Long e1;
+
+	b = *B;
+	rv = strtodg(s00, se, fpi, exp, b->x);
+	if (!(rv & STRTOG_Inexact)) {
+		B[1] = 0;
+		return *rvp = rv;
+		}
+	e1 = exp[0];
+	rv1 = rv ^ STRTOG_Inexact;
+	b1 = Balloc(b->k);
+	Bcopy(b1, b);
+	nb = fpi->nbits;
+	nb1 = nb & 31;
+	nb11 = (nb1 - 1) & 31;
+	nw = b->wds;
+	nw1 = nw - 1;
+	if (rv & STRTOG_Inexlo) {
+		swap = 0;
+		b1 = increment(b1);
+		if (fpi->sudden_underflow
+		 && (rv & STRTOG_Retmask) == STRTOG_Zero) {
+			b1->x[0] = 0;
+			b1->x[nw1] = 1L << nb11;
+			rv1 += STRTOG_Normal - STRTOG_Zero;
+			rv1 &= ~STRTOG_Underflow;
+			goto swapcheck;
+			}
+		if (b1->wds > nw
+		 || nb1 && b1->x[nw1] & 1L << nb1) {
+			if (++e1 > fpi->emax)
+				rv1 = STRTOG_Infinite | STRTOG_Inexhi;
+			rshift(b1, 1);
+			}
+		else if ((rv & STRTOG_Retmask) == STRTOG_Denormal) {
+			if (b1->x[nw1] & 1L << nb11) {
+				rv1 += STRTOG_Normal - STRTOG_Denormal;
+				rv1 &= ~STRTOG_Underflow;
+				}
+			}
+		}
+	else {
+		swap = STRTOG_Neg;
+		if ((rv & STRTOG_Retmask) == STRTOG_Infinite) {
+			b1 = set_ones(b1, nb);
+			e1 = fpi->emax;
+			rv1 = STRTOG_Normal | STRTOG_Inexlo;
+			goto swapcheck;
+			}
+		decrement(b1);
+		if ((rv & STRTOG_Retmask) == STRTOG_Denormal) {
+			for(i = nw1; !b1->x[i]; --i)
+				if (!i) {
+					rv1 = STRTOG_Zero | STRTOG_Inexlo;
+					break;
+					}
+			goto swapcheck;
+			}
+		if (!(b1->x[nw1] & 1L << nb11)) {
+			if (e1 == fpi->emin) {
+				if (fpi->sudden_underflow)
+					rv1 += STRTOG_Zero - STRTOG_Normal;
+				else
+					rv1 += STRTOG_Denormal - STRTOG_Normal;
+				rv1 |= STRTOG_Underflow;
+				}
+			else {
+				b1 = lshift(b1, 1);
+				b1->x[0] |= 1;
+				--e1;
+				}
+			}
+		}
+ swapcheck:
+	if (swap ^ (rv & STRTOG_Neg)) {
+		rvp[0] = rv1;
+		rvp[1] = rv;
+		B[0] = b1;
+		B[1] = b;
+		exp[1] = exp[0];
+		exp[0] = e1;
+		}
+	else {
+		rvp[0] = rv;
+		rvp[1] = rv1;
+		B[1] = b1;
+		exp[1] = e1;
+		}
+	return rv;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtoIx.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtoIx.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtoIx.c	(revision 2448)
@@ -0,0 +1,70 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtoIx(s, sp, a, b) CONST char *s; char **sp; void *a; void *b;
+#else
+strtoIx(CONST char *s, char **sp, void *a, void *b)
+#endif
+{
+	static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
+	Long exp[2];
+	Bigint *B[2];
+	int k, rv[2];
+	UShort *L = (UShort *)a, *M = (UShort *)b;
+
+	B[0] = Balloc(1);
+	B[0]->wds = 2;
+	k = strtoIg(s, sp, &fpi, exp, B, rv);
+	ULtox(L, B[0]->x, exp[0], rv[0]);
+	Bfree(B[0]);
+	if (B[1]) {
+		ULtox(M, B[1]->x, exp[1], rv[1]);
+		Bfree(B[1]);
+		}
+	else {
+		M[0] = L[0];
+		M[1] = L[1];
+		M[2] = L[2];
+		M[3] = L[3];
+		M[4] = L[4];
+		}
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtoIxL.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtoIxL.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtoIxL.c	(revision 2448)
@@ -0,0 +1,68 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtoIxL(s, sp, a, b) CONST char *s; char **sp; void *a; void *b;
+#else
+strtoIxL(CONST char *s, char **sp, void *a, void *b)
+#endif
+{
+	static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
+	Long exp[2];
+	Bigint *B[2];
+	int k, rv[2];
+	ULong *L = (ULong *)a, *M = (ULong *)b;
+
+	B[0] = Balloc(1);
+	B[0]->wds = 2;
+	k = strtoIg(s, sp, &fpi, exp, B, rv);
+	ULtoxL(L, B[0]->x, exp[0], rv[0]);
+	Bfree(B[0]);
+	if (B[1]) {
+		ULtoxL(M, B[1]->x, exp[1], rv[1]);
+		Bfree(B[1]);
+		}
+	else {
+		M[0] = L[0];
+		M[1] = L[1];
+		M[2] = L[2];
+		}
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtod.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtod.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtod.c	(revision 2448)
@@ -0,0 +1,970 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	dmg@acm.org
+ */
+
+#include "gdtoaimp.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+#ifdef IEEE_Arith
+#ifndef NO_IEEE_Scale
+#define Avoid_Underflow
+#undef tinytens
+/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
+/* flag unnecessarily.  It leads to a song and dance at the end of strtod. */
+static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
+		9007199254740992.e-256
+		};
+#endif
+#endif
+
+#ifdef Honor_FLT_ROUNDS
+#define Rounding rounding
+#undef Check_FLT_ROUNDS
+#define Check_FLT_ROUNDS
+#else
+#define Rounding Flt_Rounds
+#endif
+
+ double
+#ifdef __EMX__
+_STD(strtod)
+#else
+strtod
+#endif
+#ifdef KR_headers
+	(s00, se) CONST char *s00; char **se;
+#else
+	(CONST char *s00, char **se)
+#endif
+{
+#ifdef Avoid_Underflow
+	int scale;
+#endif
+	int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
+		 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+	CONST char *s, *s0, *s1;
+	double aadj, aadj1, adj, rv, rv0;
+	Long L;
+	ULong y, z;
+	Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
+#ifdef SET_INEXACT
+	int inexact, oldinexact;
+#endif
+#ifdef Honor_FLT_ROUNDS
+	int rounding;
+#endif
+
+	sign = nz0 = nz = 0;
+	dval(rv) = 0.;
+	for(s = s00;;s++) switch(*s) {
+		case '-':
+			sign = 1;
+			/* no break */
+		case '+':
+			if (*++s)
+				goto break2;
+			/* no break */
+		case 0:
+			goto ret0;
+		case '\t':
+		case '\n':
+		case '\v':
+		case '\f':
+		case '\r':
+		case ' ':
+			continue;
+		default:
+			goto break2;
+		}
+ break2:
+	if (*s == '0') {
+#ifndef NO_HEX_FP
+		{
+		static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
+		Long exp;
+		ULong bits[2];
+		switch(s[1]) {
+		  case 'x':
+		  case 'X':
+			switch((i = gethex(&s, &fpi, &exp, &bb, sign)) & STRTOG_Retmask) {
+			  case STRTOG_NoNumber:
+				s = s00;
+				sign = 0;
+			  case STRTOG_Zero:
+				break;
+			  default:
+				if (bb) {
+					copybits(bits, fpi.nbits, bb);
+					Bfree(bb);
+					}
+				ULtod(((U*)&rv)->L, bits, exp, i);
+			  }
+			goto ret;
+		  }
+		}
+#endif
+		nz0 = 1;
+		while(*++s == '0') ;
+		if (!*s)
+			goto ret;
+		}
+	s0 = s;
+	y = z = 0;
+	for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+		if (nd < 9)
+			y = 10*y + c - '0';
+		else if (nd < 16)
+			z = 10*z + c - '0';
+	nd0 = nd;
+#ifdef USE_LOCALE
+	if (c == *localeconv()->decimal_point)
+#else
+	if (c == '.')
+#endif
+		{
+		c = *++s;
+		if (!nd) {
+			for(; c == '0'; c = *++s)
+				nz++;
+			if (c > '0' && c <= '9') {
+				s0 = s;
+				nf += nz;
+				nz = 0;
+				goto have_dig;
+				}
+			goto dig_done;
+			}
+		for(; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+			nz++;
+			if (c -= '0') {
+				nf += nz;
+				for(i = 1; i < nz; i++)
+					if (nd++ < 9)
+						y *= 10;
+					else if (nd <= DBL_DIG + 1)
+						z *= 10;
+				if (nd++ < 9)
+					y = 10*y + c;
+				else if (nd <= DBL_DIG + 1)
+					z = 10*z + c;
+				nz = 0;
+				}
+			}
+		}
+ dig_done:
+	e = 0;
+	if (c == 'e' || c == 'E') {
+		if (!nd && !nz && !nz0) {
+			goto ret0;
+			}
+		s00 = s;
+		esign = 0;
+		switch(c = *++s) {
+			case '-':
+				esign = 1;
+			case '+':
+				c = *++s;
+			}
+		if (c >= '0' && c <= '9') {
+			while(c == '0')
+				c = *++s;
+			if (c > '0' && c <= '9') {
+				L = c - '0';
+				s1 = s;
+				while((c = *++s) >= '0' && c <= '9')
+					L = 10*L + c - '0';
+				if (s - s1 > 8 || L > 19999)
+					/* Avoid confusion from exponents
+					 * so large that e might overflow.
+					 */
+					e = 19999; /* safe for 16 bit ints */
+				else
+					e = (int)L;
+				if (esign)
+					e = -e;
+				}
+			else
+				e = 0;
+			}
+		else
+			s = s00;
+		}
+	if (!nd) {
+		if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+			/* Check for Nan and Infinity */
+			ULong bits[2];
+			static FPI fpinan =	/* only 52 explicit bits */
+				{ 52, 1-1023-53+1, 2046-1023-53+1, 1, SI };
+			switch(c) {
+			  case 'i':
+			  case 'I':
+				if (match(&s,"nf")) {
+					--s;
+					if (!match(&s,"inity"))
+						++s;
+					word0(rv) = 0x7ff00000;
+					word1(rv) = 0;
+					goto ret;
+					}
+				break;
+			  case 'n':
+			  case 'N':
+				if (match(&s, "an")) {
+#ifndef No_Hex_NaN
+					if (*s == '(' /*)*/
+					 && hexnan(&s, &fpinan, bits)
+							== STRTOG_NaNbits) {
+						word0(rv) = 0x7ff00000 | bits[1];
+						word1(rv) = bits[0];
+						}
+					else {
+						word0(rv) = NAN_WORD0;
+						word1(rv) = NAN_WORD1;
+						}
+#endif
+					goto ret;
+					}
+			  }
+#endif /* INFNAN_CHECK */
+ ret0:
+			s = s00;
+			sign = 0;
+			}
+		goto ret;
+		}
+	e1 = e -= nf;
+
+	/* Now we have nd0 digits, starting at s0, followed by a
+	 * decimal point, followed by nd-nd0 digits.  The number we're
+	 * after is the integer represented by those digits times
+	 * 10**e */
+
+	if (!nd0)
+		nd0 = nd;
+	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+	dval(rv) = y;
+	if (k > 9) {
+#ifdef SET_INEXACT
+		if (k > DBL_DIG)
+			oldinexact = get_inexact();
+#endif
+		dval(rv) = tens[k - 9] * dval(rv) + z;
+		}
+	bd0 = 0;
+	if (nd <= DBL_DIG
+#ifndef RND_PRODQUOT
+#ifndef Honor_FLT_ROUNDS
+		&& Flt_Rounds == 1
+#endif
+#endif
+			) {
+		if (!e)
+			goto ret;
+		if (e > 0) {
+			if (e <= Ten_pmax) {
+#ifdef VAX
+				goto vax_ovfl_check;
+#else
+#ifdef Honor_FLT_ROUNDS
+				/* round correctly FLT_ROUNDS = 2 or 3 */
+				if (sign) {
+					rv = -rv;
+					sign = 0;
+					}
+#endif
+				/* rv = */ rounded_product(dval(rv), tens[e]);
+				goto ret;
+#endif
+				}
+			i = DBL_DIG - nd;
+			if (e <= Ten_pmax + i) {
+				/* A fancier test would sometimes let us do
+				 * this for larger i values.
+				 */
+#ifdef Honor_FLT_ROUNDS
+				/* round correctly FLT_ROUNDS = 2 or 3 */
+				if (sign) {
+					rv = -rv;
+					sign = 0;
+					}
+#endif
+				e -= i;
+				dval(rv) *= tens[i];
+#ifdef VAX
+				/* VAX exponent range is so narrow we must
+				 * worry about overflow here...
+				 */
+ vax_ovfl_check:
+				word0(rv) -= P*Exp_msk1;
+				/* rv = */ rounded_product(dval(rv), tens[e]);
+				if ((word0(rv) & Exp_mask)
+				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+					goto ovfl;
+				word0(rv) += P*Exp_msk1;
+#else
+				/* rv = */ rounded_product(dval(rv), tens[e]);
+#endif
+				goto ret;
+				}
+			}
+#ifndef Inaccurate_Divide
+		else if (e >= -Ten_pmax) {
+#ifdef Honor_FLT_ROUNDS
+			/* round correctly FLT_ROUNDS = 2 or 3 */
+			if (sign) {
+				rv = -rv;
+				sign = 0;
+				}
+#endif
+			/* rv = */ rounded_quotient(dval(rv), tens[-e]);
+			goto ret;
+			}
+#endif
+		}
+	e1 += nd - k;
+
+#ifdef IEEE_Arith
+#ifdef SET_INEXACT
+	inexact = 1;
+	if (k <= DBL_DIG)
+		oldinexact = get_inexact();
+#endif
+#ifdef Avoid_Underflow
+	scale = 0;
+#endif
+#ifdef Honor_FLT_ROUNDS
+	if ((rounding = Flt_Rounds) >= 2) {
+		if (sign)
+			rounding = rounding == 2 ? 0 : 2;
+		else
+			if (rounding != 2)
+				rounding = 0;
+		}
+#endif
+#endif /*IEEE_Arith*/
+
+	/* Get starting approximation = rv * 10**e1 */
+
+	if (e1 > 0) {
+		if ( (i = e1 & 15) !=0)
+			dval(rv) *= tens[i];
+		if (e1 &= ~15) {
+			if (e1 > DBL_MAX_10_EXP) {
+ ovfl:
+#ifndef NO_ERRNO
+				errno = ERANGE;
+#endif
+				/* Can't trust HUGE_VAL */
+#ifdef IEEE_Arith
+#ifdef Honor_FLT_ROUNDS
+				switch(rounding) {
+				  case 0: /* toward 0 */
+				  case 3: /* toward -infinity */
+					word0(rv) = Big0;
+					word1(rv) = Big1;
+					break;
+				  default:
+					word0(rv) = Exp_mask;
+					word1(rv) = 0;
+				  }
+#else /*Honor_FLT_ROUNDS*/
+				word0(rv) = Exp_mask;
+				word1(rv) = 0;
+#endif /*Honor_FLT_ROUNDS*/
+#ifdef SET_INEXACT
+				/* set overflow bit */
+				dval(rv0) = 1e300;
+				dval(rv0) *= dval(rv0);
+#endif
+#else /*IEEE_Arith*/
+				word0(rv) = Big0;
+				word1(rv) = Big1;
+#endif /*IEEE_Arith*/
+				if (bd0)
+					goto retfree;
+				goto ret;
+				}
+			e1 >>= 4;
+			for(j = 0; e1 > 1; j++, e1 >>= 1)
+				if (e1 & 1)
+					dval(rv) *= bigtens[j];
+		/* The last multiplication could overflow. */
+			word0(rv) -= P*Exp_msk1;
+			dval(rv) *= bigtens[j];
+			if ((z = word0(rv) & Exp_mask)
+			 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
+				goto ovfl;
+			if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
+				/* set to largest number */
+				/* (Can't trust DBL_MAX) */
+				word0(rv) = Big0;
+				word1(rv) = Big1;
+				}
+			else
+				word0(rv) += P*Exp_msk1;
+			}
+		}
+	else if (e1 < 0) {
+		e1 = -e1;
+		if ( (i = e1 & 15) !=0)
+			dval(rv) /= tens[i];
+		if (e1 >>= 4) {
+			if (e1 >= 1 << n_bigtens)
+				goto undfl;
+#ifdef Avoid_Underflow
+			if (e1 & Scale_Bit)
+				scale = 2*P;
+			for(j = 0; e1 > 0; j++, e1 >>= 1)
+				if (e1 & 1)
+					dval(rv) *= tinytens[j];
+			if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
+						>> Exp_shift)) > 0) {
+				/* scaled rv is denormal; zap j low bits */
+				if (j >= 32) {
+					word1(rv) = 0;
+					if (j >= 53)
+					 word0(rv) = (P+2)*Exp_msk1;
+					else
+					 word0(rv) &= 0xffffffff << j-32;
+					}
+				else
+					word1(rv) &= 0xffffffff << j;
+				}
+#else
+			for(j = 0; e1 > 1; j++, e1 >>= 1)
+				if (e1 & 1)
+					dval(rv) *= tinytens[j];
+			/* The last multiplication could underflow. */
+			dval(rv0) = dval(rv);
+			dval(rv) *= tinytens[j];
+			if (!dval(rv)) {
+				dval(rv) = 2.*dval(rv0);
+				dval(rv) *= tinytens[j];
+#endif
+				if (!dval(rv)) {
+ undfl:
+					dval(rv) = 0.;
+#ifndef NO_ERRNO
+					errno = ERANGE;
+#endif
+					if (bd0)
+						goto retfree;
+					goto ret;
+					}
+#ifndef Avoid_Underflow
+				word0(rv) = Tiny0;
+				word1(rv) = Tiny1;
+				/* The refinement below will clean
+				 * this approximation up.
+				 */
+				}
+#endif
+			}
+		}
+
+	/* Now the hard part -- adjusting rv to the correct value.*/
+
+	/* Put digits into bd: true value = bd * 10^e */
+
+	bd0 = s2b(s0, nd0, nd, y);
+
+	for(;;) {
+		bd = Balloc(bd0->k);
+		Bcopy(bd, bd0);
+		bb = d2b(dval(rv), &bbe, &bbbits);	/* rv = bb * 2^bbe */
+		bs = i2b(1);
+
+		if (e >= 0) {
+			bb2 = bb5 = 0;
+			bd2 = bd5 = e;
+			}
+		else {
+			bb2 = bb5 = -e;
+			bd2 = bd5 = 0;
+			}
+		if (bbe >= 0)
+			bb2 += bbe;
+		else
+			bd2 -= bbe;
+		bs2 = bb2;
+#ifdef Honor_FLT_ROUNDS
+		if (rounding != 1)
+			bs2++;
+#endif
+#ifdef Avoid_Underflow
+		j = bbe - scale;
+		i = j + bbbits - 1;	/* logb(rv) */
+		if (i < Emin)	/* denormal */
+			j += P - Emin;
+		else
+			j = P + 1 - bbbits;
+#else /*Avoid_Underflow*/
+#ifdef Sudden_Underflow
+#ifdef IBM
+		j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
+#else
+		j = P + 1 - bbbits;
+#endif
+#else /*Sudden_Underflow*/
+		j = bbe;
+		i = j + bbbits - 1;	/* logb(rv) */
+		if (i < Emin)	/* denormal */
+			j += P - Emin;
+		else
+			j = P + 1 - bbbits;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+		bb2 += j;
+		bd2 += j;
+#ifdef Avoid_Underflow
+		bd2 += scale;
+#endif
+		i = bb2 < bd2 ? bb2 : bd2;
+		if (i > bs2)
+			i = bs2;
+		if (i > 0) {
+			bb2 -= i;
+			bd2 -= i;
+			bs2 -= i;
+			}
+		if (bb5 > 0) {
+			bs = pow5mult(bs, bb5);
+			bb1 = mult(bs, bb);
+			Bfree(bb);
+			bb = bb1;
+			}
+		if (bb2 > 0)
+			bb = lshift(bb, bb2);
+		if (bd5 > 0)
+			bd = pow5mult(bd, bd5);
+		if (bd2 > 0)
+			bd = lshift(bd, bd2);
+		if (bs2 > 0)
+			bs = lshift(bs, bs2);
+		delta = diff(bb, bd);
+		dsign = delta->sign;
+		delta->sign = 0;
+		i = cmp(delta, bs);
+#ifdef Honor_FLT_ROUNDS
+		if (rounding != 1) {
+			if (i < 0) {
+				/* Error is less than an ulp */
+				if (!delta->x[0] && delta->wds <= 1) {
+					/* exact */
+#ifdef SET_INEXACT
+					inexact = 0;
+#endif
+					break;
+					}
+				if (rounding) {
+					if (dsign) {
+						adj = 1.;
+						goto apply_adj;
+						}
+					}
+				else if (!dsign) {
+					adj = -1.;
+					if (!word1(rv)
+					 && !(word0(rv) & Frac_mask)) {
+						y = word0(rv) & Exp_mask;
+#ifdef Avoid_Underflow
+						if (!scale || y > 2*P*Exp_msk1)
+#else
+						if (y)
+#endif
+						  {
+						  delta = lshift(delta,Log2P);
+						  if (cmp(delta, bs) <= 0)
+							adj = -0.5;
+						  }
+						}
+ apply_adj:
+#ifdef Avoid_Underflow
+					if (scale && (y = word0(rv) & Exp_mask)
+						<= 2*P*Exp_msk1)
+					  word0(adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+					if ((word0(rv) & Exp_mask) <=
+							P*Exp_msk1) {
+						word0(rv) += P*Exp_msk1;
+						dval(rv) += adj*ulp(dval(rv));
+						word0(rv) -= P*Exp_msk1;
+						}
+					else
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+					dval(rv) += adj*ulp(dval(rv));
+					}
+				break;
+				}
+			adj = ratio(delta, bs);
+			if (adj < 1.)
+				adj = 1.;
+			if (adj <= 0x7ffffffe) {
+				/* adj = rounding ? ceil(adj) : floor(adj); */
+				y = adj;
+				if (y != adj) {
+					if (!((rounding>>1) ^ dsign))
+						y++;
+					adj = y;
+					}
+				}
+#ifdef Avoid_Underflow
+			if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+				word0(adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+			if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+				word0(rv) += P*Exp_msk1;
+				adj *= ulp(dval(rv));
+				if (dsign)
+					dval(rv) += adj;
+				else
+					dval(rv) -= adj;
+				word0(rv) -= P*Exp_msk1;
+				goto cont;
+				}
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+			adj *= ulp(dval(rv));
+			if (dsign)
+				dval(rv) += adj;
+			else
+				dval(rv) -= adj;
+			goto cont;
+			}
+#endif /*Honor_FLT_ROUNDS*/
+
+		if (i < 0) {
+			/* Error is less than half an ulp -- check for
+			 * special case of mantissa a power of two.
+			 */
+			if (dsign || word1(rv) || word0(rv) & Bndry_mask
+#ifdef IEEE_Arith
+#ifdef Avoid_Underflow
+			 || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+#else
+			 || (word0(rv) & Exp_mask) <= Exp_msk1
+#endif
+#endif
+				) {
+#ifdef SET_INEXACT
+				if (!delta->x[0] && delta->wds <= 1)
+					inexact = 0;
+#endif
+				break;
+				}
+			if (!delta->x[0] && delta->wds <= 1) {
+				/* exact result */
+#ifdef SET_INEXACT
+				inexact = 0;
+#endif
+				break;
+				}
+			delta = lshift(delta,Log2P);
+			if (cmp(delta, bs) > 0)
+				goto drop_down;
+			break;
+			}
+		if (i == 0) {
+			/* exactly half-way between */
+			if (dsign) {
+				if ((word0(rv) & Bndry_mask1) == Bndry_mask1
+				 &&  word1(rv) == (
+#ifdef Avoid_Underflow
+			(scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+		? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
+#endif
+						   0xffffffff)) {
+					/*boundary case -- increment exponent*/
+					word0(rv) = (word0(rv) & Exp_mask)
+						+ Exp_msk1
+#ifdef IBM
+						| Exp_msk1 >> 4
+#endif
+						;
+					word1(rv) = 0;
+#ifdef Avoid_Underflow
+					dsign = 0;
+#endif
+					break;
+					}
+				}
+			else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+ drop_down:
+				/* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow /*{{*/
+				L = word0(rv) & Exp_mask;
+#ifdef IBM
+				if (L <  Exp_msk1)
+#else
+#ifdef Avoid_Underflow
+				if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
+#else
+				if (L <= Exp_msk1)
+#endif /*Avoid_Underflow*/
+#endif /*IBM*/
+					goto undfl;
+				L -= Exp_msk1;
+#else /*Sudden_Underflow}{*/
+#ifdef Avoid_Underflow
+				if (scale) {
+					L = word0(rv) & Exp_mask;
+					if (L <= (2*P+1)*Exp_msk1) {
+						if (L > (P+2)*Exp_msk1)
+							/* round even ==> */
+							/* accept rv */
+							break;
+						/* rv = smallest denormal */
+						goto undfl;
+						}
+					}
+#endif /*Avoid_Underflow*/
+				L = (word0(rv) & Exp_mask) - Exp_msk1;
+#endif /*Sudden_Underflow}*/
+				word0(rv) = L | Bndry_mask1;
+				word1(rv) = 0xffffffff;
+#ifdef IBM
+				goto cont;
+#else
+				break;
+#endif
+				}
+#ifndef ROUND_BIASED
+			if (!(word1(rv) & LSB))
+				break;
+#endif
+			if (dsign)
+				dval(rv) += ulp(dval(rv));
+#ifndef ROUND_BIASED
+			else {
+				dval(rv) -= ulp(dval(rv));
+#ifndef Sudden_Underflow
+				if (!dval(rv))
+					goto undfl;
+#endif
+				}
+#ifdef Avoid_Underflow
+			dsign = 1 - dsign;
+#endif
+#endif
+			break;
+			}
+		if ((aadj = ratio(delta, bs)) <= 2.) {
+			if (dsign)
+				aadj = aadj1 = 1.;
+			else if (word1(rv) || word0(rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+				if (word1(rv) == Tiny1 && !word0(rv))
+					goto undfl;
+#endif
+				aadj = 1.;
+				aadj1 = -1.;
+				}
+			else {
+				/* special case -- power of FLT_RADIX to be */
+				/* rounded down... */
+
+				if (aadj < 2./FLT_RADIX)
+					aadj = 1./FLT_RADIX;
+				else
+					aadj *= 0.5;
+				aadj1 = -aadj;
+				}
+			}
+		else {
+			aadj *= 0.5;
+			aadj1 = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+			switch(Rounding) {
+				case 2: /* towards +infinity */
+					aadj1 -= 0.5;
+					break;
+				case 0: /* towards 0 */
+				case 3: /* towards -infinity */
+					aadj1 += 0.5;
+				}
+#else
+			if (Flt_Rounds == 0)
+				aadj1 += 0.5;
+#endif /*Check_FLT_ROUNDS*/
+			}
+		y = word0(rv) & Exp_mask;
+
+		/* Check for overflow */
+
+		if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
+			dval(rv0) = dval(rv);
+			word0(rv) -= P*Exp_msk1;
+			adj = aadj1 * ulp(dval(rv));
+			dval(rv) += adj;
+			if ((word0(rv) & Exp_mask) >=
+					Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
+				if (word0(rv0) == Big0 && word1(rv0) == Big1)
+					goto ovfl;
+				word0(rv) = Big0;
+				word1(rv) = Big1;
+				goto cont;
+				}
+			else
+				word0(rv) += P*Exp_msk1;
+			}
+		else {
+#ifdef Avoid_Underflow
+			if (scale && y <= 2*P*Exp_msk1) {
+				if (aadj <= 0x7fffffff) {
+					if ((z = aadj) <= 0)
+						z = 1;
+					aadj = z;
+					aadj1 = dsign ? aadj : -aadj;
+					}
+				word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+				}
+			adj = aadj1 * ulp(dval(rv));
+			dval(rv) += adj;
+#else
+#ifdef Sudden_Underflow
+			if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+				dval(rv0) = dval(rv);
+				word0(rv) += P*Exp_msk1;
+				adj = aadj1 * ulp(dval(rv));
+				dval(rv) += adj;
+#ifdef IBM
+				if ((word0(rv) & Exp_mask) <  P*Exp_msk1)
+#else
+				if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+#endif
+					{
+					if (word0(rv0) == Tiny0
+					 && word1(rv0) == Tiny1)
+						goto undfl;
+					word0(rv) = Tiny0;
+					word1(rv) = Tiny1;
+					goto cont;
+					}
+				else
+					word0(rv) -= P*Exp_msk1;
+				}
+			else {
+				adj = aadj1 * ulp(dval(rv));
+				dval(rv) += adj;
+				}
+#else /*Sudden_Underflow*/
+			/* Compute adj so that the IEEE rounding rules will
+			 * correctly round rv + adj in some half-way cases.
+			 * If rv * ulp(rv) is denormalized (i.e.,
+			 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
+			 * trouble from bits lost to denormalization;
+			 * example: 1.2e-307 .
+			 */
+			if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
+				aadj1 = (double)(int)(aadj + 0.5);
+				if (!dsign)
+					aadj1 = -aadj1;
+				}
+			adj = aadj1 * ulp(dval(rv));
+			dval(rv) += adj;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+			}
+		z = word0(rv) & Exp_mask;
+#ifndef SET_INEXACT
+#ifdef Avoid_Underflow
+		if (!scale)
+#endif
+		if (y == z) {
+			/* Can we stop now? */
+			L = (Long)aadj;
+			aadj -= L;
+			/* The tolerances below are conservative. */
+			if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+				if (aadj < .4999999 || aadj > .5000001)
+					break;
+				}
+			else if (aadj < .4999999/FLT_RADIX)
+				break;
+			}
+#endif
+ cont:
+		Bfree(bb);
+		Bfree(bd);
+		Bfree(bs);
+		Bfree(delta);
+		}
+#ifdef SET_INEXACT
+	if (inexact) {
+		if (!oldinexact) {
+			word0(rv0) = Exp_1 + (70 << Exp_shift);
+			word1(rv0) = 0;
+			dval(rv0) += 1.;
+			}
+		}
+	else if (!oldinexact)
+		clear_inexact();
+#endif
+#ifdef Avoid_Underflow
+	if (scale) {
+		word0(rv0) = Exp_1 - 2*P*Exp_msk1;
+		word1(rv0) = 0;
+		dval(rv) *= dval(rv0);
+#ifndef NO_ERRNO
+		/* try to avoid the bug of testing an 8087 register value */
+		if (word0(rv) == 0 && word1(rv) == 0)
+			errno = ERANGE;
+#endif
+		}
+#endif /* Avoid_Underflow */
+#ifdef SET_INEXACT
+	if (inexact && !(word0(rv) & Exp_mask)) {
+		/* set underflow bit */
+		dval(rv0) = 1e-300;
+		dval(rv0) *= dval(rv0);
+		}
+#endif
+ retfree:
+	Bfree(bb);
+	Bfree(bd);
+	Bfree(bs);
+	Bfree(bd0);
+	Bfree(delta);
+ ret:
+	if (se)
+		*se = (char *)s;
+	return sign ? -dval(rv) : dval(rv);
+	}
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtodI.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtodI.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtodI.c	(revision 2448)
@@ -0,0 +1,177 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ static double
+#ifdef KR_headers
+ulpdown(d) double *d;
+#else
+ulpdown(double *d)
+#endif
+{
+	double u;
+	ULong *L = (ULong*)d;
+
+	u = ulp(*d);
+	if (!(L[_1] | L[_0] & 0xfffff)
+	 && (L[_0] & 0x7ff00000) > 0x00100000)
+		u *= 0.5;
+	return u;
+	}
+
+ int
+#ifdef KR_headers
+strtodI(s, sp, dd) CONST char *s; char **sp; double *dd;
+#else
+strtodI(CONST char *s, char **sp, double *dd)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 1 };
+#else
+	static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
+#endif
+	ULong bits[2], sign;
+	Long exp;
+	int j, k;
+	typedef union {
+		double d[2];
+		ULong L[4];
+		} U;
+	U *u;
+
+	k = strtodg(s, sp, &fpi, &exp, bits);
+	u = (U*)dd;
+	sign = k & STRTOG_Neg ? 0x80000000L : 0;
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+		u->d[0] = u->d[1] = 0.;
+		break;
+
+	  case STRTOG_Zero:
+		u->d[0] = u->d[1] = 0.;
+#ifdef Sudden_Underflow
+		if (k & STRTOG_Inexact) {
+			if (sign)
+				u->L[_0] = 0x80100000L;
+			else
+				u->L[2+_0] = 0x100000L;
+			}
+		break;
+#else
+		goto contain;
+#endif
+
+	  case STRTOG_Denormal:
+		u->L[_1] = bits[0];
+		u->L[_0] = bits[1];
+		goto contain;
+
+	  case STRTOG_Normal:
+		u->L[_1] = bits[0];
+		u->L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20);
+	  contain:
+		j = k & STRTOG_Inexact;
+		if (sign) {
+			u->L[_0] |= sign;
+			j = STRTOG_Inexact - j;
+			}
+		switch(j) {
+		  case STRTOG_Inexlo:
+#ifdef Sudden_Underflow
+			if ((u->L[_0] & 0x7ff00000) < 0x3500000) {
+				u->L[2+_0] = u->L[_0] + 0x3500000;
+				u->L[2+_1] = u->L[_1];
+				u->d[1] += ulp(u->d[1]);
+				u->L[2+_0] -= 0x3500000;
+				if (!(u->L[2+_0] & 0x7ff00000)) {
+					u->L[2+_0] = sign;
+					u->L[2+_1] = 0;
+					}
+				}
+			else
+#endif
+			u->d[1] = u->d[0] + ulp(u->d[0]);
+			break;
+		  case STRTOG_Inexhi:
+			u->d[1] = u->d[0];
+#ifdef Sudden_Underflow
+			if ((u->L[_0] & 0x7ff00000) < 0x3500000) {
+				u->L[_0] += 0x3500000;
+				u->d[0] -= ulpdown(u->d);
+				u->L[_0] -= 0x3500000;
+				if (!(u->L[_0] & 0x7ff00000)) {
+					u->L[_0] = sign;
+					u->L[_1] = 0;
+					}
+				}
+			else
+#endif
+			u->d[0] -= ulpdown(u->d);
+			break;
+		  default:
+			u->d[1] = u->d[0];
+		  }
+		break;
+
+	  case STRTOG_Infinite:
+		u->L[_0] = u->L[2+_0] = sign | 0x7ff00000;
+		u->L[_1] = u->L[2+_1] = 0;
+		if (k & STRTOG_Inexact) {
+			if (sign) {
+				u->L[2+_0] = 0xffefffffL;
+				u->L[2+_1] = 0xffffffffL;
+				}
+			else {
+				u->L[_0] = 0x7fefffffL;
+				u->L[_1] = 0xffffffffL;
+				}
+			}
+		break;
+
+	  case STRTOG_NaN:
+		u->L[_0] = u->L[2+_0] = 0x7fffffff | sign;
+		u->L[_1] = u->L[2+_1] = (ULong)-1;
+		break;
+
+	  case STRTOG_NaNbits:
+		u->L[_0] = u->L[2+_0] = 0x7ff00000 | sign | bits[1];
+		u->L[_1] = u->L[2+_1] = bits[0];
+	  }
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtodg.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtodg.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtodg.c	(revision 2448)
@@ -0,0 +1,1001 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	dmg@acm.org
+ */
+
+#include "gdtoaimp.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+ static CONST int
+fivesbits[] = {	 0,  3,  5,  7, 10, 12, 14, 17, 19, 21,
+		24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
+		47, 49, 52
+#ifdef VAX
+		, 54, 56
+#endif
+		};
+
+ Bigint *
+#ifdef KR_headers
+increment(b) Bigint *b;
+#else
+increment(Bigint *b)
+#endif
+{
+	ULong *x, *xe;
+	Bigint *b1;
+#ifdef Pack_16
+	ULong carry = 1, y;
+#endif
+
+	x = b->x;
+	xe = x + b->wds;
+#ifdef Pack_32
+	do {
+		if (*x < (ULong)0xffffffffL) {
+			++*x;
+			return b;
+			}
+		*x++ = 0;
+		} while(x < xe);
+#else
+	do {
+		y = *x + carry;
+		carry = y >> 16;
+		*x++ = y & 0xffff;
+		if (!carry)
+			return b;
+		} while(x < xe);
+	if (carry)
+#endif
+	{
+		if (b->wds >= b->maxwds) {
+			b1 = Balloc(b->k+1);
+			Bcopy(b1,b);
+			Bfree(b);
+			b = b1;
+			}
+		b->x[b->wds++] = 1;
+		}
+	return b;
+	}
+
+ int
+#ifdef KR_headers
+decrement(b) Bigint *b;
+#else
+decrement(Bigint *b)
+#endif
+{
+	ULong *x, *xe;
+#ifdef Pack_16
+	ULong borrow = 1, y;
+#endif
+
+	x = b->x;
+	xe = x + b->wds;
+#ifdef Pack_32
+	do {
+		if (*x) {
+			--*x;
+			break;
+			}
+		*x++ = 0xffffffffL;
+		}
+		while(x < xe);
+#else
+	do {
+		y = *x - borrow;
+		borrow = (y & 0x10000) >> 16;
+		*x++ = y & 0xffff;
+		} while(borrow && x < xe);
+#endif
+	return STRTOG_Inexlo;
+	}
+
+ static int
+#ifdef KR_headers
+all_on(b, n) Bigint *b; int n;
+#else
+all_on(Bigint *b, int n)
+#endif
+{
+	ULong *x, *xe;
+
+	x = b->x;
+	xe = x + (n >> kshift);
+	while(x < xe)
+		if ((*x++ & ALL_ON) != ALL_ON)
+			return 0;
+	if (n &= kmask)
+		return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
+	return 1;
+	}
+
+ Bigint *
+#ifdef KR_headers
+set_ones(b, n) Bigint *b; int n;
+#else
+set_ones(Bigint *b, int n)
+#endif
+{
+	int k;
+	ULong *x, *xe;
+
+	k = (n + ((1 << kshift) - 1)) >> kshift;
+	if (b->k < k) {
+		Bfree(b);
+		b = Balloc(k);
+		}
+	k = n >> kshift;
+	if (n &= kmask)
+		k++;
+	b->wds = k;
+	x = b->x;
+	xe = x + k;
+	while(x < xe)
+		*x++ = ALL_ON;
+	if (n)
+		x[-1] >>= ULbits - n;
+	return b;
+	}
+
+ static int
+rvOK
+#ifdef KR_headers
+ (d, fpi, exp, bits, exact, rd, irv)
+ double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
+#else
+ (double d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
+#endif
+{
+	Bigint *b;
+	ULong carry, inex, lostbits;
+	int bdif, e, j, k, k1, nb, rv;
+
+	carry = rv = 0;
+	b = d2b(d, &e, &bdif);
+	bdif -= nb = fpi->nbits;
+	e += bdif;
+	if (bdif <= 0) {
+		if (exact)
+			goto trunc;
+		goto ret;
+		}
+	if (P == nb) {
+		if (
+#ifndef IMPRECISE_INEXACT
+			exact &&
+#endif
+			fpi->rounding ==
+#ifdef RND_PRODQUOT
+					FPI_Round_near
+#else
+					Flt_Rounds
+#endif
+			) goto trunc;
+		goto ret;
+		}
+	switch(rd) {
+	  case 1:
+		goto trunc;
+	  case 2:
+		break;
+	  default: /* round near */
+		k = bdif - 1;
+		if (k < 0)
+			goto trunc;
+		if (!k) {
+			if (!exact)
+				goto ret;
+			if (b->x[0] & 2)
+				break;
+			goto trunc;
+			}
+		if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
+			break;
+		goto trunc;
+	  }
+	/* "break" cases: round up 1 bit, then truncate; bdif > 0 */
+	carry = 1;
+ trunc:
+	inex = lostbits = 0;
+	if (bdif > 0) {
+		if ( (lostbits = any_on(b, bdif)) !=0)
+			inex = STRTOG_Inexlo;
+		rshift(b, bdif);
+		if (carry) {
+			inex = STRTOG_Inexhi;
+			b = increment(b);
+			if ( (j = nb & kmask) !=0)
+				j = 32 - j;
+			if (hi0bits(b->x[b->wds - 1]) != j) {
+				if (!lostbits)
+					lostbits = b->x[0] & 1;
+				rshift(b, 1);
+				e++;
+				}
+			}
+		}
+	else if (bdif < 0)
+		b = lshift(b, -bdif);
+	if (e < fpi->emin) {
+		k = fpi->emin - e;
+		e = fpi->emin;
+		if (k > nb || fpi->sudden_underflow) {
+			b->wds = inex = 0;
+			*irv = STRTOG_Underflow | STRTOG_Inexlo;
+			}
+		else {
+			k1 = k - 1;
+			if (k1 > 0 && !lostbits)
+				lostbits = any_on(b, k1);
+			if (!lostbits && !exact)
+				goto ret;
+			lostbits |=
+			  carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
+			rshift(b, k);
+			*irv = STRTOG_Denormal;
+			if (carry) {
+				b = increment(b);
+				inex = STRTOG_Inexhi | STRTOG_Underflow;
+				}
+			else if (lostbits)
+				inex = STRTOG_Inexlo | STRTOG_Underflow;
+			}
+		}
+	else if (e > fpi->emax) {
+		e = fpi->emax + 1;
+		*irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
+#ifndef NO_ERRNO
+		errno = ERANGE;
+#endif
+		b->wds = inex = 0;
+		}
+	*exp = e;
+	copybits(bits, nb, b);
+	*irv |= inex;
+	rv = 1;
+ ret:
+	Bfree(b);
+	return rv;
+	}
+
+ static int
+#ifdef KR_headers
+mantbits(d) double d;
+#else
+mantbits(double d)
+#endif
+{
+	ULong L;
+#ifdef VAX
+	L = word1(d) << 16 | word1(d) >> 16;
+	if (L)
+#else
+	if ( (L = word1(d)) !=0)
+#endif
+		return P - lo0bits(&L);
+#ifdef VAX
+	L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
+#else
+	L = word0(d) | Exp_msk1;
+#endif
+	return P - 32 - lo0bits(&L);
+	}
+
+ int
+strtodg
+#ifdef KR_headers
+	(s00, se, fpi, exp, bits)
+	CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
+#else
+	(CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
+#endif
+{
+	int abe, abits, asub;
+	int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2;
+	int c, denorm, dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
+	int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
+	int sudden_underflow;
+	CONST char *s, *s0, *s1;
+	double adj, adj0, rv, tol;
+	Long L;
+	ULong y, z;
+	Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
+
+	irv = STRTOG_Zero;
+	denorm = sign = nz0 = nz = 0;
+	dval(rv) = 0.;
+	rvb = 0;
+	nbits = fpi->nbits;
+	for(s = s00;;s++) switch(*s) {
+		case '-':
+			sign = 1;
+			/* no break */
+		case '+':
+			if (*++s)
+				goto break2;
+			/* no break */
+		case 0:
+			sign = 0;
+			irv = STRTOG_NoNumber;
+			s = s00;
+			goto ret;
+		case '\t':
+		case '\n':
+		case '\v':
+		case '\f':
+		case '\r':
+		case ' ':
+			continue;
+		default:
+			goto break2;
+		}
+ break2:
+	if (*s == '0') {
+#ifndef NO_HEX_FP
+		switch(s[1]) {
+		  case 'x':
+		  case 'X':
+			irv = gethex(&s, fpi, exp, &rvb, sign);
+			if (irv == STRTOG_NoNumber) {
+				s = s00;
+				sign = 0;
+				}
+			goto ret;
+		  }
+#endif
+		nz0 = 1;
+		while(*++s == '0') ;
+		if (!*s)
+			goto ret;
+		}
+	sudden_underflow = fpi->sudden_underflow;
+	s0 = s;
+	y = z = 0;
+	for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+		if (nd < 9)
+			y = 10*y + c - '0';
+		else if (nd < 16)
+			z = 10*z + c - '0';
+	nd0 = nd;
+#ifdef USE_LOCALE
+	if (c == *localeconv()->decimal_point)
+#else
+	if (c == '.')
+#endif
+		{
+		c = *++s;
+		if (!nd) {
+			for(; c == '0'; c = *++s)
+				nz++;
+			if (c > '0' && c <= '9') {
+				s0 = s;
+				nf += nz;
+				nz = 0;
+				goto have_dig;
+				}
+			goto dig_done;
+			}
+		for(; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+			nz++;
+			if (c -= '0') {
+				nf += nz;
+				for(i = 1; i < nz; i++)
+					if (nd++ < 9)
+						y *= 10;
+					else if (nd <= DBL_DIG + 1)
+						z *= 10;
+				if (nd++ < 9)
+					y = 10*y + c;
+				else if (nd <= DBL_DIG + 1)
+					z = 10*z + c;
+				nz = 0;
+				}
+			}
+		}
+ dig_done:
+	e = 0;
+	if (c == 'e' || c == 'E') {
+		if (!nd && !nz && !nz0) {
+			irv = STRTOG_NoNumber;
+			s = s00;
+			goto ret;
+			}
+		s00 = s;
+		esign = 0;
+		switch(c = *++s) {
+			case '-':
+				esign = 1;
+			case '+':
+				c = *++s;
+			}
+		if (c >= '0' && c <= '9') {
+			while(c == '0')
+				c = *++s;
+			if (c > '0' && c <= '9') {
+				L = c - '0';
+				s1 = s;
+				while((c = *++s) >= '0' && c <= '9')
+					L = 10*L + c - '0';
+				if (s - s1 > 8 || L > 19999)
+					/* Avoid confusion from exponents
+					 * so large that e might overflow.
+					 */
+					e = 19999; /* safe for 16 bit ints */
+				else
+					e = (int)L;
+				if (esign)
+					e = -e;
+				}
+			else
+				e = 0;
+			}
+		else
+			s = s00;
+		}
+	if (!nd) {
+		if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+			/* Check for Nan and Infinity */
+			switch(c) {
+			  case 'i':
+			  case 'I':
+				if (match(&s,"nf")) {
+					--s;
+					if (!match(&s,"inity"))
+						++s;
+					irv = STRTOG_Infinite;
+					goto infnanexp;
+					}
+				break;
+			  case 'n':
+			  case 'N':
+				if (match(&s, "an")) {
+					irv = STRTOG_NaN;
+					*exp = fpi->emax + 1;
+#ifndef No_Hex_NaN
+					if (*s == '(') /*)*/
+						irv = hexnan(&s, fpi, bits);
+#endif
+					goto infnanexp;
+					}
+			  }
+#endif /* INFNAN_CHECK */
+			irv = STRTOG_NoNumber;
+			s = s00;
+			}
+		goto ret;
+		}
+
+	irv = STRTOG_Normal;
+	e1 = e -= nf;
+	rd = 0;
+	switch(fpi->rounding & 3) {
+	  case FPI_Round_up:
+		rd = 2 - sign;
+		break;
+	  case FPI_Round_zero:
+		rd = 1;
+		break;
+	  case FPI_Round_down:
+		rd = 1 + sign;
+	  }
+
+	/* Now we have nd0 digits, starting at s0, followed by a
+	 * decimal point, followed by nd-nd0 digits.  The number we're
+	 * after is the integer represented by those digits times
+	 * 10**e */
+
+	if (!nd0)
+		nd0 = nd;
+	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+	dval(rv) = y;
+	if (k > 9)
+		dval(rv) = tens[k - 9] * dval(rv) + z;
+	bd0 = 0;
+	if (nbits <= P && nd <= DBL_DIG) {
+		if (!e) {
+			if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv))
+				goto ret;
+			}
+		else if (e > 0) {
+			if (e <= Ten_pmax) {
+#ifdef VAX
+				goto vax_ovfl_check;
+#else
+				i = fivesbits[e] + mantbits(dval(rv)) <= P;
+				/* rv = */ rounded_product(dval(rv), tens[e]);
+				if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
+					goto ret;
+				e1 -= e;
+				goto rv_notOK;
+#endif
+				}
+			i = DBL_DIG - nd;
+			if (e <= Ten_pmax + i) {
+				/* A fancier test would sometimes let us do
+				 * this for larger i values.
+				 */
+				e2 = e - i;
+				e1 -= i;
+				dval(rv) *= tens[i];
+#ifdef VAX
+				/* VAX exponent range is so narrow we must
+				 * worry about overflow here...
+				 */
+ vax_ovfl_check:
+				dval(adj) = dval(rv);
+				word0(adj) -= P*Exp_msk1;
+				/* adj = */ rounded_product(dval(adj), tens[e2]);
+				if ((word0(adj) & Exp_mask)
+				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+					goto rv_notOK;
+				word0(adj) += P*Exp_msk1;
+				dval(rv) = dval(adj);
+#else
+				/* rv = */ rounded_product(dval(rv), tens[e2]);
+#endif
+				if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+					goto ret;
+				e1 -= e2;
+				}
+			}
+#ifndef Inaccurate_Divide
+		else if (e >= -Ten_pmax) {
+			/* rv = */ rounded_quotient(dval(rv), tens[-e]);
+			if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+				goto ret;
+			e1 -= e;
+			}
+#endif
+		}
+ rv_notOK:
+	e1 += nd - k;
+
+	/* Get starting approximation = rv * 10**e1 */
+
+	e2 = 0;
+	if (e1 > 0) {
+		if ( (i = e1 & 15) !=0)
+			dval(rv) *= tens[i];
+		if (e1 &= ~15) {
+			e1 >>= 4;
+			while(e1 >= (1 << n_bigtens-1)) {
+				e2 += ((word0(rv) & Exp_mask)
+					>> Exp_shift1) - Bias;
+				word0(rv) &= ~Exp_mask;
+				word0(rv) |= Bias << Exp_shift1;
+				dval(rv) *= bigtens[n_bigtens-1];
+				e1 -= 1 << n_bigtens-1;
+				}
+			e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
+			word0(rv) &= ~Exp_mask;
+			word0(rv) |= Bias << Exp_shift1;
+			for(j = 0; e1 > 0; j++, e1 >>= 1)
+				if (e1 & 1)
+					dval(rv) *= bigtens[j];
+			}
+		}
+	else if (e1 < 0) {
+		e1 = -e1;
+		if ( (i = e1 & 15) !=0)
+			dval(rv) /= tens[i];
+		if (e1 &= ~15) {
+			e1 >>= 4;
+			while(e1 >= (1 << n_bigtens-1)) {
+				e2 += ((word0(rv) & Exp_mask)
+					>> Exp_shift1) - Bias;
+				word0(rv) &= ~Exp_mask;
+				word0(rv) |= Bias << Exp_shift1;
+				dval(rv) *= tinytens[n_bigtens-1];
+				e1 -= 1 << n_bigtens-1;
+				}
+			e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
+			word0(rv) &= ~Exp_mask;
+			word0(rv) |= Bias << Exp_shift1;
+			for(j = 0; e1 > 0; j++, e1 >>= 1)
+				if (e1 & 1)
+					dval(rv) *= tinytens[j];
+			}
+		}
+
+	rvb = d2b(dval(rv), &rve, &rvbits);	/* rv = rvb * 2^rve */
+	rve += e2;
+	if ((j = rvbits - nbits) > 0) {
+		rshift(rvb, j);
+		rvbits = nbits;
+		rve += j;
+		}
+	bb0 = 0;	/* trailing zero bits in rvb */
+	e2 = rve + rvbits - nbits;
+	if (e2 > fpi->emax) {
+		rvb->wds = 0;
+		irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
+#ifndef NO_ERRNO
+		errno = ERANGE;
+#endif
+ infnanexp:
+		*exp = fpi->emax + 1;
+		goto ret;
+		}
+	rve1 = rve + rvbits - nbits;
+	if (e2 < (emin = fpi->emin)) {
+		denorm = 1;
+		j = rve - emin;
+		if (j > 0) {
+			rvb = lshift(rvb, j);
+			rvbits += j;
+			}
+		else if (j < 0) {
+			rvbits += j;
+			if (rvbits <= 0) {
+				if (rvbits < -1) {
+ ufl:
+					rvb->wds = 0;
+					rvb->x[0] = 0;
+					*exp = emin;
+					irv = STRTOG_Underflow | STRTOG_Inexlo;
+					goto ret;
+					}
+				rvb->x[0] = rvb->wds = rvbits = 1;
+				}
+			else
+				rshift(rvb, -j);
+			}
+		rve = rve1 = emin;
+		if (sudden_underflow && e2 + 1 < emin)
+			goto ufl;
+		}
+
+	/* Now the hard part -- adjusting rv to the correct value.*/
+
+	/* Put digits into bd: true value = bd * 10^e */
+
+	bd0 = s2b(s0, nd0, nd, y);
+
+	for(;;) {
+		bd = Balloc(bd0->k);
+		Bcopy(bd, bd0);
+		bb = Balloc(rvb->k);
+		Bcopy(bb, rvb);
+		bbbits = rvbits - bb0;
+		bbe = rve + bb0;
+		bs = i2b(1);
+
+		if (e >= 0) {
+			bb2 = bb5 = 0;
+			bd2 = bd5 = e;
+			}
+		else {
+			bb2 = bb5 = -e;
+			bd2 = bd5 = 0;
+			}
+		if (bbe >= 0)
+			bb2 += bbe;
+		else
+			bd2 -= bbe;
+		bs2 = bb2;
+		j = nbits + 1 - bbbits;
+		i = bbe + bbbits - nbits;
+		if (i < emin)	/* denormal */
+			j += i - emin;
+		bb2 += j;
+		bd2 += j;
+		i = bb2 < bd2 ? bb2 : bd2;
+		if (i > bs2)
+			i = bs2;
+		if (i > 0) {
+			bb2 -= i;
+			bd2 -= i;
+			bs2 -= i;
+			}
+		if (bb5 > 0) {
+			bs = pow5mult(bs, bb5);
+			bb1 = mult(bs, bb);
+			Bfree(bb);
+			bb = bb1;
+			}
+		bb2 -= bb0;
+		if (bb2 > 0)
+			bb = lshift(bb, bb2);
+		else if (bb2 < 0)
+			rshift(bb, -bb2);
+		if (bd5 > 0)
+			bd = pow5mult(bd, bd5);
+		if (bd2 > 0)
+			bd = lshift(bd, bd2);
+		if (bs2 > 0)
+			bs = lshift(bs, bs2);
+		asub = 1;
+		inex = STRTOG_Inexhi;
+		delta = diff(bb, bd);
+		if (delta->wds <= 1 && !delta->x[0])
+			break;
+		dsign = delta->sign;
+		delta->sign = finished = 0;
+		L = 0;
+		i = cmp(delta, bs);
+		if (rd && i <= 0) {
+			irv = STRTOG_Normal;
+			if ( (finished = dsign ^ (rd&1)) !=0) {
+				if (dsign != 0) {
+					irv |= STRTOG_Inexhi;
+					goto adj1;
+					}
+				irv |= STRTOG_Inexlo;
+				if (rve1 == emin)
+					goto adj1;
+				for(i = 0, j = nbits; j >= ULbits;
+						i++, j -= ULbits) {
+					if (rvb->x[i] & ALL_ON)
+						goto adj1;
+					}
+				if (j > 1 && lo0bits(rvb->x + i) < j - 1)
+					goto adj1;
+				rve = rve1 - 1;
+				rvb = set_ones(rvb, rvbits = nbits);
+				break;
+				}
+			irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
+			break;
+			}
+		if (i < 0) {
+			/* Error is less than half an ulp -- check for
+			 * special case of mantissa a power of two.
+			 */
+			irv = dsign
+				? STRTOG_Normal | STRTOG_Inexlo
+				: STRTOG_Normal | STRTOG_Inexhi;
+			if (dsign || bbbits > 1 || denorm || rve1 == emin)
+				break;
+			delta = lshift(delta,1);
+			if (cmp(delta, bs) > 0) {
+				irv = STRTOG_Normal | STRTOG_Inexlo;
+				goto drop_down;
+				}
+			break;
+			}
+		if (i == 0) {
+			/* exactly half-way between */
+			if (dsign) {
+				if (denorm && all_on(rvb, rvbits)) {
+					/*boundary case -- increment exponent*/
+					rvb->wds = 1;
+					rvb->x[0] = 1;
+					rve = emin + nbits - (rvbits = 1);
+					irv = STRTOG_Normal | STRTOG_Inexhi;
+					denorm = 0;
+					break;
+					}
+				irv = STRTOG_Normal | STRTOG_Inexlo;
+				}
+			else if (bbbits == 1) {
+				irv = STRTOG_Normal;
+ drop_down:
+				/* boundary case -- decrement exponent */
+				if (rve1 == emin) {
+					irv = STRTOG_Normal | STRTOG_Inexhi;
+					if (rvb->wds == 1 && rvb->x[0] == 1)
+						sudden_underflow = 1;
+					break;
+					}
+				rve -= nbits;
+				rvb = set_ones(rvb, rvbits = nbits);
+				break;
+				}
+			else
+				irv = STRTOG_Normal | STRTOG_Inexhi;
+			if (bbbits < nbits && !denorm || !(rvb->x[0] & 1))
+				break;
+			if (dsign) {
+				rvb = increment(rvb);
+				if ( (j = rvbits >> kshift) !=0)
+					j = 32 - j;
+				if (hi0bits(rvb->x[(rvb->wds - 1) >> kshift])
+						!= j)
+					rvbits++;
+				irv = STRTOG_Normal | STRTOG_Inexhi;
+				}
+			else {
+				if (bbbits == 1)
+					goto undfl;
+				decrement(rvb);
+				irv = STRTOG_Normal | STRTOG_Inexlo;
+				}
+			break;
+			}
+		if ((dval(adj) = ratio(delta, bs)) <= 2.) {
+ adj1:
+			inex = STRTOG_Inexlo;
+			if (dsign) {
+				asub = 0;
+				inex = STRTOG_Inexhi;
+				}
+			else if (denorm && bbbits <= 1) {
+ undfl:
+				rvb->wds = 0;
+				rve = emin;
+				irv = STRTOG_Underflow | STRTOG_Inexlo;
+				break;
+				}
+			adj0 = dval(adj) = 1.;
+			}
+		else {
+			adj0 = dval(adj) *= 0.5;
+			if (dsign) {
+				asub = 0;
+				inex = STRTOG_Inexlo;
+				}
+			if (dval(adj) < 2147483647.) {
+				L = adj0;
+				adj0 -= L;
+				switch(rd) {
+				  case 0:
+					if (adj0 >= .5)
+						goto inc_L;
+					break;
+				  case 1:
+					if (asub && adj0 > 0.)
+						goto inc_L;
+					break;
+				  case 2:
+					if (!asub && adj0 > 0.) {
+ inc_L:
+						L++;
+						inex = STRTOG_Inexact - inex;
+						}
+				  }
+				dval(adj) = L;
+				}
+			}
+		y = rve + rvbits;
+
+		/* adj *= ulp(dval(rv)); */
+		/* if (asub) rv -= adj; else rv += adj; */
+
+		if (!denorm && rvbits < nbits) {
+			rvb = lshift(rvb, j = nbits - rvbits);
+			rve -= j;
+			rvbits = nbits;
+			}
+		ab = d2b(dval(adj), &abe, &abits);
+		if (abe < 0)
+			rshift(ab, -abe);
+		else if (abe > 0)
+			ab = lshift(ab, abe);
+		rvb0 = rvb;
+		if (asub) {
+			/* rv -= adj; */
+			j = hi0bits(rvb->x[rvb->wds-1]);
+			rvb = diff(rvb, ab);
+			k = rvb0->wds - 1;
+			if (denorm)
+				/* do nothing */;
+			else if (rvb->wds <= k
+				|| hi0bits( rvb->x[k]) >
+				   hi0bits(rvb0->x[k])) {
+				/* unlikely; can only have lost 1 high bit */
+				if (rve1 == emin) {
+					--rvbits;
+					denorm = 1;
+					}
+				else {
+					rvb = lshift(rvb, 1);
+					--rve;
+					--rve1;
+					L = finished = 0;
+					}
+				}
+			}
+		else {
+			rvb = sum(rvb, ab);
+			k = rvb->wds - 1;
+			if (k >= rvb0->wds
+			 || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
+				if (denorm) {
+					if (++rvbits == nbits)
+						denorm = 0;
+					}
+				else {
+					rshift(rvb, 1);
+					rve++;
+					rve1++;
+					L = 0;
+					}
+				}
+			}
+		Bfree(ab);
+		Bfree(rvb0);
+		if (finished)
+			break;
+
+		z = rve + rvbits;
+		if (y == z && L) {
+			/* Can we stop now? */
+			tol = dval(adj) * 5e-16; /* > max rel error */
+			dval(adj) = adj0 - .5;
+			if (dval(adj) < -tol) {
+				if (adj0 > tol) {
+					irv |= inex;
+					break;
+					}
+				}
+			else if (dval(adj) > tol && adj0 < 1. - tol) {
+				irv |= inex;
+				break;
+				}
+			}
+		bb0 = denorm ? 0 : trailz(rvb);
+		Bfree(bb);
+		Bfree(bd);
+		Bfree(bs);
+		Bfree(delta);
+		}
+	if (!denorm && rvbits < nbits) {
+		j = nbits - rvbits;
+		rvb = lshift(rvb, j);
+		rve -= j;
+		}
+	*exp = rve;
+	Bfree(bb);
+	Bfree(bd);
+	Bfree(bs);
+	Bfree(bd0);
+	Bfree(delta);
+ ret:
+	if (denorm) {
+		if (sudden_underflow) {
+			rvb->wds = 0;
+			irv = STRTOG_Underflow | STRTOG_Inexlo;
+			}
+		else  {
+			irv = (irv & ~STRTOG_Retmask) |
+				(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
+			if (irv & STRTOG_Inexact)
+				irv |= STRTOG_Underflow;
+			}
+		}
+	if (se)
+		*se = (char *)s;
+	if (sign)
+		irv |= STRTOG_Neg;
+	if (rvb) {
+		copybits(bits, nbits, rvb);
+		Bfree(rvb);
+		}
+	return irv;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtof.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtof.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtof.c	(revision 2448)
@@ -0,0 +1,84 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+#include <stdlib.h>
+
+ float
+#ifdef KR_headers
+_STD(strtof)(s, sp) CONST char *s; char **sp;
+#else
+_STD(strtof)(CONST char *s, char **sp)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi = { 24, 1-127-24+1,  254-127-24+1, 1, 1 };
+#else
+	static FPI fpi = { 24, 1-127-24+1,  254-127-24+1, 1, 0 };
+#endif
+	ULong bits[1];
+	Long exp;
+	int k;
+	union { ULong L[1]; float f; } u;
+
+	k = strtodg(s, sp, &fpi, &exp, bits);
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		u.L[0] = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_NaNbits:
+		u.L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
+		break;
+
+	  case STRTOG_Denormal:
+		u.L[0] = bits[0];
+		break;
+
+	  case STRTOG_Infinite:
+		u.L[0] = 0x7f800000;
+		break;
+
+	  case STRTOG_NaN:
+		u.L[0] = 0x7fffffff;
+	  }
+	if (k & STRTOG_Neg)
+		u.L[0] |= 0x80000000L;
+	return u.f;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtopQ.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtopQ.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtopQ.c	(revision 2448)
@@ -0,0 +1,109 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#endif
+#ifdef IEEE_8087
+#define _0 3
+#define _1 2
+#define _2 1
+#define _3 0
+#endif
+
+ int
+#ifdef KR_headers
+strtopQ(s, sp, V) CONST char *s; char **sp; void *V;
+#else
+strtopQ(CONST char *s, char **sp, void *V)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 1 };
+#else
+	static FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 };
+#endif
+	ULong bits[4];
+	Long exp;
+	int k;
+	ULong *L = (ULong*)V;
+
+	k = strtodg(s, sp, &fpi, &exp, bits);
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = L[1] = L[2] = L[3] = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_NaNbits:
+		L[_3] = bits[0];
+		L[_2] = bits[1];
+		L[_1] = bits[2];
+		L[_0] = (bits[3] & ~0x10000) | ((exp + 0x3fff + 112) << 16);
+		break;
+
+	  case STRTOG_Denormal:
+		L[_3] = bits[0];
+		L[_2] = bits[1];
+		L[_1] = bits[2];
+		L[_0] = bits[3];
+		break;
+
+	  case STRTOG_Infinite:
+		L[_0] = 0x7fff0000;
+		L[_1] = L[_2] = L[_3] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		L[_0] = 0x7fffffff;
+		L[_1] = L[_2] = L[_3] = (ULong)-1;
+	  }
+	if (k & STRTOG_Neg)
+		L[_0] |= 0x80000000L;
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtopd.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtopd.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtopd.c	(revision 2448)
@@ -0,0 +1,55 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtopd(s, sp, d) char *s; char **sp; double *d;
+#else
+strtopd(CONST char *s, char **sp, double *d)
+#endif
+{
+	static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
+	ULong bits[2];
+	Long exp;
+	int k;
+
+	k = strtodg(s, sp, &fpi0, &exp, bits);
+	ULtod((ULong*)d, bits, exp, k);
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtopdd.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtopdd.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtopdd.c	(revision 2448)
@@ -0,0 +1,184 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtopdd(s, sp, dd) CONST char *s; char **sp; double *dd;
+#else
+strtopdd(CONST char *s, char **sp, double *dd)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
+#else
+	static FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
+#endif
+	ULong bits[4];
+	Long exp;
+	int i, j, rv;
+	typedef union {
+		double d[2];
+		ULong L[4];
+		} U;
+	U *u;
+
+	rv = strtodg(s, sp, &fpi, &exp, bits);
+	u = (U*)dd;
+	switch(rv & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		u->d[0] = u->d[1] = 0.;
+		break;
+
+	  case STRTOG_Normal:
+		u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL;
+		u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
+			  | exp + 0x3ff + 105 << 20;
+		exp += 0x3ff + 52;
+		if (bits[1] &= 0x1fffff) {
+			i = hi0bits(bits[1]) - 11;
+			if (i >= exp) {
+				i = exp - 1;
+				exp = 0;
+				}
+			else
+				exp -= i;
+			if (i > 0) {
+				bits[1] = bits[1] << i | bits[0] >> 32-i;
+				bits[0] = bits[0] << i & 0xffffffffL;
+				}
+			}
+		else if (bits[0]) {
+			i = hi0bits(bits[0]) + 21;
+			if (i >= exp) {
+				i = exp - 1;
+				exp = 0;
+				}
+			else
+				exp -= i;
+			if (i < 32) {
+				bits[1] = bits[0] >> 32 - i;
+				bits[0] = bits[0] << i & 0xffffffffL;
+				}
+			else {
+				bits[1] = bits[0] << i - 32;
+				bits[0] = 0;
+				}
+			}
+		else {
+			u->L[2] = u->L[3] = 0;
+			break;
+			}
+		u->L[2+_1] = bits[0];
+		u->L[2+_0] = bits[1] & 0xfffff | exp << 20;
+		break;
+
+	  case STRTOG_Denormal:
+		if (bits[3])
+			goto nearly_normal;
+		if (bits[2])
+			goto partly_normal;
+		if (bits[1] & 0xffe00000)
+			goto hardly_normal;
+		/* completely denormal */
+		u->L[2] = u->L[3] = 0;
+		u->L[_1] = bits[0];
+		u->L[_0] = bits[1];
+		break;
+
+	  nearly_normal:
+		i = hi0bits(bits[3]) - 11;	/* i >= 12 */
+		j = 32 - i;
+		u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
+			| 65 - i << 20;
+		u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
+		u->L[2+_0] = bits[1] & (1L << j) - 1;
+		u->L[2+_1] = bits[0];
+		break;
+
+	  partly_normal:
+		i = hi0bits(bits[2]) - 11;
+		if (i < 0) {
+			j = -i;
+			i += 32;
+			u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
+			u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
+			u->L[2+_0] = bits[1] & (1L << j) - 1;
+			u->L[2+_1] = bits[0];
+			break;
+			}
+		if (i == 0) {
+			u->L[_0] = bits[2] & 0xfffff | 33 << 20;
+			u->L[_1] = bits[1];
+			u->L[2+_0] = 0;
+			u->L[2+_1] = bits[0];
+			break;
+			}
+		j = 32 - i;
+		u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
+				| j + 1 << 20;
+		u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
+		u->L[2+_0] = 0;
+		u->L[2+_1] = bits[0] & (1L << j) - 1;
+		break;
+
+	  hardly_normal:
+		j = 11 - hi0bits(bits[1]);
+		i = 32 - j;
+		u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
+		u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
+		u->L[2+_0] = 0;
+		u->L[2+_1] = bits[0] & (1L << j) - 1;
+		break;
+
+	  case STRTOG_Infinite:
+		u->L[_0] = u->L[2+_0] = 0x7ff00000;
+		u->L[_1] = u->L[2+_1] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		u->L[_0] = u->L[2+_0] = 0x7fffffff;
+		u->L[_1] = u->L[2+_1] = (ULong)-1;
+	  }
+	if (rv & STRTOG_Neg) {
+		u->L[  _0] |= 0x80000000L;
+		u->L[2+_0] |= 0x80000000L;
+		}
+	return rv;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtopf.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtopf.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtopf.c	(revision 2448)
@@ -0,0 +1,83 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ int
+#ifdef KR_headers
+strtopf(s, sp, f) CONST char *s; char **sp; float *f;
+#else
+strtopf(CONST char *s, char **sp, float *f)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi = { 24, 1-127-24+1,  254-127-24+1, 1, 1 };
+#else
+	static FPI fpi = { 24, 1-127-24+1,  254-127-24+1, 1, 0 };
+#endif
+	ULong bits[1], *L;
+	Long exp;
+	int k;
+
+	k = strtodg(s, sp, &fpi, &exp, bits);
+	L = (ULong*)f;
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_NaNbits:
+		L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
+		break;
+
+	  case STRTOG_Denormal:
+		L[0] = bits[0];
+		break;
+
+	  case STRTOG_Infinite:
+		L[0] = 0x7f800000;
+		break;
+
+	  case STRTOG_NaN:
+		L[0] = 0x7fffffff;
+	  }
+	if (k & STRTOG_Neg)
+		L[0] |= 0x80000000L;
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtopx.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtopx.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtopx.c	(revision 2448)
@@ -0,0 +1,106 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#define _4 4
+#endif
+#ifdef IEEE_8087
+#define _0 4
+#define _1 3
+#define _2 2
+#define _3 1
+#define _4 0
+#endif
+
+ int
+#ifdef KR_headers
+strtopx(s, sp, V) CONST char *s; char **sp; void *V;
+#else
+strtopx(CONST char *s, char **sp, void *V)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 1 };
+#else
+	static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
+#endif
+	ULong bits[2];
+	Long exp;
+	int k;
+	UShort *L = (UShort*)V;
+
+	k = strtodg(s, sp, &fpi, &exp, bits);
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = L[1] = L[2] = L[3] = L[4] = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_Denormal:
+	  case STRTOG_NaNbits:
+		L[_4] = (UShort)bits[0];
+		L[_3] = (UShort)(bits[0] >> 16);
+		L[_2] = (UShort)bits[1];
+		L[_1] = (UShort)(bits[1] >> 16);
+		L[_0] = exp + 0x3fff + 63;
+		break;
+
+	  case STRTOG_Infinite:
+		L[_0] = 0x7fff;
+		L[_1] = L[_2] = L[_3] = L[_4] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		L[_0] = 0x7fff;
+		L[_1] = L[_2] = L[_3] = L[_4] = (UShort)-1;
+	  }
+	if (k & STRTOG_Neg)
+		L[_0] |= 0x8000;
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtopxL.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtopxL.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtopxL.c	(revision 2448)
@@ -0,0 +1,100 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#endif
+#ifdef IEEE_8087
+#define _0 2
+#define _1 1
+#define _2 0
+#endif
+
+ int
+#ifdef KR_headers
+strtopxL(s, sp, V) CONST char *s; char **sp; void *V;
+#else
+strtopxL(CONST char *s, char **sp, void *V)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 1 };
+#else
+	static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
+#endif
+	ULong bits[2];
+	Long exp;
+	int k;
+	ULong *L = (ULong*)V;
+
+	k = strtodg(s, sp, &fpi, &exp, bits);
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = L[1] = L[2] = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_Denormal:
+	  case STRTOG_NaNbits:
+		L[_2] = bits[0];
+		L[_1] = bits[1];
+		L[_0] = (exp + 0x3fff + 63) << 16;
+		break;
+
+	  case STRTOG_Infinite:
+		L[_0] = 0x7fff << 16;
+		L[_1] = L[_2] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		L[_0] = 0x7fff << 16;
+		L[_1] = L[_2] = (ULong)-1;
+	  }
+	if (k & STRTOG_Neg)
+		L[_0] |= 0x80000000L;
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtorQ.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtorQ.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtorQ.c	(revision 2448)
@@ -0,0 +1,121 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#endif
+#ifdef IEEE_8087
+#define _0 3
+#define _1 2
+#define _2 1
+#define _3 0
+#endif
+
+ void
+#ifdef KR_headers
+ULtoQ(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
+#else
+ULtoQ(ULong *L, ULong *bits, Long exp, int k)
+#endif
+{
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = L[1] = L[2] = L[3] = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_NaNbits:
+		L[_3] = bits[0];
+		L[_2] = bits[1];
+		L[_1] = bits[2];
+		L[_0] = (bits[3] & ~0x10000) | ((exp + 0x3fff + 112) << 16);
+		break;
+
+	  case STRTOG_Denormal:
+		L[_3] = bits[0];
+		L[_2] = bits[1];
+		L[_1] = bits[2];
+		L[_0] = bits[3];
+		break;
+
+	  case STRTOG_Infinite:
+		L[_0] = 0x7fff0000;
+		L[_1] = L[_2] = L[_3] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		L[_0] = 0x7fffffff;
+		L[_1] = L[_2] = L[_3] = (ULong)-1;
+	  }
+	if (k & STRTOG_Neg)
+		L[_0] |= 0x80000000L;
+	}
+
+ int
+#ifdef KR_headers
+strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L;
+#else
+strtorQ(CONST char *s, char **sp, int rounding, void *L)
+#endif
+{
+	static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI };
+	FPI *fpi, fpi1;
+	ULong bits[4];
+	Long exp;
+	int k;
+
+	fpi = &fpi0;
+	if (rounding != FPI_Round_near) {
+		fpi1 = fpi0;
+		fpi1.rounding = rounding;
+		fpi = &fpi1;
+		}
+	k = strtodg(s, sp, fpi, &exp, bits);
+	ULtoQ((ULong*)L, bits, exp, k);
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtord.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtord.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtord.c	(revision 2448)
@@ -0,0 +1,99 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ void
+#ifdef KR_headers
+ULtod(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
+#else
+ULtod(ULong *L, ULong *bits, Long exp, int k)
+#endif
+{
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = L[1] = 0;
+		break;
+
+	  case STRTOG_Denormal:
+		L[_1] = bits[0];
+		L[_0] = bits[1];
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_NaNbits:
+		L[_1] = bits[0];
+		L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20);
+		break;
+
+	  case STRTOG_Infinite:
+		L[_0] = 0x7ff00000;
+		L[_1] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		L[_0] = 0x7fffffff;
+		L[_1] = (ULong)-1;
+	  }
+	if (k & STRTOG_Neg)
+		L[_0] |= 0x80000000L;
+	}
+
+ int
+#ifdef KR_headers
+strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d;
+#else
+strtord(CONST char *s, char **sp, int rounding, double *d)
+#endif
+{
+	static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
+	FPI *fpi, fpi1;
+	ULong bits[2];
+	Long exp;
+	int k;
+
+	fpi = &fpi0;
+	if (rounding != FPI_Round_near) {
+		fpi1 = fpi0;
+		fpi1.rounding = rounding;
+		fpi = &fpi1;
+		}
+	k = strtodg(s, sp, fpi, &exp, bits);
+	ULtod((ULong*)d, bits, exp, k);
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtordd.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtordd.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtordd.c	(revision 2448)
@@ -0,0 +1,205 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ void
+#ifdef KR_headers
+ULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
+#else
+ULtodd(ULong *L, ULong *bits, Long exp, int k)
+#endif
+{
+	int i, j;
+
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = L[1] = L[2] = L[3] = 0;
+		break;
+
+	  case STRTOG_Normal:
+		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
+		L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
+			  | exp + 0x3ff + 105 << 20;
+		exp += 0x3ff + 52;
+		if (bits[1] &= 0x1fffff) {
+			i = hi0bits(bits[1]) - 11;
+			if (i >= exp) {
+				i = exp - 1;
+				exp = 0;
+				}
+			else
+				exp -= i;
+			if (i > 0) {
+				bits[1] = bits[1] << i | bits[0] >> 32-i;
+				bits[0] = bits[0] << i & (ULong)0xffffffffL;
+				}
+			}
+		else if (bits[0]) {
+			i = hi0bits(bits[0]) + 21;
+			if (i >= exp) {
+				i = exp - 1;
+				exp = 0;
+				}
+			else
+				exp -= i;
+			if (i < 32) {
+				bits[1] = bits[0] >> 32 - i;
+				bits[0] = bits[0] << i & (ULong)0xffffffffL;
+				}
+			else {
+				bits[1] = bits[0] << i - 32;
+				bits[0] = 0;
+				}
+			}
+		else {
+			L[2] = L[3] = 0;
+			break;
+			}
+		L[2+_1] = bits[0];
+		L[2+_0] = bits[1] & 0xfffff | exp << 20;
+		break;
+
+	  case STRTOG_Denormal:
+		if (bits[3])
+			goto nearly_normal;
+		if (bits[2])
+			goto partly_normal;
+		if (bits[1] & 0xffe00000)
+			goto hardly_normal;
+		/* completely denormal */
+		L[2] = L[3] = 0;
+		L[_1] = bits[0];
+		L[_0] = bits[1];
+		break;
+
+	  nearly_normal:
+		i = hi0bits(bits[3]) - 11;	/* i >= 12 */
+		j = 32 - i;
+		L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
+			| 65 - i << 20;
+		L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
+		L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
+		L[2+_1] = bits[0];
+		break;
+
+	  partly_normal:
+		i = hi0bits(bits[2]) - 11;
+		if (i < 0) {
+			j = -i;
+			i += 32;
+			L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
+			L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
+			L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
+			L[2+_1] = bits[0];
+			break;
+			}
+		if (i == 0) {
+			L[_0] = bits[2] & 0xfffff | 33 << 20;
+			L[_1] = bits[1];
+			L[2+_0] = 0;
+			L[2+_1] = bits[0];
+			break;
+			}
+		j = 32 - i;
+		L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
+				| j + 1 << 20;
+		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
+		L[2+_0] = 0;
+		L[2+_1] = bits[0] & (1L << j) - 1;
+		break;
+
+	  hardly_normal:
+		j = 11 - hi0bits(bits[1]);
+		i = 32 - j;
+		L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
+		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
+		L[2+_0] = 0;
+		L[2+_1] = bits[0] & ((ULong)1L << j) - 1;
+		break;
+
+	  case STRTOG_Infinite:
+		L[_0] = L[2+_0] = 0x7ff00000;
+		L[_1] = L[2+_1] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		L[_0] = L[2+_0] = 0x7fffffff;
+		L[_1] = L[2+_1] = (ULong)-1;
+		break;
+
+	  case STRTOG_NaNbits:
+		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
+		L[_0] = bits[2] >> 21 | bits[3] << 11
+			  | (ULong)0x7ff00000L;
+		L[2+_1] = bits[0];
+		L[2+_0] = bits[1] | (ULong)0x7ff00000L;
+	  }
+	if (k & STRTOG_Neg) {
+		L[_0] |= 0x80000000L;
+		L[2+_0] |= 0x80000000L;
+		}
+	}
+
+ int
+#ifdef KR_headers
+strtordd(s, sp, rounding, dd) CONST char *s; char **sp; int rounding; double *dd;
+#else
+strtordd(CONST char *s, char **sp, int rounding, double *dd)
+#endif
+{
+#ifdef Sudden_Underflow
+	static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
+#else
+	static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
+#endif
+	FPI *fpi, fpi1;
+	ULong bits[4];
+	Long exp;
+	int k;
+
+	fpi = &fpi0;
+	if (rounding != FPI_Round_near) {
+		fpi1 = fpi0;
+		fpi1.rounding = rounding;
+		fpi = &fpi1;
+		}
+	k = strtodg(s, sp, fpi, &exp, bits);
+	ULtodd((ULong*)dd, bits, exp, k);
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtorf.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtorf.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtorf.c	(revision 2448)
@@ -0,0 +1,95 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ void
+#ifdef KR_headers
+ULtof(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
+#else
+ULtof(ULong *L, ULong *bits, Long exp, int k)
+#endif
+{
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		*L = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_NaNbits:
+		L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
+		break;
+
+	  case STRTOG_Denormal:
+		L[0] = bits[0];
+		break;
+
+	  case STRTOG_Infinite:
+		L[0] = 0x7f800000;
+		break;
+
+	  case STRTOG_NaN:
+		L[0] = 0x7fffffff;
+	  }
+	if (k & STRTOG_Neg)
+		L[0] |= 0x80000000L;
+	}
+
+ int
+#ifdef KR_headers
+strtorf(s, sp, rounding, f) CONST char *s; char **sp; int rounding; float *f;
+#else
+strtorf(CONST char *s, char **sp, int rounding, float *f)
+#endif
+{
+	static FPI fpi0 = { 24, 1-127-24+1,  254-127-24+1, 1, SI };
+	FPI *fpi, fpi1;
+	ULong bits[1];
+	Long exp;
+	int k;
+
+	fpi = &fpi0;
+	if (rounding != FPI_Round_near) {
+		fpi1 = fpi0;
+		fpi1.rounding = rounding;
+		fpi = &fpi1;
+		}
+	k = strtodg(s, sp, fpi, &exp, bits);
+	ULtof((ULong*)f, bits, exp, k);
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtorx.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtorx.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtorx.c	(revision 2448)
@@ -0,0 +1,118 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#define _4 4
+#endif
+#ifdef IEEE_8087
+#define _0 4
+#define _1 3
+#define _2 2
+#define _3 1
+#define _4 0
+#endif
+
+ void
+#ifdef KR_headers
+ULtox(L, bits, exp, k) UShort *L; ULong *bits; Long exp; int k;
+#else
+ULtox(UShort *L, ULong *bits, Long exp, int k)
+#endif
+{
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = L[1] = L[2] = L[3] = L[4] = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_Denormal:
+	  case STRTOG_NaNbits:
+		L[_4] = (UShort)bits[0];
+		L[_3] = (UShort)(bits[0] >> 16);
+		L[_2] = (UShort)bits[1];
+		L[_1] = (UShort)(bits[1] >> 16);
+		L[_0] = exp + 0x3fff + 63;
+		break;
+
+	  case STRTOG_Infinite:
+		L[_0] = 0x7fff;
+		L[_1] = L[_2] = L[_3] = L[_4] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		L[_0] = 0x7fff;
+		L[_1] = L[_2] = L[_3] = L[_4] = (UShort)-1;
+	  }
+	if (k & STRTOG_Neg)
+		L[_0] |= 0x8000;
+	}
+
+ int
+#ifdef KR_headers
+strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L;
+#else
+strtorx(CONST char *s, char **sp, int rounding, void *L)
+#endif
+{
+	static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
+	FPI *fpi, fpi1;
+	ULong bits[2];
+	Long exp;
+	int k;
+
+	fpi = &fpi0;
+	if (rounding != FPI_Round_near) {
+		fpi1 = fpi0;
+		fpi1.rounding = rounding;
+		fpi = &fpi1;
+		}
+	k = strtodg(s, sp, fpi, &exp, bits);
+	ULtox((UShort*)L, bits, exp, k);
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/strtorxL.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/strtorxL.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/strtorxL.c	(revision 2448)
@@ -0,0 +1,112 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#endif
+#ifdef IEEE_8087
+#define _0 2
+#define _1 1
+#define _2 0
+#endif
+
+ void
+#ifdef KR_headers
+ULtoxL(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
+#else
+ULtoxL(ULong *L, ULong *bits, Long exp, int k)
+#endif
+{
+	switch(k & STRTOG_Retmask) {
+	  case STRTOG_NoNumber:
+	  case STRTOG_Zero:
+		L[0] = L[1] = L[2] = 0;
+		break;
+
+	  case STRTOG_Normal:
+	  case STRTOG_Denormal:
+	  case STRTOG_NaNbits:
+		L[_0] = (exp + 0x3fff + 63) << 16;
+		L[_1] = bits[1];
+		L[_2] = bits[0];
+		break;
+
+	  case STRTOG_Infinite:
+		L[_0] = 0x7fff << 16;
+		L[_1] = L[_2] = 0;
+		break;
+
+	  case STRTOG_NaN:
+		L[_0] = 0x7fff << 16;
+		L[_1] = L[_2] = (ULong)-1;
+	  }
+	if (k & STRTOG_Neg)
+		L[_0] |= 0x80000000L;
+	}
+
+ int
+#ifdef KR_headers
+strtorxL(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L;
+#else
+strtorxL(CONST char *s, char **sp, int rounding, void *L)
+#endif
+{
+	static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
+	FPI *fpi, fpi1;
+	ULong bits[2];
+	Long exp;
+	int k;
+
+	fpi = &fpi0;
+	if (rounding != FPI_Round_near) {
+		fpi1 = fpi0;
+		fpi1.rounding = rounding;
+		fpi = &fpi1;
+		}
+	k = strtodg(s, sp, fpi, &exp, bits);
+	ULtoxL((ULong*)L, bits, exp, k);
+	return k;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/sum.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/sum.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/sum.c	(revision 2448)
@@ -0,0 +1,104 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ Bigint *
+#ifdef KR_headers
+sum(a, b) Bigint *a; Bigint *b;
+#else
+sum(Bigint *a, Bigint *b)
+#endif
+{
+	Bigint *c;
+	ULong carry, *xc, *xa, *xb, *xe, y;
+#ifdef Pack_32
+	ULong z;
+#endif
+
+	if (a->wds < b->wds) {
+		c = b; b = a; a = c;
+		}
+	c = Balloc(a->k);
+	c->wds = a->wds;
+	carry = 0;
+	xa = a->x;
+	xb = b->x;
+	xc = c->x;
+	xe = xc + b->wds;
+#ifdef Pack_32
+	do {
+		y = (*xa & 0xffff) + (*xb & 0xffff) + carry;
+		carry = (y & 0x10000) >> 16;
+		z = (*xa++ >> 16) + (*xb++ >> 16) + carry;
+		carry = (z & 0x10000) >> 16;
+		Storeinc(xc, z, y);
+		}
+		while(xc < xe);
+	xe += a->wds - b->wds;
+	while(xc < xe) {
+		y = (*xa & 0xffff) + carry;
+		carry = (y & 0x10000) >> 16;
+		z = (*xa++ >> 16) + carry;
+		carry = (z & 0x10000) >> 16;
+		Storeinc(xc, z, y);
+		}
+#else
+	do {
+		y = *xa++ + *xb++ + carry;
+		carry = (y & 0x10000) >> 16;
+		*xc++ = y & 0xffff;
+		}
+		while(xc < xe);
+	xe += a->wds - b->wds;
+	while(xc < xe) {
+		y = *xa++ + carry;
+		carry = (y & 0x10000) >> 16;
+		*xc++ = y & 0xffff;
+		}
+#endif
+	if (carry) {
+		if (c->wds == c->maxwds) {
+			b = Balloc(c->k + 1);
+			Bcopy(b, c);
+			Bfree(c);
+			c = b;
+			}
+		c->x[c->wds++] = 1;
+		}
+	return c;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/Q.ou0
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/Q.ou0	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/Q.ou0	(revision 2448)
@@ -0,0 +1,1180 @@
+
+Input: 1.23
+
+strtoQ consumes 4 bytes and returns 17
+with bits = #3fff3ae1 47ae147a e147ae14 7ae147ae
+g_Qfmt(0) gives 4 bytes: "1.23"
+
+strtoIQ returns 17, consuming 4 bytes.
+fI[0] = #3fff3ae1 47ae147a e147ae14 7ae147ae
+fI[1] = #3fff3ae1 47ae147a e147ae14 7ae147af
+fI[0] == strtod
+
+
+Input: 1.23e+20
+
+strtoQ consumes 8 bytes and returns 1
+with bits = #4041aabd f2145b43 0 0
+g_Qfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIQ returns 1, consuming 8 bytes.
+fI[0] == fI[1] = #4041aabd f2145b43 0 0
+
+
+Input: 1.23e-20
+
+strtoQ consumes 8 bytes and returns 17
+with bits = #3fbcd0ae 4cf76753 9e4cbca ad934841
+g_Qfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIQ returns 17, consuming 8 bytes.
+fI[0] = #3fbcd0ae 4cf76753 9e4cbca ad934841
+fI[1] = #3fbcd0ae 4cf76753 9e4cbca ad934842
+fI[0] == strtod
+
+
+Input: 1.23456789
+
+strtoQ consumes 10 bytes and returns 17
+with bits = #3fff3c0c a4283de1 b7eb6945 1304948f
+g_Qfmt(0) gives 10 bytes: "1.23456789"
+
+strtoIQ returns 17, consuming 10 bytes.
+fI[0] = #3fff3c0c a4283de1 b7eb6945 1304948f
+fI[1] = #3fff3c0c a4283de1 b7eb6945 13049490
+fI[0] == strtod
+
+
+Input: 1.23456589e+20
+
+strtoQ consumes 14 bytes and returns 1
+with bits = #4041ac53 7a660b99 74000000 0
+g_Qfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoIQ returns 1, consuming 14 bytes.
+fI[0] == fI[1] = #4041ac53 7a660b99 74000000 0
+
+
+Input: 1.23e+30
+
+strtoQ consumes 8 bytes and returns 1
+with bits = #4062f0cb 4e8fb79 4945600 0
+g_Qfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIQ returns 1, consuming 8 bytes.
+fI[0] == fI[1] = #4062f0cb 4e8fb79 4945600 0
+
+
+Input: 1.23e-30
+
+strtoQ consumes 8 bytes and returns 17
+with bits = #3f9b8f28 66f5010a a9d63f9e d7e8ba14
+g_Qfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIQ returns 17, consuming 8 bytes.
+fI[0] = #3f9b8f28 66f5010a a9d63f9e d7e8ba14
+fI[1] = #3f9b8f28 66f5010a a9d63f9e d7e8ba15
+fI[0] == strtod
+
+
+Input: 1.23456789e-20
+
+strtoQ consumes 14 bytes and returns 33
+with bits = #3fbcd268 1471e7ad a6a4a029 d86c1fa2
+g_Qfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoIQ returns 33, consuming 14 bytes.
+fI[0] = #3fbcd268 1471e7ad a6a4a029 d86c1fa1
+fI[1] = #3fbcd268 1471e7ad a6a4a029 d86c1fa2
+fI[1] == strtod
+
+
+Input: 1.23456789e-30
+
+strtoQ consumes 14 bytes and returns 17
+with bits = #3f9b90a3 e33bbd99 51f85855 5a6b19d4
+g_Qfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoIQ returns 17, consuming 14 bytes.
+fI[0] = #3f9b90a3 e33bbd99 51f85855 5a6b19d4
+fI[1] = #3f9b90a3 e33bbd99 51f85855 5a6b19d5
+fI[0] == strtod
+
+
+Input: 1.234567890123456789
+
+strtoQ consumes 20 bytes and returns 17
+with bits = #3fff3c0c a428c59f b71a4194 68dd175b
+g_Qfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIQ returns 17, consuming 20 bytes.
+fI[0] = #3fff3c0c a428c59f b71a4194 68dd175b
+fI[1] = #3fff3c0c a428c59f b71a4194 68dd175c
+fI[0] == strtod
+
+
+Input: 1.23456789012345678901234567890123456789
+
+strtoQ consumes 40 bytes and returns 17
+with bits = #3fff3c0c a428c59f b71a7be1 6b6b6d5b
+g_Qfmt(0) gives 36 bytes: "1.2345678901234567890123456789012346"
+
+strtoIQ returns 17, consuming 40 bytes.
+fI[0] = #3fff3c0c a428c59f b71a7be1 6b6b6d5b
+fI[1] = #3fff3c0c a428c59f b71a7be1 6b6b6d5c
+fI[0] == strtod
+
+
+Input: 1.23e306
+
+strtoQ consumes 8 bytes and returns 33
+with bits = #43f7c067 6cd1c61f 4daac5f1 e9fa3b55
+g_Qfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoIQ returns 33, consuming 8 bytes.
+fI[0] = #43f7c067 6cd1c61f 4daac5f1 e9fa3b54
+fI[1] = #43f7c067 6cd1c61f 4daac5f1 e9fa3b55
+fI[1] == strtod
+
+
+Input: 1.23e-306
+
+strtoQ consumes 9 bytes and returns 17
+with bits = #3c06ba3b 85da396e 7e496ab7 d233c3dd
+g_Qfmt(0) gives 9 bytes: "1.23e-306"
+
+strtoIQ returns 17, consuming 9 bytes.
+fI[0] = #3c06ba3b 85da396e 7e496ab7 d233c3dd
+fI[1] = #3c06ba3b 85da396e 7e496ab7 d233c3de
+fI[0] == strtod
+
+
+Input: 1.23e-320
+
+strtoQ consumes 9 bytes and returns 33
+with bits = #3bd83731 86e30898 7e33b2e8 355f847b
+g_Qfmt(0) gives 9 bytes: "1.23e-320"
+
+strtoIQ returns 33, consuming 9 bytes.
+fI[0] = #3bd83731 86e30898 7e33b2e8 355f847a
+fI[1] = #3bd83731 86e30898 7e33b2e8 355f847b
+fI[1] == strtod
+
+
+Input: 1.23e-20
+
+strtoQ consumes 8 bytes and returns 17
+with bits = #3fbcd0ae 4cf76753 9e4cbca ad934841
+g_Qfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIQ returns 17, consuming 8 bytes.
+fI[0] = #3fbcd0ae 4cf76753 9e4cbca ad934841
+fI[1] = #3fbcd0ae 4cf76753 9e4cbca ad934842
+fI[0] == strtod
+
+
+Input: 1.23456789e307
+
+strtoQ consumes 14 bytes and returns 17
+with bits = #43fb194b 14bdaecd bcea468c 902464cf
+g_Qfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoIQ returns 17, consuming 14 bytes.
+fI[0] = #43fb194b 14bdaecd bcea468c 902464cf
+fI[1] = #43fb194b 14bdaecd bcea468c 902464d0
+fI[0] == strtod
+
+
+Input: 1.23456589e-307
+
+strtoQ consumes 15 bytes and returns 17
+with bits = #3c036319 6bb9845f a6d234e3 39163574
+g_Qfmt(0) gives 15 bytes: "1.23456589e-307"
+
+strtoIQ returns 17, consuming 15 bytes.
+fI[0] = #3c036319 6bb9845f a6d234e3 39163574
+fI[1] = #3c036319 6bb9845f a6d234e3 39163575
+fI[0] == strtod
+
+
+Input: 1.234567890123456789
+
+strtoQ consumes 20 bytes and returns 17
+with bits = #3fff3c0c a428c59f b71a4194 68dd175b
+g_Qfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIQ returns 17, consuming 20 bytes.
+fI[0] = #3fff3c0c a428c59f b71a4194 68dd175b
+fI[1] = #3fff3c0c a428c59f b71a4194 68dd175c
+fI[0] == strtod
+
+
+Input: 1.234567890123456789e301
+
+strtoQ consumes 24 bytes and returns 33
+with bits = #43e726f5 175f5641 3017ea80 763990ef
+g_Qfmt(0) gives 25 bytes: "1.234567890123456789e+301"
+
+strtoIQ returns 33, consuming 24 bytes.
+fI[0] = #43e726f5 175f5641 3017ea80 763990ee
+fI[1] = #43e726f5 175f5641 3017ea80 763990ef
+fI[1] == strtod
+
+
+Input: 1.234567890123456789e-301
+
+strtoQ consumes 25 bytes and returns 17
+with bits = #3c1752a6 4e34ba0d 35b19b04 3222fce5
+g_Qfmt(0) gives 25 bytes: "1.234567890123456789e-301"
+
+strtoIQ returns 17, consuming 25 bytes.
+fI[0] = #3c1752a6 4e34ba0d 35b19b04 3222fce5
+fI[1] = #3c1752a6 4e34ba0d 35b19b04 3222fce6
+fI[0] == strtod
+
+
+Input: 1.234567890123456789e-321
+
+strtoQ consumes 25 bytes and returns 17
+with bits = #3bd4f3c2 3699d4db 99d1ea94 2fecd7de
+g_Qfmt(0) gives 25 bytes: "1.234567890123456789e-321"
+
+strtoIQ returns 17, consuming 25 bytes.
+fI[0] = #3bd4f3c2 3699d4db 99d1ea94 2fecd7de
+fI[1] = #3bd4f3c2 3699d4db 99d1ea94 2fecd7df
+fI[0] == strtod
+
+
+Input: 1e23
+
+strtoQ consumes 4 bytes and returns 1
+with bits = #404b52d0 2c7e14af 68000000 0
+g_Qfmt(0) gives 5 bytes: "1e+23"
+
+strtoIQ returns 1, consuming 4 bytes.
+fI[0] == fI[1] = #404b52d0 2c7e14af 68000000 0
+
+
+Input: 1e310
+
+strtoQ consumes 5 bytes and returns 33
+with bits = #4404bd03 c8140697 9e9ff00e fefd4cbd
+g_Qfmt(0) gives 6 bytes: "1e+310"
+
+strtoIQ returns 33, consuming 5 bytes.
+fI[0] = #4404bd03 c8140697 9e9ff00e fefd4cbc
+fI[1] = #4404bd03 c8140697 9e9ff00e fefd4cbd
+fI[1] == strtod
+
+
+Input: 9.0259718793241475e-277
+
+strtoQ consumes 23 bytes and returns 17
+with bits = #3c69ffff ffffffff f9ed5779 ac118fe1
+g_Qfmt(0) gives 23 bytes: "9.0259718793241475e-277"
+
+strtoIQ returns 17, consuming 23 bytes.
+fI[0] = #3c69ffff ffffffff f9ed5779 ac118fe1
+fI[1] = #3c69ffff ffffffff f9ed5779 ac118fe2
+fI[0] == strtod
+
+
+Input: 9.025971879324147880346310405869e-277
+
+strtoQ consumes 37 bytes and returns 33
+with bits = #3c6a0000 0 0 9a
+g_Qfmt(0) gives 37 bytes: "9.025971879324147880346310405869e-277"
+
+strtoIQ returns 33, consuming 37 bytes.
+fI[0] = #3c6a0000 0 0 99
+fI[1] = #3c6a0000 0 0 9a
+fI[1] == strtod
+
+
+Input: 9.025971879324147880346310405868e-277
+
+strtoQ consumes 37 bytes and returns 17
+with bits = #3c69ffff ffffffff ffffffff fffffcb5
+g_Qfmt(0) gives 37 bytes: "9.025971879324147880346310405868e-277"
+
+strtoIQ returns 17, consuming 37 bytes.
+fI[0] = #3c69ffff ffffffff ffffffff fffffcb5
+fI[1] = #3c69ffff ffffffff ffffffff fffffcb6
+fI[0] == strtod
+
+
+Input: 2.2250738585072014e-308
+
+strtoQ consumes 23 bytes and returns 33
+with bits = #3c010000 0 8c304c cf867de0
+g_Qfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoIQ returns 33, consuming 23 bytes.
+fI[0] = #3c010000 0 8c304c cf867ddf
+fI[1] = #3c010000 0 8c304c cf867de0
+fI[1] == strtod
+
+
+Input: 2.2250738585072013e-308
+
+strtoQ consumes 23 bytes and returns 33
+with bits = #3c00ffff ffffffff fa9e4c4f 4c1e8a10
+g_Qfmt(0) gives 23 bytes: "2.2250738585072013e-308"
+
+strtoIQ returns 33, consuming 23 bytes.
+fI[0] = #3c00ffff ffffffff fa9e4c4f 4c1e8a0f
+fI[1] = #3c00ffff ffffffff fa9e4c4f 4c1e8a10
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff1999 99999999 99999999 99999999
+g_Qfmt(0) gives 36 bytes: "1.0999999999999999999999999999999999"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff1999 99999999 99999999 99999999
+fI[1] = #3fff1999 99999999 99999999 9999999a
+fI[0] == strtod
+
+
+Input: -1.1
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff1999 99999999 99999999 99999999
+g_Qfmt(0) gives 37 bytes: "-1.0999999999999999999999999999999999"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff1999 99999999 99999999 9999999a
+fI[1] = #bfff1999 99999999 99999999 99999999
+fI[1] == strtod
+
+
+Input: 1.2
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff3333 33333333 33333333 33333333
+g_Qfmt(0) gives 3 bytes: "1.2"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff3333 33333333 33333333 33333333
+fI[1] = #3fff3333 33333333 33333333 33333334
+fI[0] == strtod
+
+
+Input: -1.2
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff3333 33333333 33333333 33333333
+g_Qfmt(0) gives 4 bytes: "-1.2"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff3333 33333333 33333333 33333334
+fI[1] = #bfff3333 33333333 33333333 33333333
+fI[1] == strtod
+
+
+Input: 1.3
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff4ccc cccccccc cccccccc cccccccc
+g_Qfmt(0) gives 36 bytes: "1.2999999999999999999999999999999998"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff4ccc cccccccc cccccccc cccccccc
+fI[1] = #3fff4ccc cccccccc cccccccc cccccccd
+fI[0] == strtod
+
+
+Input: -1.3
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff4ccc cccccccc cccccccc cccccccc
+g_Qfmt(0) gives 37 bytes: "-1.2999999999999999999999999999999998"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff4ccc cccccccc cccccccc cccccccd
+fI[1] = #bfff4ccc cccccccc cccccccc cccccccc
+fI[1] == strtod
+
+
+Input: 1.4
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff6666 66666666 66666666 66666666
+g_Qfmt(0) gives 3 bytes: "1.4"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff6666 66666666 66666666 66666666
+fI[1] = #3fff6666 66666666 66666666 66666667
+fI[0] == strtod
+
+
+Input: -1.4
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff6666 66666666 66666666 66666666
+g_Qfmt(0) gives 4 bytes: "-1.4"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff6666 66666666 66666666 66666667
+fI[1] = #bfff6666 66666666 66666666 66666666
+fI[1] == strtod
+
+
+Input: 1.5
+
+strtoQ consumes 3 bytes and returns 1
+with bits = #3fff8000 0 0 0
+g_Qfmt(0) gives 3 bytes: "1.5"
+
+strtoIQ returns 1, consuming 3 bytes.
+fI[0] == fI[1] = #3fff8000 0 0 0
+
+
+Input: -1.5
+
+strtoQ consumes 4 bytes and returns 9
+with bits = #bfff8000 0 0 0
+g_Qfmt(0) gives 4 bytes: "-1.5"
+
+strtoIQ returns 9, consuming 4 bytes.
+fI[0] == fI[1] = #bfff8000 0 0 0
+
+
+Input: 1.6
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff9999 99999999 99999999 99999999
+g_Qfmt(0) gives 36 bytes: "1.5999999999999999999999999999999999"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff9999 99999999 99999999 99999999
+fI[1] = #3fff9999 99999999 99999999 9999999a
+fI[0] == strtod
+
+
+Input: -1.6
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff9999 99999999 99999999 99999999
+g_Qfmt(0) gives 37 bytes: "-1.5999999999999999999999999999999999"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff9999 99999999 99999999 9999999a
+fI[1] = #bfff9999 99999999 99999999 99999999
+fI[1] == strtod
+
+
+Input: 1.7
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffb333 33333333 33333333 33333333
+g_Qfmt(0) gives 3 bytes: "1.7"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffb333 33333333 33333333 33333333
+fI[1] = #3fffb333 33333333 33333333 33333334
+fI[0] == strtod
+
+
+Input: -1.7
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffb333 33333333 33333333 33333333
+g_Qfmt(0) gives 4 bytes: "-1.7"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffb333 33333333 33333333 33333334
+fI[1] = #bfffb333 33333333 33333333 33333333
+fI[1] == strtod
+
+
+Input: 1.8
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffcccc cccccccc cccccccc cccccccc
+g_Qfmt(0) gives 36 bytes: "1.7999999999999999999999999999999998"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fffcccc cccccccc cccccccc cccccccc
+fI[1] = #3fffcccc cccccccc cccccccc cccccccd
+fI[0] == strtod
+
+
+Input: -1.8
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffcccc cccccccc cccccccc cccccccc
+g_Qfmt(0) gives 37 bytes: "-1.7999999999999999999999999999999998"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfffcccc cccccccc cccccccc cccccccd
+fI[1] = #bfffcccc cccccccc cccccccc cccccccc
+fI[1] == strtod
+
+
+Input: 1.9
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffe666 66666666 66666666 66666666
+g_Qfmt(0) gives 3 bytes: "1.9"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffe666 66666666 66666666 66666666
+fI[1] = #3fffe666 66666666 66666666 66666667
+fI[0] == strtod
+
+
+Input: -1.9
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffe666 66666666 66666666 66666666
+g_Qfmt(0) gives 4 bytes: "-1.9"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffe666 66666666 66666666 66666667
+fI[1] = #bfffe666 66666666 66666666 66666666
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff1999 99999999 99999999 9999999a
+g_Qfmt(0) gives 3 bytes: "1.1"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff1999 99999999 99999999 99999999
+fI[1] = #3fff1999 99999999 99999999 9999999a
+fI[1] == strtod
+
+
+Input: -1.1
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff1999 99999999 99999999 9999999a
+g_Qfmt(0) gives 4 bytes: "-1.1"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff1999 99999999 99999999 9999999a
+fI[1] = #bfff1999 99999999 99999999 99999999
+fI[0] == strtod
+
+
+Input: 1.2
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff3333 33333333 33333333 33333333
+g_Qfmt(0) gives 3 bytes: "1.2"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff3333 33333333 33333333 33333333
+fI[1] = #3fff3333 33333333 33333333 33333334
+fI[0] == strtod
+
+
+Input: -1.2
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff3333 33333333 33333333 33333333
+g_Qfmt(0) gives 4 bytes: "-1.2"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff3333 33333333 33333333 33333334
+fI[1] = #bfff3333 33333333 33333333 33333333
+fI[1] == strtod
+
+
+Input: 1.3
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff4ccc cccccccc cccccccc cccccccd
+g_Qfmt(0) gives 3 bytes: "1.3"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff4ccc cccccccc cccccccc cccccccc
+fI[1] = #3fff4ccc cccccccc cccccccc cccccccd
+fI[1] == strtod
+
+
+Input: -1.3
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff4ccc cccccccc cccccccc cccccccd
+g_Qfmt(0) gives 4 bytes: "-1.3"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff4ccc cccccccc cccccccc cccccccd
+fI[1] = #bfff4ccc cccccccc cccccccc cccccccc
+fI[0] == strtod
+
+
+Input: 1.4
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff6666 66666666 66666666 66666666
+g_Qfmt(0) gives 3 bytes: "1.4"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff6666 66666666 66666666 66666666
+fI[1] = #3fff6666 66666666 66666666 66666667
+fI[0] == strtod
+
+
+Input: -1.4
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff6666 66666666 66666666 66666666
+g_Qfmt(0) gives 4 bytes: "-1.4"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff6666 66666666 66666666 66666667
+fI[1] = #bfff6666 66666666 66666666 66666666
+fI[1] == strtod
+
+
+Input: 1.5
+
+strtoQ consumes 3 bytes and returns 1
+with bits = #3fff8000 0 0 0
+g_Qfmt(0) gives 3 bytes: "1.5"
+
+strtoIQ returns 1, consuming 3 bytes.
+fI[0] == fI[1] = #3fff8000 0 0 0
+
+
+Input: -1.5
+
+strtoQ consumes 4 bytes and returns 9
+with bits = #bfff8000 0 0 0
+g_Qfmt(0) gives 4 bytes: "-1.5"
+
+strtoIQ returns 9, consuming 4 bytes.
+fI[0] == fI[1] = #bfff8000 0 0 0
+
+
+Input: 1.6
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff9999 99999999 99999999 9999999a
+g_Qfmt(0) gives 3 bytes: "1.6"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff9999 99999999 99999999 99999999
+fI[1] = #3fff9999 99999999 99999999 9999999a
+fI[1] == strtod
+
+
+Input: -1.6
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff9999 99999999 99999999 9999999a
+g_Qfmt(0) gives 4 bytes: "-1.6"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff9999 99999999 99999999 9999999a
+fI[1] = #bfff9999 99999999 99999999 99999999
+fI[0] == strtod
+
+
+Input: 1.7
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffb333 33333333 33333333 33333333
+g_Qfmt(0) gives 3 bytes: "1.7"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffb333 33333333 33333333 33333333
+fI[1] = #3fffb333 33333333 33333333 33333334
+fI[0] == strtod
+
+
+Input: -1.7
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffb333 33333333 33333333 33333333
+g_Qfmt(0) gives 4 bytes: "-1.7"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffb333 33333333 33333333 33333334
+fI[1] = #bfffb333 33333333 33333333 33333333
+fI[1] == strtod
+
+
+Input: 1.8
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fffcccc cccccccc cccccccc cccccccd
+g_Qfmt(0) gives 3 bytes: "1.8"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fffcccc cccccccc cccccccc cccccccc
+fI[1] = #3fffcccc cccccccc cccccccc cccccccd
+fI[1] == strtod
+
+
+Input: -1.8
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfffcccc cccccccc cccccccc cccccccd
+g_Qfmt(0) gives 4 bytes: "-1.8"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfffcccc cccccccc cccccccc cccccccd
+fI[1] = #bfffcccc cccccccc cccccccc cccccccc
+fI[0] == strtod
+
+
+Input: 1.9
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffe666 66666666 66666666 66666666
+g_Qfmt(0) gives 3 bytes: "1.9"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffe666 66666666 66666666 66666666
+fI[1] = #3fffe666 66666666 66666666 66666667
+fI[0] == strtod
+
+
+Input: -1.9
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffe666 66666666 66666666 66666666
+g_Qfmt(0) gives 4 bytes: "-1.9"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffe666 66666666 66666666 66666667
+fI[1] = #bfffe666 66666666 66666666 66666666
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff1999 99999999 99999999 9999999a
+g_Qfmt(0) gives 3 bytes: "1.1"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff1999 99999999 99999999 99999999
+fI[1] = #3fff1999 99999999 99999999 9999999a
+fI[1] == strtod
+
+
+Input: -1.1
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff1999 99999999 99999999 99999999
+g_Qfmt(0) gives 37 bytes: "-1.0999999999999999999999999999999999"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff1999 99999999 99999999 9999999a
+fI[1] = #bfff1999 99999999 99999999 99999999
+fI[1] == strtod
+
+
+Input: 1.2
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff3333 33333333 33333333 33333334
+g_Qfmt(0) gives 36 bytes: "1.2000000000000000000000000000000002"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff3333 33333333 33333333 33333333
+fI[1] = #3fff3333 33333333 33333333 33333334
+fI[1] == strtod
+
+
+Input: -1.2
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff3333 33333333 33333333 33333333
+g_Qfmt(0) gives 4 bytes: "-1.2"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff3333 33333333 33333333 33333334
+fI[1] = #bfff3333 33333333 33333333 33333333
+fI[1] == strtod
+
+
+Input: 1.3
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff4ccc cccccccc cccccccc cccccccd
+g_Qfmt(0) gives 3 bytes: "1.3"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff4ccc cccccccc cccccccc cccccccc
+fI[1] = #3fff4ccc cccccccc cccccccc cccccccd
+fI[1] == strtod
+
+
+Input: -1.3
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff4ccc cccccccc cccccccc cccccccc
+g_Qfmt(0) gives 37 bytes: "-1.2999999999999999999999999999999998"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff4ccc cccccccc cccccccc cccccccd
+fI[1] = #bfff4ccc cccccccc cccccccc cccccccc
+fI[1] == strtod
+
+
+Input: 1.4
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff6666 66666666 66666666 66666667
+g_Qfmt(0) gives 36 bytes: "1.4000000000000000000000000000000001"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff6666 66666666 66666666 66666666
+fI[1] = #3fff6666 66666666 66666666 66666667
+fI[1] == strtod
+
+
+Input: -1.4
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff6666 66666666 66666666 66666666
+g_Qfmt(0) gives 4 bytes: "-1.4"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff6666 66666666 66666666 66666667
+fI[1] = #bfff6666 66666666 66666666 66666666
+fI[1] == strtod
+
+
+Input: 1.5
+
+strtoQ consumes 3 bytes and returns 1
+with bits = #3fff8000 0 0 0
+g_Qfmt(0) gives 3 bytes: "1.5"
+
+strtoIQ returns 1, consuming 3 bytes.
+fI[0] == fI[1] = #3fff8000 0 0 0
+
+
+Input: -1.5
+
+strtoQ consumes 4 bytes and returns 9
+with bits = #bfff8000 0 0 0
+g_Qfmt(0) gives 4 bytes: "-1.5"
+
+strtoIQ returns 9, consuming 4 bytes.
+fI[0] == fI[1] = #bfff8000 0 0 0
+
+
+Input: 1.6
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff9999 99999999 99999999 9999999a
+g_Qfmt(0) gives 3 bytes: "1.6"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff9999 99999999 99999999 99999999
+fI[1] = #3fff9999 99999999 99999999 9999999a
+fI[1] == strtod
+
+
+Input: -1.6
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff9999 99999999 99999999 99999999
+g_Qfmt(0) gives 37 bytes: "-1.5999999999999999999999999999999999"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff9999 99999999 99999999 9999999a
+fI[1] = #bfff9999 99999999 99999999 99999999
+fI[1] == strtod
+
+
+Input: 1.7
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fffb333 33333333 33333333 33333334
+g_Qfmt(0) gives 36 bytes: "1.7000000000000000000000000000000002"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffb333 33333333 33333333 33333333
+fI[1] = #3fffb333 33333333 33333333 33333334
+fI[1] == strtod
+
+
+Input: -1.7
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffb333 33333333 33333333 33333333
+g_Qfmt(0) gives 4 bytes: "-1.7"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffb333 33333333 33333333 33333334
+fI[1] = #bfffb333 33333333 33333333 33333333
+fI[1] == strtod
+
+
+Input: 1.8
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fffcccc cccccccc cccccccc cccccccd
+g_Qfmt(0) gives 3 bytes: "1.8"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fffcccc cccccccc cccccccc cccccccc
+fI[1] = #3fffcccc cccccccc cccccccc cccccccd
+fI[1] == strtod
+
+
+Input: -1.8
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffcccc cccccccc cccccccc cccccccc
+g_Qfmt(0) gives 37 bytes: "-1.7999999999999999999999999999999998"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfffcccc cccccccc cccccccc cccccccd
+fI[1] = #bfffcccc cccccccc cccccccc cccccccc
+fI[1] == strtod
+
+
+Input: 1.9
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fffe666 66666666 66666666 66666667
+g_Qfmt(0) gives 36 bytes: "1.9000000000000000000000000000000001"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffe666 66666666 66666666 66666666
+fI[1] = #3fffe666 66666666 66666666 66666667
+fI[1] == strtod
+
+
+Input: -1.9
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffe666 66666666 66666666 66666666
+g_Qfmt(0) gives 4 bytes: "-1.9"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffe666 66666666 66666666 66666667
+fI[1] = #bfffe666 66666666 66666666 66666666
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff1999 99999999 99999999 99999999
+g_Qfmt(0) gives 36 bytes: "1.0999999999999999999999999999999999"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff1999 99999999 99999999 99999999
+fI[1] = #3fff1999 99999999 99999999 9999999a
+fI[0] == strtod
+
+
+Input: -1.1
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff1999 99999999 99999999 9999999a
+g_Qfmt(0) gives 4 bytes: "-1.1"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff1999 99999999 99999999 9999999a
+fI[1] = #bfff1999 99999999 99999999 99999999
+fI[0] == strtod
+
+
+Input: 1.2
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff3333 33333333 33333333 33333333
+g_Qfmt(0) gives 3 bytes: "1.2"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff3333 33333333 33333333 33333333
+fI[1] = #3fff3333 33333333 33333333 33333334
+fI[0] == strtod
+
+
+Input: -1.2
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff3333 33333333 33333333 33333334
+g_Qfmt(0) gives 37 bytes: "-1.2000000000000000000000000000000002"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff3333 33333333 33333333 33333334
+fI[1] = #bfff3333 33333333 33333333 33333333
+fI[0] == strtod
+
+
+Input: 1.3
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff4ccc cccccccc cccccccc cccccccc
+g_Qfmt(0) gives 36 bytes: "1.2999999999999999999999999999999998"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff4ccc cccccccc cccccccc cccccccc
+fI[1] = #3fff4ccc cccccccc cccccccc cccccccd
+fI[0] == strtod
+
+
+Input: -1.3
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff4ccc cccccccc cccccccc cccccccd
+g_Qfmt(0) gives 4 bytes: "-1.3"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff4ccc cccccccc cccccccc cccccccd
+fI[1] = #bfff4ccc cccccccc cccccccc cccccccc
+fI[0] == strtod
+
+
+Input: 1.4
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff6666 66666666 66666666 66666666
+g_Qfmt(0) gives 3 bytes: "1.4"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff6666 66666666 66666666 66666666
+fI[1] = #3fff6666 66666666 66666666 66666667
+fI[0] == strtod
+
+
+Input: -1.4
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff6666 66666666 66666666 66666667
+g_Qfmt(0) gives 37 bytes: "-1.4000000000000000000000000000000001"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff6666 66666666 66666666 66666667
+fI[1] = #bfff6666 66666666 66666666 66666666
+fI[0] == strtod
+
+
+Input: 1.5
+
+strtoQ consumes 3 bytes and returns 1
+with bits = #3fff8000 0 0 0
+g_Qfmt(0) gives 3 bytes: "1.5"
+
+strtoIQ returns 1, consuming 3 bytes.
+fI[0] == fI[1] = #3fff8000 0 0 0
+
+
+Input: -1.5
+
+strtoQ consumes 4 bytes and returns 9
+with bits = #bfff8000 0 0 0
+g_Qfmt(0) gives 4 bytes: "-1.5"
+
+strtoIQ returns 9, consuming 4 bytes.
+fI[0] == fI[1] = #bfff8000 0 0 0
+
+
+Input: 1.6
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff9999 99999999 99999999 99999999
+g_Qfmt(0) gives 36 bytes: "1.5999999999999999999999999999999999"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff9999 99999999 99999999 99999999
+fI[1] = #3fff9999 99999999 99999999 9999999a
+fI[0] == strtod
+
+
+Input: -1.6
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff9999 99999999 99999999 9999999a
+g_Qfmt(0) gives 4 bytes: "-1.6"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff9999 99999999 99999999 9999999a
+fI[1] = #bfff9999 99999999 99999999 99999999
+fI[0] == strtod
+
+
+Input: 1.7
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffb333 33333333 33333333 33333333
+g_Qfmt(0) gives 3 bytes: "1.7"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffb333 33333333 33333333 33333333
+fI[1] = #3fffb333 33333333 33333333 33333334
+fI[0] == strtod
+
+
+Input: -1.7
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfffb333 33333333 33333333 33333334
+g_Qfmt(0) gives 37 bytes: "-1.7000000000000000000000000000000002"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffb333 33333333 33333333 33333334
+fI[1] = #bfffb333 33333333 33333333 33333333
+fI[0] == strtod
+
+
+Input: 1.8
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffcccc cccccccc cccccccc cccccccc
+g_Qfmt(0) gives 36 bytes: "1.7999999999999999999999999999999998"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fffcccc cccccccc cccccccc cccccccc
+fI[1] = #3fffcccc cccccccc cccccccc cccccccd
+fI[0] == strtod
+
+
+Input: -1.8
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfffcccc cccccccc cccccccc cccccccd
+g_Qfmt(0) gives 4 bytes: "-1.8"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfffcccc cccccccc cccccccc cccccccd
+fI[1] = #bfffcccc cccccccc cccccccc cccccccc
+fI[0] == strtod
+
+
+Input: 1.9
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffe666 66666666 66666666 66666666
+g_Qfmt(0) gives 3 bytes: "1.9"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffe666 66666666 66666666 66666666
+fI[1] = #3fffe666 66666666 66666666 66666667
+fI[0] == strtod
+
+
+Input: -1.9
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfffe666 66666666 66666666 66666667
+g_Qfmt(0) gives 37 bytes: "-1.9000000000000000000000000000000001"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffe666 66666666 66666666 66666667
+fI[1] = #bfffe666 66666666 66666666 66666666
+fI[0] == strtod
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/Q.ou1
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/Q.ou1	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/Q.ou1	(revision 2448)
@@ -0,0 +1,1468 @@
+
+Input: 1.23
+
+strtoQ consumes 4 bytes and returns 17
+with bits = #3fff3ae1 47ae147a e147ae14 7ae147ae
+printf("%.35Lg") gives 1.23
+g_Qfmt(0) gives 4 bytes: "1.23"
+
+strtoIQ returns 17, consuming 4 bytes.
+fI[0] = #3fff3ae1 47ae147a e147ae14 7ae147ae
+= 1.23
+fI[1] = #3fff3ae1 47ae147a e147ae14 7ae147af
+= 1.2300000000000000000000000000000002
+fI[0] == strtod
+
+
+Input: 1.23e+20
+
+strtoQ consumes 8 bytes and returns 1
+with bits = #4041aabd f2145b43 0 0
+printf("%.35Lg") gives 123000000000000000000
+g_Qfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIQ returns 1, consuming 8 bytes.
+fI[0] == fI[1] = #4041aabd f2145b43 0 0
+= 123000000000000000000
+
+
+Input: 1.23e-20
+
+strtoQ consumes 8 bytes and returns 17
+with bits = #3fbcd0ae 4cf76753 9e4cbca ad934841
+printf("%.35Lg") gives 1.2299999999999999999999999999999999e-20
+g_Qfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIQ returns 17, consuming 8 bytes.
+fI[0] = #3fbcd0ae 4cf76753 9e4cbca ad934841
+= 1.2299999999999999999999999999999999e-20
+fI[1] = #3fbcd0ae 4cf76753 9e4cbca ad934842
+= 1.2300000000000000000000000000000001e-20
+fI[0] == strtod
+
+
+Input: 1.23456789
+
+strtoQ consumes 10 bytes and returns 17
+with bits = #3fff3c0c a4283de1 b7eb6945 1304948f
+printf("%.35Lg") gives 1.2345678899999999999999999999999999
+g_Qfmt(0) gives 10 bytes: "1.23456789"
+
+strtoIQ returns 17, consuming 10 bytes.
+fI[0] = #3fff3c0c a4283de1 b7eb6945 1304948f
+= 1.2345678899999999999999999999999999
+fI[1] = #3fff3c0c a4283de1 b7eb6945 13049490
+= 1.2345678900000000000000000000000001
+fI[0] == strtod
+
+
+Input: 1.23456589e+20
+
+strtoQ consumes 14 bytes and returns 1
+with bits = #4041ac53 7a660b99 74000000 0
+printf("%.35Lg") gives 123456589000000000000
+g_Qfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoIQ returns 1, consuming 14 bytes.
+fI[0] == fI[1] = #4041ac53 7a660b99 74000000 0
+= 123456589000000000000
+
+
+Input: 1.23e+30
+
+strtoQ consumes 8 bytes and returns 1
+with bits = #4062f0cb 4e8fb79 4945600 0
+printf("%.35Lg") gives 1230000000000000000000000000000
+g_Qfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIQ returns 1, consuming 8 bytes.
+fI[0] == fI[1] = #4062f0cb 4e8fb79 4945600 0
+= 1230000000000000000000000000000
+
+
+Input: 1.23e-30
+
+strtoQ consumes 8 bytes and returns 17
+with bits = #3f9b8f28 66f5010a a9d63f9e d7e8ba14
+printf("%.35Lg") gives 1.2299999999999999999999999999999999e-30
+g_Qfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIQ returns 17, consuming 8 bytes.
+fI[0] = #3f9b8f28 66f5010a a9d63f9e d7e8ba14
+= 1.2299999999999999999999999999999999e-30
+fI[1] = #3f9b8f28 66f5010a a9d63f9e d7e8ba15
+= 1.2300000000000000000000000000000001e-30
+fI[0] == strtod
+
+
+Input: 1.23456789e-20
+
+strtoQ consumes 14 bytes and returns 33
+with bits = #3fbcd268 1471e7ad a6a4a029 d86c1fa2
+printf("%.35Lg") gives 1.2345678900000000000000000000000001e-20
+g_Qfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoIQ returns 33, consuming 14 bytes.
+fI[0] = #3fbcd268 1471e7ad a6a4a029 d86c1fa1
+= 1.2345678899999999999999999999999999e-20
+fI[1] = #3fbcd268 1471e7ad a6a4a029 d86c1fa2
+= 1.2345678900000000000000000000000001e-20
+fI[1] == strtod
+
+
+Input: 1.23456789e-30
+
+strtoQ consumes 14 bytes and returns 17
+with bits = #3f9b90a3 e33bbd99 51f85855 5a6b19d4
+printf("%.35Lg") gives 1.23456789e-30
+g_Qfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoIQ returns 17, consuming 14 bytes.
+fI[0] = #3f9b90a3 e33bbd99 51f85855 5a6b19d4
+= 1.23456789e-30
+fI[1] = #3f9b90a3 e33bbd99 51f85855 5a6b19d5
+= 1.2345678900000000000000000000000001e-30
+fI[0] == strtod
+
+
+Input: 1.234567890123456789
+
+strtoQ consumes 20 bytes and returns 17
+with bits = #3fff3c0c a428c59f b71a4194 68dd175b
+printf("%.35Lg") gives 1.234567890123456789
+g_Qfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIQ returns 17, consuming 20 bytes.
+fI[0] = #3fff3c0c a428c59f b71a4194 68dd175b
+= 1.234567890123456789
+fI[1] = #3fff3c0c a428c59f b71a4194 68dd175c
+= 1.2345678901234567890000000000000002
+fI[0] == strtod
+
+
+Input: 1.23456789012345678901234567890123456789
+
+strtoQ consumes 40 bytes and returns 17
+with bits = #3fff3c0c a428c59f b71a7be1 6b6b6d5b
+printf("%.35Lg") gives 1.2345678901234567890123456789012346
+g_Qfmt(0) gives 36 bytes: "1.2345678901234567890123456789012346"
+
+strtoIQ returns 17, consuming 40 bytes.
+fI[0] = #3fff3c0c a428c59f b71a7be1 6b6b6d5b
+= 1.2345678901234567890123456789012346
+fI[1] = #3fff3c0c a428c59f b71a7be1 6b6b6d5c
+= 1.2345678901234567890123456789012347
+fI[0] == strtod
+
+
+Input: 1.23e306
+
+strtoQ consumes 8 bytes and returns 33
+with bits = #43f7c067 6cd1c61f 4daac5f1 e9fa3b55
+printf("%.35Lg") gives 1.23e+306
+g_Qfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoIQ returns 33, consuming 8 bytes.
+fI[0] = #43f7c067 6cd1c61f 4daac5f1 e9fa3b54
+= 1.2299999999999999999999999999999999e+306
+fI[1] = #43f7c067 6cd1c61f 4daac5f1 e9fa3b55
+= 1.23e+306
+fI[1] == strtod
+
+
+Input: 1.23e-306
+
+strtoQ consumes 9 bytes and returns 17
+with bits = #3c06ba3b 85da396e 7e496ab7 d233c3dd
+printf("%.35Lg") gives 1.23e-306
+g_Qfmt(0) gives 9 bytes: "1.23e-306"
+
+strtoIQ returns 17, consuming 9 bytes.
+fI[0] = #3c06ba3b 85da396e 7e496ab7 d233c3dd
+= 1.23e-306
+fI[1] = #3c06ba3b 85da396e 7e496ab7 d233c3de
+= 1.2300000000000000000000000000000001e-306
+fI[0] == strtod
+
+
+Input: 1.23e-320
+
+strtoQ consumes 9 bytes and returns 33
+with bits = #3bd83731 86e30898 7e33b2e8 355f847b
+printf("%.35Lg") gives 1.2300000000000000000000000000000001e-320
+g_Qfmt(0) gives 9 bytes: "1.23e-320"
+
+strtoIQ returns 33, consuming 9 bytes.
+fI[0] = #3bd83731 86e30898 7e33b2e8 355f847a
+= 1.2299999999999999999999999999999999e-320
+fI[1] = #3bd83731 86e30898 7e33b2e8 355f847b
+= 1.2300000000000000000000000000000001e-320
+fI[1] == strtod
+
+
+Input: 1.23e-20
+
+strtoQ consumes 8 bytes and returns 17
+with bits = #3fbcd0ae 4cf76753 9e4cbca ad934841
+printf("%.35Lg") gives 1.2299999999999999999999999999999999e-20
+g_Qfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIQ returns 17, consuming 8 bytes.
+fI[0] = #3fbcd0ae 4cf76753 9e4cbca ad934841
+= 1.2299999999999999999999999999999999e-20
+fI[1] = #3fbcd0ae 4cf76753 9e4cbca ad934842
+= 1.2300000000000000000000000000000001e-20
+fI[0] == strtod
+
+
+Input: 1.23456789e307
+
+strtoQ consumes 14 bytes and returns 17
+with bits = #43fb194b 14bdaecd bcea468c 902464cf
+printf("%.35Lg") gives 1.2345678899999999999999999999999999e+307
+g_Qfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoIQ returns 17, consuming 14 bytes.
+fI[0] = #43fb194b 14bdaecd bcea468c 902464cf
+= 1.2345678899999999999999999999999999e+307
+fI[1] = #43fb194b 14bdaecd bcea468c 902464d0
+= 1.2345678900000000000000000000000001e+307
+fI[0] == strtod
+
+
+Input: 1.23456589e-307
+
+strtoQ consumes 15 bytes and returns 17
+with bits = #3c036319 6bb9845f a6d234e3 39163574
+printf("%.35Lg") gives 1.23456589e-307
+g_Qfmt(0) gives 15 bytes: "1.23456589e-307"
+
+strtoIQ returns 17, consuming 15 bytes.
+fI[0] = #3c036319 6bb9845f a6d234e3 39163574
+= 1.23456589e-307
+fI[1] = #3c036319 6bb9845f a6d234e3 39163575
+= 1.2345658900000000000000000000000002e-307
+fI[0] == strtod
+
+
+Input: 1.234567890123456789
+
+strtoQ consumes 20 bytes and returns 17
+with bits = #3fff3c0c a428c59f b71a4194 68dd175b
+printf("%.35Lg") gives 1.234567890123456789
+g_Qfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIQ returns 17, consuming 20 bytes.
+fI[0] = #3fff3c0c a428c59f b71a4194 68dd175b
+= 1.234567890123456789
+fI[1] = #3fff3c0c a428c59f b71a4194 68dd175c
+= 1.2345678901234567890000000000000002
+fI[0] == strtod
+
+
+Input: 1.234567890123456789e301
+
+strtoQ consumes 24 bytes and returns 33
+with bits = #43e726f5 175f5641 3017ea80 763990ef
+printf("%.35Lg") gives 1.2345678901234567890000000000000001e+301
+g_Qfmt(0) gives 25 bytes: "1.234567890123456789e+301"
+
+strtoIQ returns 33, consuming 24 bytes.
+fI[0] = #43e726f5 175f5641 3017ea80 763990ee
+= 1.2345678901234567889999999999999999e+301
+fI[1] = #43e726f5 175f5641 3017ea80 763990ef
+= 1.2345678901234567890000000000000001e+301
+fI[1] == strtod
+
+
+Input: 1.234567890123456789e-301
+
+strtoQ consumes 25 bytes and returns 17
+with bits = #3c1752a6 4e34ba0d 35b19b04 3222fce5
+printf("%.35Lg") gives 1.234567890123456789e-301
+g_Qfmt(0) gives 25 bytes: "1.234567890123456789e-301"
+
+strtoIQ returns 17, consuming 25 bytes.
+fI[0] = #3c1752a6 4e34ba0d 35b19b04 3222fce5
+= 1.234567890123456789e-301
+fI[1] = #3c1752a6 4e34ba0d 35b19b04 3222fce6
+= 1.2345678901234567890000000000000002e-301
+fI[0] == strtod
+
+
+Input: 1.234567890123456789e-321
+
+strtoQ consumes 25 bytes and returns 17
+with bits = #3bd4f3c2 3699d4db 99d1ea94 2fecd7de
+printf("%.35Lg") gives 1.234567890123456789e-321
+g_Qfmt(0) gives 25 bytes: "1.234567890123456789e-321"
+
+strtoIQ returns 17, consuming 25 bytes.
+fI[0] = #3bd4f3c2 3699d4db 99d1ea94 2fecd7de
+= 1.234567890123456789e-321
+fI[1] = #3bd4f3c2 3699d4db 99d1ea94 2fecd7df
+= 1.2345678901234567890000000000000001e-321
+fI[0] == strtod
+
+
+Input: 1e23
+
+strtoQ consumes 4 bytes and returns 1
+with bits = #404b52d0 2c7e14af 68000000 0
+printf("%.35Lg") gives 100000000000000000000000
+g_Qfmt(0) gives 5 bytes: "1e+23"
+
+strtoIQ returns 1, consuming 4 bytes.
+fI[0] == fI[1] = #404b52d0 2c7e14af 68000000 0
+= 100000000000000000000000
+
+
+Input: 1e310
+
+strtoQ consumes 5 bytes and returns 33
+with bits = #4404bd03 c8140697 9e9ff00e fefd4cbd
+printf("%.35Lg") gives 1e+310
+g_Qfmt(0) gives 6 bytes: "1e+310"
+
+strtoIQ returns 33, consuming 5 bytes.
+fI[0] = #4404bd03 c8140697 9e9ff00e fefd4cbc
+= 9.9999999999999999999999999999999992e+309
+fI[1] = #4404bd03 c8140697 9e9ff00e fefd4cbd
+= 1e+310
+fI[1] == strtod
+
+
+Input: 9.0259718793241475e-277
+
+strtoQ consumes 23 bytes and returns 17
+with bits = #3c69ffff ffffffff f9ed5779 ac118fe1
+printf("%.35Lg") gives 9.0259718793241474999999999999999997e-277
+g_Qfmt(0) gives 23 bytes: "9.0259718793241475e-277"
+
+strtoIQ returns 17, consuming 23 bytes.
+fI[0] = #3c69ffff ffffffff f9ed5779 ac118fe1
+= 9.0259718793241474999999999999999997e-277
+fI[1] = #3c69ffff ffffffff f9ed5779 ac118fe2
+= 9.0259718793241475000000000000000006e-277
+fI[0] == strtod
+
+
+Input: 9.025971879324147880346310405869e-277
+
+strtoQ consumes 37 bytes and returns 33
+with bits = #3c6a0000 0 0 9a
+printf("%.35Lg") gives 9.0259718793241478803463104058690004e-277
+g_Qfmt(0) gives 37 bytes: "9.025971879324147880346310405869e-277"
+
+strtoIQ returns 33, consuming 37 bytes.
+fI[0] = #3c6a0000 0 0 99
+= 9.0259718793241478803463104058689987e-277
+fI[1] = #3c6a0000 0 0 9a
+= 9.0259718793241478803463104058690004e-277
+fI[1] == strtod
+
+
+Input: 9.025971879324147880346310405868e-277
+
+strtoQ consumes 37 bytes and returns 17
+with bits = #3c69ffff ffffffff ffffffff fffffcb5
+printf("%.35Lg") gives 9.025971879324147880346310405868e-277
+g_Qfmt(0) gives 37 bytes: "9.025971879324147880346310405868e-277"
+
+strtoIQ returns 17, consuming 37 bytes.
+fI[0] = #3c69ffff ffffffff ffffffff fffffcb5
+= 9.025971879324147880346310405868e-277
+fI[1] = #3c69ffff ffffffff ffffffff fffffcb6
+= 9.0259718793241478803463104058680009e-277
+fI[0] == strtod
+
+
+Input: 2.2250738585072014e-308
+
+strtoQ consumes 23 bytes and returns 33
+with bits = #3c010000 0 8c304c cf867de0
+printf("%.35Lg") gives 2.2250738585072014000000000000000001e-308
+g_Qfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoIQ returns 33, consuming 23 bytes.
+fI[0] = #3c010000 0 8c304c cf867ddf
+= 2.2250738585072013999999999999999997e-308
+fI[1] = #3c010000 0 8c304c cf867de0
+= 2.2250738585072014000000000000000001e-308
+fI[1] == strtod
+
+
+Input: 2.2250738585072013e-308
+
+strtoQ consumes 23 bytes and returns 33
+with bits = #3c00ffff ffffffff fa9e4c4f 4c1e8a10
+printf("%.35Lg") gives 2.2250738585072013e-308
+g_Qfmt(0) gives 23 bytes: "2.2250738585072013e-308"
+
+strtoIQ returns 33, consuming 23 bytes.
+fI[0] = #3c00ffff ffffffff fa9e4c4f 4c1e8a0f
+= 2.2250738585072012999999999999999998e-308
+fI[1] = #3c00ffff ffffffff fa9e4c4f 4c1e8a10
+= 2.2250738585072013e-308
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff1999 99999999 99999999 99999999
+printf("%.35Lg") gives 1.0999999999999999999999999999999999
+g_Qfmt(0) gives 36 bytes: "1.0999999999999999999999999999999999"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff1999 99999999 99999999 99999999
+= 1.0999999999999999999999999999999999
+fI[1] = #3fff1999 99999999 99999999 9999999a
+= 1.1000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.1
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff1999 99999999 99999999 99999999
+printf("%.35Lg") gives -1.0999999999999999999999999999999999
+g_Qfmt(0) gives 37 bytes: "-1.0999999999999999999999999999999999"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff1999 99999999 99999999 9999999a
+= -1.1000000000000000000000000000000001
+fI[1] = #bfff1999 99999999 99999999 99999999
+= -1.0999999999999999999999999999999999
+fI[1] == strtod
+
+
+Input: 1.2
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff3333 33333333 33333333 33333333
+printf("%.35Lg") gives 1.2
+g_Qfmt(0) gives 3 bytes: "1.2"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff3333 33333333 33333333 33333333
+= 1.2
+fI[1] = #3fff3333 33333333 33333333 33333334
+= 1.2000000000000000000000000000000002
+fI[0] == strtod
+
+
+Input: -1.2
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff3333 33333333 33333333 33333333
+printf("%.35Lg") gives -1.2
+g_Qfmt(0) gives 4 bytes: "-1.2"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff3333 33333333 33333333 33333334
+= -1.2000000000000000000000000000000002
+fI[1] = #bfff3333 33333333 33333333 33333333
+= -1.2
+fI[1] == strtod
+
+
+Input: 1.3
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff4ccc cccccccc cccccccc cccccccc
+printf("%.35Lg") gives 1.2999999999999999999999999999999998
+g_Qfmt(0) gives 36 bytes: "1.2999999999999999999999999999999998"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff4ccc cccccccc cccccccc cccccccc
+= 1.2999999999999999999999999999999998
+fI[1] = #3fff4ccc cccccccc cccccccc cccccccd
+= 1.3
+fI[0] == strtod
+
+
+Input: -1.3
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff4ccc cccccccc cccccccc cccccccc
+printf("%.35Lg") gives -1.2999999999999999999999999999999998
+g_Qfmt(0) gives 37 bytes: "-1.2999999999999999999999999999999998"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff4ccc cccccccc cccccccc cccccccd
+= -1.3
+fI[1] = #bfff4ccc cccccccc cccccccc cccccccc
+= -1.2999999999999999999999999999999998
+fI[1] == strtod
+
+
+Input: 1.4
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff6666 66666666 66666666 66666666
+printf("%.35Lg") gives 1.3999999999999999999999999999999999
+g_Qfmt(0) gives 3 bytes: "1.4"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff6666 66666666 66666666 66666666
+= 1.3999999999999999999999999999999999
+fI[1] = #3fff6666 66666666 66666666 66666667
+= 1.4000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.4
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff6666 66666666 66666666 66666666
+printf("%.35Lg") gives -1.3999999999999999999999999999999999
+g_Qfmt(0) gives 4 bytes: "-1.4"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff6666 66666666 66666666 66666667
+= -1.4000000000000000000000000000000001
+fI[1] = #bfff6666 66666666 66666666 66666666
+= -1.3999999999999999999999999999999999
+fI[1] == strtod
+
+
+Input: 1.5
+
+strtoQ consumes 3 bytes and returns 1
+with bits = #3fff8000 0 0 0
+printf("%.35Lg") gives 1.5
+g_Qfmt(0) gives 3 bytes: "1.5"
+
+strtoIQ returns 1, consuming 3 bytes.
+fI[0] == fI[1] = #3fff8000 0 0 0
+= 1.5
+
+
+Input: -1.5
+
+strtoQ consumes 4 bytes and returns 9
+with bits = #bfff8000 0 0 0
+printf("%.35Lg") gives -1.5
+g_Qfmt(0) gives 4 bytes: "-1.5"
+
+strtoIQ returns 9, consuming 4 bytes.
+fI[0] == fI[1] = #bfff8000 0 0 0
+= -1.5
+
+
+Input: 1.6
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff9999 99999999 99999999 99999999
+printf("%.35Lg") gives 1.5999999999999999999999999999999999
+g_Qfmt(0) gives 36 bytes: "1.5999999999999999999999999999999999"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff9999 99999999 99999999 99999999
+= 1.5999999999999999999999999999999999
+fI[1] = #3fff9999 99999999 99999999 9999999a
+= 1.6000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.6
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff9999 99999999 99999999 99999999
+printf("%.35Lg") gives -1.5999999999999999999999999999999999
+g_Qfmt(0) gives 37 bytes: "-1.5999999999999999999999999999999999"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff9999 99999999 99999999 9999999a
+= -1.6000000000000000000000000000000001
+fI[1] = #bfff9999 99999999 99999999 99999999
+= -1.5999999999999999999999999999999999
+fI[1] == strtod
+
+
+Input: 1.7
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffb333 33333333 33333333 33333333
+printf("%.35Lg") gives 1.7
+g_Qfmt(0) gives 3 bytes: "1.7"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffb333 33333333 33333333 33333333
+= 1.7
+fI[1] = #3fffb333 33333333 33333333 33333334
+= 1.7000000000000000000000000000000002
+fI[0] == strtod
+
+
+Input: -1.7
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffb333 33333333 33333333 33333333
+printf("%.35Lg") gives -1.7
+g_Qfmt(0) gives 4 bytes: "-1.7"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffb333 33333333 33333333 33333334
+= -1.7000000000000000000000000000000002
+fI[1] = #bfffb333 33333333 33333333 33333333
+= -1.7
+fI[1] == strtod
+
+
+Input: 1.8
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffcccc cccccccc cccccccc cccccccc
+printf("%.35Lg") gives 1.7999999999999999999999999999999998
+g_Qfmt(0) gives 36 bytes: "1.7999999999999999999999999999999998"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fffcccc cccccccc cccccccc cccccccc
+= 1.7999999999999999999999999999999998
+fI[1] = #3fffcccc cccccccc cccccccc cccccccd
+= 1.8
+fI[0] == strtod
+
+
+Input: -1.8
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffcccc cccccccc cccccccc cccccccc
+printf("%.35Lg") gives -1.7999999999999999999999999999999998
+g_Qfmt(0) gives 37 bytes: "-1.7999999999999999999999999999999998"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfffcccc cccccccc cccccccc cccccccd
+= -1.8
+fI[1] = #bfffcccc cccccccc cccccccc cccccccc
+= -1.7999999999999999999999999999999998
+fI[1] == strtod
+
+
+Input: 1.9
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffe666 66666666 66666666 66666666
+printf("%.35Lg") gives 1.8999999999999999999999999999999999
+g_Qfmt(0) gives 3 bytes: "1.9"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffe666 66666666 66666666 66666666
+= 1.8999999999999999999999999999999999
+fI[1] = #3fffe666 66666666 66666666 66666667
+= 1.9000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.9
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffe666 66666666 66666666 66666666
+printf("%.35Lg") gives -1.8999999999999999999999999999999999
+g_Qfmt(0) gives 4 bytes: "-1.9"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffe666 66666666 66666666 66666667
+= -1.9000000000000000000000000000000001
+fI[1] = #bfffe666 66666666 66666666 66666666
+= -1.8999999999999999999999999999999999
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff1999 99999999 99999999 9999999a
+printf("%.35Lg") gives 1.1000000000000000000000000000000001
+g_Qfmt(0) gives 3 bytes: "1.1"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff1999 99999999 99999999 99999999
+= 1.0999999999999999999999999999999999
+fI[1] = #3fff1999 99999999 99999999 9999999a
+= 1.1000000000000000000000000000000001
+fI[1] == strtod
+
+
+Input: -1.1
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff1999 99999999 99999999 9999999a
+printf("%.35Lg") gives -1.1000000000000000000000000000000001
+g_Qfmt(0) gives 4 bytes: "-1.1"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff1999 99999999 99999999 9999999a
+= -1.1000000000000000000000000000000001
+fI[1] = #bfff1999 99999999 99999999 99999999
+= -1.0999999999999999999999999999999999
+fI[0] == strtod
+
+
+Input: 1.2
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff3333 33333333 33333333 33333333
+printf("%.35Lg") gives 1.2
+g_Qfmt(0) gives 3 bytes: "1.2"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff3333 33333333 33333333 33333333
+= 1.2
+fI[1] = #3fff3333 33333333 33333333 33333334
+= 1.2000000000000000000000000000000002
+fI[0] == strtod
+
+
+Input: -1.2
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff3333 33333333 33333333 33333333
+printf("%.35Lg") gives -1.2
+g_Qfmt(0) gives 4 bytes: "-1.2"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff3333 33333333 33333333 33333334
+= -1.2000000000000000000000000000000002
+fI[1] = #bfff3333 33333333 33333333 33333333
+= -1.2
+fI[1] == strtod
+
+
+Input: 1.3
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff4ccc cccccccc cccccccc cccccccd
+printf("%.35Lg") gives 1.3
+g_Qfmt(0) gives 3 bytes: "1.3"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff4ccc cccccccc cccccccc cccccccc
+= 1.2999999999999999999999999999999998
+fI[1] = #3fff4ccc cccccccc cccccccc cccccccd
+= 1.3
+fI[1] == strtod
+
+
+Input: -1.3
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff4ccc cccccccc cccccccc cccccccd
+printf("%.35Lg") gives -1.3
+g_Qfmt(0) gives 4 bytes: "-1.3"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff4ccc cccccccc cccccccc cccccccd
+= -1.3
+fI[1] = #bfff4ccc cccccccc cccccccc cccccccc
+= -1.2999999999999999999999999999999998
+fI[0] == strtod
+
+
+Input: 1.4
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff6666 66666666 66666666 66666666
+printf("%.35Lg") gives 1.3999999999999999999999999999999999
+g_Qfmt(0) gives 3 bytes: "1.4"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff6666 66666666 66666666 66666666
+= 1.3999999999999999999999999999999999
+fI[1] = #3fff6666 66666666 66666666 66666667
+= 1.4000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.4
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff6666 66666666 66666666 66666666
+printf("%.35Lg") gives -1.3999999999999999999999999999999999
+g_Qfmt(0) gives 4 bytes: "-1.4"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff6666 66666666 66666666 66666667
+= -1.4000000000000000000000000000000001
+fI[1] = #bfff6666 66666666 66666666 66666666
+= -1.3999999999999999999999999999999999
+fI[1] == strtod
+
+
+Input: 1.5
+
+strtoQ consumes 3 bytes and returns 1
+with bits = #3fff8000 0 0 0
+printf("%.35Lg") gives 1.5
+g_Qfmt(0) gives 3 bytes: "1.5"
+
+strtoIQ returns 1, consuming 3 bytes.
+fI[0] == fI[1] = #3fff8000 0 0 0
+= 1.5
+
+
+Input: -1.5
+
+strtoQ consumes 4 bytes and returns 9
+with bits = #bfff8000 0 0 0
+printf("%.35Lg") gives -1.5
+g_Qfmt(0) gives 4 bytes: "-1.5"
+
+strtoIQ returns 9, consuming 4 bytes.
+fI[0] == fI[1] = #bfff8000 0 0 0
+= -1.5
+
+
+Input: 1.6
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff9999 99999999 99999999 9999999a
+printf("%.35Lg") gives 1.6000000000000000000000000000000001
+g_Qfmt(0) gives 3 bytes: "1.6"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff9999 99999999 99999999 99999999
+= 1.5999999999999999999999999999999999
+fI[1] = #3fff9999 99999999 99999999 9999999a
+= 1.6000000000000000000000000000000001
+fI[1] == strtod
+
+
+Input: -1.6
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff9999 99999999 99999999 9999999a
+printf("%.35Lg") gives -1.6000000000000000000000000000000001
+g_Qfmt(0) gives 4 bytes: "-1.6"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff9999 99999999 99999999 9999999a
+= -1.6000000000000000000000000000000001
+fI[1] = #bfff9999 99999999 99999999 99999999
+= -1.5999999999999999999999999999999999
+fI[0] == strtod
+
+
+Input: 1.7
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffb333 33333333 33333333 33333333
+printf("%.35Lg") gives 1.7
+g_Qfmt(0) gives 3 bytes: "1.7"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffb333 33333333 33333333 33333333
+= 1.7
+fI[1] = #3fffb333 33333333 33333333 33333334
+= 1.7000000000000000000000000000000002
+fI[0] == strtod
+
+
+Input: -1.7
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffb333 33333333 33333333 33333333
+printf("%.35Lg") gives -1.7
+g_Qfmt(0) gives 4 bytes: "-1.7"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffb333 33333333 33333333 33333334
+= -1.7000000000000000000000000000000002
+fI[1] = #bfffb333 33333333 33333333 33333333
+= -1.7
+fI[1] == strtod
+
+
+Input: 1.8
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fffcccc cccccccc cccccccc cccccccd
+printf("%.35Lg") gives 1.8
+g_Qfmt(0) gives 3 bytes: "1.8"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fffcccc cccccccc cccccccc cccccccc
+= 1.7999999999999999999999999999999998
+fI[1] = #3fffcccc cccccccc cccccccc cccccccd
+= 1.8
+fI[1] == strtod
+
+
+Input: -1.8
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfffcccc cccccccc cccccccc cccccccd
+printf("%.35Lg") gives -1.8
+g_Qfmt(0) gives 4 bytes: "-1.8"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfffcccc cccccccc cccccccc cccccccd
+= -1.8
+fI[1] = #bfffcccc cccccccc cccccccc cccccccc
+= -1.7999999999999999999999999999999998
+fI[0] == strtod
+
+
+Input: 1.9
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffe666 66666666 66666666 66666666
+printf("%.35Lg") gives 1.8999999999999999999999999999999999
+g_Qfmt(0) gives 3 bytes: "1.9"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffe666 66666666 66666666 66666666
+= 1.8999999999999999999999999999999999
+fI[1] = #3fffe666 66666666 66666666 66666667
+= 1.9000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.9
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffe666 66666666 66666666 66666666
+printf("%.35Lg") gives -1.8999999999999999999999999999999999
+g_Qfmt(0) gives 4 bytes: "-1.9"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffe666 66666666 66666666 66666667
+= -1.9000000000000000000000000000000001
+fI[1] = #bfffe666 66666666 66666666 66666666
+= -1.8999999999999999999999999999999999
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff1999 99999999 99999999 9999999a
+printf("%.35Lg") gives 1.1000000000000000000000000000000001
+g_Qfmt(0) gives 3 bytes: "1.1"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff1999 99999999 99999999 99999999
+= 1.0999999999999999999999999999999999
+fI[1] = #3fff1999 99999999 99999999 9999999a
+= 1.1000000000000000000000000000000001
+fI[1] == strtod
+
+
+Input: -1.1
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff1999 99999999 99999999 99999999
+printf("%.35Lg") gives -1.0999999999999999999999999999999999
+g_Qfmt(0) gives 37 bytes: "-1.0999999999999999999999999999999999"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff1999 99999999 99999999 9999999a
+= -1.1000000000000000000000000000000001
+fI[1] = #bfff1999 99999999 99999999 99999999
+= -1.0999999999999999999999999999999999
+fI[1] == strtod
+
+
+Input: 1.2
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff3333 33333333 33333333 33333334
+printf("%.35Lg") gives 1.2000000000000000000000000000000002
+g_Qfmt(0) gives 36 bytes: "1.2000000000000000000000000000000002"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff3333 33333333 33333333 33333333
+= 1.2
+fI[1] = #3fff3333 33333333 33333333 33333334
+= 1.2000000000000000000000000000000002
+fI[1] == strtod
+
+
+Input: -1.2
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff3333 33333333 33333333 33333333
+printf("%.35Lg") gives -1.2
+g_Qfmt(0) gives 4 bytes: "-1.2"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff3333 33333333 33333333 33333334
+= -1.2000000000000000000000000000000002
+fI[1] = #bfff3333 33333333 33333333 33333333
+= -1.2
+fI[1] == strtod
+
+
+Input: 1.3
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff4ccc cccccccc cccccccc cccccccd
+printf("%.35Lg") gives 1.3
+g_Qfmt(0) gives 3 bytes: "1.3"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff4ccc cccccccc cccccccc cccccccc
+= 1.2999999999999999999999999999999998
+fI[1] = #3fff4ccc cccccccc cccccccc cccccccd
+= 1.3
+fI[1] == strtod
+
+
+Input: -1.3
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff4ccc cccccccc cccccccc cccccccc
+printf("%.35Lg") gives -1.2999999999999999999999999999999998
+g_Qfmt(0) gives 37 bytes: "-1.2999999999999999999999999999999998"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff4ccc cccccccc cccccccc cccccccd
+= -1.3
+fI[1] = #bfff4ccc cccccccc cccccccc cccccccc
+= -1.2999999999999999999999999999999998
+fI[1] == strtod
+
+
+Input: 1.4
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff6666 66666666 66666666 66666667
+printf("%.35Lg") gives 1.4000000000000000000000000000000001
+g_Qfmt(0) gives 36 bytes: "1.4000000000000000000000000000000001"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff6666 66666666 66666666 66666666
+= 1.3999999999999999999999999999999999
+fI[1] = #3fff6666 66666666 66666666 66666667
+= 1.4000000000000000000000000000000001
+fI[1] == strtod
+
+
+Input: -1.4
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff6666 66666666 66666666 66666666
+printf("%.35Lg") gives -1.3999999999999999999999999999999999
+g_Qfmt(0) gives 4 bytes: "-1.4"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff6666 66666666 66666666 66666667
+= -1.4000000000000000000000000000000001
+fI[1] = #bfff6666 66666666 66666666 66666666
+= -1.3999999999999999999999999999999999
+fI[1] == strtod
+
+
+Input: 1.5
+
+strtoQ consumes 3 bytes and returns 1
+with bits = #3fff8000 0 0 0
+printf("%.35Lg") gives 1.5
+g_Qfmt(0) gives 3 bytes: "1.5"
+
+strtoIQ returns 1, consuming 3 bytes.
+fI[0] == fI[1] = #3fff8000 0 0 0
+= 1.5
+
+
+Input: -1.5
+
+strtoQ consumes 4 bytes and returns 9
+with bits = #bfff8000 0 0 0
+printf("%.35Lg") gives -1.5
+g_Qfmt(0) gives 4 bytes: "-1.5"
+
+strtoIQ returns 9, consuming 4 bytes.
+fI[0] == fI[1] = #bfff8000 0 0 0
+= -1.5
+
+
+Input: 1.6
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fff9999 99999999 99999999 9999999a
+printf("%.35Lg") gives 1.6000000000000000000000000000000001
+g_Qfmt(0) gives 3 bytes: "1.6"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff9999 99999999 99999999 99999999
+= 1.5999999999999999999999999999999999
+fI[1] = #3fff9999 99999999 99999999 9999999a
+= 1.6000000000000000000000000000000001
+fI[1] == strtod
+
+
+Input: -1.6
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfff9999 99999999 99999999 99999999
+printf("%.35Lg") gives -1.5999999999999999999999999999999999
+g_Qfmt(0) gives 37 bytes: "-1.5999999999999999999999999999999999"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff9999 99999999 99999999 9999999a
+= -1.6000000000000000000000000000000001
+fI[1] = #bfff9999 99999999 99999999 99999999
+= -1.5999999999999999999999999999999999
+fI[1] == strtod
+
+
+Input: 1.7
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fffb333 33333333 33333333 33333334
+printf("%.35Lg") gives 1.7000000000000000000000000000000002
+g_Qfmt(0) gives 36 bytes: "1.7000000000000000000000000000000002"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffb333 33333333 33333333 33333333
+= 1.7
+fI[1] = #3fffb333 33333333 33333333 33333334
+= 1.7000000000000000000000000000000002
+fI[1] == strtod
+
+
+Input: -1.7
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffb333 33333333 33333333 33333333
+printf("%.35Lg") gives -1.7
+g_Qfmt(0) gives 4 bytes: "-1.7"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffb333 33333333 33333333 33333334
+= -1.7000000000000000000000000000000002
+fI[1] = #bfffb333 33333333 33333333 33333333
+= -1.7
+fI[1] == strtod
+
+
+Input: 1.8
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fffcccc cccccccc cccccccc cccccccd
+printf("%.35Lg") gives 1.8
+g_Qfmt(0) gives 3 bytes: "1.8"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fffcccc cccccccc cccccccc cccccccc
+= 1.7999999999999999999999999999999998
+fI[1] = #3fffcccc cccccccc cccccccc cccccccd
+= 1.8
+fI[1] == strtod
+
+
+Input: -1.8
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffcccc cccccccc cccccccc cccccccc
+printf("%.35Lg") gives -1.7999999999999999999999999999999998
+g_Qfmt(0) gives 37 bytes: "-1.7999999999999999999999999999999998"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfffcccc cccccccc cccccccc cccccccd
+= -1.8
+fI[1] = #bfffcccc cccccccc cccccccc cccccccc
+= -1.7999999999999999999999999999999998
+fI[1] == strtod
+
+
+Input: 1.9
+
+strtoQ consumes 3 bytes and returns 33
+with bits = #3fffe666 66666666 66666666 66666667
+printf("%.35Lg") gives 1.9000000000000000000000000000000001
+g_Qfmt(0) gives 36 bytes: "1.9000000000000000000000000000000001"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffe666 66666666 66666666 66666666
+= 1.8999999999999999999999999999999999
+fI[1] = #3fffe666 66666666 66666666 66666667
+= 1.9000000000000000000000000000000001
+fI[1] == strtod
+
+
+Input: -1.9
+
+strtoQ consumes 4 bytes and returns 25
+with bits = #bfffe666 66666666 66666666 66666666
+printf("%.35Lg") gives -1.8999999999999999999999999999999999
+g_Qfmt(0) gives 4 bytes: "-1.9"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffe666 66666666 66666666 66666667
+= -1.9000000000000000000000000000000001
+fI[1] = #bfffe666 66666666 66666666 66666666
+= -1.8999999999999999999999999999999999
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff1999 99999999 99999999 99999999
+printf("%.35Lg") gives 1.0999999999999999999999999999999999
+g_Qfmt(0) gives 36 bytes: "1.0999999999999999999999999999999999"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff1999 99999999 99999999 99999999
+= 1.0999999999999999999999999999999999
+fI[1] = #3fff1999 99999999 99999999 9999999a
+= 1.1000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.1
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff1999 99999999 99999999 9999999a
+printf("%.35Lg") gives -1.1000000000000000000000000000000001
+g_Qfmt(0) gives 4 bytes: "-1.1"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff1999 99999999 99999999 9999999a
+= -1.1000000000000000000000000000000001
+fI[1] = #bfff1999 99999999 99999999 99999999
+= -1.0999999999999999999999999999999999
+fI[0] == strtod
+
+
+Input: 1.2
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff3333 33333333 33333333 33333333
+printf("%.35Lg") gives 1.2
+g_Qfmt(0) gives 3 bytes: "1.2"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff3333 33333333 33333333 33333333
+= 1.2
+fI[1] = #3fff3333 33333333 33333333 33333334
+= 1.2000000000000000000000000000000002
+fI[0] == strtod
+
+
+Input: -1.2
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff3333 33333333 33333333 33333334
+printf("%.35Lg") gives -1.2000000000000000000000000000000002
+g_Qfmt(0) gives 37 bytes: "-1.2000000000000000000000000000000002"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff3333 33333333 33333333 33333334
+= -1.2000000000000000000000000000000002
+fI[1] = #bfff3333 33333333 33333333 33333333
+= -1.2
+fI[0] == strtod
+
+
+Input: 1.3
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff4ccc cccccccc cccccccc cccccccc
+printf("%.35Lg") gives 1.2999999999999999999999999999999998
+g_Qfmt(0) gives 36 bytes: "1.2999999999999999999999999999999998"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff4ccc cccccccc cccccccc cccccccc
+= 1.2999999999999999999999999999999998
+fI[1] = #3fff4ccc cccccccc cccccccc cccccccd
+= 1.3
+fI[0] == strtod
+
+
+Input: -1.3
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff4ccc cccccccc cccccccc cccccccd
+printf("%.35Lg") gives -1.3
+g_Qfmt(0) gives 4 bytes: "-1.3"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff4ccc cccccccc cccccccc cccccccd
+= -1.3
+fI[1] = #bfff4ccc cccccccc cccccccc cccccccc
+= -1.2999999999999999999999999999999998
+fI[0] == strtod
+
+
+Input: 1.4
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff6666 66666666 66666666 66666666
+printf("%.35Lg") gives 1.3999999999999999999999999999999999
+g_Qfmt(0) gives 3 bytes: "1.4"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fff6666 66666666 66666666 66666666
+= 1.3999999999999999999999999999999999
+fI[1] = #3fff6666 66666666 66666666 66666667
+= 1.4000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.4
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff6666 66666666 66666666 66666667
+printf("%.35Lg") gives -1.4000000000000000000000000000000001
+g_Qfmt(0) gives 37 bytes: "-1.4000000000000000000000000000000001"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfff6666 66666666 66666666 66666667
+= -1.4000000000000000000000000000000001
+fI[1] = #bfff6666 66666666 66666666 66666666
+= -1.3999999999999999999999999999999999
+fI[0] == strtod
+
+
+Input: 1.5
+
+strtoQ consumes 3 bytes and returns 1
+with bits = #3fff8000 0 0 0
+printf("%.35Lg") gives 1.5
+g_Qfmt(0) gives 3 bytes: "1.5"
+
+strtoIQ returns 1, consuming 3 bytes.
+fI[0] == fI[1] = #3fff8000 0 0 0
+= 1.5
+
+
+Input: -1.5
+
+strtoQ consumes 4 bytes and returns 9
+with bits = #bfff8000 0 0 0
+printf("%.35Lg") gives -1.5
+g_Qfmt(0) gives 4 bytes: "-1.5"
+
+strtoIQ returns 9, consuming 4 bytes.
+fI[0] == fI[1] = #bfff8000 0 0 0
+= -1.5
+
+
+Input: 1.6
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fff9999 99999999 99999999 99999999
+printf("%.35Lg") gives 1.5999999999999999999999999999999999
+g_Qfmt(0) gives 36 bytes: "1.5999999999999999999999999999999999"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fff9999 99999999 99999999 99999999
+= 1.5999999999999999999999999999999999
+fI[1] = #3fff9999 99999999 99999999 9999999a
+= 1.6000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.6
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfff9999 99999999 99999999 9999999a
+printf("%.35Lg") gives -1.6000000000000000000000000000000001
+g_Qfmt(0) gives 4 bytes: "-1.6"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfff9999 99999999 99999999 9999999a
+= -1.6000000000000000000000000000000001
+fI[1] = #bfff9999 99999999 99999999 99999999
+= -1.5999999999999999999999999999999999
+fI[0] == strtod
+
+
+Input: 1.7
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffb333 33333333 33333333 33333333
+printf("%.35Lg") gives 1.7
+g_Qfmt(0) gives 3 bytes: "1.7"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffb333 33333333 33333333 33333333
+= 1.7
+fI[1] = #3fffb333 33333333 33333333 33333334
+= 1.7000000000000000000000000000000002
+fI[0] == strtod
+
+
+Input: -1.7
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfffb333 33333333 33333333 33333334
+printf("%.35Lg") gives -1.7000000000000000000000000000000002
+g_Qfmt(0) gives 37 bytes: "-1.7000000000000000000000000000000002"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffb333 33333333 33333333 33333334
+= -1.7000000000000000000000000000000002
+fI[1] = #bfffb333 33333333 33333333 33333333
+= -1.7
+fI[0] == strtod
+
+
+Input: 1.8
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffcccc cccccccc cccccccc cccccccc
+printf("%.35Lg") gives 1.7999999999999999999999999999999998
+g_Qfmt(0) gives 36 bytes: "1.7999999999999999999999999999999998"
+
+strtoIQ returns 33, consuming 3 bytes.
+fI[0] = #3fffcccc cccccccc cccccccc cccccccc
+= 1.7999999999999999999999999999999998
+fI[1] = #3fffcccc cccccccc cccccccc cccccccd
+= 1.8
+fI[0] == strtod
+
+
+Input: -1.8
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfffcccc cccccccc cccccccc cccccccd
+printf("%.35Lg") gives -1.8
+g_Qfmt(0) gives 4 bytes: "-1.8"
+
+strtoIQ returns 41, consuming 4 bytes.
+fI[0] = #bfffcccc cccccccc cccccccc cccccccd
+= -1.8
+fI[1] = #bfffcccc cccccccc cccccccc cccccccc
+= -1.7999999999999999999999999999999998
+fI[0] == strtod
+
+
+Input: 1.9
+
+strtoQ consumes 3 bytes and returns 17
+with bits = #3fffe666 66666666 66666666 66666666
+printf("%.35Lg") gives 1.8999999999999999999999999999999999
+g_Qfmt(0) gives 3 bytes: "1.9"
+
+strtoIQ returns 17, consuming 3 bytes.
+fI[0] = #3fffe666 66666666 66666666 66666666
+= 1.8999999999999999999999999999999999
+fI[1] = #3fffe666 66666666 66666666 66666667
+= 1.9000000000000000000000000000000001
+fI[0] == strtod
+
+
+Input: -1.9
+
+strtoQ consumes 4 bytes and returns 41
+with bits = #bfffe666 66666666 66666666 66666667
+printf("%.35Lg") gives -1.9000000000000000000000000000000001
+g_Qfmt(0) gives 37 bytes: "-1.9000000000000000000000000000000001"
+
+strtoIQ returns 25, consuming 4 bytes.
+fI[0] = #bfffe666 66666666 66666666 66666667
+= -1.9000000000000000000000000000000001
+fI[1] = #bfffe666 66666666 66666666 66666666
+= -1.8999999999999999999999999999999999
+fI[0] == strtod
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/Qtest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/Qtest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/Qtest.c	(revision 2448)
@@ -0,0 +1,170 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* Test program for g_Qfmt, strtoIQ, strtopQ, and strtorQ.
+ *
+ * Inputs (on stdin):
+ *		r rounding_mode
+ *		n ndig
+ *		number
+ *		#hex0 hex1 hex2 hex3
+ *
+ *	rounding_mode values:
+ *		0 = toward zero
+ *		1 = nearest
+ *		2 = toward +Infinity
+ *		3 = toward -Infinity
+ *
+ * where number is a decimal floating-point number,
+ * hex0 is a string of <= 8 Hex digits for the most significant
+ * word of the number, hex1 is a similar string for the next
+ * word, etc., and ndig is a parameters to g_Qfmt.
+ */
+
+#include "gdtoa.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+ extern int getround ANSI((int,char*));
+
+ static char ibuf[2048], obuf[2048];
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#endif
+#ifdef IEEE_8087
+#define _0 3
+#define _1 2
+#define _2 1
+#define _3 0
+#endif
+
+#define U (unsigned long)
+
+ int
+main(Void)
+{
+	char *s, *se, *se1;
+	int i, dItry, ndig = 0, r = 1;
+	union { long double d; ULong bits[4]; } u, v[2];
+
+	while( (s = fgets(ibuf, sizeof(ibuf), stdin)) !=0) {
+		while(*s <= ' ')
+			if (!*s++)
+				continue;
+		dItry = 0;
+		switch(*s) {
+		  case 'r':
+			r = getround(r, s);
+			continue;
+		  case 'n':
+			i = s[1];
+			if (i <= ' ' || i >= '0' && i <= '9') {
+				ndig = atoi(s+1);
+				continue;
+				}
+			break; /* nan? */
+		  case '#':
+			sscanf(s+1, "%lx %lx %lx %lx", &u.bits[_0],
+				&u.bits[_1], &u.bits[_2], &u.bits[_3]);
+			printf("\nInput: %s", ibuf);
+			printf(" --> f = #%lx %lx %lx %lx\n", u.bits[_0],
+				u.bits[_1], u.bits[_2], u.bits[_3]);
+			goto fmt_test;
+			}
+		dItry = 1;
+		printf("\nInput: %s", ibuf);
+		i = strtorQ(ibuf, &se, r, u.bits);
+		if (r == 1 && (strtopQ(ibuf,&se1,v[0].bits) != i
+		 || se != se1 || memcmp(u.bits, v[0].bits, 16)))
+			printf("***strtoQ and strtorQ disagree!!\n:");
+		printf("\nstrtoQ consumes %d bytes and returns %d\n",
+				(int)(se-ibuf), i);
+		printf("with bits = #%lx %lx %lx %lx\n",
+			U u.bits[_0], U u.bits[_1], U u.bits[_2], U u.bits[_3]);
+ fmt_test:
+		if (sizeof(long double) == 16)
+			printf("printf(\"%%.35Lg\") gives %.35Lg\n", u.d);
+		se = g_Qfmt(obuf, u.bits, ndig, sizeof(obuf));
+		printf("g_Qfmt(%d) gives %d bytes: \"%s\"\n\n", ndig,
+			(int)(se-obuf), se ? obuf : "<null>");
+		if (!dItry)
+			continue;
+		printf("strtoIQ returns %d,",
+			strtoIQ(ibuf, &se, v[0].bits, v[1].bits));
+		printf(" consuming %d bytes.\n", (int)(se-ibuf));
+		if (!memcmp(v[0].bits, v[1].bits, 16)) {
+			if (!memcpy(u.bits, v[0].bits, 16))
+				printf("fI[0] == fI[1] == strtoQ\n");
+			else {
+				printf("fI[0] == fI[1] = #%lx %lx %lx %lx\n",
+					U v[0].bits[_0], U v[0].bits[_1],
+					U v[0].bits[_2], U v[0].bits[_3]);
+				if (sizeof(long double) == 16)
+				    printf("= %.35Lg\n", v[0].d);
+				}
+			}
+		else {
+			printf("fI[0] = #%lx %lx %lx %lx\n",
+					U v[0].bits[_0], U v[0].bits[_1],
+					U v[0].bits[_2], U v[0].bits[_3]);
+			if (sizeof(long double) == 16)
+				printf("= %.35Lg\n", v[0].d);
+			printf("fI[1] = #%lx %lx %lx %lx\n",
+					U v[1].bits[_0], U v[1].bits[_1],
+					U v[1].bits[_2], U v[1].bits[_3]);
+			if (sizeof(long double) == 16)
+				printf("= %.35Lg\n", v[1].d);
+			if (!memcmp(v[0].bits, u.bits, 16))
+				printf("fI[0] == strtod\n");
+			else if (!memcmp(v[1].bits, u.bits, 16))
+				printf("fI[1] == strtod\n");
+			else
+				printf("**** Both differ from strtod ****\n");
+			}
+		printf("\n");
+		}
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/README
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/README	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/README	(revision 2448)
@@ -0,0 +1,61 @@
+This directory contains source for several test programs:
+
+dt is for conversion to/from double; it permits input of pairs of
+32-bit hex integers as #hhhhhhhh hhhhhhhh (i.e., the initial '#'
+indicates hex input).  No initial # ==> decimal input.
+After the input number is an optional : mode ndigits
+(colon, and decimal integers for parameters "mode" and "ndigits"
+to gdtoa).
+
+Qtest, ddtest, dtest, ftest, xLtest and xtest are for conversion to/from
+
+	f	IEEE single precision
+	d	IEEE double precision
+	xL	IEEE extended precision, as on Motorola 680x0 chips
+	x	IEEE extended precision, as on Intel 80x87 chips or
+			software emulation of Motorola 680x0 chips
+	Q	quad precision, as on Sun Sparc chips
+	dd	double double, pairs of IEEE double numbers
+		whose sum is the desired value
+
+They're all similar, except for the precision.  They test both
+directed roundings and interval input (the strtoI* routines).
+Lines that begin with "r" specify or interrogate the desired rounding
+direction:
+
+	0 = toward 0
+	1 = nearest (default)
+	2 = toward +Infinity
+	3 = toward -Infinity
+
+These are the FPI_Round_* values in gdota.h.  The "r" value is sticky:
+it stays in effect til changed.  To change the value, give a line that
+starts with r followed by 0, 1, 2, or 3.  To check the value, give "r"
+by itself.
+
+Lines that begin with n followed by a number specify the ndig
+argument for subsequent calls to the relevant g_*fmt routine.
+
+Lines that start with # followed by the appropriate number of
+hexadecimal strings (see the comments) give the big-endian
+internal representation of the desired number.
+
+When routines Qtest, xLtest, and xtest are used on machines whose
+long double is of type "quad" (for Qtest) or "extended" (for x*test),
+they try to print with %Lg as another way to show binary values.
+
+Program ddtest also accepts (white-space separated) pairs of decimal
+input numbers; it converts both with strtod and feeds the result
+to g_ddfmt.
+
+Program dItest exercises strtodI and strtoId.
+
+Programs dItestsi and ddtestsi are for testing the sudden-underflow
+logic (on double and double-double conversions).
+
+Program strtodt tests strtod on some hard cases (in file testnos3)
+posted by Fred Tydeman to comp.arch.arithmetic on 26 Feb. 1996.
+
+These are simple test programs, not meant for exhaustive testing,
+but for manually testing "interesting" cases.  Paxson's testbase
+is good for more exhaustive testing, in part with random inputs.
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/d.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/d.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/d.out	(revision 2448)
@@ -0,0 +1,986 @@
+
+Input: 1.23
+strtod consumes 4 bytes and returns 17 with f = 1.23 = #3ff3ae14 7ae147ae
+g_dfmt(0) gives 4 bytes: "1.23"
+
+strtoId returns 17, consuming 4 bytes.
+fI[0] = #3ff3ae14 7ae147ae = 1.23
+fI[1] = #3ff3ae14 7ae147af = 1.2300000000000002
+fI[0] == strtod
+
+
+Input: 1.23e+20
+strtod consumes 8 bytes and returns 1 with f = 1.23e+20 = #441aabdf 2145b430
+g_dfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoId returns 1, consuming 8 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: 1.23e-20
+strtod consumes 8 bytes and returns 33 with f = 1.2300000000000001e-20 = #3bcd0ae4 cf767531
+g_dfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoId returns 33, consuming 8 bytes.
+fI[0] = #3bcd0ae4 cf767530 = 1.2299999999999999e-20
+fI[1] = #3bcd0ae4 cf767531 = 1.2300000000000001e-20
+fI[1] == strtod
+
+
+Input: 1.23456789
+strtod consumes 10 bytes and returns 17 with f = 1.2345678899999999 = #3ff3c0ca 4283de1b
+g_dfmt(0) gives 10 bytes: "1.23456789"
+
+strtoId returns 17, consuming 10 bytes.
+fI[0] = #3ff3c0ca 4283de1b = 1.2345678899999999
+fI[1] = #3ff3c0ca 4283de1c = 1.2345678900000001
+fI[0] == strtod
+
+
+Input: 1.23456589e+20
+strtod consumes 14 bytes and returns 17 with f = 1.23456589e+20 = #441ac537 a660b997
+g_dfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoId returns 17, consuming 14 bytes.
+fI[0] = #441ac537 a660b997 = 1.23456589e+20
+fI[1] = #441ac537 a660b998 = 1.2345658900000001e+20
+fI[0] == strtod
+
+
+Input: 1.23e+30
+strtod consumes 8 bytes and returns 17 with f = 1.23e+30 = #462f0cb0 4e8fb790
+g_dfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoId returns 17, consuming 8 bytes.
+fI[0] = #462f0cb0 4e8fb790 = 1.23e+30
+fI[1] = #462f0cb0 4e8fb791 = 1.2300000000000001e+30
+fI[0] == strtod
+
+
+Input: 1.23e-30
+strtod consumes 8 bytes and returns 33 with f = 1.2300000000000001e-30 = #39b8f286 6f5010ab
+g_dfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoId returns 33, consuming 8 bytes.
+fI[0] = #39b8f286 6f5010aa = 1.2299999999999999e-30
+fI[1] = #39b8f286 6f5010ab = 1.2300000000000001e-30
+fI[1] == strtod
+
+
+Input: 1.23456789e-20
+strtod consumes 14 bytes and returns 17 with f = 1.2345678899999999e-20 = #3bcd2681 471e7ada
+g_dfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoId returns 17, consuming 14 bytes.
+fI[0] = #3bcd2681 471e7ada = 1.2345678899999999e-20
+fI[1] = #3bcd2681 471e7adb = 1.2345678900000001e-20
+fI[0] == strtod
+
+
+Input: 1.23456789e-30
+strtod consumes 14 bytes and returns 17 with f = 1.23456789e-30 = #39b90a3e 33bbd995
+g_dfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoId returns 17, consuming 14 bytes.
+fI[0] = #39b90a3e 33bbd995 = 1.23456789e-30
+fI[1] = #39b90a3e 33bbd996 = 1.2345678900000002e-30
+fI[0] == strtod
+
+
+Input: 1.234567890123456789
+strtod consumes 20 bytes and returns 17 with f = 1.2345678901234567 = #3ff3c0ca 428c59fb
+g_dfmt(0) gives 18 bytes: "1.2345678901234567"
+
+strtoId returns 17, consuming 20 bytes.
+fI[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+fI[1] = #3ff3c0ca 428c59fc = 1.2345678901234569
+fI[0] == strtod
+
+
+Input: 1.23456789012345678901234567890123456789
+strtod consumes 40 bytes and returns 17 with f = 1.2345678901234567 = #3ff3c0ca 428c59fb
+g_dfmt(0) gives 18 bytes: "1.2345678901234567"
+
+strtoId returns 17, consuming 40 bytes.
+fI[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+fI[1] = #3ff3c0ca 428c59fc = 1.2345678901234569
+fI[0] == strtod
+
+
+Input: 1.23e306
+strtod consumes 8 bytes and returns 33 with f = 1.23e+306 = #7f7c0676 cd1c61f5
+g_dfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoId returns 33, consuming 8 bytes.
+fI[0] = #7f7c0676 cd1c61f4 = 1.2299999999999999e+306
+fI[1] = #7f7c0676 cd1c61f5 = 1.23e+306
+fI[1] == strtod
+
+
+Input: 1.23e-306
+strtod consumes 9 bytes and returns 33 with f = 1.23e-306 = #6ba3b8 5da396e8
+g_dfmt(0) gives 9 bytes: "1.23e-306"
+
+strtoId returns 33, consuming 9 bytes.
+fI[0] = #6ba3b8 5da396e7 = 1.2299999999999999e-306
+fI[1] = #6ba3b8 5da396e8 = 1.23e-306
+fI[1] == strtod
+
+
+Input: 1.23e-320
+strtod consumes 9 bytes and returns 98 with f = 1.2302234581447039e-320 = #0 9ba
+g_dfmt(0) gives 9 bytes: "1.23e-320"
+
+strtoId returns 98, consuming 9 bytes.
+fI[0] = #0 9b9 = 1.2297293924988626e-320
+fI[1] = #0 9ba = 1.2302234581447039e-320
+fI[1] == strtod
+
+
+Input: 1.23e-20
+strtod consumes 8 bytes and returns 33 with f = 1.2300000000000001e-20 = #3bcd0ae4 cf767531
+g_dfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoId returns 33, consuming 8 bytes.
+fI[0] = #3bcd0ae4 cf767530 = 1.2299999999999999e-20
+fI[1] = #3bcd0ae4 cf767531 = 1.2300000000000001e-20
+fI[1] == strtod
+
+
+Input: 1.23456789e307
+strtod consumes 14 bytes and returns 33 with f = 1.23456789e+307 = #7fb194b1 4bdaecdc
+g_dfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoId returns 33, consuming 14 bytes.
+fI[0] = #7fb194b1 4bdaecdb = 1.2345678899999998e+307
+fI[1] = #7fb194b1 4bdaecdc = 1.23456789e+307
+fI[1] == strtod
+
+
+Input: 1.23456589e-307
+strtod consumes 15 bytes and returns 17 with f = 1.2345658899999999e-307 = #363196 bb9845fa
+g_dfmt(0) gives 15 bytes: "1.23456589e-307"
+
+strtoId returns 17, consuming 15 bytes.
+fI[0] = #363196 bb9845fa = 1.2345658899999999e-307
+fI[1] = #363196 bb9845fb = 1.2345658900000001e-307
+fI[0] == strtod
+
+
+Input: 1.234567890123456789
+strtod consumes 20 bytes and returns 17 with f = 1.2345678901234567 = #3ff3c0ca 428c59fb
+g_dfmt(0) gives 18 bytes: "1.2345678901234567"
+
+strtoId returns 17, consuming 20 bytes.
+fI[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+fI[1] = #3ff3c0ca 428c59fc = 1.2345678901234569
+fI[0] == strtod
+
+
+Input: 1.234567890123456789e301
+strtod consumes 24 bytes and returns 17 with f = 1.2345678901234568e+301 = #7e726f51 75f56413
+g_dfmt(0) gives 23 bytes: "1.2345678901234568e+301"
+
+strtoId returns 17, consuming 24 bytes.
+fI[0] = #7e726f51 75f56413 = 1.2345678901234568e+301
+fI[1] = #7e726f51 75f56414 = 1.234567890123457e+301
+fI[0] == strtod
+
+
+Input: 1.234567890123456789e-301
+strtod consumes 25 bytes and returns 17 with f = 1.2345678901234567e-301 = #1752a64 e34ba0d3
+g_dfmt(0) gives 23 bytes: "1.2345678901234567e-301"
+
+strtoId returns 17, consuming 25 bytes.
+fI[0] = #1752a64 e34ba0d3 = 1.2345678901234567e-301
+fI[1] = #1752a64 e34ba0d4 = 1.2345678901234569e-301
+fI[0] == strtod
+
+
+Input: 1.234567890123456789e-321
+strtod consumes 25 bytes and returns 98 with f = 1.2351641146031164e-321 = #0 fa
+g_dfmt(0) gives 10 bytes: "1.235e-321"
+
+strtoId returns 98, consuming 25 bytes.
+fI[0] = #0 f9 = 1.2302234581447039e-321
+fI[1] = #0 fa = 1.2351641146031164e-321
+fI[1] == strtod
+
+
+Input: 1e23
+strtod consumes 4 bytes and returns 17 with f = 9.9999999999999992e+22 = #44b52d02 c7e14af6
+g_dfmt(0) gives 5 bytes: "1e+23"
+
+strtoId returns 17, consuming 4 bytes.
+fI[0] = #44b52d02 c7e14af6 = 9.9999999999999992e+22
+fI[1] = #44b52d02 c7e14af7 = 1.0000000000000001e+23
+fI[0] == strtod
+
+
+Input: 1e310
+strtod consumes 5 bytes and returns 163 with f = Infinity = #7ff00000 0
+g_dfmt(0) gives 8 bytes: "Infinity"
+
+strtoId returns 163, consuming 5 bytes.
+fI[0] = #7fefffff ffffffff = 1.7976931348623157e+308
+fI[1] = #7ff00000 0 = Infinity
+fI[1] == strtod
+
+
+Input: 9.0259718793241475e-277
+strtod consumes 23 bytes and returns 33 with f = 9.0259718793241479e-277 = #6a00000 0
+g_dfmt(0) gives 22 bytes: "9.025971879324148e-277"
+
+strtoId returns 33, consuming 23 bytes.
+fI[0] = #69fffff ffffffff = 9.0259718793241469e-277
+fI[1] = #6a00000 0 = 9.0259718793241479e-277
+fI[1] == strtod
+
+
+Input: 9.025971879324147880346310405869e-277
+strtod consumes 37 bytes and returns 17 with f = 9.0259718793241479e-277 = #6a00000 0
+g_dfmt(0) gives 22 bytes: "9.025971879324148e-277"
+
+strtoId returns 17, consuming 37 bytes.
+fI[0] = #6a00000 0 = 9.0259718793241479e-277
+fI[1] = #6a00000 1 = 9.0259718793241499e-277
+fI[0] == strtod
+
+
+Input: 9.025971879324147880346310405868e-277
+strtod consumes 37 bytes and returns 33 with f = 9.0259718793241479e-277 = #6a00000 0
+g_dfmt(0) gives 22 bytes: "9.025971879324148e-277"
+
+strtoId returns 33, consuming 37 bytes.
+fI[0] = #69fffff ffffffff = 9.0259718793241469e-277
+fI[1] = #6a00000 0 = 9.0259718793241479e-277
+fI[1] == strtod
+
+
+Input: 2.2250738585072014e-308
+strtod consumes 23 bytes and returns 17 with f = 2.2250738585072014e-308 = #100000 0
+g_dfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoId returns 17, consuming 23 bytes.
+fI[0] = #100000 0 = 2.2250738585072014e-308
+fI[1] = #100000 1 = 2.2250738585072019e-308
+fI[0] == strtod
+
+
+Input: 2.2250738585072013e-308
+strtod consumes 23 bytes and returns 33 with f = 2.2250738585072014e-308 = #100000 0
+g_dfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoId returns 33, consuming 23 bytes.
+fI[0] = #fffff ffffffff = 2.2250738585072009e-308
+fI[1] = #100000 0 = 2.2250738585072014e-308
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+strtod consumes 3 bytes and returns 17 with f = 1.0999999999999999 = #3ff19999 99999999
+g_dfmt(0) gives 18 bytes: "1.0999999999999999"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff19999 99999999 = 1.0999999999999999
+fI[1] = #3ff19999 9999999a = 1.1000000000000001
+fI[0] == strtod
+
+
+Input: -1.1
+strtod consumes 4 bytes and returns 25 with f = -1.0999999999999999 = #bff19999 99999999
+g_dfmt(0) gives 19 bytes: "-1.0999999999999999"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff19999 9999999a = -1.1000000000000001
+fI[1] = #bff19999 99999999 = -1.0999999999999999
+fI[1] == strtod
+
+
+Input: 1.2
+strtod consumes 3 bytes and returns 17 with f = 1.2 = #3ff33333 33333333
+g_dfmt(0) gives 3 bytes: "1.2"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ff33333 33333333 = 1.2
+fI[1] = #3ff33333 33333334 = 1.2000000000000002
+fI[0] == strtod
+
+
+Input: -1.2
+strtod consumes 4 bytes and returns 25 with f = -1.2 = #bff33333 33333333
+g_dfmt(0) gives 4 bytes: "-1.2"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bff33333 33333334 = -1.2000000000000002
+fI[1] = #bff33333 33333333 = -1.2
+fI[1] == strtod
+
+
+Input: 1.3
+strtod consumes 3 bytes and returns 17 with f = 1.2999999999999998 = #3ff4cccc cccccccc
+g_dfmt(0) gives 18 bytes: "1.2999999999999998"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff4cccc cccccccc = 1.2999999999999998
+fI[1] = #3ff4cccc cccccccd = 1.3
+fI[0] == strtod
+
+
+Input: -1.3
+strtod consumes 4 bytes and returns 25 with f = -1.2999999999999998 = #bff4cccc cccccccc
+g_dfmt(0) gives 19 bytes: "-1.2999999999999998"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff4cccc cccccccd = -1.3
+fI[1] = #bff4cccc cccccccc = -1.2999999999999998
+fI[1] == strtod
+
+
+Input: 1.4
+strtod consumes 3 bytes and returns 17 with f = 1.3999999999999999 = #3ff66666 66666666
+g_dfmt(0) gives 3 bytes: "1.4"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ff66666 66666666 = 1.3999999999999999
+fI[1] = #3ff66666 66666667 = 1.4000000000000001
+fI[0] == strtod
+
+
+Input: -1.4
+strtod consumes 4 bytes and returns 25 with f = -1.3999999999999999 = #bff66666 66666666
+g_dfmt(0) gives 4 bytes: "-1.4"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bff66666 66666667 = -1.4000000000000001
+fI[1] = #bff66666 66666666 = -1.3999999999999999
+fI[1] == strtod
+
+
+Input: 1.5
+strtod consumes 3 bytes and returns 1 with f = 1.5 = #3ff80000 0
+g_dfmt(0) gives 3 bytes: "1.5"
+
+strtoId returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: -1.5
+strtod consumes 4 bytes and returns 9 with f = -1.5 = #bff80000 0
+g_dfmt(0) gives 4 bytes: "-1.5"
+
+strtoId returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: 1.6
+strtod consumes 3 bytes and returns 17 with f = 1.5999999999999999 = #3ff99999 99999999
+g_dfmt(0) gives 18 bytes: "1.5999999999999999"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff99999 99999999 = 1.5999999999999999
+fI[1] = #3ff99999 9999999a = 1.6000000000000001
+fI[0] == strtod
+
+
+Input: -1.6
+strtod consumes 4 bytes and returns 25 with f = -1.5999999999999999 = #bff99999 99999999
+g_dfmt(0) gives 19 bytes: "-1.5999999999999999"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff99999 9999999a = -1.6000000000000001
+fI[1] = #bff99999 99999999 = -1.5999999999999999
+fI[1] == strtod
+
+
+Input: 1.7
+strtod consumes 3 bytes and returns 17 with f = 1.7 = #3ffb3333 33333333
+g_dfmt(0) gives 3 bytes: "1.7"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ffb3333 33333333 = 1.7
+fI[1] = #3ffb3333 33333334 = 1.7000000000000002
+fI[0] == strtod
+
+
+Input: -1.7
+strtod consumes 4 bytes and returns 25 with f = -1.7 = #bffb3333 33333333
+g_dfmt(0) gives 4 bytes: "-1.7"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bffb3333 33333334 = -1.7000000000000002
+fI[1] = #bffb3333 33333333 = -1.7
+fI[1] == strtod
+
+
+Input: 1.8
+strtod consumes 3 bytes and returns 17 with f = 1.7999999999999998 = #3ffccccc cccccccc
+g_dfmt(0) gives 18 bytes: "1.7999999999999998"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ffccccc cccccccc = 1.7999999999999998
+fI[1] = #3ffccccc cccccccd = 1.8
+fI[0] == strtod
+
+
+Input: -1.8
+strtod consumes 4 bytes and returns 25 with f = -1.7999999999999998 = #bffccccc cccccccc
+g_dfmt(0) gives 19 bytes: "-1.7999999999999998"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bffccccc cccccccd = -1.8
+fI[1] = #bffccccc cccccccc = -1.7999999999999998
+fI[1] == strtod
+
+
+Input: 1.9
+strtod consumes 3 bytes and returns 17 with f = 1.8999999999999999 = #3ffe6666 66666666
+g_dfmt(0) gives 3 bytes: "1.9"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ffe6666 66666666 = 1.8999999999999999
+fI[1] = #3ffe6666 66666667 = 1.9000000000000001
+fI[0] == strtod
+
+
+Input: -1.9
+strtod consumes 4 bytes and returns 25 with f = -1.8999999999999999 = #bffe6666 66666666
+g_dfmt(0) gives 4 bytes: "-1.9"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bffe6666 66666667 = -1.9000000000000001
+fI[1] = #bffe6666 66666666 = -1.8999999999999999
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+strtod consumes 3 bytes and returns 33 with f = 1.1000000000000001 = #3ff19999 9999999a
+g_dfmt(0) gives 3 bytes: "1.1"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff19999 99999999 = 1.0999999999999999
+fI[1] = #3ff19999 9999999a = 1.1000000000000001
+fI[1] == strtod
+
+
+Input: -1.1
+strtod consumes 4 bytes and returns 41 with f = -1.1000000000000001 = #bff19999 9999999a
+g_dfmt(0) gives 4 bytes: "-1.1"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff19999 9999999a = -1.1000000000000001
+fI[1] = #bff19999 99999999 = -1.0999999999999999
+fI[0] == strtod
+
+
+Input: 1.2
+strtod consumes 3 bytes and returns 17 with f = 1.2 = #3ff33333 33333333
+g_dfmt(0) gives 3 bytes: "1.2"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ff33333 33333333 = 1.2
+fI[1] = #3ff33333 33333334 = 1.2000000000000002
+fI[0] == strtod
+
+
+Input: -1.2
+strtod consumes 4 bytes and returns 25 with f = -1.2 = #bff33333 33333333
+g_dfmt(0) gives 4 bytes: "-1.2"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bff33333 33333334 = -1.2000000000000002
+fI[1] = #bff33333 33333333 = -1.2
+fI[1] == strtod
+
+
+Input: 1.3
+strtod consumes 3 bytes and returns 33 with f = 1.3 = #3ff4cccc cccccccd
+g_dfmt(0) gives 3 bytes: "1.3"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff4cccc cccccccc = 1.2999999999999998
+fI[1] = #3ff4cccc cccccccd = 1.3
+fI[1] == strtod
+
+
+Input: -1.3
+strtod consumes 4 bytes and returns 41 with f = -1.3 = #bff4cccc cccccccd
+g_dfmt(0) gives 4 bytes: "-1.3"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff4cccc cccccccd = -1.3
+fI[1] = #bff4cccc cccccccc = -1.2999999999999998
+fI[0] == strtod
+
+
+Input: 1.4
+strtod consumes 3 bytes and returns 17 with f = 1.3999999999999999 = #3ff66666 66666666
+g_dfmt(0) gives 3 bytes: "1.4"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ff66666 66666666 = 1.3999999999999999
+fI[1] = #3ff66666 66666667 = 1.4000000000000001
+fI[0] == strtod
+
+
+Input: -1.4
+strtod consumes 4 bytes and returns 25 with f = -1.3999999999999999 = #bff66666 66666666
+g_dfmt(0) gives 4 bytes: "-1.4"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bff66666 66666667 = -1.4000000000000001
+fI[1] = #bff66666 66666666 = -1.3999999999999999
+fI[1] == strtod
+
+
+Input: 1.5
+strtod consumes 3 bytes and returns 1 with f = 1.5 = #3ff80000 0
+g_dfmt(0) gives 3 bytes: "1.5"
+
+strtoId returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: -1.5
+strtod consumes 4 bytes and returns 9 with f = -1.5 = #bff80000 0
+g_dfmt(0) gives 4 bytes: "-1.5"
+
+strtoId returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: 1.6
+strtod consumes 3 bytes and returns 33 with f = 1.6000000000000001 = #3ff99999 9999999a
+g_dfmt(0) gives 3 bytes: "1.6"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff99999 99999999 = 1.5999999999999999
+fI[1] = #3ff99999 9999999a = 1.6000000000000001
+fI[1] == strtod
+
+
+Input: -1.6
+strtod consumes 4 bytes and returns 41 with f = -1.6000000000000001 = #bff99999 9999999a
+g_dfmt(0) gives 4 bytes: "-1.6"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff99999 9999999a = -1.6000000000000001
+fI[1] = #bff99999 99999999 = -1.5999999999999999
+fI[0] == strtod
+
+
+Input: 1.7
+strtod consumes 3 bytes and returns 17 with f = 1.7 = #3ffb3333 33333333
+g_dfmt(0) gives 3 bytes: "1.7"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ffb3333 33333333 = 1.7
+fI[1] = #3ffb3333 33333334 = 1.7000000000000002
+fI[0] == strtod
+
+
+Input: -1.7
+strtod consumes 4 bytes and returns 25 with f = -1.7 = #bffb3333 33333333
+g_dfmt(0) gives 4 bytes: "-1.7"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bffb3333 33333334 = -1.7000000000000002
+fI[1] = #bffb3333 33333333 = -1.7
+fI[1] == strtod
+
+
+Input: 1.8
+strtod consumes 3 bytes and returns 33 with f = 1.8 = #3ffccccc cccccccd
+g_dfmt(0) gives 3 bytes: "1.8"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ffccccc cccccccc = 1.7999999999999998
+fI[1] = #3ffccccc cccccccd = 1.8
+fI[1] == strtod
+
+
+Input: -1.8
+strtod consumes 4 bytes and returns 41 with f = -1.8 = #bffccccc cccccccd
+g_dfmt(0) gives 4 bytes: "-1.8"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bffccccc cccccccd = -1.8
+fI[1] = #bffccccc cccccccc = -1.7999999999999998
+fI[0] == strtod
+
+
+Input: 1.9
+strtod consumes 3 bytes and returns 17 with f = 1.8999999999999999 = #3ffe6666 66666666
+g_dfmt(0) gives 3 bytes: "1.9"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ffe6666 66666666 = 1.8999999999999999
+fI[1] = #3ffe6666 66666667 = 1.9000000000000001
+fI[0] == strtod
+
+
+Input: -1.9
+strtod consumes 4 bytes and returns 25 with f = -1.8999999999999999 = #bffe6666 66666666
+g_dfmt(0) gives 4 bytes: "-1.9"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bffe6666 66666667 = -1.9000000000000001
+fI[1] = #bffe6666 66666666 = -1.8999999999999999
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+strtod consumes 3 bytes and returns 33 with f = 1.1000000000000001 = #3ff19999 9999999a
+g_dfmt(0) gives 3 bytes: "1.1"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff19999 99999999 = 1.0999999999999999
+fI[1] = #3ff19999 9999999a = 1.1000000000000001
+fI[1] == strtod
+
+
+Input: -1.1
+strtod consumes 4 bytes and returns 25 with f = -1.0999999999999999 = #bff19999 99999999
+g_dfmt(0) gives 19 bytes: "-1.0999999999999999"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff19999 9999999a = -1.1000000000000001
+fI[1] = #bff19999 99999999 = -1.0999999999999999
+fI[1] == strtod
+
+
+Input: 1.2
+strtod consumes 3 bytes and returns 33 with f = 1.2000000000000002 = #3ff33333 33333334
+g_dfmt(0) gives 18 bytes: "1.2000000000000002"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ff33333 33333333 = 1.2
+fI[1] = #3ff33333 33333334 = 1.2000000000000002
+fI[1] == strtod
+
+
+Input: -1.2
+strtod consumes 4 bytes and returns 25 with f = -1.2 = #bff33333 33333333
+g_dfmt(0) gives 4 bytes: "-1.2"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bff33333 33333334 = -1.2000000000000002
+fI[1] = #bff33333 33333333 = -1.2
+fI[1] == strtod
+
+
+Input: 1.3
+strtod consumes 3 bytes and returns 33 with f = 1.3 = #3ff4cccc cccccccd
+g_dfmt(0) gives 3 bytes: "1.3"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff4cccc cccccccc = 1.2999999999999998
+fI[1] = #3ff4cccc cccccccd = 1.3
+fI[1] == strtod
+
+
+Input: -1.3
+strtod consumes 4 bytes and returns 25 with f = -1.2999999999999998 = #bff4cccc cccccccc
+g_dfmt(0) gives 19 bytes: "-1.2999999999999998"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff4cccc cccccccd = -1.3
+fI[1] = #bff4cccc cccccccc = -1.2999999999999998
+fI[1] == strtod
+
+
+Input: 1.4
+strtod consumes 3 bytes and returns 33 with f = 1.4000000000000001 = #3ff66666 66666667
+g_dfmt(0) gives 18 bytes: "1.4000000000000001"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ff66666 66666666 = 1.3999999999999999
+fI[1] = #3ff66666 66666667 = 1.4000000000000001
+fI[1] == strtod
+
+
+Input: -1.4
+strtod consumes 4 bytes and returns 25 with f = -1.3999999999999999 = #bff66666 66666666
+g_dfmt(0) gives 4 bytes: "-1.4"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bff66666 66666667 = -1.4000000000000001
+fI[1] = #bff66666 66666666 = -1.3999999999999999
+fI[1] == strtod
+
+
+Input: 1.5
+strtod consumes 3 bytes and returns 1 with f = 1.5 = #3ff80000 0
+g_dfmt(0) gives 3 bytes: "1.5"
+
+strtoId returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: -1.5
+strtod consumes 4 bytes and returns 9 with f = -1.5 = #bff80000 0
+g_dfmt(0) gives 4 bytes: "-1.5"
+
+strtoId returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: 1.6
+strtod consumes 3 bytes and returns 33 with f = 1.6000000000000001 = #3ff99999 9999999a
+g_dfmt(0) gives 3 bytes: "1.6"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff99999 99999999 = 1.5999999999999999
+fI[1] = #3ff99999 9999999a = 1.6000000000000001
+fI[1] == strtod
+
+
+Input: -1.6
+strtod consumes 4 bytes and returns 25 with f = -1.5999999999999999 = #bff99999 99999999
+g_dfmt(0) gives 19 bytes: "-1.5999999999999999"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff99999 9999999a = -1.6000000000000001
+fI[1] = #bff99999 99999999 = -1.5999999999999999
+fI[1] == strtod
+
+
+Input: 1.7
+strtod consumes 3 bytes and returns 33 with f = 1.7000000000000002 = #3ffb3333 33333334
+g_dfmt(0) gives 18 bytes: "1.7000000000000002"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ffb3333 33333333 = 1.7
+fI[1] = #3ffb3333 33333334 = 1.7000000000000002
+fI[1] == strtod
+
+
+Input: -1.7
+strtod consumes 4 bytes and returns 25 with f = -1.7 = #bffb3333 33333333
+g_dfmt(0) gives 4 bytes: "-1.7"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bffb3333 33333334 = -1.7000000000000002
+fI[1] = #bffb3333 33333333 = -1.7
+fI[1] == strtod
+
+
+Input: 1.8
+strtod consumes 3 bytes and returns 33 with f = 1.8 = #3ffccccc cccccccd
+g_dfmt(0) gives 3 bytes: "1.8"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ffccccc cccccccc = 1.7999999999999998
+fI[1] = #3ffccccc cccccccd = 1.8
+fI[1] == strtod
+
+
+Input: -1.8
+strtod consumes 4 bytes and returns 25 with f = -1.7999999999999998 = #bffccccc cccccccc
+g_dfmt(0) gives 19 bytes: "-1.7999999999999998"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bffccccc cccccccd = -1.8
+fI[1] = #bffccccc cccccccc = -1.7999999999999998
+fI[1] == strtod
+
+
+Input: 1.9
+strtod consumes 3 bytes and returns 33 with f = 1.9000000000000001 = #3ffe6666 66666667
+g_dfmt(0) gives 18 bytes: "1.9000000000000001"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ffe6666 66666666 = 1.8999999999999999
+fI[1] = #3ffe6666 66666667 = 1.9000000000000001
+fI[1] == strtod
+
+
+Input: -1.9
+strtod consumes 4 bytes and returns 25 with f = -1.8999999999999999 = #bffe6666 66666666
+g_dfmt(0) gives 4 bytes: "-1.9"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bffe6666 66666667 = -1.9000000000000001
+fI[1] = #bffe6666 66666666 = -1.8999999999999999
+fI[1] == strtod
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+strtod consumes 3 bytes and returns 17 with f = 1.0999999999999999 = #3ff19999 99999999
+g_dfmt(0) gives 18 bytes: "1.0999999999999999"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff19999 99999999 = 1.0999999999999999
+fI[1] = #3ff19999 9999999a = 1.1000000000000001
+fI[0] == strtod
+
+
+Input: -1.1
+strtod consumes 4 bytes and returns 41 with f = -1.1000000000000001 = #bff19999 9999999a
+g_dfmt(0) gives 4 bytes: "-1.1"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff19999 9999999a = -1.1000000000000001
+fI[1] = #bff19999 99999999 = -1.0999999999999999
+fI[0] == strtod
+
+
+Input: 1.2
+strtod consumes 3 bytes and returns 17 with f = 1.2 = #3ff33333 33333333
+g_dfmt(0) gives 3 bytes: "1.2"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ff33333 33333333 = 1.2
+fI[1] = #3ff33333 33333334 = 1.2000000000000002
+fI[0] == strtod
+
+
+Input: -1.2
+strtod consumes 4 bytes and returns 41 with f = -1.2000000000000002 = #bff33333 33333334
+g_dfmt(0) gives 19 bytes: "-1.2000000000000002"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bff33333 33333334 = -1.2000000000000002
+fI[1] = #bff33333 33333333 = -1.2
+fI[0] == strtod
+
+
+Input: 1.3
+strtod consumes 3 bytes and returns 17 with f = 1.2999999999999998 = #3ff4cccc cccccccc
+g_dfmt(0) gives 18 bytes: "1.2999999999999998"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff4cccc cccccccc = 1.2999999999999998
+fI[1] = #3ff4cccc cccccccd = 1.3
+fI[0] == strtod
+
+
+Input: -1.3
+strtod consumes 4 bytes and returns 41 with f = -1.3 = #bff4cccc cccccccd
+g_dfmt(0) gives 4 bytes: "-1.3"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff4cccc cccccccd = -1.3
+fI[1] = #bff4cccc cccccccc = -1.2999999999999998
+fI[0] == strtod
+
+
+Input: 1.4
+strtod consumes 3 bytes and returns 17 with f = 1.3999999999999999 = #3ff66666 66666666
+g_dfmt(0) gives 3 bytes: "1.4"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ff66666 66666666 = 1.3999999999999999
+fI[1] = #3ff66666 66666667 = 1.4000000000000001
+fI[0] == strtod
+
+
+Input: -1.4
+strtod consumes 4 bytes and returns 41 with f = -1.4000000000000001 = #bff66666 66666667
+g_dfmt(0) gives 19 bytes: "-1.4000000000000001"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bff66666 66666667 = -1.4000000000000001
+fI[1] = #bff66666 66666666 = -1.3999999999999999
+fI[0] == strtod
+
+
+Input: 1.5
+strtod consumes 3 bytes and returns 1 with f = 1.5 = #3ff80000 0
+g_dfmt(0) gives 3 bytes: "1.5"
+
+strtoId returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: -1.5
+strtod consumes 4 bytes and returns 9 with f = -1.5 = #bff80000 0
+g_dfmt(0) gives 4 bytes: "-1.5"
+
+strtoId returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtod
+
+
+Input: 1.6
+strtod consumes 3 bytes and returns 17 with f = 1.5999999999999999 = #3ff99999 99999999
+g_dfmt(0) gives 18 bytes: "1.5999999999999999"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ff99999 99999999 = 1.5999999999999999
+fI[1] = #3ff99999 9999999a = 1.6000000000000001
+fI[0] == strtod
+
+
+Input: -1.6
+strtod consumes 4 bytes and returns 41 with f = -1.6000000000000001 = #bff99999 9999999a
+g_dfmt(0) gives 4 bytes: "-1.6"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bff99999 9999999a = -1.6000000000000001
+fI[1] = #bff99999 99999999 = -1.5999999999999999
+fI[0] == strtod
+
+
+Input: 1.7
+strtod consumes 3 bytes and returns 17 with f = 1.7 = #3ffb3333 33333333
+g_dfmt(0) gives 3 bytes: "1.7"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ffb3333 33333333 = 1.7
+fI[1] = #3ffb3333 33333334 = 1.7000000000000002
+fI[0] == strtod
+
+
+Input: -1.7
+strtod consumes 4 bytes and returns 41 with f = -1.7000000000000002 = #bffb3333 33333334
+g_dfmt(0) gives 19 bytes: "-1.7000000000000002"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bffb3333 33333334 = -1.7000000000000002
+fI[1] = #bffb3333 33333333 = -1.7
+fI[0] == strtod
+
+
+Input: 1.8
+strtod consumes 3 bytes and returns 17 with f = 1.7999999999999998 = #3ffccccc cccccccc
+g_dfmt(0) gives 18 bytes: "1.7999999999999998"
+
+strtoId returns 33, consuming 3 bytes.
+fI[0] = #3ffccccc cccccccc = 1.7999999999999998
+fI[1] = #3ffccccc cccccccd = 1.8
+fI[0] == strtod
+
+
+Input: -1.8
+strtod consumes 4 bytes and returns 41 with f = -1.8 = #bffccccc cccccccd
+g_dfmt(0) gives 4 bytes: "-1.8"
+
+strtoId returns 41, consuming 4 bytes.
+fI[0] = #bffccccc cccccccd = -1.8
+fI[1] = #bffccccc cccccccc = -1.7999999999999998
+fI[0] == strtod
+
+
+Input: 1.9
+strtod consumes 3 bytes and returns 17 with f = 1.8999999999999999 = #3ffe6666 66666666
+g_dfmt(0) gives 3 bytes: "1.9"
+
+strtoId returns 17, consuming 3 bytes.
+fI[0] = #3ffe6666 66666666 = 1.8999999999999999
+fI[1] = #3ffe6666 66666667 = 1.9000000000000001
+fI[0] == strtod
+
+
+Input: -1.9
+strtod consumes 4 bytes and returns 41 with f = -1.9000000000000001 = #bffe6666 66666667
+g_dfmt(0) gives 19 bytes: "-1.9000000000000001"
+
+strtoId returns 25, consuming 4 bytes.
+fI[0] = #bffe6666 66666667 = -1.9000000000000001
+fI[1] = #bffe6666 66666666 = -1.8999999999999999
+fI[0] == strtod
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/dI.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/dI.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/dI.out	(revision 2448)
@@ -0,0 +1,168 @@
+
+Input: 1.23
+strtodI consumes 4 bytes and returns 17
+dd[0] = #3ff3ae14 7ae147ae = 1.23
+dd[1] = #3ff3ae14 7ae147af = 1.2300000000000002
+
+
+Input: 1.23e+20
+strtodI consumes 8 bytes and returns 1
+dd[0] = #441aabdf 2145b430 = 1.23e+20
+dd[1] = #441aabdf 2145b430 = 1.23e+20
+
+
+Input: 1.23e-20
+strtodI consumes 8 bytes and returns 33
+dd[0] = #3bcd0ae4 cf767530 = 1.2299999999999999e-20
+dd[1] = #3bcd0ae4 cf767531 = 1.23e-20
+
+
+Input: 1.23456789
+strtodI consumes 10 bytes and returns 17
+dd[0] = #3ff3c0ca 4283de1b = 1.23456789
+dd[1] = #3ff3c0ca 4283de1c = 1.2345678900000001
+
+
+Input: 1.23456589e+20
+strtodI consumes 14 bytes and returns 17
+dd[0] = #441ac537 a660b997 = 1.23456589e+20
+dd[1] = #441ac537 a660b998 = 123456589000000010000
+
+
+Input: 1.23e+30
+strtodI consumes 8 bytes and returns 17
+dd[0] = #462f0cb0 4e8fb790 = 1.23e+30
+dd[1] = #462f0cb0 4e8fb791 = 1.2300000000000001e+30
+
+
+Input: 1.23e-30
+strtodI consumes 8 bytes and returns 33
+dd[0] = #39b8f286 6f5010aa = 1.2299999999999999e-30
+dd[1] = #39b8f286 6f5010ab = 1.23e-30
+
+
+Input: 1.23456789e-20
+strtodI consumes 14 bytes and returns 17
+dd[0] = #3bcd2681 471e7ada = 1.23456789e-20
+dd[1] = #3bcd2681 471e7adb = 1.2345678900000001e-20
+
+
+Input: 1.23456789e-30
+strtodI consumes 14 bytes and returns 17
+dd[0] = #39b90a3e 33bbd995 = 1.23456789e-30
+dd[1] = #39b90a3e 33bbd996 = 1.2345678900000002e-30
+
+
+Input: 1.234567890123456789
+strtodI consumes 20 bytes and returns 17
+dd[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+dd[1] = #3ff3c0ca 428c59fc = 1.234567890123457
+
+
+Input: 1.23456789012345678901234567890123456789
+strtodI consumes 40 bytes and returns 17
+dd[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+dd[1] = #3ff3c0ca 428c59fc = 1.234567890123457
+
+
+Input: 1.23e306
+strtodI consumes 8 bytes and returns 33
+dd[0] = #7f7c0676 cd1c61f4 = 1.2299999999999999e+306
+dd[1] = #7f7c0676 cd1c61f5 = 1.23e+306
+
+
+Input: 1.23e-306
+strtodI consumes 9 bytes and returns 33
+dd[0] = #6ba3b8 5da396e7 = 1.2299999999999999e-306
+dd[1] = #6ba3b8 5da396e8 = 1.23e-306
+
+
+Input: 1.23e-320
+strtodI consumes 9 bytes and returns 98
+dd[0] = #0 9b9 = 1.2297e-320
+dd[1] = #0 9ba = 1.23e-320
+
+
+Input: 1.23e-20
+strtodI consumes 8 bytes and returns 33
+dd[0] = #3bcd0ae4 cf767530 = 1.2299999999999999e-20
+dd[1] = #3bcd0ae4 cf767531 = 1.23e-20
+
+
+Input: 1.23456789e307
+strtodI consumes 14 bytes and returns 33
+dd[0] = #7fb194b1 4bdaecdb = 1.2345678899999998e+307
+dd[1] = #7fb194b1 4bdaecdc = 1.23456789e+307
+
+
+Input: 1.23456589e-307
+strtodI consumes 15 bytes and returns 17
+dd[0] = #363196 bb9845fa = 1.23456589e-307
+dd[1] = #363196 bb9845fb = 1.2345658900000001e-307
+
+
+Input: 1.234567890123456789
+strtodI consumes 20 bytes and returns 17
+dd[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+dd[1] = #3ff3c0ca 428c59fc = 1.234567890123457
+
+
+Input: 1.234567890123456789e301
+strtodI consumes 24 bytes and returns 17
+dd[0] = #7e726f51 75f56413 = 1.2345678901234568e+301
+dd[1] = #7e726f51 75f56414 = 1.234567890123457e+301
+
+
+Input: 1.234567890123456789e-301
+strtodI consumes 25 bytes and returns 17
+dd[0] = #1752a64 e34ba0d3 = 1.2345678901234567e-301
+dd[1] = #1752a64 e34ba0d4 = 1.234567890123457e-301
+
+
+Input: 1.234567890123456789e-321
+strtodI consumes 25 bytes and returns 98
+dd[0] = #0 f9 = 1.23e-321
+dd[1] = #0 fa = 1.235e-321
+
+
+Input: 1e23
+strtodI consumes 4 bytes and returns 17
+dd[0] = #44b52d02 c7e14af6 = 1e+23
+dd[1] = #44b52d02 c7e14af7 = 1.0000000000000001e+23
+
+
+Input: 1e310
+strtodI consumes 5 bytes and returns 163
+dd[0] = #7fefffff ffffffff = 1.7976931348623157e+308
+dd[1] = #7ff00000 0 = Infinity
+
+
+Input: 9.0259718793241475e-277
+strtodI consumes 23 bytes and returns 33
+dd[0] = #69fffff ffffffff = 9.025971879324147e-277
+dd[1] = #6a00000 0 = 9.025971879324148e-277
+
+
+Input: 9.025971879324147880346310405869e-277
+strtodI consumes 37 bytes and returns 17
+dd[0] = #6a00000 0 = 9.025971879324148e-277
+dd[1] = #6a00000 1 = 9.02597187932415e-277
+
+
+Input: 9.025971879324147880346310405868e-277
+strtodI consumes 37 bytes and returns 33
+dd[0] = #69fffff ffffffff = 9.025971879324147e-277
+dd[1] = #6a00000 0 = 9.025971879324148e-277
+
+
+Input: 2.2250738585072014e-308
+strtodI consumes 23 bytes and returns 17
+dd[0] = #100000 0 = 2.2250738585072014e-308
+dd[1] = #100000 1 = 2.225073858507202e-308
+
+
+Input: 2.2250738585072013e-308
+strtodI consumes 23 bytes and returns 33
+dd[0] = #fffff ffffffff = 2.225073858507201e-308
+dd[1] = #100000 0 = 2.2250738585072014e-308
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/dIsi.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/dIsi.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/dIsi.out	(revision 2448)
@@ -0,0 +1,168 @@
+
+Input: 1.23
+strtodI consumes 4 bytes and returns 17
+dd[0] = #3ff3ae14 7ae147ae = 1.23
+dd[1] = #3ff3ae14 7ae147af = 1.2300000000000002
+
+
+Input: 1.23e+20
+strtodI consumes 8 bytes and returns 1
+dd[0] = #441aabdf 2145b430 = 1.23e+20
+dd[1] = #441aabdf 2145b430 = 1.23e+20
+
+
+Input: 1.23e-20
+strtodI consumes 8 bytes and returns 33
+dd[0] = #3bcd0ae4 cf767530 = 1.2299999999999999e-20
+dd[1] = #3bcd0ae4 cf767531 = 1.23e-20
+
+
+Input: 1.23456789
+strtodI consumes 10 bytes and returns 17
+dd[0] = #3ff3c0ca 4283de1b = 1.23456789
+dd[1] = #3ff3c0ca 4283de1c = 1.2345678900000001
+
+
+Input: 1.23456589e+20
+strtodI consumes 14 bytes and returns 17
+dd[0] = #441ac537 a660b997 = 1.23456589e+20
+dd[1] = #441ac537 a660b998 = 123456589000000010000
+
+
+Input: 1.23e+30
+strtodI consumes 8 bytes and returns 17
+dd[0] = #462f0cb0 4e8fb790 = 1.23e+30
+dd[1] = #462f0cb0 4e8fb791 = 1.2300000000000001e+30
+
+
+Input: 1.23e-30
+strtodI consumes 8 bytes and returns 33
+dd[0] = #39b8f286 6f5010aa = 1.2299999999999999e-30
+dd[1] = #39b8f286 6f5010ab = 1.23e-30
+
+
+Input: 1.23456789e-20
+strtodI consumes 14 bytes and returns 17
+dd[0] = #3bcd2681 471e7ada = 1.23456789e-20
+dd[1] = #3bcd2681 471e7adb = 1.2345678900000001e-20
+
+
+Input: 1.23456789e-30
+strtodI consumes 14 bytes and returns 17
+dd[0] = #39b90a3e 33bbd995 = 1.23456789e-30
+dd[1] = #39b90a3e 33bbd996 = 1.2345678900000002e-30
+
+
+Input: 1.234567890123456789
+strtodI consumes 20 bytes and returns 17
+dd[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+dd[1] = #3ff3c0ca 428c59fc = 1.234567890123457
+
+
+Input: 1.23456789012345678901234567890123456789
+strtodI consumes 40 bytes and returns 17
+dd[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+dd[1] = #3ff3c0ca 428c59fc = 1.234567890123457
+
+
+Input: 1.23e306
+strtodI consumes 8 bytes and returns 33
+dd[0] = #7f7c0676 cd1c61f4 = 1.2299999999999999e+306
+dd[1] = #7f7c0676 cd1c61f5 = 1.23e+306
+
+
+Input: 1.23e-306
+strtodI consumes 9 bytes and returns 33
+dd[0] = #6ba3b8 5da396e7 = 1.2299999999999999e-306
+dd[1] = #6ba3b8 5da396e8 = 1.23e-306
+
+
+Input: 1.23e-320
+strtodI consumes 9 bytes and returns 80
+dd[0] = #0 0 = 0
+dd[1] = #100000 0 = 2.2250738585072014e-308
+
+
+Input: 1.23e-20
+strtodI consumes 8 bytes and returns 33
+dd[0] = #3bcd0ae4 cf767530 = 1.2299999999999999e-20
+dd[1] = #3bcd0ae4 cf767531 = 1.23e-20
+
+
+Input: 1.23456789e307
+strtodI consumes 14 bytes and returns 33
+dd[0] = #7fb194b1 4bdaecdb = 1.2345678899999998e+307
+dd[1] = #7fb194b1 4bdaecdc = 1.23456789e+307
+
+
+Input: 1.23456589e-307
+strtodI consumes 15 bytes and returns 17
+dd[0] = #363196 bb9845fa = 1.23456589e-307
+dd[1] = #363196 bb9845fb = 1.2345658900000001e-307
+
+
+Input: 1.234567890123456789
+strtodI consumes 20 bytes and returns 17
+dd[0] = #3ff3c0ca 428c59fb = 1.2345678901234567
+dd[1] = #3ff3c0ca 428c59fc = 1.234567890123457
+
+
+Input: 1.234567890123456789e301
+strtodI consumes 24 bytes and returns 17
+dd[0] = #7e726f51 75f56413 = 1.2345678901234568e+301
+dd[1] = #7e726f51 75f56414 = 1.234567890123457e+301
+
+
+Input: 1.234567890123456789e-301
+strtodI consumes 25 bytes and returns 17
+dd[0] = #1752a64 e34ba0d3 = 1.2345678901234567e-301
+dd[1] = #1752a64 e34ba0d4 = 1.234567890123457e-301
+
+
+Input: 1.234567890123456789e-321
+strtodI consumes 25 bytes and returns 80
+dd[0] = #0 0 = 0
+dd[1] = #100000 0 = 2.2250738585072014e-308
+
+
+Input: 1e23
+strtodI consumes 4 bytes and returns 17
+dd[0] = #44b52d02 c7e14af6 = 1e+23
+dd[1] = #44b52d02 c7e14af7 = 1.0000000000000001e+23
+
+
+Input: 1e310
+strtodI consumes 5 bytes and returns 163
+dd[0] = #7fefffff ffffffff = 1.7976931348623157e+308
+dd[1] = #7ff00000 0 = Infinity
+
+
+Input: 9.0259718793241475e-277
+strtodI consumes 23 bytes and returns 33
+dd[0] = #69fffff ffffffff = 9.025971879324147e-277
+dd[1] = #6a00000 0 = 9.025971879324148e-277
+
+
+Input: 9.025971879324147880346310405869e-277
+strtodI consumes 37 bytes and returns 17
+dd[0] = #6a00000 0 = 9.025971879324148e-277
+dd[1] = #6a00000 1 = 9.02597187932415e-277
+
+
+Input: 9.025971879324147880346310405868e-277
+strtodI consumes 37 bytes and returns 33
+dd[0] = #69fffff ffffffff = 9.025971879324147e-277
+dd[1] = #6a00000 0 = 9.025971879324148e-277
+
+
+Input: 2.2250738585072014e-308
+strtodI consumes 23 bytes and returns 17
+dd[0] = #100000 0 = 2.2250738585072014e-308
+dd[1] = #100000 1 = 2.225073858507202e-308
+
+
+Input: 2.2250738585072013e-308
+strtodI consumes 23 bytes and returns 33
+dd[0] = #0 0 = 0
+dd[1] = #100000 0 = 2.2250738585072014e-308
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/dItest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/dItest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/dItest.c	(revision 2448)
@@ -0,0 +1,88 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+ static char ibuf[2048];
+
+#define U (unsigned long)
+
+ static void
+#ifdef KR_headers
+dshow(what, d) char *what; double d;
+#else
+dshow(char *what, double d)
+#endif
+{
+	char buf[32];
+	g_dfmt(buf, &d, 0, sizeof(buf));
+	printf("%s = #%lx %lx = %s\n", what,
+		U ((ULong*)&d)[_0], U ((ULong*)&d)[_1], buf);
+	}
+
+ int
+main(Void)
+{
+	/* Input: one number per line */
+
+	char *s, *se, *se1;
+	int i, j;
+	double dd[2], dd1, dd2;
+	static char cfmt[] = "%s consumes %d bytes and returns %d\n";
+
+	while( (s = fgets(ibuf, sizeof(ibuf), stdin)) !=0) {
+		while(*s <= ' ')
+			if (!*s++)
+				continue;
+		printf("\nInput: %s", ibuf);
+		i = strtodI(ibuf, &se, dd);
+		printf(cfmt, "strtodI", (int)(se-ibuf), i);
+		dshow("dd[0]", dd[0]);
+		dshow("dd[1]", dd[1]);
+		printf("\n");
+		j = strtoId(ibuf, &se1, &dd1, &dd2);
+		if (j != i || se != se1
+		 || dd[0] != dd1 || dd[1] != dd2) {
+			printf(cfmt, "**** strtoId", (int)(se-ibuf), j);
+			dshow("dd1", dd1);
+			dshow("dd2", dd2);
+			}
+		}
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/dd.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/dd.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/dd.out	(revision 2448)
@@ -0,0 +1,1356 @@
+
+Input: 1.23
+strtopdd consumes 4 bytes and returns 17
+dd[0] = 1.23 = #3ff3ae14 7ae147ae
+dd[1] = 1.7763568394002496e-17 = #3c747ae1 47ae1478
+g_ddfmt(0) gives 4 bytes: "1.23"
+
+strtoIdd returns 17, consuming 4 bytes.
+ddI[0] = #3ff3ae14 7ae147ae + 3c747ae1 47ae1478
+= 1.23 + 1.7763568394002496e-17
+ddI[1] = #3ff3ae14 7ae147ae + 3c747ae1 47ae1480
+= 1.23 + 1.776356839400252e-17
+ddI[0] == strtod
+
+
+Input: 1.23e+20
+strtopdd consumes 8 bytes and returns 1
+dd[0] = 1.23e+20 = #441aabdf 2145b430
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIdd returns 1, consuming 8 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.23e-20
+strtopdd consumes 8 bytes and returns 33
+dd[0] = 1.2299999999999999e-20 = #3bcd0ae4 cf767530
+dd[1] = 9.304023318521521e-37 = #3873c997 955b2691
+g_ddfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIdd returns 33, consuming 8 bytes.
+ddI[0] = #3bcd0ae4 cf767530 + 3873c997 955b2690
+= 1.2299999999999999e-20 + 9.3040233185215194e-37
+ddI[1] = #3bcd0ae4 cf767530 + 3873c997 955b2691
+= 1.2299999999999999e-20 + 9.3040233185215211e-37
+ddI[1] == strtod
+
+
+Input: 1.23456789
+strtopdd consumes 10 bytes and returns 17
+dd[0] = 1.23456789 = #3ff3c0ca 4283de1b
+dd[1] = 1.0990618193318369e-16 = #3c9fada5 144c1252
+g_ddfmt(0) gives 10 bytes: "1.23456789"
+
+strtoIdd returns 17, consuming 10 bytes.
+ddI[0] = #3ff3c0ca 4283de1b + 3c9fada5 144c1252
+= 1.2345678899999999 + 1.0990618193318369e-16
+ddI[1] = #3ff3c0ca 4283de1b + 3c9fada5 144c1254
+= 1.2345678899999999 + 1.0990618193318371e-16
+ddI[0] == strtod
+
+
+Input: 1.23456589e+20
+strtopdd consumes 14 bytes and returns 1
+dd[0] = 1.23456589e+20 = #441ac537 a660b997
+dd[1] = 4096 = #40b00000 0
+g_ddfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoIdd returns 1, consuming 14 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.23e+30
+strtopdd consumes 8 bytes and returns 1
+dd[0] = 1.23e+30 = #462f0cb0 4e8fb790
+dd[1] = 40281156091904 = #42c25158 0
+g_ddfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIdd returns 1, consuming 8 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.23e-30
+strtopdd consumes 8 bytes and returns 17
+dd[0] = 1.2299999999999999e-30 = #39b8f286 6f5010aa
+dd[1] = 1.076909723013918e-46 = #3663ac7f 3dafd174
+g_ddfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIdd returns 17, consuming 8 bytes.
+ddI[0] = #39b8f286 6f5010aa + 3663ac7f 3dafd174
+= 1.2299999999999999e-30 + 1.076909723013918e-46
+ddI[1] = #39b8f286 6f5010aa + 3663ac7f 3dafd175
+= 1.2299999999999999e-30 + 1.0769097230139181e-46
+ddI[0] == strtod
+
+
+Input: 1.23456789e-20
+strtopdd consumes 14 bytes and returns 17
+dd[0] = 1.23456789e-20 = #3bcd2681 471e7ada
+dd[1] = 6.247111971663133e-37 = #386a9280 a761b07e
+g_ddfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoIdd returns 17, consuming 14 bytes.
+ddI[0] = #3bcd2681 471e7ada + 386a9280 a761b07e
+= 1.2345678899999999e-20 + 6.2471119716631328e-37
+ddI[1] = #3bcd2681 471e7ada + 386a9280 a761b080
+= 1.2345678899999999e-20 + 6.2471119716631345e-37
+ddI[0] == strtod
+
+
+Input: 1.23456789e-30
+strtopdd consumes 14 bytes and returns 33
+dd[0] = 1.23456789e-30 = #39b90a3e 33bbd995
+dd[1] = 2.1567930523648577e-47 = #363f8585 55a6b1a0
+g_ddfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoIdd returns 33, consuming 14 bytes.
+ddI[0] = #39b90a3e 33bbd995 + 363f8585 55a6b198
+= 1.23456789e-30 + 2.1567930523648558e-47
+ddI[1] = #39b90a3e 33bbd995 + 363f8585 55a6b1a0
+= 1.23456789e-30 + 2.1567930523648577e-47
+ddI[1] == strtod
+
+
+Input: 1.234567890123456789
+strtopdd consumes 20 bytes and returns 33
+dd[0] = 1.2345678901234567 = #3ff3c0ca 428c59fb
+dd[1] = 9.856786452588859e-17 = #3c9c6906 51a3745e
+g_ddfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIdd returns 33, consuming 20 bytes.
+ddI[0] = #3ff3c0ca 428c59fb + 3c9c6906 51a3745c
+= 1.2345678901234567 + 9.8567864525888563e-17
+ddI[1] = #3ff3c0ca 428c59fb + 3c9c6906 51a3745e
+= 1.2345678901234567 + 9.8567864525888588e-17
+ddI[1] == strtod
+
+
+Input: 1.23456789012345678901234567890123456789
+strtopdd consumes 40 bytes and returns 33
+dd[0] = 1.2345678901234567 = #3ff3c0ca 428c59fb
+dd[1] = 9.858021020478982e-17 = #3c9c69ef 85adadb6
+g_ddfmt(0) gives 34 bytes: "1.23456789012345678901234567890124"
+
+strtoIdd returns 33, consuming 40 bytes.
+ddI[0] = #3ff3c0ca 428c59fb + 3c9c69ef 85adadb4
+= 1.2345678901234567 + 9.8580210204789798e-17
+ddI[1] = #3ff3c0ca 428c59fb + 3c9c69ef 85adadb6
+= 1.2345678901234567 + 9.8580210204789823e-17
+ddI[1] == strtod
+
+
+Input: 1.23e306
+strtopdd consumes 8 bytes and returns 33
+dd[0] = 1.2299999999999999e+306 = #7f7c0676 cd1c61f4
+dd[1] = 1.3319001448659015e+290 = #7c2b558b e3d3f477
+g_ddfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoIdd returns 33, consuming 8 bytes.
+ddI[0] = #7f7c0676 cd1c61f4 + 7c2b558b e3d3f476
+= 1.2299999999999999e+306 + 1.3319001448659013e+290
+ddI[1] = #7f7c0676 cd1c61f4 + 7c2b558b e3d3f477
+= 1.2299999999999999e+306 + 1.3319001448659015e+290
+ddI[1] == strtod
+
+
+Input: 1.23e-306
+strtopdd consumes 9 bytes and returns 98
+dd[0] = 1.2299999999999999e-306 = #6ba3b8 5da396e7
+dd[1] = 1.43e-322 = #0 1d
+g_ddfmt(0) gives 9 bytes: "1.23e-306"
+
+strtoIdd returns 98, consuming 9 bytes.
+ddI[0] = #6ba3b8 5da396e7 + 0 1c
+= 1.2299999999999999e-306 + 1.3833838083554903e-322
+ddI[1] = #6ba3b8 5da396e7 + 0 1d
+= 1.2299999999999999e-306 + 1.432790372939615e-322
+ddI[1] == strtod
+
+
+Input: 1.23e-320
+strtopdd consumes 9 bytes and returns 98
+dd[0] = 1.23e-320 = #0 9ba
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 9 bytes: "1.23e-320"
+
+strtoIdd returns 98, consuming 9 bytes.
+ddI[0] = #0 9b9 + 0 0
+= 1.2297293924988626e-320 + 0
+ddI[1] = #0 9ba + 0 0
+= 1.2302234581447039e-320 + 0
+ddI[1] == strtod
+
+
+Input: 1.23e-20
+strtopdd consumes 8 bytes and returns 33
+dd[0] = 1.2299999999999999e-20 = #3bcd0ae4 cf767530
+dd[1] = 9.304023318521521e-37 = #3873c997 955b2691
+g_ddfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIdd returns 33, consuming 8 bytes.
+ddI[0] = #3bcd0ae4 cf767530 + 3873c997 955b2690
+= 1.2299999999999999e-20 + 9.3040233185215194e-37
+ddI[1] = #3bcd0ae4 cf767530 + 3873c997 955b2691
+= 1.2299999999999999e-20 + 9.3040233185215211e-37
+ddI[1] == strtod
+
+
+Input: 1.23456789e307
+strtopdd consumes 14 bytes and returns 33
+dd[0] = 1.2345678899999998e+307 = #7fb194b1 4bdaecdb
+dd[1] = 2.0137933598720243e+291 = #7c69d48d 192048ca
+g_ddfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoIdd returns 33, consuming 14 bytes.
+ddI[0] = #7fb194b1 4bdaecdb + 7c69d48d 192048c9
+= 1.2345678899999998e+307 + 2.013793359872024e+291
+ddI[1] = #7fb194b1 4bdaecdb + 7c69d48d 192048ca
+= 1.2345678899999998e+307 + 2.0137933598720243e+291
+ddI[1] == strtod
+
+
+Input: 1.23456589e-307
+strtopdd consumes 15 bytes and returns 98
+dd[0] = 1.23456589e-307 = #363196 bb9845fa
+dd[1] = 1e-323 = #0 2
+g_ddfmt(0) gives 15 bytes: "1.23456589e-307"
+
+strtoIdd returns 98, consuming 15 bytes.
+ddI[0] = #363196 bb9845fa + 0 1
+= 1.2345658899999999e-307 + 4.9406564584124654e-324
+ddI[1] = #363196 bb9845fa + 0 2
+= 1.2345658899999999e-307 + 9.8813129168249309e-324
+ddI[1] == strtod
+
+
+Input: 1.234567890123456789
+strtopdd consumes 20 bytes and returns 33
+dd[0] = 1.2345678901234567 = #3ff3c0ca 428c59fb
+dd[1] = 9.856786452588859e-17 = #3c9c6906 51a3745e
+g_ddfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIdd returns 33, consuming 20 bytes.
+ddI[0] = #3ff3c0ca 428c59fb + 3c9c6906 51a3745c
+= 1.2345678901234567 + 9.8567864525888563e-17
+ddI[1] = #3ff3c0ca 428c59fb + 3c9c6906 51a3745e
+= 1.2345678901234567 + 9.8567864525888588e-17
+ddI[1] == strtod
+
+
+Input: 1.234567890123456789e301
+strtopdd consumes 24 bytes and returns 33
+dd[0] = 1.2345678901234568e+301 = #7e726f51 75f56413
+dd[1] = 1.3892003943918827e+283 = #7ab7ea80 76399100
+g_ddfmt(0) gives 25 bytes: "1.234567890123456789e+301"
+
+strtoIdd returns 33, consuming 24 bytes.
+ddI[0] = #7e726f51 75f56413 + 7ab7ea80 76399080
+= 1.2345678901234568e+301 + 1.3892003943918563e+283
+ddI[1] = #7e726f51 75f56413 + 7ab7ea80 76399100
+= 1.2345678901234568e+301 + 1.3892003943918827e+283
+ddI[1] == strtod
+
+
+Input: 1.234567890123456789e-301
+strtopdd consumes 25 bytes and returns 82
+dd[0] = 1.2345678901234567e-301 = #1752a64 e34ba0d3
+dd[1] = 7.374365e-318 = #0 16c66c
+g_ddfmt(0) gives 25 bytes: "1.234567890123456789e-301"
+
+strtoIdd returns 82, consuming 25 bytes.
+ddI[0] = #1752a64 e34ba0d3 + 0 16c66c
+= 1.2345678901234567e-301 + 7.374364541948945e-318
+ddI[1] = #1752a64 e34ba0d3 + 0 16c66d
+= 1.2345678901234567e-301 + 7.3743694826054034e-318
+ddI[0] == strtod
+
+
+Input: 1.234567890123456789e-321
+strtopdd consumes 25 bytes and returns 98
+dd[0] = 1.235e-321 = #0 fa
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 10 bytes: "1.235e-321"
+
+strtoIdd returns 98, consuming 25 bytes.
+ddI[0] = #0 f9 + 0 0
+= 1.2302234581447039e-321 + 0
+ddI[1] = #0 fa + 0 0
+= 1.2351641146031164e-321 + 0
+ddI[1] == strtod
+
+
+Input: 1e23
+strtopdd consumes 4 bytes and returns 1
+dd[0] = 1e+23 = #44b52d02 c7e14af6
+dd[1] = 8388608 = #41600000 0
+g_ddfmt(0) gives 5 bytes: "1e+23"
+
+strtoIdd returns 1, consuming 4 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1e310
+strtopdd consumes 5 bytes and returns 163
+dd[0] = Infinity = #7ff00000 0
+dd[1] = Infinity = #7ff00000 0
+g_ddfmt(0) gives 8 bytes: "Infinity"
+
+strtoIdd returns 163, consuming 5 bytes.
+ddI[0] = #7fefffff ffffffff + 7c9fffff ffffffff
+= 1.7976931348623157e+308 + 1.9958403095347196e+292
+ddI[1] = #7ff00000 0 + 7ff00000 0
+= Infinity + Infinity
+ddI[1] == strtod
+
+
+Input: 9.0259718793241475e-277
+strtopdd consumes 23 bytes and returns 33
+dd[0] = 9.025971879324147e-277 = #69fffff ffffffff
+dd[1] = 6.217378695986177e-293 = #343daae f3582320
+g_ddfmt(0) gives 23 bytes: "9.0259718793241475e-277"
+
+strtoIdd returns 33, consuming 23 bytes.
+ddI[0] = #69fffff ffffffff + 343daae f358231f
+= 9.0259718793241469e-277 + 6.2173786959861757e-293
+ddI[1] = #69fffff ffffffff + 343daae f3582320
+= 9.0259718793241469e-277 + 6.2173786959861768e-293
+ddI[1] == strtod
+
+
+Input: 9.025971879324147880346310405869e-277
+strtopdd consumes 37 bytes and returns 17
+dd[0] = 9.025971879324148e-277 = #6a00000 0
+dd[1] = 2.2250738585072014e-308 = #100000 0
+g_ddfmt(0) gives 37 bytes: "9.025971879324147880346310405869e-277"
+
+strtoIdd returns 17, consuming 37 bytes.
+ddI[0] = #6a00000 0 + 100000 0
+= 9.0259718793241479e-277 + 2.2250738585072014e-308
+ddI[1] = #6a00000 0 + 200000 0
+= 9.0259718793241479e-277 + 4.4501477170144028e-308
+ddI[0] == strtod
+
+
+Input: 9.025971879324147880346310405868e-277
+strtopdd consumes 37 bytes and returns 17
+dd[0] = 9.025971879324147e-277 = #69fffff ffffffff
+dd[1] = 1.0020841800044856e-292 = #34fffff fffffff9
+g_ddfmt(0) gives 37 bytes: "9.025971879324147880346310405868e-277"
+
+strtoIdd returns 17, consuming 37 bytes.
+ddI[0] = #69fffff ffffffff + 34fffff fffffff9
+= 9.0259718793241469e-277 + 1.0020841800044856e-292
+ddI[1] = #69fffff ffffffff + 34fffff fffffffa
+= 9.0259718793241469e-277 + 1.0020841800044857e-292
+ddI[0] == strtod
+
+
+Input: 2.2250738585072014e-308
+strtopdd consumes 23 bytes and returns 82
+dd[0] = 2.2250738585072014e-308 = #100000 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoIdd returns 82, consuming 23 bytes.
+ddI[0] = #100000 0 + 0 0
+= 2.2250738585072014e-308 + 0
+ddI[1] = #100000 1 + 0 0
+= 2.2250738585072019e-308 + 0
+ddI[0] == strtod
+
+
+Input: 2.2250738585072013e-308
+strtopdd consumes 23 bytes and returns 98
+dd[0] = 2.2250738585072014e-308 = #100000 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoIdd returns 98, consuming 23 bytes.
+ddI[0] = #fffff ffffffff + 0 0
+= 2.2250738585072009e-308 + 0
+ddI[1] = #100000 0 + 0 0
+= 2.2250738585072014e-308 + 0
+ddI[1] == strtod
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.0999999999999999 = #3ff19999 99999999
+dd[1] = 1.3322676295501878e-16 = #3ca33333 33333333
+g_ddfmt(0) gives 3 bytes: "1.1"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff19999 99999999 + 3ca33333 33333333
+= 1.0999999999999999 + 1.3322676295501878e-16
+ddI[1] = #3ff19999 99999999 + 3ca33333 33333334
+= 1.0999999999999999 + 1.332267629550188e-16
+ddI[0] == strtod
+
+
+Input: -1.1
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.0999999999999999 = #bff19999 99999999
+dd[1] = -1.3322676295501878e-16 = #bca33333 33333333
+g_ddfmt(0) gives 4 bytes: "-1.1"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff19999 99999999 + bca33333 33333334
+= -1.0999999999999999 + -1.332267629550188e-16
+ddI[1] = #bff19999 99999999 + bca33333 33333333
+= -1.0999999999999999 + -1.3322676295501878e-16
+ddI[1] == strtod
+
+
+Input: 1.2
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.2 = #3ff33333 33333333
+dd[1] = 4.440892098500625e-17 = #3c899999 99999998
+g_ddfmt(0) gives 3 bytes: "1.2"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff33333 33333333 + 3c899999 99999998
+= 1.2 + 4.4408920985006252e-17
+ddI[1] = #3ff33333 33333333 + 3c899999 9999999c
+= 1.2 + 4.4408920985006276e-17
+ddI[0] == strtod
+
+
+Input: -1.2
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.2 = #bff33333 33333333
+dd[1] = -4.440892098500625e-17 = #bc899999 99999998
+g_ddfmt(0) gives 4 bytes: "-1.2"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff33333 33333333 + bc899999 9999999c
+= -1.2 + -4.4408920985006276e-17
+ddI[1] = #bff33333 33333333 + bc899999 99999998
+= -1.2 + -4.4408920985006252e-17
+ddI[1] == strtod
+
+
+Input: 1.3
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.2999999999999998 = #3ff4cccc cccccccc
+dd[1] = 1.7763568394002503e-16 = #3ca99999 99999999
+g_ddfmt(0) gives 34 bytes: "1.29999999999999999999999999999999"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ff4cccc cccccccc + 3ca99999 99999999
+= 1.2999999999999998 + 1.7763568394002503e-16
+ddI[1] = #3ff4cccc cccccccc + 3ca99999 9999999a
+= 1.2999999999999998 + 1.7763568394002506e-16
+ddI[0] == strtod
+
+
+Input: -1.3
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.2999999999999998 = #bff4cccc cccccccc
+dd[1] = -1.7763568394002503e-16 = #bca99999 99999999
+g_ddfmt(0) gives 35 bytes: "-1.29999999999999999999999999999999"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bff4cccc cccccccc + bca99999 9999999a
+= -1.2999999999999998 + -1.7763568394002506e-16
+ddI[1] = #bff4cccc cccccccc + bca99999 99999999
+= -1.2999999999999998 + -1.7763568394002503e-16
+ddI[1] == strtod
+
+
+Input: 1.4
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.4 = #3ff66666 66666666
+dd[1] = 8.88178419700125e-17 = #3c999999 99999998
+g_ddfmt(0) gives 34 bytes: "1.39999999999999999999999999999998"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ff66666 66666666 + 3c999999 99999998
+= 1.3999999999999999 + 8.8817841970012504e-17
+ddI[1] = #3ff66666 66666666 + 3c999999 9999999a
+= 1.3999999999999999 + 8.8817841970012528e-17
+ddI[0] == strtod
+
+
+Input: -1.4
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.4 = #bff66666 66666666
+dd[1] = -8.88178419700125e-17 = #bc999999 99999998
+g_ddfmt(0) gives 35 bytes: "-1.39999999999999999999999999999998"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bff66666 66666666 + bc999999 9999999a
+= -1.3999999999999999 + -8.8817841970012528e-17
+ddI[1] = #bff66666 66666666 + bc999999 99999998
+= -1.3999999999999999 + -8.8817841970012504e-17
+ddI[1] == strtod
+
+
+Input: 1.5
+strtopdd consumes 3 bytes and returns 1
+dd[0] = 1.5 = #3ff80000 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 3 bytes: "1.5"
+
+strtoIdd returns 1, consuming 3 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: -1.5
+strtopdd consumes 4 bytes and returns 9
+dd[0] = -1.5 = #bff80000 0
+dd[1] = -0 = #80000000 0
+g_ddfmt(0) gives 3 bytes: "1.5"
+
+strtoIdd returns 9, consuming 4 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.6
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.5999999999999999 = #3ff99999 99999999
+dd[1] = 1.3322676295501878e-16 = #3ca33333 33333333
+g_ddfmt(0) gives 3 bytes: "1.6"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff99999 99999999 + 3ca33333 33333333
+= 1.5999999999999999 + 1.3322676295501878e-16
+ddI[1] = #3ff99999 99999999 + 3ca33333 33333334
+= 1.5999999999999999 + 1.332267629550188e-16
+ddI[0] == strtod
+
+
+Input: -1.6
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.5999999999999999 = #bff99999 99999999
+dd[1] = -1.3322676295501878e-16 = #bca33333 33333333
+g_ddfmt(0) gives 4 bytes: "-1.6"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff99999 99999999 + bca33333 33333334
+= -1.5999999999999999 + -1.332267629550188e-16
+ddI[1] = #bff99999 99999999 + bca33333 33333333
+= -1.5999999999999999 + -1.3322676295501878e-16
+ddI[1] == strtod
+
+
+Input: 1.7
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.7 = #3ffb3333 33333333
+dd[1] = 4.440892098500625e-17 = #3c899999 99999998
+g_ddfmt(0) gives 3 bytes: "1.7"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ffb3333 33333333 + 3c899999 99999998
+= 1.7 + 4.4408920985006252e-17
+ddI[1] = #3ffb3333 33333333 + 3c899999 9999999c
+= 1.7 + 4.4408920985006276e-17
+ddI[0] == strtod
+
+
+Input: -1.7
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.7 = #bffb3333 33333333
+dd[1] = -4.440892098500625e-17 = #bc899999 99999998
+g_ddfmt(0) gives 4 bytes: "-1.7"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bffb3333 33333333 + bc899999 9999999c
+= -1.7 + -4.4408920985006276e-17
+ddI[1] = #bffb3333 33333333 + bc899999 99999998
+= -1.7 + -4.4408920985006252e-17
+ddI[1] == strtod
+
+
+Input: 1.8
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.7999999999999998 = #3ffccccc cccccccc
+dd[1] = 1.7763568394002503e-16 = #3ca99999 99999999
+g_ddfmt(0) gives 34 bytes: "1.79999999999999999999999999999999"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ffccccc cccccccc + 3ca99999 99999999
+= 1.7999999999999998 + 1.7763568394002503e-16
+ddI[1] = #3ffccccc cccccccc + 3ca99999 9999999a
+= 1.7999999999999998 + 1.7763568394002506e-16
+ddI[0] == strtod
+
+
+Input: -1.8
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.7999999999999998 = #bffccccc cccccccc
+dd[1] = -1.7763568394002503e-16 = #bca99999 99999999
+g_ddfmt(0) gives 35 bytes: "-1.79999999999999999999999999999999"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bffccccc cccccccc + bca99999 9999999a
+= -1.7999999999999998 + -1.7763568394002506e-16
+ddI[1] = #bffccccc cccccccc + bca99999 99999999
+= -1.7999999999999998 + -1.7763568394002503e-16
+ddI[1] == strtod
+
+
+Input: 1.9
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.9 = #3ffe6666 66666666
+dd[1] = 8.88178419700125e-17 = #3c999999 99999998
+g_ddfmt(0) gives 34 bytes: "1.89999999999999999999999999999998"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ffe6666 66666666 + 3c999999 99999998
+= 1.8999999999999999 + 8.8817841970012504e-17
+ddI[1] = #3ffe6666 66666666 + 3c999999 9999999a
+= 1.8999999999999999 + 8.8817841970012528e-17
+ddI[0] == strtod
+
+
+Input: -1.9
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.9 = #bffe6666 66666666
+dd[1] = -8.88178419700125e-17 = #bc999999 99999998
+g_ddfmt(0) gives 35 bytes: "-1.89999999999999999999999999999998"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bffe6666 66666666 + bc999999 9999999a
+= -1.8999999999999999 + -8.8817841970012528e-17
+ddI[1] = #bffe6666 66666666 + bc999999 99999998
+= -1.8999999999999999 + -8.8817841970012504e-17
+ddI[1] == strtod
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.0999999999999999 = #3ff19999 99999999
+dd[1] = 1.3322676295501878e-16 = #3ca33333 33333333
+g_ddfmt(0) gives 3 bytes: "1.1"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff19999 99999999 + 3ca33333 33333333
+= 1.0999999999999999 + 1.3322676295501878e-16
+ddI[1] = #3ff19999 99999999 + 3ca33333 33333334
+= 1.0999999999999999 + 1.332267629550188e-16
+ddI[0] == strtod
+
+
+Input: -1.1
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.0999999999999999 = #bff19999 99999999
+dd[1] = -1.3322676295501878e-16 = #bca33333 33333333
+g_ddfmt(0) gives 4 bytes: "-1.1"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff19999 99999999 + bca33333 33333334
+= -1.0999999999999999 + -1.332267629550188e-16
+ddI[1] = #bff19999 99999999 + bca33333 33333333
+= -1.0999999999999999 + -1.3322676295501878e-16
+ddI[1] == strtod
+
+
+Input: 1.2
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.2 = #3ff33333 33333333
+dd[1] = 4.440892098500625e-17 = #3c899999 99999998
+g_ddfmt(0) gives 3 bytes: "1.2"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff33333 33333333 + 3c899999 99999998
+= 1.2 + 4.4408920985006252e-17
+ddI[1] = #3ff33333 33333333 + 3c899999 9999999c
+= 1.2 + 4.4408920985006276e-17
+ddI[0] == strtod
+
+
+Input: -1.2
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.2 = #bff33333 33333333
+dd[1] = -4.440892098500625e-17 = #bc899999 99999998
+g_ddfmt(0) gives 4 bytes: "-1.2"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff33333 33333333 + bc899999 9999999c
+= -1.2 + -4.4408920985006276e-17
+ddI[1] = #bff33333 33333333 + bc899999 99999998
+= -1.2 + -4.4408920985006252e-17
+ddI[1] == strtod
+
+
+Input: 1.3
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.2999999999999998 = #3ff4cccc cccccccc
+dd[1] = 1.7763568394002506e-16 = #3ca99999 9999999a
+g_ddfmt(0) gives 3 bytes: "1.3"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ff4cccc cccccccc + 3ca99999 99999999
+= 1.2999999999999998 + 1.7763568394002503e-16
+ddI[1] = #3ff4cccc cccccccc + 3ca99999 9999999a
+= 1.2999999999999998 + 1.7763568394002506e-16
+ddI[1] == strtod
+
+
+Input: -1.3
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.2999999999999998 = #bff4cccc cccccccc
+dd[1] = -1.7763568394002506e-16 = #bca99999 9999999a
+g_ddfmt(0) gives 4 bytes: "-1.3"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bff4cccc cccccccc + bca99999 9999999a
+= -1.2999999999999998 + -1.7763568394002506e-16
+ddI[1] = #bff4cccc cccccccc + bca99999 99999999
+= -1.2999999999999998 + -1.7763568394002503e-16
+ddI[0] == strtod
+
+
+Input: 1.4
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.4 = #3ff66666 66666666
+dd[1] = 8.881784197001253e-17 = #3c999999 9999999a
+g_ddfmt(0) gives 3 bytes: "1.4"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ff66666 66666666 + 3c999999 99999998
+= 1.3999999999999999 + 8.8817841970012504e-17
+ddI[1] = #3ff66666 66666666 + 3c999999 9999999a
+= 1.3999999999999999 + 8.8817841970012528e-17
+ddI[1] == strtod
+
+
+Input: -1.4
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.4 = #bff66666 66666666
+dd[1] = -8.881784197001253e-17 = #bc999999 9999999a
+g_ddfmt(0) gives 4 bytes: "-1.4"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bff66666 66666666 + bc999999 9999999a
+= -1.3999999999999999 + -8.8817841970012528e-17
+ddI[1] = #bff66666 66666666 + bc999999 99999998
+= -1.3999999999999999 + -8.8817841970012504e-17
+ddI[0] == strtod
+
+
+Input: 1.5
+strtopdd consumes 3 bytes and returns 1
+dd[0] = 1.5 = #3ff80000 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 3 bytes: "1.5"
+
+strtoIdd returns 1, consuming 3 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: -1.5
+strtopdd consumes 4 bytes and returns 9
+dd[0] = -1.5 = #bff80000 0
+dd[1] = -0 = #80000000 0
+g_ddfmt(0) gives 3 bytes: "1.5"
+
+strtoIdd returns 9, consuming 4 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.6
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.5999999999999999 = #3ff99999 99999999
+dd[1] = 1.3322676295501878e-16 = #3ca33333 33333333
+g_ddfmt(0) gives 3 bytes: "1.6"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff99999 99999999 + 3ca33333 33333333
+= 1.5999999999999999 + 1.3322676295501878e-16
+ddI[1] = #3ff99999 99999999 + 3ca33333 33333334
+= 1.5999999999999999 + 1.332267629550188e-16
+ddI[0] == strtod
+
+
+Input: -1.6
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.5999999999999999 = #bff99999 99999999
+dd[1] = -1.3322676295501878e-16 = #bca33333 33333333
+g_ddfmt(0) gives 4 bytes: "-1.6"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff99999 99999999 + bca33333 33333334
+= -1.5999999999999999 + -1.332267629550188e-16
+ddI[1] = #bff99999 99999999 + bca33333 33333333
+= -1.5999999999999999 + -1.3322676295501878e-16
+ddI[1] == strtod
+
+
+Input: 1.7
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.7 = #3ffb3333 33333333
+dd[1] = 4.440892098500625e-17 = #3c899999 99999998
+g_ddfmt(0) gives 3 bytes: "1.7"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ffb3333 33333333 + 3c899999 99999998
+= 1.7 + 4.4408920985006252e-17
+ddI[1] = #3ffb3333 33333333 + 3c899999 9999999c
+= 1.7 + 4.4408920985006276e-17
+ddI[0] == strtod
+
+
+Input: -1.7
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.7 = #bffb3333 33333333
+dd[1] = -4.440892098500625e-17 = #bc899999 99999998
+g_ddfmt(0) gives 4 bytes: "-1.7"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bffb3333 33333333 + bc899999 9999999c
+= -1.7 + -4.4408920985006276e-17
+ddI[1] = #bffb3333 33333333 + bc899999 99999998
+= -1.7 + -4.4408920985006252e-17
+ddI[1] == strtod
+
+
+Input: 1.8
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.7999999999999998 = #3ffccccc cccccccc
+dd[1] = 1.7763568394002506e-16 = #3ca99999 9999999a
+g_ddfmt(0) gives 3 bytes: "1.8"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ffccccc cccccccc + 3ca99999 99999999
+= 1.7999999999999998 + 1.7763568394002503e-16
+ddI[1] = #3ffccccc cccccccc + 3ca99999 9999999a
+= 1.7999999999999998 + 1.7763568394002506e-16
+ddI[1] == strtod
+
+
+Input: -1.8
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.7999999999999998 = #bffccccc cccccccc
+dd[1] = -1.7763568394002506e-16 = #bca99999 9999999a
+g_ddfmt(0) gives 4 bytes: "-1.8"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bffccccc cccccccc + bca99999 9999999a
+= -1.7999999999999998 + -1.7763568394002506e-16
+ddI[1] = #bffccccc cccccccc + bca99999 99999999
+= -1.7999999999999998 + -1.7763568394002503e-16
+ddI[0] == strtod
+
+
+Input: 1.9
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.9 = #3ffe6666 66666666
+dd[1] = 8.881784197001253e-17 = #3c999999 9999999a
+g_ddfmt(0) gives 3 bytes: "1.9"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ffe6666 66666666 + 3c999999 99999998
+= 1.8999999999999999 + 8.8817841970012504e-17
+ddI[1] = #3ffe6666 66666666 + 3c999999 9999999a
+= 1.8999999999999999 + 8.8817841970012528e-17
+ddI[1] == strtod
+
+
+Input: -1.9
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.9 = #bffe6666 66666666
+dd[1] = -8.881784197001253e-17 = #bc999999 9999999a
+g_ddfmt(0) gives 4 bytes: "-1.9"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bffe6666 66666666 + bc999999 9999999a
+= -1.8999999999999999 + -8.8817841970012528e-17
+ddI[1] = #bffe6666 66666666 + bc999999 99999998
+= -1.8999999999999999 + -8.8817841970012504e-17
+ddI[0] == strtod
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.0999999999999999 = #3ff19999 99999999
+dd[1] = 1.332267629550188e-16 = #3ca33333 33333334
+g_ddfmt(0) gives 34 bytes: "1.10000000000000000000000000000002"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff19999 99999999 + 3ca33333 33333333
+= 1.0999999999999999 + 1.3322676295501878e-16
+ddI[1] = #3ff19999 99999999 + 3ca33333 33333334
+= 1.0999999999999999 + 1.332267629550188e-16
+ddI[1] == strtod
+
+
+Input: -1.1
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.0999999999999999 = #bff19999 99999999
+dd[1] = -1.3322676295501878e-16 = #bca33333 33333333
+g_ddfmt(0) gives 4 bytes: "-1.1"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff19999 99999999 + bca33333 33333334
+= -1.0999999999999999 + -1.332267629550188e-16
+ddI[1] = #bff19999 99999999 + bca33333 33333333
+= -1.0999999999999999 + -1.3322676295501878e-16
+ddI[1] == strtod
+
+
+Input: 1.2
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.2 = #3ff33333 33333333
+dd[1] = 4.4408920985006276e-17 = #3c899999 9999999c
+g_ddfmt(0) gives 34 bytes: "1.20000000000000000000000000000001"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff33333 33333333 + 3c899999 99999998
+= 1.2 + 4.4408920985006252e-17
+ddI[1] = #3ff33333 33333333 + 3c899999 9999999c
+= 1.2 + 4.4408920985006276e-17
+ddI[1] == strtod
+
+
+Input: -1.2
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.2 = #bff33333 33333333
+dd[1] = -4.440892098500625e-17 = #bc899999 99999998
+g_ddfmt(0) gives 4 bytes: "-1.2"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff33333 33333333 + bc899999 9999999c
+= -1.2 + -4.4408920985006276e-17
+ddI[1] = #bff33333 33333333 + bc899999 99999998
+= -1.2 + -4.4408920985006252e-17
+ddI[1] == strtod
+
+
+Input: 1.3
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.2999999999999998 = #3ff4cccc cccccccc
+dd[1] = 1.7763568394002506e-16 = #3ca99999 9999999a
+g_ddfmt(0) gives 3 bytes: "1.3"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ff4cccc cccccccc + 3ca99999 99999999
+= 1.2999999999999998 + 1.7763568394002503e-16
+ddI[1] = #3ff4cccc cccccccc + 3ca99999 9999999a
+= 1.2999999999999998 + 1.7763568394002506e-16
+ddI[1] == strtod
+
+
+Input: -1.3
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.2999999999999998 = #bff4cccc cccccccc
+dd[1] = -1.7763568394002503e-16 = #bca99999 99999999
+g_ddfmt(0) gives 35 bytes: "-1.29999999999999999999999999999999"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bff4cccc cccccccc + bca99999 9999999a
+= -1.2999999999999998 + -1.7763568394002506e-16
+ddI[1] = #bff4cccc cccccccc + bca99999 99999999
+= -1.2999999999999998 + -1.7763568394002503e-16
+ddI[1] == strtod
+
+
+Input: 1.4
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.4 = #3ff66666 66666666
+dd[1] = 8.881784197001253e-17 = #3c999999 9999999a
+g_ddfmt(0) gives 3 bytes: "1.4"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ff66666 66666666 + 3c999999 99999998
+= 1.3999999999999999 + 8.8817841970012504e-17
+ddI[1] = #3ff66666 66666666 + 3c999999 9999999a
+= 1.3999999999999999 + 8.8817841970012528e-17
+ddI[1] == strtod
+
+
+Input: -1.4
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.4 = #bff66666 66666666
+dd[1] = -8.88178419700125e-17 = #bc999999 99999998
+g_ddfmt(0) gives 35 bytes: "-1.39999999999999999999999999999998"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bff66666 66666666 + bc999999 9999999a
+= -1.3999999999999999 + -8.8817841970012528e-17
+ddI[1] = #bff66666 66666666 + bc999999 99999998
+= -1.3999999999999999 + -8.8817841970012504e-17
+ddI[1] == strtod
+
+
+Input: 1.5
+strtopdd consumes 3 bytes and returns 1
+dd[0] = 1.5 = #3ff80000 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 3 bytes: "1.5"
+
+strtoIdd returns 1, consuming 3 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: -1.5
+strtopdd consumes 4 bytes and returns 9
+dd[0] = -1.5 = #bff80000 0
+dd[1] = -0 = #80000000 0
+g_ddfmt(0) gives 3 bytes: "1.5"
+
+strtoIdd returns 9, consuming 4 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.6
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.5999999999999999 = #3ff99999 99999999
+dd[1] = 1.332267629550188e-16 = #3ca33333 33333334
+g_ddfmt(0) gives 34 bytes: "1.60000000000000000000000000000002"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff99999 99999999 + 3ca33333 33333333
+= 1.5999999999999999 + 1.3322676295501878e-16
+ddI[1] = #3ff99999 99999999 + 3ca33333 33333334
+= 1.5999999999999999 + 1.332267629550188e-16
+ddI[1] == strtod
+
+
+Input: -1.6
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.5999999999999999 = #bff99999 99999999
+dd[1] = -1.3322676295501878e-16 = #bca33333 33333333
+g_ddfmt(0) gives 4 bytes: "-1.6"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff99999 99999999 + bca33333 33333334
+= -1.5999999999999999 + -1.332267629550188e-16
+ddI[1] = #bff99999 99999999 + bca33333 33333333
+= -1.5999999999999999 + -1.3322676295501878e-16
+ddI[1] == strtod
+
+
+Input: 1.7
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.7 = #3ffb3333 33333333
+dd[1] = 4.4408920985006276e-17 = #3c899999 9999999c
+g_ddfmt(0) gives 34 bytes: "1.70000000000000000000000000000001"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ffb3333 33333333 + 3c899999 99999998
+= 1.7 + 4.4408920985006252e-17
+ddI[1] = #3ffb3333 33333333 + 3c899999 9999999c
+= 1.7 + 4.4408920985006276e-17
+ddI[1] == strtod
+
+
+Input: -1.7
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.7 = #bffb3333 33333333
+dd[1] = -4.440892098500625e-17 = #bc899999 99999998
+g_ddfmt(0) gives 4 bytes: "-1.7"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bffb3333 33333333 + bc899999 9999999c
+= -1.7 + -4.4408920985006276e-17
+ddI[1] = #bffb3333 33333333 + bc899999 99999998
+= -1.7 + -4.4408920985006252e-17
+ddI[1] == strtod
+
+
+Input: 1.8
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.7999999999999998 = #3ffccccc cccccccc
+dd[1] = 1.7763568394002506e-16 = #3ca99999 9999999a
+g_ddfmt(0) gives 3 bytes: "1.8"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ffccccc cccccccc + 3ca99999 99999999
+= 1.7999999999999998 + 1.7763568394002503e-16
+ddI[1] = #3ffccccc cccccccc + 3ca99999 9999999a
+= 1.7999999999999998 + 1.7763568394002506e-16
+ddI[1] == strtod
+
+
+Input: -1.8
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.7999999999999998 = #bffccccc cccccccc
+dd[1] = -1.7763568394002503e-16 = #bca99999 99999999
+g_ddfmt(0) gives 35 bytes: "-1.79999999999999999999999999999999"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bffccccc cccccccc + bca99999 9999999a
+= -1.7999999999999998 + -1.7763568394002506e-16
+ddI[1] = #bffccccc cccccccc + bca99999 99999999
+= -1.7999999999999998 + -1.7763568394002503e-16
+ddI[1] == strtod
+
+
+Input: 1.9
+strtopdd consumes 3 bytes and returns 33
+dd[0] = 1.9 = #3ffe6666 66666666
+dd[1] = 8.881784197001253e-17 = #3c999999 9999999a
+g_ddfmt(0) gives 3 bytes: "1.9"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ffe6666 66666666 + 3c999999 99999998
+= 1.8999999999999999 + 8.8817841970012504e-17
+ddI[1] = #3ffe6666 66666666 + 3c999999 9999999a
+= 1.8999999999999999 + 8.8817841970012528e-17
+ddI[1] == strtod
+
+
+Input: -1.9
+strtopdd consumes 4 bytes and returns 25
+dd[0] = -1.9 = #bffe6666 66666666
+dd[1] = -8.88178419700125e-17 = #bc999999 99999998
+g_ddfmt(0) gives 35 bytes: "-1.89999999999999999999999999999998"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bffe6666 66666666 + bc999999 9999999a
+= -1.8999999999999999 + -8.8817841970012528e-17
+ddI[1] = #bffe6666 66666666 + bc999999 99999998
+= -1.8999999999999999 + -8.8817841970012504e-17
+ddI[1] == strtod
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.0999999999999999 = #3ff19999 99999999
+dd[1] = 1.3322676295501878e-16 = #3ca33333 33333333
+g_ddfmt(0) gives 3 bytes: "1.1"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff19999 99999999 + 3ca33333 33333333
+= 1.0999999999999999 + 1.3322676295501878e-16
+ddI[1] = #3ff19999 99999999 + 3ca33333 33333334
+= 1.0999999999999999 + 1.332267629550188e-16
+ddI[0] == strtod
+
+
+Input: -1.1
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.0999999999999999 = #bff19999 99999999
+dd[1] = -1.332267629550188e-16 = #bca33333 33333334
+g_ddfmt(0) gives 35 bytes: "-1.10000000000000000000000000000002"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff19999 99999999 + bca33333 33333334
+= -1.0999999999999999 + -1.332267629550188e-16
+ddI[1] = #bff19999 99999999 + bca33333 33333333
+= -1.0999999999999999 + -1.3322676295501878e-16
+ddI[0] == strtod
+
+
+Input: 1.2
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.2 = #3ff33333 33333333
+dd[1] = 4.440892098500625e-17 = #3c899999 99999998
+g_ddfmt(0) gives 3 bytes: "1.2"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff33333 33333333 + 3c899999 99999998
+= 1.2 + 4.4408920985006252e-17
+ddI[1] = #3ff33333 33333333 + 3c899999 9999999c
+= 1.2 + 4.4408920985006276e-17
+ddI[0] == strtod
+
+
+Input: -1.2
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.2 = #bff33333 33333333
+dd[1] = -4.4408920985006276e-17 = #bc899999 9999999c
+g_ddfmt(0) gives 35 bytes: "-1.20000000000000000000000000000001"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff33333 33333333 + bc899999 9999999c
+= -1.2 + -4.4408920985006276e-17
+ddI[1] = #bff33333 33333333 + bc899999 99999998
+= -1.2 + -4.4408920985006252e-17
+ddI[0] == strtod
+
+
+Input: 1.3
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.2999999999999998 = #3ff4cccc cccccccc
+dd[1] = 1.7763568394002503e-16 = #3ca99999 99999999
+g_ddfmt(0) gives 34 bytes: "1.29999999999999999999999999999999"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ff4cccc cccccccc + 3ca99999 99999999
+= 1.2999999999999998 + 1.7763568394002503e-16
+ddI[1] = #3ff4cccc cccccccc + 3ca99999 9999999a
+= 1.2999999999999998 + 1.7763568394002506e-16
+ddI[0] == strtod
+
+
+Input: -1.3
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.2999999999999998 = #bff4cccc cccccccc
+dd[1] = -1.7763568394002506e-16 = #bca99999 9999999a
+g_ddfmt(0) gives 4 bytes: "-1.3"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bff4cccc cccccccc + bca99999 9999999a
+= -1.2999999999999998 + -1.7763568394002506e-16
+ddI[1] = #bff4cccc cccccccc + bca99999 99999999
+= -1.2999999999999998 + -1.7763568394002503e-16
+ddI[0] == strtod
+
+
+Input: 1.4
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.4 = #3ff66666 66666666
+dd[1] = 8.88178419700125e-17 = #3c999999 99999998
+g_ddfmt(0) gives 34 bytes: "1.39999999999999999999999999999998"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ff66666 66666666 + 3c999999 99999998
+= 1.3999999999999999 + 8.8817841970012504e-17
+ddI[1] = #3ff66666 66666666 + 3c999999 9999999a
+= 1.3999999999999999 + 8.8817841970012528e-17
+ddI[0] == strtod
+
+
+Input: -1.4
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.4 = #bff66666 66666666
+dd[1] = -8.881784197001253e-17 = #bc999999 9999999a
+g_ddfmt(0) gives 4 bytes: "-1.4"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bff66666 66666666 + bc999999 9999999a
+= -1.3999999999999999 + -8.8817841970012528e-17
+ddI[1] = #bff66666 66666666 + bc999999 99999998
+= -1.3999999999999999 + -8.8817841970012504e-17
+ddI[0] == strtod
+
+
+Input: 1.5
+strtopdd consumes 3 bytes and returns 1
+dd[0] = 1.5 = #3ff80000 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 3 bytes: "1.5"
+
+strtoIdd returns 1, consuming 3 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: -1.5
+strtopdd consumes 4 bytes and returns 9
+dd[0] = -1.5 = #bff80000 0
+dd[1] = -0 = #80000000 0
+g_ddfmt(0) gives 3 bytes: "1.5"
+
+strtoIdd returns 9, consuming 4 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.6
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.5999999999999999 = #3ff99999 99999999
+dd[1] = 1.3322676295501878e-16 = #3ca33333 33333333
+g_ddfmt(0) gives 3 bytes: "1.6"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ff99999 99999999 + 3ca33333 33333333
+= 1.5999999999999999 + 1.3322676295501878e-16
+ddI[1] = #3ff99999 99999999 + 3ca33333 33333334
+= 1.5999999999999999 + 1.332267629550188e-16
+ddI[0] == strtod
+
+
+Input: -1.6
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.5999999999999999 = #bff99999 99999999
+dd[1] = -1.332267629550188e-16 = #bca33333 33333334
+g_ddfmt(0) gives 35 bytes: "-1.60000000000000000000000000000002"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bff99999 99999999 + bca33333 33333334
+= -1.5999999999999999 + -1.332267629550188e-16
+ddI[1] = #bff99999 99999999 + bca33333 33333333
+= -1.5999999999999999 + -1.3322676295501878e-16
+ddI[0] == strtod
+
+
+Input: 1.7
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.7 = #3ffb3333 33333333
+dd[1] = 4.440892098500625e-17 = #3c899999 99999998
+g_ddfmt(0) gives 3 bytes: "1.7"
+
+strtoIdd returns 17, consuming 3 bytes.
+ddI[0] = #3ffb3333 33333333 + 3c899999 99999998
+= 1.7 + 4.4408920985006252e-17
+ddI[1] = #3ffb3333 33333333 + 3c899999 9999999c
+= 1.7 + 4.4408920985006276e-17
+ddI[0] == strtod
+
+
+Input: -1.7
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.7 = #bffb3333 33333333
+dd[1] = -4.4408920985006276e-17 = #bc899999 9999999c
+g_ddfmt(0) gives 35 bytes: "-1.70000000000000000000000000000001"
+
+strtoIdd returns 25, consuming 4 bytes.
+ddI[0] = #bffb3333 33333333 + bc899999 9999999c
+= -1.7 + -4.4408920985006276e-17
+ddI[1] = #bffb3333 33333333 + bc899999 99999998
+= -1.7 + -4.4408920985006252e-17
+ddI[0] == strtod
+
+
+Input: 1.8
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.7999999999999998 = #3ffccccc cccccccc
+dd[1] = 1.7763568394002503e-16 = #3ca99999 99999999
+g_ddfmt(0) gives 34 bytes: "1.79999999999999999999999999999999"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ffccccc cccccccc + 3ca99999 99999999
+= 1.7999999999999998 + 1.7763568394002503e-16
+ddI[1] = #3ffccccc cccccccc + 3ca99999 9999999a
+= 1.7999999999999998 + 1.7763568394002506e-16
+ddI[0] == strtod
+
+
+Input: -1.8
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.7999999999999998 = #bffccccc cccccccc
+dd[1] = -1.7763568394002506e-16 = #bca99999 9999999a
+g_ddfmt(0) gives 4 bytes: "-1.8"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bffccccc cccccccc + bca99999 9999999a
+= -1.7999999999999998 + -1.7763568394002506e-16
+ddI[1] = #bffccccc cccccccc + bca99999 99999999
+= -1.7999999999999998 + -1.7763568394002503e-16
+ddI[0] == strtod
+
+
+Input: 1.9
+strtopdd consumes 3 bytes and returns 17
+dd[0] = 1.9 = #3ffe6666 66666666
+dd[1] = 8.88178419700125e-17 = #3c999999 99999998
+g_ddfmt(0) gives 34 bytes: "1.89999999999999999999999999999998"
+
+strtoIdd returns 33, consuming 3 bytes.
+ddI[0] = #3ffe6666 66666666 + 3c999999 99999998
+= 1.8999999999999999 + 8.8817841970012504e-17
+ddI[1] = #3ffe6666 66666666 + 3c999999 9999999a
+= 1.8999999999999999 + 8.8817841970012528e-17
+ddI[0] == strtod
+
+
+Input: -1.9
+strtopdd consumes 4 bytes and returns 41
+dd[0] = -1.9 = #bffe6666 66666666
+dd[1] = -8.881784197001253e-17 = #bc999999 9999999a
+g_ddfmt(0) gives 4 bytes: "-1.9"
+
+strtoIdd returns 41, consuming 4 bytes.
+ddI[0] = #bffe6666 66666666 + bc999999 9999999a
+= -1.8999999999999999 + -8.8817841970012528e-17
+ddI[1] = #bffe6666 66666666 + bc999999 99999998
+= -1.8999999999999999 + -8.8817841970012504e-17
+ddI[0] == strtod
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/ddsi.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/ddsi.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/ddsi.out	(revision 2448)
@@ -0,0 +1,376 @@
+
+Input: 1.23
+strtopdd consumes 4 bytes and returns 17
+dd[0] = 1.23 = #3ff3ae14 7ae147ae
+dd[1] = 1.7763568394002496e-17 = #3c747ae1 47ae1478
+g_ddfmt(0) gives 4 bytes: "1.23"
+
+strtoIdd returns 17, consuming 4 bytes.
+ddI[0] = #3ff3ae14 7ae147ae + 3c747ae1 47ae1478
+= 1.23 + 1.7763568394002496e-17
+ddI[1] = #3ff3ae14 7ae147ae + 3c747ae1 47ae1480
+= 1.23 + 1.776356839400252e-17
+ddI[0] == strtod
+
+
+Input: 1.23e+20
+strtopdd consumes 8 bytes and returns 1
+dd[0] = 1.23e+20 = #441aabdf 2145b430
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIdd returns 1, consuming 8 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.23e-20
+strtopdd consumes 8 bytes and returns 33
+dd[0] = 1.2299999999999999e-20 = #3bcd0ae4 cf767530
+dd[1] = 9.304023318521521e-37 = #3873c997 955b2691
+g_ddfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIdd returns 33, consuming 8 bytes.
+ddI[0] = #3bcd0ae4 cf767530 + 3873c997 955b2690
+= 1.2299999999999999e-20 + 9.3040233185215194e-37
+ddI[1] = #3bcd0ae4 cf767530 + 3873c997 955b2691
+= 1.2299999999999999e-20 + 9.3040233185215211e-37
+ddI[1] == strtod
+
+
+Input: 1.23456789
+strtopdd consumes 10 bytes and returns 17
+dd[0] = 1.23456789 = #3ff3c0ca 4283de1b
+dd[1] = 1.0990618193318369e-16 = #3c9fada5 144c1252
+g_ddfmt(0) gives 10 bytes: "1.23456789"
+
+strtoIdd returns 17, consuming 10 bytes.
+ddI[0] = #3ff3c0ca 4283de1b + 3c9fada5 144c1252
+= 1.2345678899999999 + 1.0990618193318369e-16
+ddI[1] = #3ff3c0ca 4283de1b + 3c9fada5 144c1254
+= 1.2345678899999999 + 1.0990618193318371e-16
+ddI[0] == strtod
+
+
+Input: 1.23456589e+20
+strtopdd consumes 14 bytes and returns 1
+dd[0] = 1.23456589e+20 = #441ac537 a660b997
+dd[1] = 4096 = #40b00000 0
+g_ddfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoIdd returns 1, consuming 14 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.23e+30
+strtopdd consumes 8 bytes and returns 1
+dd[0] = 1.23e+30 = #462f0cb0 4e8fb790
+dd[1] = 40281156091904 = #42c25158 0
+g_ddfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIdd returns 1, consuming 8 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1.23e-30
+strtopdd consumes 8 bytes and returns 17
+dd[0] = 1.2299999999999999e-30 = #39b8f286 6f5010aa
+dd[1] = 1.076909723013918e-46 = #3663ac7f 3dafd174
+g_ddfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIdd returns 17, consuming 8 bytes.
+ddI[0] = #39b8f286 6f5010aa + 3663ac7f 3dafd174
+= 1.2299999999999999e-30 + 1.076909723013918e-46
+ddI[1] = #39b8f286 6f5010aa + 3663ac7f 3dafd175
+= 1.2299999999999999e-30 + 1.0769097230139181e-46
+ddI[0] == strtod
+
+
+Input: 1.23456789e-20
+strtopdd consumes 14 bytes and returns 17
+dd[0] = 1.23456789e-20 = #3bcd2681 471e7ada
+dd[1] = 6.247111971663133e-37 = #386a9280 a761b07e
+g_ddfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoIdd returns 17, consuming 14 bytes.
+ddI[0] = #3bcd2681 471e7ada + 386a9280 a761b07e
+= 1.2345678899999999e-20 + 6.2471119716631328e-37
+ddI[1] = #3bcd2681 471e7ada + 386a9280 a761b080
+= 1.2345678899999999e-20 + 6.2471119716631345e-37
+ddI[0] == strtod
+
+
+Input: 1.23456789e-30
+strtopdd consumes 14 bytes and returns 33
+dd[0] = 1.23456789e-30 = #39b90a3e 33bbd995
+dd[1] = 2.1567930523648577e-47 = #363f8585 55a6b1a0
+g_ddfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoIdd returns 33, consuming 14 bytes.
+ddI[0] = #39b90a3e 33bbd995 + 363f8585 55a6b198
+= 1.23456789e-30 + 2.1567930523648558e-47
+ddI[1] = #39b90a3e 33bbd995 + 363f8585 55a6b1a0
+= 1.23456789e-30 + 2.1567930523648577e-47
+ddI[1] == strtod
+
+
+Input: 1.234567890123456789
+strtopdd consumes 20 bytes and returns 33
+dd[0] = 1.2345678901234567 = #3ff3c0ca 428c59fb
+dd[1] = 9.856786452588859e-17 = #3c9c6906 51a3745e
+g_ddfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIdd returns 33, consuming 20 bytes.
+ddI[0] = #3ff3c0ca 428c59fb + 3c9c6906 51a3745c
+= 1.2345678901234567 + 9.8567864525888563e-17
+ddI[1] = #3ff3c0ca 428c59fb + 3c9c6906 51a3745e
+= 1.2345678901234567 + 9.8567864525888588e-17
+ddI[1] == strtod
+
+
+Input: 1.23456789012345678901234567890123456789
+strtopdd consumes 40 bytes and returns 33
+dd[0] = 1.2345678901234567 = #3ff3c0ca 428c59fb
+dd[1] = 9.858021020478982e-17 = #3c9c69ef 85adadb6
+g_ddfmt(0) gives 34 bytes: "1.23456789012345678901234567890124"
+
+strtoIdd returns 33, consuming 40 bytes.
+ddI[0] = #3ff3c0ca 428c59fb + 3c9c69ef 85adadb4
+= 1.2345678901234567 + 9.8580210204789798e-17
+ddI[1] = #3ff3c0ca 428c59fb + 3c9c69ef 85adadb6
+= 1.2345678901234567 + 9.8580210204789823e-17
+ddI[1] == strtod
+
+
+Input: 1.23e306
+strtopdd consumes 8 bytes and returns 33
+dd[0] = 1.2299999999999999e+306 = #7f7c0676 cd1c61f4
+dd[1] = 1.3319001448659015e+290 = #7c2b558b e3d3f477
+g_ddfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoIdd returns 33, consuming 8 bytes.
+ddI[0] = #7f7c0676 cd1c61f4 + 7c2b558b e3d3f476
+= 1.2299999999999999e+306 + 1.3319001448659013e+290
+ddI[1] = #7f7c0676 cd1c61f4 + 7c2b558b e3d3f477
+= 1.2299999999999999e+306 + 1.3319001448659015e+290
+ddI[1] == strtod
+
+
+Input: 1.23e-306
+strtopdd consumes 9 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 9 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
+
+Input: 1.23e-320
+strtopdd consumes 9 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 9 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
+
+Input: 1.23e-20
+strtopdd consumes 8 bytes and returns 33
+dd[0] = 1.2299999999999999e-20 = #3bcd0ae4 cf767530
+dd[1] = 9.304023318521521e-37 = #3873c997 955b2691
+g_ddfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIdd returns 33, consuming 8 bytes.
+ddI[0] = #3bcd0ae4 cf767530 + 3873c997 955b2690
+= 1.2299999999999999e-20 + 9.3040233185215194e-37
+ddI[1] = #3bcd0ae4 cf767530 + 3873c997 955b2691
+= 1.2299999999999999e-20 + 9.3040233185215211e-37
+ddI[1] == strtod
+
+
+Input: 1.23456789e307
+strtopdd consumes 14 bytes and returns 33
+dd[0] = 1.2345678899999998e+307 = #7fb194b1 4bdaecdb
+dd[1] = 2.0137933598720243e+291 = #7c69d48d 192048ca
+g_ddfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoIdd returns 33, consuming 14 bytes.
+ddI[0] = #7fb194b1 4bdaecdb + 7c69d48d 192048c9
+= 1.2345678899999998e+307 + 2.013793359872024e+291
+ddI[1] = #7fb194b1 4bdaecdb + 7c69d48d 192048ca
+= 1.2345678899999998e+307 + 2.0137933598720243e+291
+ddI[1] == strtod
+
+
+Input: 1.23456589e-307
+strtopdd consumes 15 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 15 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
+
+Input: 1.234567890123456789
+strtopdd consumes 20 bytes and returns 33
+dd[0] = 1.2345678901234567 = #3ff3c0ca 428c59fb
+dd[1] = 9.856786452588859e-17 = #3c9c6906 51a3745e
+g_ddfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIdd returns 33, consuming 20 bytes.
+ddI[0] = #3ff3c0ca 428c59fb + 3c9c6906 51a3745c
+= 1.2345678901234567 + 9.8567864525888563e-17
+ddI[1] = #3ff3c0ca 428c59fb + 3c9c6906 51a3745e
+= 1.2345678901234567 + 9.8567864525888588e-17
+ddI[1] == strtod
+
+
+Input: 1.234567890123456789e301
+strtopdd consumes 24 bytes and returns 33
+dd[0] = 1.2345678901234568e+301 = #7e726f51 75f56413
+dd[1] = 1.3892003943918827e+283 = #7ab7ea80 76399100
+g_ddfmt(0) gives 25 bytes: "1.234567890123456789e+301"
+
+strtoIdd returns 33, consuming 24 bytes.
+ddI[0] = #7e726f51 75f56413 + 7ab7ea80 76399080
+= 1.2345678901234568e+301 + 1.3892003943918563e+283
+ddI[1] = #7e726f51 75f56413 + 7ab7ea80 76399100
+= 1.2345678901234568e+301 + 1.3892003943918827e+283
+ddI[1] == strtod
+
+
+Input: 1.234567890123456789e-301
+strtopdd consumes 25 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 25 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
+
+Input: 1.234567890123456789e-321
+strtopdd consumes 25 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 25 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
+
+Input: 1e23
+strtopdd consumes 4 bytes and returns 1
+dd[0] = 1e+23 = #44b52d02 c7e14af6
+dd[1] = 8388608 = #41600000 0
+g_ddfmt(0) gives 5 bytes: "1e+23"
+
+strtoIdd returns 1, consuming 4 bytes.
+ddI[0] == ddI[1] == strtopdd
+
+
+Input: 1e310
+strtopdd consumes 5 bytes and returns 163
+dd[0] = Infinity = #7ff00000 0
+dd[1] = Infinity = #7ff00000 0
+g_ddfmt(0) gives 8 bytes: "Infinity"
+
+strtoIdd returns 163, consuming 5 bytes.
+ddI[0] = #7fefffff ffffffff + 7c9fffff ffffffff
+= 1.7976931348623157e+308 + 1.9958403095347196e+292
+ddI[1] = #7ff00000 0 + 7ff00000 0
+= Infinity + Infinity
+ddI[1] == strtod
+
+
+Input: 9.0259718793241475e-277
+strtopdd consumes 23 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 23 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
+
+Input: 9.025971879324147880346310405869e-277
+strtopdd consumes 37 bytes and returns 17
+dd[0] = 9.025971879324148e-277 = #6a00000 0
+dd[1] = 2.2250738585072014e-308 = #100000 0
+g_ddfmt(0) gives 37 bytes: "9.025971879324147880346310405869e-277"
+
+strtoIdd returns 17, consuming 37 bytes.
+ddI[0] = #6a00000 0 + 100000 0
+= 9.0259718793241479e-277 + 2.2250738585072014e-308
+ddI[1] = #6a00000 0 + 200000 0
+= 9.0259718793241479e-277 + 4.4501477170144028e-308
+ddI[0] == strtod
+
+
+Input: 9.025971879324147880346310405868e-277
+strtopdd consumes 37 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 37 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
+
+Input: 2.2250738585072014e-308
+strtopdd consumes 23 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 23 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
+
+Input: 2.2250738585072013e-308
+strtopdd consumes 23 bytes and returns 80
+dd[0] = 0 = #0 0
+dd[1] = 0 = #0 0
+g_ddfmt(0) gives 1 bytes: "0"
+
+strtoIdd returns 80, consuming 23 bytes.
+ddI[0] = #0 0 + 0 0
+= 0 + 0
+ddI[1] = #6a00000 0 + 0 0
+= 9.0259718793241479e-277 + 0
+ddI[0] == strtod
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/ddtest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/ddtest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/ddtest.c	(revision 2448)
@@ -0,0 +1,183 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* Test program for g_ddfmt, strtoIdd, strtopdd, and strtordd.
+ *
+ * Inputs (on stdin):
+ *		r rounding_mode
+ *		n ndig
+ *		number
+ *		#hex0 hex1 hex2 hex3
+ *
+ *	rounding_mode values:
+ *		0 = toward zero
+ *		1 = nearest
+ *		2 = toward +Infinity
+ *		3 = toward -Infinity
+ *
+ * where number is a decimal floating-point number,
+ * hex0 is a string of <= 8 Hex digits for the most significant
+ * word of the number, hex1 is a similar string for the next
+ * word, etc., and ndig is a parameters to g_ddfmt.
+ */
+
+#include "gdtoaimp.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+ extern int getround ANSI((int,char*));
+
+ static char ibuf[2048], obuf[1024];
+
+#define U (unsigned long)
+
+ static void
+#ifdef KR_headers
+dprint(what, d) char *what; double d;
+#else
+dprint(char *what, double d)
+#endif
+{
+	char buf[32];
+	ULong *L = (ULong*)&d;
+
+	g_dfmt(buf,&d,0,sizeof(buf));
+	printf("%s = %s = #%lx %lx\n", what, buf, U L[_0], U L[_1]);
+	}
+
+ int
+main(Void)
+{
+	ULong *L;
+	char *s, *s1, *se, *se1;
+	int dItry, i, j, r = 1, ndig = 0;
+	double dd[2], ddI[4];
+	long LL[4];
+
+	L = (ULong*)&dd[0];
+	while( (s = fgets(ibuf, sizeof(ibuf), stdin)) !=0) {
+		while(*s <= ' ')
+			if (!*s++)
+				continue;
+		dItry = 0;
+		switch(*s) {
+		  case 'r':
+			r = getround(r, s);
+			continue;
+		  case 'n':
+			i = s[1];
+			if (i <= ' ' || i >= '0' && i <= '9') {
+				ndig = atoi(s+1);
+				continue;
+				}
+			break; /* nan? */
+		  case '#':
+			LL[0] = L[_0];
+			LL[1] = L[_1];
+			LL[2] = L[2+_0];
+			LL[3] = L[2+_1];
+			sscanf(s+1, "%lx %lx %lx %lx", &LL[0], &LL[1],
+				&LL[2], &LL[3]);
+			L[_0] = LL[0];
+			L[_1] = LL[1];
+			L[2+_0] = LL[2];
+			L[2+_1] = LL[3];
+			printf("\nInput: %s", ibuf);
+			printf(" --> f = #%lx %lx %lx %lx\n",
+				LL[0],LL[1],LL[2],LL[3]);
+			goto fmt_test;
+			}
+		printf("\nInput: %s", ibuf);
+		for(s1 = s; *s1 > ' '; s1++){};
+		while(*s1 <= ' ' && *s1) s1++;
+		if (!*s1) {
+			dItry = 1;
+			i = strtordd(ibuf, &se, r, dd);
+			if (r == 1) {
+				j = strtopdd(ibuf, &se1, ddI);
+				if (i != j || dd[0] != ddI[0]
+				 || dd[1] != ddI[1] || se != se1)
+					printf("***strtopdd and strtordd disagree!!\n:");
+				}
+			printf("strtopdd consumes %d bytes and returns %d\n",
+				(int)(se-ibuf), i);
+			}
+		else {
+			dd[0] = strtod(s, &se);
+			dd[1] = strtod(se, &se);
+			}
+ fmt_test:
+		dprint("dd[0]", dd[0]);
+		dprint("dd[1]", dd[1]);
+		se = g_ddfmt(obuf, dd, ndig, sizeof(obuf));
+		printf("g_ddfmt(%d) gives %d bytes: \"%s\"\n\n",
+			ndig, (int)(se-obuf), se ? obuf : "<null>");
+		if (!dItry)
+			continue;
+		printf("strtoIdd returns %d,", strtoIdd(ibuf, &se, ddI,&ddI[2]));
+		printf(" consuming %d bytes.\n", (int)(se-ibuf));
+		if (ddI[0] == ddI[2] && ddI[1] == ddI[3]) {
+			if (ddI[0] == dd[0] && ddI[1] == dd[1])
+				printf("ddI[0] == ddI[1] == strtopdd\n");
+			else
+				printf("ddI[0] == ddI[1] = #%lx %lx + %lx %lx\n= %.17g + %17.g\n",
+					U ((ULong*)ddI)[_0],
+					U ((ULong*)ddI)[_1],
+					U ((ULong*)ddI)[2+_0],
+					U ((ULong*)ddI)[2+_1],
+					ddI[0], ddI[1]);
+			}
+		else {
+			printf("ddI[0] = #%lx %lx + %lx %lx\n= %.17g + %.17g\n",
+				U ((ULong*)ddI)[_0], U ((ULong*)ddI)[_1],
+				U ((ULong*)ddI)[2+_0], U ((ULong*)ddI)[2+_1],
+				ddI[0], ddI[1]);
+			printf("ddI[1] = #%lx %lx + %lx %lx\n= %.17g + %.17g\n",
+				U ((ULong*)ddI)[4+_0], U ((ULong*)ddI)[4+_1],
+				U ((ULong*)ddI)[6+_0], U ((ULong*)ddI)[6+_1],
+				ddI[2], ddI[3]);
+			if (ddI[0] == dd[0] && ddI[1] == dd[1])
+				printf("ddI[0] == strtod\n");
+			else if (ddI[2] == dd[0] && ddI[3] == dd[1])
+				printf("ddI[1] == strtod\n");
+			else
+				printf("**** Both differ from strtopdd ****\n");
+			}
+		printf("\n");
+		}
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/dt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/dt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/dt.c	(revision 2448)
@@ -0,0 +1,275 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* Test program for strtod and dtoa.
+ *
+ * Inputs (on stdin):
+ *		number[: mode [ndigits]]
+ * or
+ *		#hex0 hex1[: mode [ndigits]]
+ * where number is a decimal floating-point number,
+ * hex0 is a string of Hex digits for the most significant
+ * word of the number, hex1 is a similar string for the other
+ * (least significant) word, and mode and ndigits are
+ * parameters to dtoa.
+ */
+
+#include <stdio.h>
+#include "gdtoa.h"
+#ifdef KR_headers
+#define Void /*void*/
+#else
+#define Void void
+#endif
+
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#ifdef __cplusplus
+extern "C" double atof(const char*);
+#else
+extern double atof ANSI((char*));
+#endif
+#endif
+#ifdef IEEE_8087
+#define word0(x) ((ULong *)&x)[1]
+#define word1(x) ((ULong *)&x)[0]
+#else
+#define word0(x) ((ULong *)&x)[0]
+#define word1(x) ((ULong *)&x)[1]
+#endif
+#include "errno.h"
+
+#ifdef __cplusplus
+extern "C" char *dtoa(double, int, int, int*, int*, char **);
+#else
+extern char *dtoa ANSI((double, int, int, int*, int*, char **));
+#endif
+
+ static void
+#ifdef KR_headers
+g_fmt(b, x) char *b; double x;
+#else
+g_fmt(char *b, double x)
+#endif
+{
+	char *s, *se;
+	int decpt, i, j, k, sign;
+
+	if (!x) {
+		*b++ = '0';
+		*b = 0;
+		return;
+		}
+	s = dtoa(x, 0, 0, &decpt, &sign, &se);
+	if (sign)
+		*b++ = '-';
+	if (decpt == 9999) /* Infinity or Nan */ {
+		while(*b++ = *s++);
+		return;
+		}
+	if (decpt <= -4 || decpt > se - s + 5) {
+		*b++ = *s++;
+		if (*s) {
+			*b++ = '.';
+			while(*b = *s++)
+				b++;
+			}
+		*b++ = 'e';
+		/* sprintf(b, "%+.2d", decpt - 1); */
+		if (--decpt < 0) {
+			*b++ = '-';
+			decpt = -decpt;
+			}
+		else
+			*b++ = '+';
+		for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){};
+		for(;;) {
+			i = decpt / k;
+			*b++ = i + '0';
+			if (--j <= 0)
+				break;
+			decpt -= i*k;
+			decpt *= 10;
+			}
+		*b = 0;
+		}
+	else if (decpt <= 0) {
+		*b++ = '.';
+		for(; decpt < 0; decpt++)
+			*b++ = '0';
+		while(*b++ = *s++);
+		}
+	else {
+		while(*b = *s++) {
+			b++;
+			if (--decpt == 0 && *s)
+				*b++ = '.';
+			}
+		for(; decpt > 0; decpt--)
+			*b++ = '0';
+		*b = 0;
+		}
+	}
+
+ static void
+baderrno(Void)
+{
+	fflush(stdout);
+	perror("\nerrno strtod");
+	fflush(stderr);
+	}
+
+#define U (unsigned long)
+
+ static void
+#ifdef KR_headers
+check(d) double d;
+#else
+check(double d)
+#endif
+{
+	char buf[64];
+	int decpt, sign;
+	char *s, *se;
+	double d1;
+
+	s = dtoa(d, 0, 0, &decpt, &sign, &se);
+	sprintf(buf, "%s.%se%d", sign ? "-" : "", s, decpt);
+	errno = 0;
+	d1 = strtod(buf, (char **)0);
+	if (errno)
+		baderrno();
+	if (d != d1) {
+		printf("sent d = %.17g = 0x%lx %lx, buf = %s\n",
+			d, U word0(d), U word1(d), buf);
+		printf("got d1 = %.17g = 0x%lx %lx\n",
+			d1, U word0(d1), U word1(d1));
+		}
+	}
+
+main(Void){
+	char buf[2048], buf1[32];
+	char *fmt, *s, *se;
+	double d, d1;
+	int decpt, sign;
+	int mode = 0, ndigits = 17;
+	ULong x, y;
+#ifdef VAX
+	ULong z;
+#endif
+
+	while(fgets(buf, sizeof(buf), stdin)) {
+		if (*buf == '*') {
+			printf("%s", buf);
+			continue;
+			}
+		printf("Input: %s", buf);
+		if (*buf == '#') {
+			x = word0(d);
+			y = word1(d);
+			sscanf(buf+1, "%lx %lx:%d %d", &x, &y, &mode, &ndigits);
+			word0(d) = x;
+			word1(d) = y;
+			fmt = "Output: d =\n%.17g = 0x%lx %lx\n";
+			}
+		else {
+			errno = 0;
+			d = strtod(buf,&se);
+			if (*se == ':')
+				sscanf(se+1,"%d %d", &mode, &ndigits);
+			d1 = atof(buf);
+			fmt = "Output: d =\n%.17g = 0x%lx %lx, se = %s";
+			if (errno)
+				baderrno();
+			}
+		printf(fmt, d, U word0(d), U word1(d), se);
+		g_fmt(buf1, d);
+		printf("\tg_fmt gives \"%s\"\n", buf1);
+		if (*buf != '#' && d != d1)
+			printf("atof gives\n\
+	d1 = %.17g = 0x%lx %lx\nversus\n\
+	d  = %.17g = 0x%lx %lx\n", d1, U word0(d1), U word1(d1),
+				d, U word0(d), U word1(d));
+		check(d);
+		s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
+		printf("\tdtoa(mode = %d, ndigits = %d):\n", mode, ndigits);
+		printf("\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
+			sign, decpt, se-s, s);
+		x = word1(d);
+		if (x != 0xffffffff
+		 && (word0(d) & 0x7ff00000) != 0x7ff00000) {
+#ifdef VAX
+			z = x << 16 | x >> 16;
+			z++;
+			z = z << 16 | z >> 16;
+			word1(d) = z;
+#else
+			word1(d) = x + 1;
+#endif
+			printf("\tnextafter(d,+Inf) = %.17g = 0x%lx %lx:\n",
+				d, U word0(d), U word1(d));
+			g_fmt(buf1, d);
+			printf("\tg_fmt gives \"%s\"\n", buf1);
+			s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
+			printf(
+		"\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
+				sign, decpt, se-s, s);
+			check(d);
+			}
+		if (x) {
+#ifdef VAX
+			z = x << 16 | x >> 16;
+			z--;
+			z = z << 16 | z >> 16;
+			word1(d) = z;
+#else
+			word1(d) = x - 1;
+#endif
+			printf("\tnextafter(d,-Inf) = %.17g = 0x%lx %lx:\n",
+				d, U word0(d), U word1(d));
+			g_fmt(buf1, d);
+			printf("\tg_fmt gives \"%s\"\n", buf1);
+			s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
+			printf(
+		"\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
+				sign, decpt, se-s, s);
+			check(d);
+			}
+		}
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/dtest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/dtest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/dtest.c	(revision 2448)
@@ -0,0 +1,146 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* Test program for g_dfmt, strtoId, strtod, strtopd, and strtord.
+ *
+ * Inputs (on stdin):
+ *		r rounding_mode
+ *		n ndig
+ *		number
+ *		#hex0 hex1
+ *
+ *	rounding_mode values:
+ *		0 = toward zero
+ *		1 = nearest
+ *		2 = toward +Infinity
+ *		3 = toward -Infinity
+ *
+ * where number is a decimal floating-point number,
+ * hex0 is a string of Hex <= 8 digits for the most significant
+ * word of the number, hex1 is a similar string for the other
+ * (least significant) word, and ndig is a parameters to g_dfmt.
+ */
+
+#include "gdtoaimp.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+ extern int getround ANSI((int,char*));
+
+ static char ibuf[2048], obuf[1024];
+
+#define U (unsigned long)
+
+ int
+main(Void)
+{
+	ULong *L;
+	char *s, *se, *se1;
+	double f, f1, fI[2];
+	int i, i1, ndig = 0, r = 1;
+	long LL[2];
+
+	L = (ULong*)&f;
+	while( (s = fgets(ibuf, sizeof(ibuf), stdin)) !=0) {
+		while(*s <= ' ')
+			if (!*s++)
+				continue;
+		switch(*s) {
+		  case 'r':
+			r = getround(r, s);
+			continue;
+		  case 'n':
+			i = s[1];
+			if (i <= ' ' || i >= '0' && i <= '9') {
+				ndig = atoi(s+1);
+				continue;
+				}
+			break; /* nan? */
+		  case '#':
+			LL[0] = L[_0];
+			LL[1] = L[_1];
+			sscanf(s+1, "%lx %lx", &LL[0], &LL[1]);
+			L[_0] = LL[0];
+			L[_1] = LL[1];
+			printf("\nInput: %s", ibuf);
+			printf("--> f = #%lx %lx\n", (long)L[_0], (long)L[_1]);
+			goto fmt_test;
+			}
+		printf("\nInput: %s", ibuf);
+		i = strtord(ibuf, &se, r, &f);
+		if (r == 1) {
+			if ((f != strtod(ibuf, &se1) || se1 != se))
+				printf("***strtod and strtord disagree!!\n");
+			i1 = strtopd(ibuf, &se, &f1);
+			if (i != i1 || f != f1 || se != se1)
+				printf("***strtord and strtopd disagree!!\n");
+			}
+		printf("strtod consumes %d bytes and returns %d with f = %.17g = #%lx %lx\n",
+				(int)(se-ibuf), i, f, U L[_0], U L[_1]);
+ fmt_test:
+		se = g_dfmt(obuf, &f, ndig, sizeof(obuf));
+		printf("g_dfmt(%d) gives %d bytes: \"%s\"\n\n",
+			ndig, (int)(se-obuf), se ? obuf : "<null>");
+		if (*s == '#')
+			continue;
+		printf("strtoId returns %d,", strtoId(ibuf, &se, fI, &fI[1]));
+		printf(" consuming %d bytes.\n", (int)(se-ibuf));
+		if (fI[0] == fI[1]) {
+			if (fI[0] == f)
+				printf("fI[0] == fI[1] == strtod\n");
+			else
+				printf("fI[0] == fI[1] = #%lx %lx = %.17g\n",
+					U ((ULong*)fI)[_0], U ((ULong*)fI)[_1],
+					fI[0]);
+			}
+		else {
+			printf("fI[0] = #%lx %lx = %.17g\n",
+				U ((ULong*)fI)[_0], U ((ULong*)fI)[_1], fI[0]);
+			printf("fI[1] = #%lx %lx = %.17g\n",
+				U ((ULong*)&fI[1])[_0], U ((ULong*)&fI[1])[_1],
+				fI[1]);
+			if (fI[0] == f)
+				printf("fI[0] == strtod\n");
+			else if (fI[1] == f)
+				printf("fI[1] == strtod\n");
+			else
+				printf("**** Both differ from strtod ****\n");
+			}
+		printf("\n");
+		}
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/dtst.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/dtst.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/dtst.out	(revision 2448)
@@ -0,0 +1,686 @@
+Input: 1.23
+Output: d =
+1.23 = 0x3ff3ae14 7ae147ae, se = 
+	g_fmt gives "1.23"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 1, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002 = 0x3ff3ae14 7ae147af:
+	g_fmt gives "1.2300000000000002"
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12300000000000002
+	nextafter(d,-Inf) = 1.2299999999999998 = 0x3ff3ae14 7ae147ad:
+	g_fmt gives "1.2299999999999998"
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12299999999999998
+Input: 1.23e+20
+Output: d =
+1.23e+20 = 0x441aabdf 2145b430, se = 
+	g_fmt gives "1.23e+20"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 21, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e+20 = 0x441aabdf 2145b431:
+	g_fmt gives "123000000000000020000"
+	dtoa returns sign = 0, decpt = 21, 17 digits:
+12300000000000002
+	nextafter(d,-Inf) = 1.2299999999999998e+20 = 0x441aabdf 2145b42f:
+	g_fmt gives "122999999999999980000"
+	dtoa returns sign = 0, decpt = 21, 17 digits:
+12299999999999998
+Input: 1.23e-20
+Output: d =
+1.2300000000000001e-20 = 0x3bcd0ae4 cf767531, se = 
+	g_fmt gives "1.23e-20"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -19, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e-20 = 0x3bcd0ae4 cf767532:
+	g_fmt gives "1.2300000000000002e-20"
+	dtoa returns sign = 0, decpt = -19, 17 digits:
+12300000000000002
+	nextafter(d,-Inf) = 1.2299999999999999e-20 = 0x3bcd0ae4 cf767530:
+	g_fmt gives "1.2299999999999999e-20"
+	dtoa returns sign = 0, decpt = -19, 17 digits:
+12299999999999999
+Input: 1.23456789
+Output: d =
+1.2345678899999999 = 0x3ff3c0ca 4283de1b, se = 
+	g_fmt gives "1.23456789"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 1, 9 digits:
+123456789
+	nextafter(d,+Inf) = 1.2345678900000001 = 0x3ff3c0ca 4283de1c:
+	g_fmt gives "1.2345678900000001"
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12345678900000001
+	nextafter(d,-Inf) = 1.2345678899999997 = 0x3ff3c0ca 4283de1a:
+	g_fmt gives "1.2345678899999997"
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12345678899999997
+Input: 1.23456589e+20
+Output: d =
+1.23456589e+20 = 0x441ac537 a660b997, se = 
+	g_fmt gives "1.23456589e+20"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 21, 9 digits:
+123456589
+	nextafter(d,+Inf) = 1.2345658900000001e+20 = 0x441ac537 a660b998:
+	g_fmt gives "123456589000000010000"
+	dtoa returns sign = 0, decpt = 21, 17 digits:
+12345658900000001
+	nextafter(d,-Inf) = 1.2345658899999998e+20 = 0x441ac537 a660b996:
+	g_fmt gives "123456588999999980000"
+	dtoa returns sign = 0, decpt = 21, 17 digits:
+12345658899999998
+Input: 1.23e+30
+Output: d =
+1.23e+30 = 0x462f0cb0 4e8fb790, se = 
+	g_fmt gives "1.23e+30"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 31, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000001e+30 = 0x462f0cb0 4e8fb791:
+	g_fmt gives "1.2300000000000001e+30"
+	dtoa returns sign = 0, decpt = 31, 17 digits:
+12300000000000001
+	nextafter(d,-Inf) = 1.2299999999999998e+30 = 0x462f0cb0 4e8fb78f:
+	g_fmt gives "1.2299999999999998e+30"
+	dtoa returns sign = 0, decpt = 31, 17 digits:
+12299999999999998
+Input: 1.23e-30
+Output: d =
+1.2300000000000001e-30 = 0x39b8f286 6f5010ab, se = 
+	g_fmt gives "1.23e-30"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -29, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e-30 = 0x39b8f286 6f5010ac:
+	g_fmt gives "1.2300000000000002e-30"
+	dtoa returns sign = 0, decpt = -29, 17 digits:
+12300000000000002
+	nextafter(d,-Inf) = 1.2299999999999999e-30 = 0x39b8f286 6f5010aa:
+	g_fmt gives "1.2299999999999999e-30"
+	dtoa returns sign = 0, decpt = -29, 17 digits:
+12299999999999999
+Input: 1.23456789e-20
+Output: d =
+1.2345678899999999e-20 = 0x3bcd2681 471e7ada, se = 
+	g_fmt gives "1.23456789e-20"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -19, 9 digits:
+123456789
+	nextafter(d,+Inf) = 1.2345678900000001e-20 = 0x3bcd2681 471e7adb:
+	g_fmt gives "1.2345678900000001e-20"
+	dtoa returns sign = 0, decpt = -19, 17 digits:
+12345678900000001
+	nextafter(d,-Inf) = 1.2345678899999998e-20 = 0x3bcd2681 471e7ad9:
+	g_fmt gives "1.2345678899999998e-20"
+	dtoa returns sign = 0, decpt = -19, 17 digits:
+12345678899999998
+Input: 1.23456789e-30
+Output: d =
+1.23456789e-30 = 0x39b90a3e 33bbd995, se = 
+	g_fmt gives "1.23456789e-30"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -29, 9 digits:
+123456789
+	nextafter(d,+Inf) = 1.2345678900000002e-30 = 0x39b90a3e 33bbd996:
+	g_fmt gives "1.2345678900000002e-30"
+	dtoa returns sign = 0, decpt = -29, 17 digits:
+12345678900000002
+	nextafter(d,-Inf) = 1.2345678899999998e-30 = 0x39b90a3e 33bbd994:
+	g_fmt gives "1.2345678899999998e-30"
+	dtoa returns sign = 0, decpt = -29, 17 digits:
+12345678899999998
+Input: 1.234567890123456789
+Output: d =
+1.2345678901234567 = 0x3ff3c0ca 428c59fb, se = 
+	g_fmt gives "1.2345678901234567"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12345678901234567
+	nextafter(d,+Inf) = 1.2345678901234569 = 0x3ff3c0ca 428c59fc:
+	g_fmt gives "1.234567890123457"
+	dtoa returns sign = 0, decpt = 1, 16 digits:
+1234567890123457
+	nextafter(d,-Inf) = 1.2345678901234565 = 0x3ff3c0ca 428c59fa:
+	g_fmt gives "1.2345678901234565"
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12345678901234565
+Input: 1.23456789012345678901234567890123456789
+Output: d =
+1.2345678901234567 = 0x3ff3c0ca 428c59fb, se = 
+	g_fmt gives "1.2345678901234567"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12345678901234567
+	nextafter(d,+Inf) = 1.2345678901234569 = 0x3ff3c0ca 428c59fc:
+	g_fmt gives "1.234567890123457"
+	dtoa returns sign = 0, decpt = 1, 16 digits:
+1234567890123457
+	nextafter(d,-Inf) = 1.2345678901234565 = 0x3ff3c0ca 428c59fa:
+	g_fmt gives "1.2345678901234565"
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12345678901234565
+Input: 1.23e306
+Output: d =
+1.23e+306 = 0x7f7c0676 cd1c61f5, se = 
+	g_fmt gives "1.23e+306"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 307, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e+306 = 0x7f7c0676 cd1c61f6:
+	g_fmt gives "1.2300000000000002e+306"
+	dtoa returns sign = 0, decpt = 307, 17 digits:
+12300000000000002
+	nextafter(d,-Inf) = 1.2299999999999999e+306 = 0x7f7c0676 cd1c61f4:
+	g_fmt gives "1.2299999999999999e+306"
+	dtoa returns sign = 0, decpt = 307, 17 digits:
+12299999999999999
+Input: 1.23e-306
+Output: d =
+1.23e-306 = 0x6ba3b8 5da396e8, se = 
+	g_fmt gives "1.23e-306"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -305, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e-306 = 0x6ba3b8 5da396e9:
+	g_fmt gives "1.2300000000000002e-306"
+	dtoa returns sign = 0, decpt = -305, 17 digits:
+12300000000000002
+	nextafter(d,-Inf) = 1.2299999999999999e-306 = 0x6ba3b8 5da396e7:
+	g_fmt gives "1.2299999999999999e-306"
+	dtoa returns sign = 0, decpt = -305, 17 digits:
+12299999999999999
+Input: 1.23e-320
+Output: d =
+1.2302234581447039e-320 = 0x0 9ba, se = 
+	g_fmt gives "1.23e-320"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -319, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2307175237905451e-320 = 0x0 9bb:
+	g_fmt gives "1.2307e-320"
+	dtoa returns sign = 0, decpt = -319, 5 digits:
+12307
+	nextafter(d,-Inf) = 1.2297293924988626e-320 = 0x0 9b9:
+	g_fmt gives "1.2297e-320"
+	dtoa returns sign = 0, decpt = -319, 5 digits:
+12297
+Input: 1.23e-20
+Output: d =
+1.2300000000000001e-20 = 0x3bcd0ae4 cf767531, se = 
+	g_fmt gives "1.23e-20"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -19, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e-20 = 0x3bcd0ae4 cf767532:
+	g_fmt gives "1.2300000000000002e-20"
+	dtoa returns sign = 0, decpt = -19, 17 digits:
+12300000000000002
+	nextafter(d,-Inf) = 1.2299999999999999e-20 = 0x3bcd0ae4 cf767530:
+	g_fmt gives "1.2299999999999999e-20"
+	dtoa returns sign = 0, decpt = -19, 17 digits:
+12299999999999999
+Input: 1.23456789e307
+Output: d =
+1.23456789e+307 = 0x7fb194b1 4bdaecdc, se = 
+	g_fmt gives "1.23456789e+307"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 308, 9 digits:
+123456789
+	nextafter(d,+Inf) = 1.2345678900000003e+307 = 0x7fb194b1 4bdaecdd:
+	g_fmt gives "1.2345678900000003e+307"
+	dtoa returns sign = 0, decpt = 308, 17 digits:
+12345678900000003
+	nextafter(d,-Inf) = 1.2345678899999998e+307 = 0x7fb194b1 4bdaecdb:
+	g_fmt gives "1.2345678899999998e+307"
+	dtoa returns sign = 0, decpt = 308, 17 digits:
+12345678899999998
+Input: 1.23456589e-307
+Output: d =
+1.2345658899999999e-307 = 0x363196 bb9845fa, se = 
+	g_fmt gives "1.23456589e-307"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -306, 9 digits:
+123456589
+	nextafter(d,+Inf) = 1.2345658900000001e-307 = 0x363196 bb9845fb:
+	g_fmt gives "1.2345658900000001e-307"
+	dtoa returns sign = 0, decpt = -306, 17 digits:
+12345658900000001
+	nextafter(d,-Inf) = 1.2345658899999997e-307 = 0x363196 bb9845f9:
+	g_fmt gives "1.2345658899999997e-307"
+	dtoa returns sign = 0, decpt = -306, 17 digits:
+12345658899999997
+Input: 1.234567890123456789
+Output: d =
+1.2345678901234567 = 0x3ff3c0ca 428c59fb, se = 
+	g_fmt gives "1.2345678901234567"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12345678901234567
+	nextafter(d,+Inf) = 1.2345678901234569 = 0x3ff3c0ca 428c59fc:
+	g_fmt gives "1.234567890123457"
+	dtoa returns sign = 0, decpt = 1, 16 digits:
+1234567890123457
+	nextafter(d,-Inf) = 1.2345678901234565 = 0x3ff3c0ca 428c59fa:
+	g_fmt gives "1.2345678901234565"
+	dtoa returns sign = 0, decpt = 1, 17 digits:
+12345678901234565
+Input: 1.234567890123456789e301
+Output: d =
+1.2345678901234568e+301 = 0x7e726f51 75f56413, se = 
+	g_fmt gives "1.2345678901234568e+301"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 302, 17 digits:
+12345678901234568
+	nextafter(d,+Inf) = 1.234567890123457e+301 = 0x7e726f51 75f56414:
+	g_fmt gives "1.234567890123457e+301"
+	dtoa returns sign = 0, decpt = 302, 16 digits:
+1234567890123457
+	nextafter(d,-Inf) = 1.2345678901234565e+301 = 0x7e726f51 75f56412:
+	g_fmt gives "1.2345678901234565e+301"
+	dtoa returns sign = 0, decpt = 302, 17 digits:
+12345678901234565
+Input: 1.234567890123456789e-301
+Output: d =
+1.2345678901234567e-301 = 0x1752a64 e34ba0d3, se = 
+	g_fmt gives "1.2345678901234567e-301"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -300, 17 digits:
+12345678901234567
+	nextafter(d,+Inf) = 1.2345678901234569e-301 = 0x1752a64 e34ba0d4:
+	g_fmt gives "1.234567890123457e-301"
+	dtoa returns sign = 0, decpt = -300, 16 digits:
+1234567890123457
+	nextafter(d,-Inf) = 1.2345678901234565e-301 = 0x1752a64 e34ba0d2:
+	g_fmt gives "1.2345678901234565e-301"
+	dtoa returns sign = 0, decpt = -300, 17 digits:
+12345678901234565
+Input: 1.234567890123456789e-321
+Output: d =
+1.2351641146031164e-321 = 0x0 fa, se = 
+	g_fmt gives "1.235e-321"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -320, 4 digits:
+1235
+	nextafter(d,+Inf) = 1.2401047710615288e-321 = 0x0 fb:
+	g_fmt gives "1.24e-321"
+	dtoa returns sign = 0, decpt = -320, 3 digits:
+124
+	nextafter(d,-Inf) = 1.2302234581447039e-321 = 0x0 f9:
+	g_fmt gives "1.23e-321"
+	dtoa returns sign = 0, decpt = -320, 3 digits:
+123
+Input: 1e23
+Output: d =
+9.9999999999999992e+22 = 0x44b52d02 c7e14af6, se = 
+	g_fmt gives "1e+23"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 24, 1 digits:
+1
+	nextafter(d,+Inf) = 1.0000000000000001e+23 = 0x44b52d02 c7e14af7:
+	g_fmt gives "1.0000000000000001e+23"
+	dtoa returns sign = 0, decpt = 24, 17 digits:
+10000000000000001
+	nextafter(d,-Inf) = 9.9999999999999975e+22 = 0x44b52d02 c7e14af5:
+	g_fmt gives "9.999999999999997e+22"
+	dtoa returns sign = 0, decpt = 23, 16 digits:
+9999999999999997
+Input: 1e310
+
+errno strtod: Result too large
+Output: d =
+Infinity = 0x7ff00000 0, se = 
+	g_fmt gives "Infinity"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = 9999, 8 digits:
+Infinity
+Input: 9.0259718793241475e-277
+Output: d =
+9.0259718793241479e-277 = 0x6a00000 0, se = 
+	g_fmt gives "9.025971879324148e-277"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -276, 16 digits:
+9025971879324148
+	nextafter(d,+Inf) = 9.0259718793241499e-277 = 0x6a00000 1:
+	g_fmt gives "9.02597187932415e-277"
+	dtoa returns sign = 0, decpt = -276, 15 digits:
+902597187932415
+Input: 9.025971879324147880346310405869e-277
+Output: d =
+9.0259718793241479e-277 = 0x6a00000 0, se = 
+	g_fmt gives "9.025971879324148e-277"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -276, 16 digits:
+9025971879324148
+	nextafter(d,+Inf) = 9.0259718793241499e-277 = 0x6a00000 1:
+	g_fmt gives "9.02597187932415e-277"
+	dtoa returns sign = 0, decpt = -276, 15 digits:
+902597187932415
+Input: 9.025971879324147880346310405868e-277
+Output: d =
+9.0259718793241479e-277 = 0x6a00000 0, se = 
+	g_fmt gives "9.025971879324148e-277"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -276, 16 digits:
+9025971879324148
+	nextafter(d,+Inf) = 9.0259718793241499e-277 = 0x6a00000 1:
+	g_fmt gives "9.02597187932415e-277"
+	dtoa returns sign = 0, decpt = -276, 15 digits:
+902597187932415
+Input: 2.2250738585072014e-308
+Output: d =
+2.2250738585072014e-308 = 0x100000 0, se = 
+	g_fmt gives "2.2250738585072014e-308"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -307, 17 digits:
+22250738585072014
+	nextafter(d,+Inf) = 2.2250738585072019e-308 = 0x100000 1:
+	g_fmt gives "2.225073858507202e-308"
+	dtoa returns sign = 0, decpt = -307, 16 digits:
+2225073858507202
+Input: 2.2250738585072013e-308
+Output: d =
+2.2250738585072014e-308 = 0x100000 0, se = 
+	g_fmt gives "2.2250738585072014e-308"
+	dtoa(mode = 0, ndigits = 17):
+	dtoa returns sign = 0, decpt = -307, 17 digits:
+22250738585072014
+	nextafter(d,+Inf) = 2.2250738585072019e-308 = 0x100000 1:
+	g_fmt gives "2.225073858507202e-308"
+	dtoa returns sign = 0, decpt = -307, 16 digits:
+2225073858507202
+Input: 1.23:2 6
+Output: d =
+1.23 = 0x3ff3ae14 7ae147ae, se = :2 6
+	g_fmt gives "1.23"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = 1, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002 = 0x3ff3ae14 7ae147af:
+	g_fmt gives "1.2300000000000002"
+	dtoa returns sign = 0, decpt = 1, 3 digits:
+123
+	nextafter(d,-Inf) = 1.2299999999999998 = 0x3ff3ae14 7ae147ad:
+	g_fmt gives "1.2299999999999998"
+	dtoa returns sign = 0, decpt = 1, 3 digits:
+123
+Input: 1.23:4 6
+Output: d =
+1.23 = 0x3ff3ae14 7ae147ae, se = :4 6
+	g_fmt gives "1.23"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = 1, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002 = 0x3ff3ae14 7ae147af:
+	g_fmt gives "1.2300000000000002"
+	dtoa returns sign = 0, decpt = 1, 3 digits:
+123
+	nextafter(d,-Inf) = 1.2299999999999998 = 0x3ff3ae14 7ae147ad:
+	g_fmt gives "1.2299999999999998"
+	dtoa returns sign = 0, decpt = 1, 3 digits:
+123
+Input: 1.23e+20:2 6
+Output: d =
+1.23e+20 = 0x441aabdf 2145b430, se = :2 6
+	g_fmt gives "1.23e+20"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = 21, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e+20 = 0x441aabdf 2145b431:
+	g_fmt gives "123000000000000020000"
+	dtoa returns sign = 0, decpt = 21, 3 digits:
+123
+	nextafter(d,-Inf) = 1.2299999999999998e+20 = 0x441aabdf 2145b42f:
+	g_fmt gives "122999999999999980000"
+	dtoa returns sign = 0, decpt = 21, 3 digits:
+123
+Input: 1.23e+20:4 6
+Output: d =
+1.23e+20 = 0x441aabdf 2145b430, se = :4 6
+	g_fmt gives "1.23e+20"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = 21, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e+20 = 0x441aabdf 2145b431:
+	g_fmt gives "123000000000000020000"
+	dtoa returns sign = 0, decpt = 21, 3 digits:
+123
+	nextafter(d,-Inf) = 1.2299999999999998e+20 = 0x441aabdf 2145b42f:
+	g_fmt gives "122999999999999980000"
+	dtoa returns sign = 0, decpt = 21, 3 digits:
+123
+Input: 1.23e-20:2 6
+Output: d =
+1.2300000000000001e-20 = 0x3bcd0ae4 cf767531, se = :2 6
+	g_fmt gives "1.23e-20"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = -19, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e-20 = 0x3bcd0ae4 cf767532:
+	g_fmt gives "1.2300000000000002e-20"
+	dtoa returns sign = 0, decpt = -19, 3 digits:
+123
+	nextafter(d,-Inf) = 1.2299999999999999e-20 = 0x3bcd0ae4 cf767530:
+	g_fmt gives "1.2299999999999999e-20"
+	dtoa returns sign = 0, decpt = -19, 3 digits:
+123
+Input: 1.23e-20:4 6
+Output: d =
+1.2300000000000001e-20 = 0x3bcd0ae4 cf767531, se = :4 6
+	g_fmt gives "1.23e-20"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = -19, 3 digits:
+123
+	nextafter(d,+Inf) = 1.2300000000000002e-20 = 0x3bcd0ae4 cf767532:
+	g_fmt gives "1.2300000000000002e-20"
+	dtoa returns sign = 0, decpt = -19, 3 digits:
+123
+	nextafter(d,-Inf) = 1.2299999999999999e-20 = 0x3bcd0ae4 cf767530:
+	g_fmt gives "1.2299999999999999e-20"
+	dtoa returns sign = 0, decpt = -19, 3 digits:
+123
+Input: 1.23456789:2 6
+Output: d =
+1.2345678899999999 = 0x3ff3c0ca 4283de1b, se = :2 6
+	g_fmt gives "1.23456789"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123457
+	nextafter(d,+Inf) = 1.2345678900000001 = 0x3ff3c0ca 4283de1c:
+	g_fmt gives "1.2345678900000001"
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345678899999997 = 0x3ff3c0ca 4283de1a:
+	g_fmt gives "1.2345678899999997"
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123457
+Input: 1.23456789:4 6
+Output: d =
+1.2345678899999999 = 0x3ff3c0ca 4283de1b, se = :4 6
+	g_fmt gives "1.23456789"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123457
+	nextafter(d,+Inf) = 1.2345678900000001 = 0x3ff3c0ca 4283de1c:
+	g_fmt gives "1.2345678900000001"
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345678899999997 = 0x3ff3c0ca 4283de1a:
+	g_fmt gives "1.2345678899999997"
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123457
+Input: 1.23456589e+20:2 6
+Output: d =
+1.23456589e+20 = 0x441ac537 a660b997, se = :2 6
+	g_fmt gives "1.23456589e+20"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123457
+	nextafter(d,+Inf) = 1.2345658900000001e+20 = 0x441ac537 a660b998:
+	g_fmt gives "123456589000000010000"
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345658899999998e+20 = 0x441ac537 a660b996:
+	g_fmt gives "123456588999999980000"
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123457
+Input: 1.23456589e+20:4 6
+Output: d =
+1.23456589e+20 = 0x441ac537 a660b997, se = :4 6
+	g_fmt gives "1.23456589e+20"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123457
+	nextafter(d,+Inf) = 1.2345658900000001e+20 = 0x441ac537 a660b998:
+	g_fmt gives "123456589000000010000"
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345658899999998e+20 = 0x441ac537 a660b996:
+	g_fmt gives "123456588999999980000"
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123457
+Input: 1.23456789e-20:2 6
+Output: d =
+1.2345678899999999e-20 = 0x3bcd2681 471e7ada, se = :2 6
+	g_fmt gives "1.23456789e-20"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123457
+	nextafter(d,+Inf) = 1.2345678900000001e-20 = 0x3bcd2681 471e7adb:
+	g_fmt gives "1.2345678900000001e-20"
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345678899999998e-20 = 0x3bcd2681 471e7ad9:
+	g_fmt gives "1.2345678899999998e-20"
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123457
+Input: 1.23456789e-20:4 6
+Output: d =
+1.2345678899999999e-20 = 0x3bcd2681 471e7ada, se = :4 6
+	g_fmt gives "1.23456789e-20"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123457
+	nextafter(d,+Inf) = 1.2345678900000001e-20 = 0x3bcd2681 471e7adb:
+	g_fmt gives "1.2345678900000001e-20"
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345678899999998e-20 = 0x3bcd2681 471e7ad9:
+	g_fmt gives "1.2345678899999998e-20"
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123457
+Input: 1234565:2 6
+Output: d =
+1234565 = 0x4132d685 0, se = :2 6
+	g_fmt gives "1234565"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = 7, 6 digits:
+123456
+	nextafter(d,+Inf) = 1234565.0000000002 = 0x4132d685 1:
+	g_fmt gives "1234565.0000000002"
+	dtoa returns sign = 0, decpt = 7, 6 digits:
+123457
+Input: 1234565:4 6
+Output: d =
+1234565 = 0x4132d685 0, se = :4 6
+	g_fmt gives "1234565"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = 7, 6 digits:
+123456
+	nextafter(d,+Inf) = 1234565.0000000002 = 0x4132d685 1:
+	g_fmt gives "1234565.0000000002"
+	dtoa returns sign = 0, decpt = 7, 6 digits:
+123457
+Input: 1.234565:2 6
+Output: d =
+1.2345649999999999 = 0x3ff3c0c7 3abc9470, se = :2 6
+	g_fmt gives "1.234565"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123456
+	nextafter(d,+Inf) = 1.2345650000000001 = 0x3ff3c0c7 3abc9471:
+	g_fmt gives "1.2345650000000001"
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345649999999997 = 0x3ff3c0c7 3abc946f:
+	g_fmt gives "1.2345649999999997"
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123456
+Input: 1.234565:4 6
+Output: d =
+1.2345649999999999 = 0x3ff3c0c7 3abc9470, se = :4 6
+	g_fmt gives "1.234565"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123456
+	nextafter(d,+Inf) = 1.2345650000000001 = 0x3ff3c0c7 3abc9471:
+	g_fmt gives "1.2345650000000001"
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345649999999997 = 0x3ff3c0c7 3abc946f:
+	g_fmt gives "1.2345649999999997"
+	dtoa returns sign = 0, decpt = 1, 6 digits:
+123456
+Input: 1.234565e+20:2 6
+Output: d =
+1.234565e+20 = 0x441ac536 6299040d, se = :2 6
+	g_fmt gives "1.234565e+20"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123456
+	nextafter(d,+Inf) = 1.2345650000000002e+20 = 0x441ac536 6299040e:
+	g_fmt gives "123456500000000020000"
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345649999999998e+20 = 0x441ac536 6299040c:
+	g_fmt gives "123456499999999980000"
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123456
+Input: 1.234565e+20:4 6
+Output: d =
+1.234565e+20 = 0x441ac536 6299040d, se = :4 6
+	g_fmt gives "1.234565e+20"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123456
+	nextafter(d,+Inf) = 1.2345650000000002e+20 = 0x441ac536 6299040e:
+	g_fmt gives "123456500000000020000"
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345649999999998e+20 = 0x441ac536 6299040c:
+	g_fmt gives "123456499999999980000"
+	dtoa returns sign = 0, decpt = 21, 6 digits:
+123456
+Input: 1.234565e-20:2 6
+Output: d =
+1.234565e-20 = 0x3bcd267c ce45a93f, se = :2 6
+	g_fmt gives "1.234565e-20"
+	dtoa(mode = 2, ndigits = 6):
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123456
+	nextafter(d,+Inf) = 1.2345650000000001e-20 = 0x3bcd267c ce45a940:
+	g_fmt gives "1.2345650000000001e-20"
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345649999999998e-20 = 0x3bcd267c ce45a93e:
+	g_fmt gives "1.2345649999999998e-20"
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123456
+Input: 1.234565e-20:4 6
+Output: d =
+1.234565e-20 = 0x3bcd267c ce45a93f, se = :4 6
+	g_fmt gives "1.234565e-20"
+	dtoa(mode = 4, ndigits = 6):
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123456
+	nextafter(d,+Inf) = 1.2345650000000001e-20 = 0x3bcd267c ce45a940:
+	g_fmt gives "1.2345650000000001e-20"
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123457
+	nextafter(d,-Inf) = 1.2345649999999998e-20 = 0x3bcd267c ce45a93e:
+	g_fmt gives "1.2345649999999998e-20"
+	dtoa returns sign = 0, decpt = -19, 6 digits:
+123456
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/f.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/f.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/f.out	(revision 2448)
@@ -0,0 +1,968 @@
+
+Input: 1.23
+strtof consumes 4 bytes and returns 1.23 = #3f9d70a4
+g_ffmt(0) gives 4 bytes: "1.23"
+
+strtoIf returns 33, consuming 4 bytes.
+fI[0] = #3f9d70a3 = 1.2299999
+fI[1] = #3f9d70a4 = 1.23
+fI[1] == strtof
+
+
+Input: 1.23e+20
+strtof consumes 8 bytes and returns 1.23e+20 = #60d55ef9
+g_ffmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIf returns 17, consuming 8 bytes.
+fI[0] = #60d55ef9 = 1.23e+20
+fI[1] = #60d55efa = 1.2300001e+20
+fI[0] == strtof
+
+
+Input: 1.23e-20
+strtof consumes 8 bytes and returns 1.23e-20 = #1e685726
+g_ffmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIf returns 17, consuming 8 bytes.
+fI[0] = #1e685726 = 1.23e-20
+fI[1] = #1e685727 = 1.23e-20
+fI[0] == strtof
+
+
+Input: 1.23456789
+strtof consumes 10 bytes and returns 1.2345679 = #3f9e0652
+g_ffmt(0) gives 9 bytes: "1.2345679"
+
+strtoIf returns 17, consuming 10 bytes.
+fI[0] = #3f9e0652 = 1.2345679
+fI[1] = #3f9e0653 = 1.234568
+fI[0] == strtof
+
+
+Input: 1.23456589e+20
+strtof consumes 14 bytes and returns 1.2345659e+20 = #60d629bd
+g_ffmt(0) gives 13 bytes: "1.2345659e+20"
+
+strtoIf returns 17, consuming 14 bytes.
+fI[0] = #60d629bd = 1.2345659e+20
+fI[1] = #60d629be = 1.234566e+20
+fI[0] == strtof
+
+
+Input: 1.23e+30
+strtof consumes 8 bytes and returns 1.23e+30 = #71786582
+g_ffmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIf returns 17, consuming 8 bytes.
+fI[0] = #71786582 = 1.23e+30
+fI[1] = #71786583 = 1.23e+30
+fI[0] == strtof
+
+
+Input: 1.23e-30
+strtof consumes 8 bytes and returns 1.23e-30 = #dc79433
+g_ffmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIf returns 17, consuming 8 bytes.
+fI[0] = #dc79433 = 1.23e-30
+fI[1] = #dc79434 = 1.23e-30
+fI[0] == strtof
+
+
+Input: 1.23456789e-20
+strtof consumes 14 bytes and returns 1.2345679e-20 = #1e69340a
+g_ffmt(0) gives 13 bytes: "1.2345679e-20"
+
+strtoIf returns 17, consuming 14 bytes.
+fI[0] = #1e69340a = 1.2345679e-20
+fI[1] = #1e69340b = 1.234568e-20
+fI[0] == strtof
+
+
+Input: 1.23456789e-30
+strtof consumes 14 bytes and returns 1.2345679e-30 = #dc851f2
+g_ffmt(0) gives 13 bytes: "1.2345679e-30"
+
+strtoIf returns 33, consuming 14 bytes.
+fI[0] = #dc851f1 = 1.2345678e-30
+fI[1] = #dc851f2 = 1.2345679e-30
+fI[1] == strtof
+
+
+Input: 1.234567890123456789
+strtof consumes 20 bytes and returns 1.2345679 = #3f9e0652
+g_ffmt(0) gives 9 bytes: "1.2345679"
+
+strtoIf returns 17, consuming 20 bytes.
+fI[0] = #3f9e0652 = 1.2345679
+fI[1] = #3f9e0653 = 1.234568
+fI[0] == strtof
+
+
+Input: 1.23456789012345678901234567890123456789
+strtof consumes 40 bytes and returns 1.2345679 = #3f9e0652
+g_ffmt(0) gives 9 bytes: "1.2345679"
+
+strtoIf returns 17, consuming 40 bytes.
+fI[0] = #3f9e0652 = 1.2345679
+fI[1] = #3f9e0653 = 1.234568
+fI[0] == strtof
+
+
+Input: 1.23e306
+strtof consumes 8 bytes and returns Infinity = #7f800000
+g_ffmt(0) gives 8 bytes: "Infinity"
+
+strtoIf returns 163, consuming 8 bytes.
+fI[0] = #7f7fffff = 3.4028235e+38
+fI[1] = #7f800000 = Infinity
+fI[1] == strtof
+
+
+Input: 1.23e-306
+strtof consumes 9 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 9 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1.23e-320
+strtof consumes 9 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 9 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1.23e-20
+strtof consumes 8 bytes and returns 1.23e-20 = #1e685726
+g_ffmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIf returns 17, consuming 8 bytes.
+fI[0] = #1e685726 = 1.23e-20
+fI[1] = #1e685727 = 1.23e-20
+fI[0] == strtof
+
+
+Input: 1.23456789e307
+strtof consumes 14 bytes and returns Infinity = #7f800000
+g_ffmt(0) gives 8 bytes: "Infinity"
+
+strtoIf returns 163, consuming 14 bytes.
+fI[0] = #7f7fffff = 3.4028235e+38
+fI[1] = #7f800000 = Infinity
+fI[1] == strtof
+
+
+Input: 1.23456589e-307
+strtof consumes 15 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 15 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1.234567890123456789
+strtof consumes 20 bytes and returns 1.2345679 = #3f9e0652
+g_ffmt(0) gives 9 bytes: "1.2345679"
+
+strtoIf returns 17, consuming 20 bytes.
+fI[0] = #3f9e0652 = 1.2345679
+fI[1] = #3f9e0653 = 1.234568
+fI[0] == strtof
+
+
+Input: 1.234567890123456789e301
+strtof consumes 24 bytes and returns Infinity = #7f800000
+g_ffmt(0) gives 8 bytes: "Infinity"
+
+strtoIf returns 163, consuming 24 bytes.
+fI[0] = #7f7fffff = 3.4028235e+38
+fI[1] = #7f800000 = Infinity
+fI[1] == strtof
+
+
+Input: 1.234567890123456789e-301
+strtof consumes 25 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 25 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1.234567890123456789e-321
+strtof consumes 25 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 25 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1e23
+strtof consumes 4 bytes and returns 9.9999998e+22 = #65a96816
+g_ffmt(0) gives 5 bytes: "1e+23"
+
+strtoIf returns 17, consuming 4 bytes.
+fI[0] = #65a96816 = 9.9999998e+22
+fI[1] = #65a96817 = 1.0000001e+23
+fI[0] == strtof
+
+
+Input: 1e310
+strtof consumes 5 bytes and returns Infinity = #7f800000
+g_ffmt(0) gives 8 bytes: "Infinity"
+
+strtoIf returns 163, consuming 5 bytes.
+fI[0] = #7f7fffff = 3.4028235e+38
+fI[1] = #7f800000 = Infinity
+fI[1] == strtof
+
+
+Input: 9.0259718793241475e-277
+strtof consumes 23 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 23 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 9.025971879324147880346310405869e-277
+strtof consumes 37 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 37 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 9.025971879324147880346310405868e-277
+strtof consumes 37 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 37 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 2.2250738585072014e-308
+strtof consumes 23 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 23 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 2.2250738585072013e-308
+strtof consumes 23 bytes and returns 0 = #0
+g_ffmt(0) gives 1 bytes: "0"
+
+strtoIf returns 80, consuming 23 bytes.
+fI[0] == fI[1] == strtof
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+strtof consumes 3 bytes and returns 1.0999999 = #3f8ccccc
+g_ffmt(0) gives 9 bytes: "1.0999999"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3f8ccccc = 1.0999999
+fI[1] = #3f8ccccd = 1.1
+fI[0] == strtof
+
+
+Input: -1.1
+strtof consumes 4 bytes and returns -1.0999999 = #bf8ccccc
+g_ffmt(0) gives 10 bytes: "-1.0999999"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bf8ccccd = -1.1
+fI[1] = #bf8ccccc = -1.0999999
+fI[1] == strtof
+
+
+Input: 1.2
+strtof consumes 3 bytes and returns 1.1999999 = #3f999999
+g_ffmt(0) gives 9 bytes: "1.1999999"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3f999999 = 1.1999999
+fI[1] = #3f99999a = 1.2
+fI[0] == strtof
+
+
+Input: -1.2
+strtof consumes 4 bytes and returns -1.1999999 = #bf999999
+g_ffmt(0) gives 10 bytes: "-1.1999999"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bf99999a = -1.2
+fI[1] = #bf999999 = -1.1999999
+fI[1] == strtof
+
+
+Input: 1.3
+strtof consumes 3 bytes and returns 1.3 = #3fa66666
+g_ffmt(0) gives 3 bytes: "1.3"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fa66666 = 1.3
+fI[1] = #3fa66667 = 1.3000001
+fI[0] == strtof
+
+
+Input: -1.3
+strtof consumes 4 bytes and returns -1.3 = #bfa66666
+g_ffmt(0) gives 4 bytes: "-1.3"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfa66667 = -1.3000001
+fI[1] = #bfa66666 = -1.3
+fI[1] == strtof
+
+
+Input: 1.4
+strtof consumes 3 bytes and returns 1.4 = #3fb33333
+g_ffmt(0) gives 3 bytes: "1.4"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fb33333 = 1.4
+fI[1] = #3fb33334 = 1.4000001
+fI[0] == strtof
+
+
+Input: -1.4
+strtof consumes 4 bytes and returns -1.4 = #bfb33333
+g_ffmt(0) gives 4 bytes: "-1.4"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfb33334 = -1.4000001
+fI[1] = #bfb33333 = -1.4
+fI[1] == strtof
+
+
+Input: 1.5
+strtof consumes 3 bytes and returns 1.5 = #3fc00000
+g_ffmt(0) gives 3 bytes: "1.5"
+
+strtoIf returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: -1.5
+strtof consumes 4 bytes and returns -1.5 = #bfc00000
+g_ffmt(0) gives 4 bytes: "-1.5"
+
+strtoIf returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1.6
+strtof consumes 3 bytes and returns 1.5999999 = #3fcccccc
+g_ffmt(0) gives 9 bytes: "1.5999999"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3fcccccc = 1.5999999
+fI[1] = #3fcccccd = 1.6
+fI[0] == strtof
+
+
+Input: -1.6
+strtof consumes 4 bytes and returns -1.5999999 = #bfcccccc
+g_ffmt(0) gives 10 bytes: "-1.5999999"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bfcccccd = -1.6
+fI[1] = #bfcccccc = -1.5999999
+fI[1] == strtof
+
+
+Input: 1.7
+strtof consumes 3 bytes and returns 1.6999999 = #3fd99999
+g_ffmt(0) gives 9 bytes: "1.6999999"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3fd99999 = 1.6999999
+fI[1] = #3fd9999a = 1.7
+fI[0] == strtof
+
+
+Input: -1.7
+strtof consumes 4 bytes and returns -1.6999999 = #bfd99999
+g_ffmt(0) gives 10 bytes: "-1.6999999"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bfd9999a = -1.7
+fI[1] = #bfd99999 = -1.6999999
+fI[1] == strtof
+
+
+Input: 1.8
+strtof consumes 3 bytes and returns 1.8 = #3fe66666
+g_ffmt(0) gives 3 bytes: "1.8"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fe66666 = 1.8
+fI[1] = #3fe66667 = 1.8000001
+fI[0] == strtof
+
+
+Input: -1.8
+strtof consumes 4 bytes and returns -1.8 = #bfe66666
+g_ffmt(0) gives 4 bytes: "-1.8"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfe66667 = -1.8000001
+fI[1] = #bfe66666 = -1.8
+fI[1] == strtof
+
+
+Input: 1.9
+strtof consumes 3 bytes and returns 1.9 = #3ff33333
+g_ffmt(0) gives 3 bytes: "1.9"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3ff33333 = 1.9
+fI[1] = #3ff33334 = 1.9000001
+fI[0] == strtof
+
+
+Input: -1.9
+strtof consumes 4 bytes and returns -1.9 = #bff33333
+g_ffmt(0) gives 4 bytes: "-1.9"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bff33334 = -1.9000001
+fI[1] = #bff33333 = -1.9
+fI[1] == strtof
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+strtof consumes 3 bytes and returns 1.1 = #3f8ccccd
+g_ffmt(0) gives 3 bytes: "1.1"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3f8ccccc = 1.0999999
+fI[1] = #3f8ccccd = 1.1
+fI[1] == strtof
+
+
+Input: -1.1
+strtof consumes 4 bytes and returns -1.1 = #bf8ccccd
+g_ffmt(0) gives 4 bytes: "-1.1"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bf8ccccd = -1.1
+fI[1] = #bf8ccccc = -1.0999999
+fI[0] == strtof
+
+
+Input: 1.2
+strtof consumes 3 bytes and returns 1.2 = #3f99999a
+g_ffmt(0) gives 3 bytes: "1.2"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3f999999 = 1.1999999
+fI[1] = #3f99999a = 1.2
+fI[1] == strtof
+
+
+Input: -1.2
+strtof consumes 4 bytes and returns -1.2 = #bf99999a
+g_ffmt(0) gives 4 bytes: "-1.2"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bf99999a = -1.2
+fI[1] = #bf999999 = -1.1999999
+fI[0] == strtof
+
+
+Input: 1.3
+strtof consumes 3 bytes and returns 1.3 = #3fa66666
+g_ffmt(0) gives 3 bytes: "1.3"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fa66666 = 1.3
+fI[1] = #3fa66667 = 1.3000001
+fI[0] == strtof
+
+
+Input: -1.3
+strtof consumes 4 bytes and returns -1.3 = #bfa66666
+g_ffmt(0) gives 4 bytes: "-1.3"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfa66667 = -1.3000001
+fI[1] = #bfa66666 = -1.3
+fI[1] == strtof
+
+
+Input: 1.4
+strtof consumes 3 bytes and returns 1.4 = #3fb33333
+g_ffmt(0) gives 3 bytes: "1.4"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fb33333 = 1.4
+fI[1] = #3fb33334 = 1.4000001
+fI[0] == strtof
+
+
+Input: -1.4
+strtof consumes 4 bytes and returns -1.4 = #bfb33333
+g_ffmt(0) gives 4 bytes: "-1.4"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfb33334 = -1.4000001
+fI[1] = #bfb33333 = -1.4
+fI[1] == strtof
+
+
+Input: 1.5
+strtof consumes 3 bytes and returns 1.5 = #3fc00000
+g_ffmt(0) gives 3 bytes: "1.5"
+
+strtoIf returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: -1.5
+strtof consumes 4 bytes and returns -1.5 = #bfc00000
+g_ffmt(0) gives 4 bytes: "-1.5"
+
+strtoIf returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1.6
+strtof consumes 3 bytes and returns 1.6 = #3fcccccd
+g_ffmt(0) gives 3 bytes: "1.6"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3fcccccc = 1.5999999
+fI[1] = #3fcccccd = 1.6
+fI[1] == strtof
+
+
+Input: -1.6
+strtof consumes 4 bytes and returns -1.6 = #bfcccccd
+g_ffmt(0) gives 4 bytes: "-1.6"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bfcccccd = -1.6
+fI[1] = #bfcccccc = -1.5999999
+fI[0] == strtof
+
+
+Input: 1.7
+strtof consumes 3 bytes and returns 1.7 = #3fd9999a
+g_ffmt(0) gives 3 bytes: "1.7"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3fd99999 = 1.6999999
+fI[1] = #3fd9999a = 1.7
+fI[1] == strtof
+
+
+Input: -1.7
+strtof consumes 4 bytes and returns -1.7 = #bfd9999a
+g_ffmt(0) gives 4 bytes: "-1.7"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bfd9999a = -1.7
+fI[1] = #bfd99999 = -1.6999999
+fI[0] == strtof
+
+
+Input: 1.8
+strtof consumes 3 bytes and returns 1.8 = #3fe66666
+g_ffmt(0) gives 3 bytes: "1.8"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fe66666 = 1.8
+fI[1] = #3fe66667 = 1.8000001
+fI[0] == strtof
+
+
+Input: -1.8
+strtof consumes 4 bytes and returns -1.8 = #bfe66666
+g_ffmt(0) gives 4 bytes: "-1.8"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfe66667 = -1.8000001
+fI[1] = #bfe66666 = -1.8
+fI[1] == strtof
+
+
+Input: 1.9
+strtof consumes 3 bytes and returns 1.9 = #3ff33333
+g_ffmt(0) gives 3 bytes: "1.9"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3ff33333 = 1.9
+fI[1] = #3ff33334 = 1.9000001
+fI[0] == strtof
+
+
+Input: -1.9
+strtof consumes 4 bytes and returns -1.9 = #bff33333
+g_ffmt(0) gives 4 bytes: "-1.9"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bff33334 = -1.9000001
+fI[1] = #bff33333 = -1.9
+fI[1] == strtof
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+strtof consumes 3 bytes and returns 1.1 = #3f8ccccd
+g_ffmt(0) gives 3 bytes: "1.1"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3f8ccccc = 1.0999999
+fI[1] = #3f8ccccd = 1.1
+fI[1] == strtof
+
+
+Input: -1.1
+strtof consumes 4 bytes and returns -1.0999999 = #bf8ccccc
+g_ffmt(0) gives 10 bytes: "-1.0999999"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bf8ccccd = -1.1
+fI[1] = #bf8ccccc = -1.0999999
+fI[1] == strtof
+
+
+Input: 1.2
+strtof consumes 3 bytes and returns 1.2 = #3f99999a
+g_ffmt(0) gives 3 bytes: "1.2"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3f999999 = 1.1999999
+fI[1] = #3f99999a = 1.2
+fI[1] == strtof
+
+
+Input: -1.2
+strtof consumes 4 bytes and returns -1.1999999 = #bf999999
+g_ffmt(0) gives 10 bytes: "-1.1999999"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bf99999a = -1.2
+fI[1] = #bf999999 = -1.1999999
+fI[1] == strtof
+
+
+Input: 1.3
+strtof consumes 3 bytes and returns 1.3000001 = #3fa66667
+g_ffmt(0) gives 9 bytes: "1.3000001"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fa66666 = 1.3
+fI[1] = #3fa66667 = 1.3000001
+fI[1] == strtof
+
+
+Input: -1.3
+strtof consumes 4 bytes and returns -1.3 = #bfa66666
+g_ffmt(0) gives 4 bytes: "-1.3"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfa66667 = -1.3000001
+fI[1] = #bfa66666 = -1.3
+fI[1] == strtof
+
+
+Input: 1.4
+strtof consumes 3 bytes and returns 1.4000001 = #3fb33334
+g_ffmt(0) gives 9 bytes: "1.4000001"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fb33333 = 1.4
+fI[1] = #3fb33334 = 1.4000001
+fI[1] == strtof
+
+
+Input: -1.4
+strtof consumes 4 bytes and returns -1.4 = #bfb33333
+g_ffmt(0) gives 4 bytes: "-1.4"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfb33334 = -1.4000001
+fI[1] = #bfb33333 = -1.4
+fI[1] == strtof
+
+
+Input: 1.5
+strtof consumes 3 bytes and returns 1.5 = #3fc00000
+g_ffmt(0) gives 3 bytes: "1.5"
+
+strtoIf returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: -1.5
+strtof consumes 4 bytes and returns -1.5 = #bfc00000
+g_ffmt(0) gives 4 bytes: "-1.5"
+
+strtoIf returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1.6
+strtof consumes 3 bytes and returns 1.6 = #3fcccccd
+g_ffmt(0) gives 3 bytes: "1.6"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3fcccccc = 1.5999999
+fI[1] = #3fcccccd = 1.6
+fI[1] == strtof
+
+
+Input: -1.6
+strtof consumes 4 bytes and returns -1.5999999 = #bfcccccc
+g_ffmt(0) gives 10 bytes: "-1.5999999"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bfcccccd = -1.6
+fI[1] = #bfcccccc = -1.5999999
+fI[1] == strtof
+
+
+Input: 1.7
+strtof consumes 3 bytes and returns 1.7 = #3fd9999a
+g_ffmt(0) gives 3 bytes: "1.7"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3fd99999 = 1.6999999
+fI[1] = #3fd9999a = 1.7
+fI[1] == strtof
+
+
+Input: -1.7
+strtof consumes 4 bytes and returns -1.6999999 = #bfd99999
+g_ffmt(0) gives 10 bytes: "-1.6999999"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bfd9999a = -1.7
+fI[1] = #bfd99999 = -1.6999999
+fI[1] == strtof
+
+
+Input: 1.8
+strtof consumes 3 bytes and returns 1.8000001 = #3fe66667
+g_ffmt(0) gives 9 bytes: "1.8000001"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fe66666 = 1.8
+fI[1] = #3fe66667 = 1.8000001
+fI[1] == strtof
+
+
+Input: -1.8
+strtof consumes 4 bytes and returns -1.8 = #bfe66666
+g_ffmt(0) gives 4 bytes: "-1.8"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfe66667 = -1.8000001
+fI[1] = #bfe66666 = -1.8
+fI[1] == strtof
+
+
+Input: 1.9
+strtof consumes 3 bytes and returns 1.9000001 = #3ff33334
+g_ffmt(0) gives 9 bytes: "1.9000001"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3ff33333 = 1.9
+fI[1] = #3ff33334 = 1.9000001
+fI[1] == strtof
+
+
+Input: -1.9
+strtof consumes 4 bytes and returns -1.9 = #bff33333
+g_ffmt(0) gives 4 bytes: "-1.9"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bff33334 = -1.9000001
+fI[1] = #bff33333 = -1.9
+fI[1] == strtof
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+strtof consumes 3 bytes and returns 1.0999999 = #3f8ccccc
+g_ffmt(0) gives 9 bytes: "1.0999999"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3f8ccccc = 1.0999999
+fI[1] = #3f8ccccd = 1.1
+fI[0] == strtof
+
+
+Input: -1.1
+strtof consumes 4 bytes and returns -1.1 = #bf8ccccd
+g_ffmt(0) gives 4 bytes: "-1.1"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bf8ccccd = -1.1
+fI[1] = #bf8ccccc = -1.0999999
+fI[0] == strtof
+
+
+Input: 1.2
+strtof consumes 3 bytes and returns 1.1999999 = #3f999999
+g_ffmt(0) gives 9 bytes: "1.1999999"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3f999999 = 1.1999999
+fI[1] = #3f99999a = 1.2
+fI[0] == strtof
+
+
+Input: -1.2
+strtof consumes 4 bytes and returns -1.2 = #bf99999a
+g_ffmt(0) gives 4 bytes: "-1.2"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bf99999a = -1.2
+fI[1] = #bf999999 = -1.1999999
+fI[0] == strtof
+
+
+Input: 1.3
+strtof consumes 3 bytes and returns 1.3 = #3fa66666
+g_ffmt(0) gives 3 bytes: "1.3"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fa66666 = 1.3
+fI[1] = #3fa66667 = 1.3000001
+fI[0] == strtof
+
+
+Input: -1.3
+strtof consumes 4 bytes and returns -1.3000001 = #bfa66667
+g_ffmt(0) gives 10 bytes: "-1.3000001"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfa66667 = -1.3000001
+fI[1] = #bfa66666 = -1.3
+fI[0] == strtof
+
+
+Input: 1.4
+strtof consumes 3 bytes and returns 1.4 = #3fb33333
+g_ffmt(0) gives 3 bytes: "1.4"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fb33333 = 1.4
+fI[1] = #3fb33334 = 1.4000001
+fI[0] == strtof
+
+
+Input: -1.4
+strtof consumes 4 bytes and returns -1.4000001 = #bfb33334
+g_ffmt(0) gives 10 bytes: "-1.4000001"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfb33334 = -1.4000001
+fI[1] = #bfb33333 = -1.4
+fI[0] == strtof
+
+
+Input: 1.5
+strtof consumes 3 bytes and returns 1.5 = #3fc00000
+g_ffmt(0) gives 3 bytes: "1.5"
+
+strtoIf returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: -1.5
+strtof consumes 4 bytes and returns -1.5 = #bfc00000
+g_ffmt(0) gives 4 bytes: "-1.5"
+
+strtoIf returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtof
+
+
+Input: 1.6
+strtof consumes 3 bytes and returns 1.5999999 = #3fcccccc
+g_ffmt(0) gives 9 bytes: "1.5999999"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3fcccccc = 1.5999999
+fI[1] = #3fcccccd = 1.6
+fI[0] == strtof
+
+
+Input: -1.6
+strtof consumes 4 bytes and returns -1.6 = #bfcccccd
+g_ffmt(0) gives 4 bytes: "-1.6"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bfcccccd = -1.6
+fI[1] = #bfcccccc = -1.5999999
+fI[0] == strtof
+
+
+Input: 1.7
+strtof consumes 3 bytes and returns 1.6999999 = #3fd99999
+g_ffmt(0) gives 9 bytes: "1.6999999"
+
+strtoIf returns 33, consuming 3 bytes.
+fI[0] = #3fd99999 = 1.6999999
+fI[1] = #3fd9999a = 1.7
+fI[0] == strtof
+
+
+Input: -1.7
+strtof consumes 4 bytes and returns -1.7 = #bfd9999a
+g_ffmt(0) gives 4 bytes: "-1.7"
+
+strtoIf returns 41, consuming 4 bytes.
+fI[0] = #bfd9999a = -1.7
+fI[1] = #bfd99999 = -1.6999999
+fI[0] == strtof
+
+
+Input: 1.8
+strtof consumes 3 bytes and returns 1.8 = #3fe66666
+g_ffmt(0) gives 3 bytes: "1.8"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3fe66666 = 1.8
+fI[1] = #3fe66667 = 1.8000001
+fI[0] == strtof
+
+
+Input: -1.8
+strtof consumes 4 bytes and returns -1.8000001 = #bfe66667
+g_ffmt(0) gives 10 bytes: "-1.8000001"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bfe66667 = -1.8000001
+fI[1] = #bfe66666 = -1.8
+fI[0] == strtof
+
+
+Input: 1.9
+strtof consumes 3 bytes and returns 1.9 = #3ff33333
+g_ffmt(0) gives 3 bytes: "1.9"
+
+strtoIf returns 17, consuming 3 bytes.
+fI[0] = #3ff33333 = 1.9
+fI[1] = #3ff33334 = 1.9000001
+fI[0] == strtof
+
+
+Input: -1.9
+strtof consumes 4 bytes and returns -1.9000001 = #bff33334
+g_ffmt(0) gives 10 bytes: "-1.9000001"
+
+strtoIf returns 25, consuming 4 bytes.
+fI[0] = #bff33334 = -1.9000001
+fI[1] = #bff33333 = -1.9
+fI[0] == strtof
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/ftest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/ftest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/ftest.c	(revision 2448)
@@ -0,0 +1,146 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* Test program for g_ffmt, strtof, strtoIf, strtopf, and strtorf.
+ *
+ * Inputs (on stdin):
+ *		r rounding_mode
+ *		n ndig
+ *		number
+ *		#hex
+ *
+ *	rounding_mode values:
+ *		0 = toward zero
+ *		1 = nearest
+ *		2 = toward +Infinity
+ *		3 = toward -Infinity
+ *
+ * where number is a decimal floating-point number,
+ * hex is a string of <= 8 Hex digits for the internal representation
+ * of the number, and ndig is a parameters to g_ffmt.
+ */
+
+#include "gdtoa.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+ extern int getround ANSI((int,char*));
+
+ static char ibuf[2048], obuf[1024];
+
+#define U (unsigned long)
+
+ int
+main(Void)
+{
+	ULong *L;
+	char *s, *se, *se1;
+	int dItry, i, i1, ndig = 0, r = 1;
+	float f, f1, fI[2];
+
+	L = (ULong*)&f;
+	while( (s = fgets(ibuf, sizeof(ibuf), stdin)) !=0) {
+		while(*s <= ' ')
+			if (!*s++)
+				continue;
+		dItry = 0;
+		switch(*s) {
+		  case 'r':
+			r = getround(r, s);
+			continue;
+		  case 'n':
+			i = s[1];
+			if (i <= ' ' || i >= '0' && i <= '9') {
+				ndig = atoi(s+1);
+				continue;
+				}
+			break; /* nan? */
+		  case '#':
+			sscanf(s+1, "%lx", &L[0]);
+			printf("\nInput: %s", ibuf);
+			printf(" --> f = #%lx\n", L[0]);
+			goto fmt_test;
+			}
+		dItry = 1;
+		printf("\nInput: %s", ibuf);
+		i = strtorf(ibuf, &se, r, &f);
+		if (r == 1) {
+		    if (f != (i1 = strtopf(ibuf, &se1, &f1), f1)
+				 || se != se1 || i != i1) {
+			printf("***strtopf and strtorf disagree!!\n");
+			if (f != f1)
+				printf("\tf1 = %g\n", (double)f1);
+			if (i != i1)
+				printf("\ti = %d but i1 = %d\n", i, i1);
+			if (se != se1)
+				printf("se - se1 = %d\n", (int)(se-se1));
+			}
+		    if (f != strtof(ibuf, &se1) || se != se1)
+			printf("***strtof and strtorf disagree!\n");
+		    }
+		printf("strtof consumes %d bytes and returns %.8g = #%lx\n",
+				(int)(se-ibuf), f, U *(ULong*)&f);
+ fmt_test:
+		se = g_ffmt(obuf, &f, ndig, sizeof(obuf));
+		printf("g_ffmt(%d) gives %d bytes: \"%s\"\n\n",
+			ndig, (int)(se-obuf), se ? obuf : "<null>");
+		if (!dItry)
+			continue;
+		printf("strtoIf returns %d,", strtoIf(ibuf, &se, fI, &fI[1]));
+		printf(" consuming %d bytes.\n", (int)(se-ibuf));
+		if (fI[0] == fI[1]) {
+			if (fI[0] == f)
+				printf("fI[0] == fI[1] == strtof\n");
+			else
+				printf("fI[0] == fI[1] = #%lx = %.8g\n",
+					U *(ULong*)fI, fI[0]);
+			}
+		else {
+			printf("fI[0] = #%lx = %.8g\nfI[1] = #%lx = %.8g\n",
+				U *(ULong*)fI, fI[0],
+				U *(ULong*)&fI[1], fI[1]);
+			if (fI[0] == f)
+				printf("fI[0] == strtof\n");
+			else if (fI[1] == f)
+				printf("fI[1] == strtof\n");
+			else
+				printf("**** Both differ from strtof ****\n");
+			}
+		printf("\n");
+		}
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/getround.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/getround.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/getround.c	(revision 2448)
@@ -0,0 +1,68 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static char *dir[4] = { "toward zero", "nearest", "toward +Infinity",
+			"toward -Infinity" };
+
+ int
+#ifdef KR_headers
+getround(r, s) int r; char *s;
+#else
+getround(int r, char *s)
+#endif
+{
+	int i;
+
+	i = atoi(s+1);
+	if (i >= 0 && i < 4) {
+		printf("Rounding mode for strtor... ");
+		if (i == r)
+			printf("was and is %d (%s)\n", i, dir[i]);
+		else
+			printf("changed from %d (%s) to %d (%s)\n",
+				r, dir[r], i, dir[i]);
+		return i;
+		}
+	printf("Bad rounding direction %d: choose among\n", i);
+	for(i = 0; i < 4; i++)
+		printf("\t%d (%s)\n", i, dir[i]);
+	printf("Leaving rounding mode for strtor... at %d (%s)\n", r, dir[r]);
+	return r;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/makefile
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/makefile	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/makefile	(revision 2448)
@@ -0,0 +1,135 @@
+# /****************************************************************
+# Copyright (C) 1998, 2000 by Lucent Technologies
+# All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appear in all
+# copies and that both that the copyright notice and this
+# permission notice and warranty disclaimer appear in supporting
+# documentation, and that the name of Lucent or any of its entities
+# not be used in advertising or publicity pertaining to
+# distribution of the software without specific, written prior
+# permission.
+#
+# LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+# IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+# THIS SOFTWARE.
+#
+# ****************************************************************/
+
+.SUFFIXES: .c .o
+CC = cc
+CFLAGS = -g -I..
+A = ../gdtoa.a
+
+.c.o:
+	$(CC) -c $(CFLAGS) $*.c
+
+all: dt dItest ddtest dtest ftest Qtest xLtest xtest ddtestsi dItestsi tests
+
+dt = dt.o $A
+dt: $(dt)
+	$(CC) -o dt $(dt)
+
+dItest = dItest.o getround.o $A
+dItest: $(dItest)
+	$(CC) -o dItest $(dItest)
+
+ddtest = ddtest.o getround.o $A
+ddtest: $(ddtest)
+	$(CC) -o ddtest $(ddtest)
+
+dtest = dtest.o getround.o $A
+dtest: $(dtest)
+	$(CC) -o dtest $(dtest)
+
+ftest = ftest.o getround.o $A
+ftest: $(ftest)
+	$(CC) -o ftest $(ftest)
+
+Qtest = Qtest.o getround.o $A
+Qtest: $(Qtest)
+	$(CC) -o Qtest $(Qtest)
+
+xtest = xtest.o getround.o $A
+xtest: $(xtest)
+	$(CC) -o xtest $(xtest)
+
+xLtest = xLtest.o getround.o $A
+xLtest: $(xLtest)
+	$(CC) -o xLtest $(xLtest)
+
+strtopddSI.o: strtopddSI.c ../strtopdd.c
+
+strtorddSI.o: strtorddSI.c ../strtordd.c
+
+strtodISI.o: strtodISI.c ../strtodI.c
+
+strtoIddSI.o: strtoIddSI.c ../strtoIdd.c
+
+strtoIdSI.o: strtoIdSI.c ../strtoId.c
+
+ddtestsi = ddtest.o strtopddSI.o strtorddSI.o strtoIddSI.o getround.o $A
+ddtestsi: $(ddtestsi)
+	$(CC) -o ddtestsi $(ddtestsi)
+
+dItestsi = dItest.o strtodISI.o strtoIdSI.o getround.o $A
+dItestsi: $(dItestsi)
+	$(CC) -o dItestsi $(dItestsi)
+
+strtodt = strtodt.o $A
+strtodt: $(strtodt)
+	$(CC) -o strtodt $(strtodt)
+
+# xQtest generates cp commands that depend on sizeof(long double).
+# See the source for details.  If you know better, create Q.out,
+# x.out and xL.out by copying the relevant *.ou0 or *.ou1 files
+# to the corresponding .out files.  In short, the *.ou0 files are
+# for long double == double; x.ou1 and xL.ou1 are for
+# long double == extended (a la 80x87 and MC680x0), and Q.ou1 is
+# for long double == quad.
+
+Q.out x.out xL.out:
+	$(CC) -o xQtest xQtest.c
+	./xQtest | sh
+	rm -f xQtest xQtest.o
+
+## The rmdir below will fail if any test results differ.
+
+tests: Q.out x.out xL.out dt dItest ddtest dtest ftest Qtest xLtest xtest ddtestsi dItestsi strtodt
+	mkdir bad
+	cat testnos testnos1 | ./dt >zap 2>&1
+	cmp dtst.out zap || mv zap bad/dtst.out
+	./dItest <testnos >zap 2>&1
+	cmp dI.out zap || mv zap bad/dI.out
+	./dItestsi <testnos >zap 2>&1
+	cmp dIsi.out zap || mv zap bad/dIsi.out
+	./ddtestsi <testnos >zap 2>&1
+	cmp ddsi.out zap || mv zap bad/ddsi.out
+	for i in dd d f x xL Q; do cat testnos rtestnos | \
+	 ./"$$i"test >zap 2>&1;\
+	cmp $$i.out zap || mv zap bad/$$i.out; done
+	./strtodt testnos3 >bad/strtodt.out && rm bad/strtodt.out || \
+		cat bad/strtodt.out
+	rmdir bad
+	touch tests
+
+xs0 = README Qtest.c dItest.c ddtest.c dtest.c dt.c ftest.c getround.c \
+	strtoIdSI.c strtoIddSI.c strtodISI.c strtodt.c strtopddSI.c \
+	strtorddSI.c xLtest.c xQtest.c xtest.c rtestnos testnos testnos1 \
+	testnos3 dI.out dIsi.out ddsi.out dd.out dtst.out d.out f.out \
+	x.ou0 xL.ou0 x.ou1 xL.ou1 Q.ou0 Q.ou1 makefile
+
+xsum.out: xsum0.out $(xs0)
+	xsum $(xs0) >xsum1.out
+	cmp xsum0.out xsum1.out && mv xsum1.out xsum.out || diff xsum[01].out
+
+clean:
+	rm -f *.[ao] dt *test *testsi strtodt xsum.out xsum1.out tests zap x.out xL.out Q.out
+	rm -rf bad
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/rtestnos
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/rtestnos	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/rtestnos	(revision 2448)
@@ -0,0 +1,76 @@
+r0
+1.1
+-1.1
+1.2
+-1.2
+1.3
+-1.3
+1.4
+-1.4
+1.5
+-1.5
+1.6
+-1.6
+1.7
+-1.7
+1.8
+-1.8
+1.9
+-1.9
+r1
+1.1
+-1.1
+1.2
+-1.2
+1.3
+-1.3
+1.4
+-1.4
+1.5
+-1.5
+1.6
+-1.6
+1.7
+-1.7
+1.8
+-1.8
+1.9
+-1.9
+r2
+1.1
+-1.1
+1.2
+-1.2
+1.3
+-1.3
+1.4
+-1.4
+1.5
+-1.5
+1.6
+-1.6
+1.7
+-1.7
+1.8
+-1.8
+1.9
+-1.9
+r3
+1.1
+-1.1
+1.2
+-1.2
+1.3
+-1.3
+1.4
+-1.4
+1.5
+-1.5
+1.6
+-1.6
+1.7
+-1.7
+1.8
+-1.8
+1.9
+-1.9
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/strtoIdSI.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/strtoIdSI.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/strtoIdSI.c	(revision 2448)
@@ -0,0 +1,2 @@
+#define Sudden_Underflow
+#include "../strtoId.c"
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/strtoIddSI.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/strtoIddSI.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/strtoIddSI.c	(revision 2448)
@@ -0,0 +1,2 @@
+#define Sudden_Underflow
+#include "../strtoIdd.c"
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/strtodISI.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/strtodISI.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/strtodISI.c	(revision 2448)
@@ -0,0 +1,2 @@
+#define Sudden_Underflow
+#include "../strtodI.c"
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/strtodt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/strtodt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/strtodt.c	(revision 2448)
@@ -0,0 +1,140 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* Test strtod.  */
+
+/* On stdin, read triples: d x y:
+ *	d = decimal string
+ *	x = high-order Hex value expected from strtod
+ *	y = low-order Hex value
+ * Complain about errors.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+ static int W0, W1;
+ typedef union {
+		double d;
+		long L[2];
+		} U;
+
+ static int
+process(char *fname, FILE *f)
+{
+	U a, b;
+	char buf[2048];
+	double d;
+	char *s;
+	int line, n;
+
+	line = n = 0;
+
+ top:
+	while(fgets(s = buf, sizeof(buf), f)) {
+		line++;
+		while(*s <= ' ')
+			if (!*s++)
+				goto top; /* break 2 */
+		if (*s == '#')
+			continue;
+		while(*s > ' ')
+			s++;
+		if (sscanf(s,"\t%lx\t%lx", &a.L[0], &a.L[1]) != 2) {
+			printf("Badly formatted line %d of %s\n",
+				line, fname);
+			n++;
+			continue;
+			}
+		b.d = strtod(buf,0);
+		if (b.L[W0] != a.L[0] || b.L[W1] != a.L[1]) {
+			n++;
+			printf("Line %d of %s: got %lx %lx; expected %lx %lx\n",
+				line, fname, b.L[W0], b.L[W1], a.L[0], a.L[1]);
+			}
+		}
+	return n;
+	}
+
+ int
+main(int argc, char **argv)
+{
+	FILE *f;
+	char *prog, *s;
+	int n, rc;
+	U u;
+
+	prog = argv[0];
+	if (argc == 2 && !strcmp(argv[1],"-?")) {
+		fprintf(stderr, "Usage: %s [file [file...]]\n"
+			"\tto read data file(s) of tab-separated triples d x y with\n"
+			"\t\td decimal string\n"
+			"\t\tx = high-order Hex value expected from strtod\n"
+			"\t\ty = low-order Hex value\n"
+			"\tComplain about errors by strtod.\n"
+			"\tIf no files, read triples from stdin.\n",
+			prog);
+		return 0;
+		}
+
+	/* determine endian-ness */
+
+	u.d = 1.;
+	W0 = u.L[0] == 0;
+	W1 = 1 - W0;
+
+	/* test */
+
+	n = rc = 0;
+	if (argc <= 1)
+		n = process("<stdin>", stdin);
+	else
+		while(s = *++argv)
+			if (f = fopen(s,"r")) {
+				n += process(s, f);
+				fclose(f);
+				}
+			else {
+				rc = 2;
+				fprintf(stderr, "Cannot open %s\n", s);
+				}
+	printf("%d bad conversions\n", n);
+	if (n)
+		rc |= 1;
+	return rc;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/strtopddSI.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/strtopddSI.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/strtopddSI.c	(revision 2448)
@@ -0,0 +1,2 @@
+#define Sudden_Underflow
+#include "../strtopdd.c"
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/strtorddSI.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/strtorddSI.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/strtorddSI.c	(revision 2448)
@@ -0,0 +1,2 @@
+#define Sudden_Underflow
+#include "../strtordd.c"
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/testnos
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/testnos	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/testnos	(revision 2448)
@@ -0,0 +1,28 @@
+1.23
+1.23e+20
+1.23e-20
+1.23456789
+1.23456589e+20
+1.23e+30
+1.23e-30
+1.23456789e-20
+1.23456789e-30
+1.234567890123456789
+1.23456789012345678901234567890123456789
+1.23e306
+1.23e-306
+1.23e-320
+1.23e-20
+1.23456789e307
+1.23456589e-307
+1.234567890123456789
+1.234567890123456789e301
+1.234567890123456789e-301
+1.234567890123456789e-321
+1e23
+1e310
+9.0259718793241475e-277
+9.025971879324147880346310405869e-277
+9.025971879324147880346310405868e-277
+2.2250738585072014e-308
+2.2250738585072013e-308
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/testnos1
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/testnos1	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/testnos1	(revision 2448)
@@ -0,0 +1,20 @@
+1.23:2 6
+1.23:4 6
+1.23e+20:2 6
+1.23e+20:4 6
+1.23e-20:2 6
+1.23e-20:4 6
+1.23456789:2 6
+1.23456789:4 6
+1.23456589e+20:2 6
+1.23456589e+20:4 6
+1.23456789e-20:2 6
+1.23456789e-20:4 6
+1234565:2 6
+1234565:4 6
+1.234565:2 6
+1.234565:4 6
+1.234565e+20:2 6
+1.234565e+20:4 6
+1.234565e-20:2 6
+1.234565e-20:4 6
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/testnos3
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/testnos3	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/testnos3	(revision 2448)
@@ -0,0 +1,328 @@
+# Test triples for strtodt, derived from Fred Tydeman's posting
+# of 26 February 1996 to comp.arch.arithmetic.
+
+9e0306	7fa9a202	8368022e
+4e-079	2fa7b6d7	1d20b96c
+7e-261	9eb8d7e	32be6396
+6e-025	3ae7361c	b863de62
+7e-161	1eaf7e0d	b3799aa3
+7e0289	7c1cbb54	7777a285
+5e0079	507afcef	51f0fb5f
+1e0080	508afcef	51f0fb5f
+7e-303	1333391	31c46f8b
+5e0152	5fa317e5	ef3ab327
+5e0125	5a07a2ec	c414a03f
+2e0126	5a27a2ec	c414a03f
+7e-141	22d5570f	59bd178c
+4e-192	18323ff0	6eea847a
+9e0043	49102498	ea6df0c4
+1e0303	7ed754e3	1cd072da
+95e-089	2dde3cbc	9907fdc8
+85e0194	689d1c26	db7d0dae
+69e0267	77c0b7cb	60c994da
+97e-019	3c665dde	8e688ba6
+37e0046	49d033d7	eca0adef
+74e0046	49e033d7	eca0adef
+61e-099	2bc0ad83	6f269a17
+53e-208	151b39ae	1909c31b
+93e-234	fc27b2e	4f210075
+79e-095	2c9a5db8	12948281
+87e-274	772d36c	f48e7abd
+83e0025	4585747a	b143e353
+17e-036	38b698cc	dc60015a
+53e0033	47246a34	18629ef6
+51e-074	30ecd5be	e57763e6
+63e-022	3bbdc03b	8fd7016a
+839e0143	5e3ae03f	245703e2
+749e-182	1abf1472	7744c63e
+999e-026	3b282782	afe1869e
+345e0266	77b0b7cb	60c994da
+914e-102	2b5ffc81	bc29f02b
+829e0102	55b7221a	79cdd1d9
+307e0090	5322d6b1	83fe4b55
+859e0182	6654374d	8b87ac63
+283e0085	5216c309	24bab4b
+589e0187	675526be	9c22eb17
+302e0176	64fdcf7d	f8f573b7
+604e0176	650dcf7d	f8f573b7
+761e-244	de03cea	3586452e
+647e0230	7044d64d	4079150c
+755e0174	64a7d931	93f78fc6
+255e-075	30dcd5be	e57763e6
+3391e0055	4c159bd3	ad46e346
+4147e-015	3d923d1b	5eb1d778
+3996e-026	3b482782	afe1869e
+1998e-026	3b382782	afe1869e
+3338e-296	335519a	c5142aab
+1669e-296	325519a	c5142aab
+8699e-276	772d2df	246ecd2d
+5311e0243	73284e91	f4aa0fdb
+7903e-096	2cd07c2d	27a5b989
+7611e-226	11d19b87	44033457
+3257e0058	4cb444b3	4a6fb3eb
+6514e0058	4cc444b3	4a6fb3eb
+3571e0263	77462644	c61d41aa
+7142e0263	77562644	c61d41aa
+5311e0242	72f3720e	5d54d97c
+1617e-063	3384c98f	ce16152e
+51881e0037	4897d295	dc76da4
+31441e-118	285ef890	f5de4c86
+30179e0079	5143e272	a77478e8
+60358e0079	5153e272	a77478e8
+63876e-020	3cc70385	6844bdbf
+31938e-020	3cb70385	6844bdbf
+46073e-032	3a42405b	773fbdf3
+32941e0051	4b757eb8	ad52a5c9
+82081e0041	49770105	df3d47cb
+38701e-215	1440492a	4a8a37fd
+62745e0047	4ab0c52f	e6dc6a1b
+12549e0048	4ac0c52f	e6dc6a1b
+64009e-183	1af099b3	93b84832
+89275e0261	77262644	c61d41aa
+75859e0025	46232645	e1ba93f0
+57533e0287	7c8272ed	2307f56a
+584169e0229	70ad6570	59dc79aa
+940189e-112	29eb99d6	240c1a28
+416121e0197	6a00fd07	ed297f80
+832242e0197	6a10fd07	ed297f80
+584738e0076	50e8a85e	b277e645
+933587e-140	241b2487	28b9c117
+252601e0121	5a2dda59	2e398dd7
+358423e0274	79f9463b	59b8f2bd
+892771e-213	14f25818	c7294f27
+410405e0040	49670105	df3d47cb
+928609e-261	afbe2dd	66200bef
+302276e-254	c55a462	d91c6ab3
+920657e-023	3c653a99	85dbde6c
+609019e-025	3bf1f99e	11ea0a24
+252601e0120	59f7e1e0	f1c7a4ac
+654839e-060	34b00e7d	b3b3f242
+8823691e0130	5c5e597c	b94b7ae
+2920845e0228	709d6570	59dc79aa
+9210917e0080	51fda232	347e6032
+5800419e-303	26e58ff	a48f4fce
+6119898e-243	ee3ecf2	2ea07863
+3059949e-243	ed3ecf2	2ea07863
+2572231e0223	6f90f73b	e1dff9ad
+5444097e-021	3cf8849d	d33c95af
+5783893e-127	26f7e590	2ce0e151
+3865421e-225	1295d4fe	53afec65
+4590831e0156	61b4689b	4a5fa201
+9181662e0156	61c4689b	4a5fa201
+5906361e-027	3bbbe45a	312d08a0
+7315057e0235	7225f0d4	8362a72
+9088115e0106	5762e51a	84a3c6a0
+1817623e0107	5772e51a	84a3c6a0
+44118455e0129	5c4e597c	b94b7ae
+35282041e0293	7e5512d5	273e62e8
+31279898e-291	5129b01	b6885d36
+15639949e-291	5029b01	b6885d36
+27966061e0145	5f955bcf	72fd10f9
+55932122e0145	5fa55bcf	72fd10f9
+70176353e-053	36900683	a21de855
+40277543e-032	3adf29ca	ff893b1
+50609263e0157	622193af	f1f1c8e3
+66094077e0077	518b37c4	b7928317
+84863171e0114	59406e98	f5ec8f37
+89396333e0264	786526f0	61ca9053
+87575437e-309	16e0732	602056c
+78693511e-044	3870bc7b	7603a2ca
+90285923e-206	16d14700	83f89d48
+30155207e-030	3b423a4a	d20748a2
+245540327e0121	5acc569e	968e0944
+263125459e0287	7d44997a	298b2f2e
+566446538e-257	c64472b	a9550e86
+283223269e-257	c54472b	a9550e86
+245540327e0122	5b01b623	1e18c5cb
+491080654e0122	5b11b623	1e18c5cb
+971212611e-126	27a397d3	c9745d2f
+229058583e0052	4c76ce94	febdc7a5
+325270231e0039	49cc7ccf	90c9f8ab
+989648089e-035	3a8880a3	d515e849
+653777767e0273	7a720223	f2b3a881
+923091487e0209	6d30bc60	e6896717
+526250918e0288	7d89bfd8	b3edfafa
+350301748e-309	18e0732	602056c
+741111169e-203	17a14fe7	daf8f3ae
+667284113e-240	ff09355	f8050c02
+1227701635e0120	5abc569e	968e0944
+9981396317e-182	1c38afe1	a2a66aa
+5232604057e-298	41465b8	96c24520
+5572170023e-088	2fb08478	22f765b2
+1964322616e0122	5b31b623	1e18c5cb
+3928645232e0122	5b41b623	1e18c5cb
+8715380633e-058	35f4614c	3219891f
+4856063055e-127	279397d3	c9745d2f
+8336960483e-153	223a06a1	24b95e1
+1007046393e-155	21a01891	fc4717fd
+5378822089e-176	1d695fd4	c88d4b1b
+5981342308e-190	1a83db11	ac608107
+7214782613e-086	3020b552	d2edcdea
+5458466829e0142	5f70acde	6a98eb4c
+9078555839e-109	2b5fc575	867314ee
+6418488827e0079	526021f1	4ed7b3fa
+65325840981e0069	5081a151	ddbd3c4a
+49573485983e0089	54a221bd	871d2cf4
+46275205733e0074	51830e6c	7d4e3480
+92550411466e0074	51930e6c	7d4e3480
+41129842097e-202	1832c3e7	2d179607
+93227267727e-049	380960fe	8d5847f
+41297294357e0185	688c4943	7fccfadb
+41534892987e-067	343a1266	6477886d
+42333842451e0201	6be0189a	26df575f
+78564021519e-227	13115551	5fd37265
+53587107423e-061	35800a19	a3ffd981
+53827010643e-200	18a32fa6	9a69bd6d
+83356057653e0193	6a4544e6	daee2a18
+45256834646e-118	29a541ec	dfd48694
+45392779195e-110	2b4fc575	867314ee
+23934638219e0291	7e81deaf	40ead9a0
+995779191233e0113	59e2d44e	dcc51304
+997422852243e-265	b676688	faee99bc
+653532977297e-123	28d925a0	aabcdc68
+938885684947e0147	60f11894	b202e9f4
+619534293513e0124	5c210c20	303fe0f1
+539879452414e-042	39a5e66d	c3d6bdb5
+742522891517e0259	782c1c35	2fc3c309
+254901016865e-022	3dbc06d3	66394441
+685763015669e0280	7c85fd7a	a44d9477
+384865004907e-285	72aa65b	58639e69
+286556458711e0081	5321958b	36c5102b
+573112917422e0081	5331958b	36c5102b
+769525178383e-150	234253ec	e161420
+416780288265e0192	6a3544e6	daee2a18
+226963895975e-111	2b3fc575	867314ee
+665592809339e0063	4f778b65	16c2b478
+3891901811465e0217	6f99ab82	61990292
+4764593340755e0069	50e4177a	9915fbf8
+6336156586177e0269	7a7173f7	6c63b792
+8233559360849e0095	56566fee	5649a7a
+3662265515198e-107	2c538e6e	dd48f2a3
+1831132757599e-107	2c438e6e	dd48f2a3
+7812878489261e-179	1d726dae	7bbeda75
+6363857920591e0145	60b28a61	cf9483b7
+8811915538555e0082	53a51f50	8b287ae7
+9997878507563e-195	1a253db2	fea1ea31
+9224786422069e-291	634ee5d	56b32957
+6284426329974e-294	58d3409	dfbca26f
+9199302046091e-062	35c13597	2630774c
+6070482281213e-122	29423fa9	e6fcf47e
+2780161250963e-301	405acc2	53064c2
+8233559360849e0094	5621f324	d11d4862
+72027097041701e0206	6d946778	12d3a606
+97297545286625e0215	6f79ab82	61990292
+99021992302453e-025	3da5c671	4def374c
+54104687080198e-022	3e373cdf	8db7a7bc
+33519685743233e0089	5537f203	339c9629
+67039371486466e0089	5547f203	339c9629
+39064392446305e-180	1d626dae	7bbeda75
+17796979903653e0261	78e072f3	819c1321
+28921916763211e0038	4a9eebab	e0957af3
+87605699161665e0155	6302920f	96e7f9ef
+41921560615349e-067	34d9b2a5	c4041e4b
+80527976643809e0061	4f7c7c5a	ea080a49
+72335858886654e-159	21cce77c	2b3328fc
+52656615219377e0102	57f561de	f4a9ee32
+15400733123779e-072	33b8bf7e	7fa6f02a
+77003665618895e-073	33a8bf7e	7fa6f02a
+475603213226859e-042	3a42d730	88f4050a
+972708181182949e0116	5b218a7f	36172332
+246411729980464e-071	342eef5e	1f90ac34
+123205864990232e-071	341eef5e	1f90ac34
+609610927149051e-255	e104273	b18918b1
+475603213226859e-041	3a778cfc	ab31064d
+672574798934795e0065	508226c6	84c87261
+134514959786959e0066	509226c6	84c87261
+294897574603217e-151	2395f2df	5e675a0f
+723047919080275e0036	4a7eebab	e0957af3
+660191429952702e-088	30bddc7e	975c5045
+330095714976351e-088	30addc7e	975c5045
+578686871093232e-159	21fce77c	2b3328fc
+144671717773308e-159	21dce77c	2b3328fc
+385018328094475e-074	3398bf7e	7fa6f02a
+330095714976351e-089	3077e398	7916a69e
+2215901545757777e-212	171a80a6	e566428c
+1702061899637397e-276	9cacc46	749dccfe
+1864950924021923e0213	6f53ae60	753af6ca
+3729901848043846e0213	6f63ae60	753af6ca
+7487252720986826e-165	20f8823a	57adbef9
+3743626360493413e-165	20e8823a	57adbef9
+4988915232824583e0119	5be5f6de	9d5d6b5b
+3771476185376383e0277	7cae3c14	d6916ce9
+6182410494241627e-119	2a81b964	58445d07
+2572981889477453e0142	609dfc11	fbf46087
+7793560217139653e0051	4dd28046	1b856ec5
+9163942927285259e-202	194fe601	457dce4d
+6353227084707473e0155	63650aff	653ffe8a
+4431803091515554e-211	17609068	4f5fe998
+9324754620109615e0211	6f0f7d67	21f7f144
+8870461176410409e0263	79d90529	a37b7e22
+90372559027740405e0143	612491da	ad0ba280
+18074511805548081e0146	61a011f2	d73116f4
+54897030182071313e0029	496ec556	66d8f9ec
+76232626624829156e-032	3ccb7738	11e75fe
+59898021767894608e-165	2128823a	57adbef9
+29949010883947304e-165	2118823a	57adbef9
+26153245263757307e0049	4d83de00	5bd620df
+27176258005319167e-261	d27c074	7bd76fa1
+18074511805548081e0147	61d4166f	8cfd5cb1
+24691002732654881e-115	2b759a27	83ce70ab
+58483921078398283e0057	4f408ce4	99519ce3
+64409240769861689e-159	22692238	f7987779
+94080055902682397e-242	11364981	e39e66ca
+31766135423537365e0154	63550aff	653ffe8a
+68985865317742005e0164	657a999d	dec72aca
+13797173063548401e0165	658a999d	dec72aca
+902042358290366539e-281	9522dc0	1ca1cb8c
+238296178309629163e0272	7c038fd9	3f1f5342
+783308178698887621e0226	72925ae6	2cb346d8
+439176241456570504e0029	499ec556	66d8f9ec
+899810892172646163e0283	7e6adf51	fa055e03
+926145344610700019e-225	14f307a6	7f1f69ff
+653831131593932675e0047	4d63de00	5bd620df
+130766226318786535e0048	4d73de00	5bd620df
+557035730189854663e-294	693bfac	6bc4767b
+902042358290366539e-280	986b930	23ca3e6f
+272104041512242479e0200	6d13bbb4	bf05f087
+544208083024484958e0200	6d23bbb4	bf05f087
+680429695511221511e0192	6b808ebc	116f8a20
+308975121073410857e0236	7490db75	cc001072
+792644927852378159e0078	53d7bff3	36d8ff06
+783308178698887621e0223	71f2cbac	35f71140
+8396094300569779681e-252	f8ab223	efcee35a
+3507665085003296281e-074	346b85c0	26a264e4
+7322325862592278999e0074	5336775b	6caa5ae0
+6014546754280072926e0209	6f396397	b06732a4
+7120190517612959703e0120	5cc3220d	cd5899fd
+3507665085003296281e-073	34a13398	18257f0f
+4345544743100783551e-218	168a9c42	e5b6d89f
+9778613303868468131e-090	313146fe	1075e1ef
+7539204280836061195e-082	32d3d969	e3dbe723
+7862637540082247119e-202	19eaba32	62ee707b
+2176832332097939832e0200	6d43bbb4	bf05f087
+8643988913946659879e0115	5bbe71ec	1ed0a4f9
+5529436763613147623e0138	6079c677	be6f236e
+6764958008109694533e-173	1fed0669	2e6f5ef6
+6802601037806061975e0197	6cbf92ba	cb3cb40c
+1360520207561212395e0198	6ccf92ba	cb3cb40c
+62259110684423957791e0047	4dcd8f2c	fc20d6e8
+88800290202542652011e-226	1526cec5	1a43f41a
+41010852717673354694e-221	16201295	4b6aabba
+20505426358836677347e-221	16101295	4b6aabba
+66102447903809911604e0055	4f776206	8a24fd55
+35600952588064798515e0119	5cb3220d	cd5899fd
+14371240869903838702e0205	6e78d92d	2bcc7a81
+57500690832492901689e0043	4cf65d3e	2acd616b
+23432630639573022093e-107	2dbdd54c	40a2f25f
+62259110684423957791e0048	4e02797c	1d948651
+35620497849450218807e-306	475b220	82529425
+69658634627134074624e0200	6d93bbb4	bf05f087
+99440755792436956989e-062	37362d10	462a26f4
+55277197169490210673e0081	54d945bf	a911e32a
+36992084760177624177e-318	1f8c5f9	551c2f9a
+30888265282878466443e-111	2cf01b8e	f28251fc
+
+# examples of bugs introduced 20001113, fixed 20010207
+# first is 2^-1075 (half the smallest denormal)
+2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125e-324	0	0
+2.47032822920623272e-324	0	0
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/x.ou0
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/x.ou0	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/x.ou0	(revision 2448)
@@ -0,0 +1,1182 @@
+
+Input: 1.23
+
+strtox consumes 4 bytes and returns 33
+with bits = #3fff 9d70 a3d7 a3d 70a4
+g_xfmt(0) gives 4 bytes: "1.23"
+
+strtoIx returns 33, consuming 4 bytes.
+fI[0] = #3fff 9d70 a3d7 a3d 70a3
+fI[1] = #3fff 9d70 a3d7 a3d 70a3
+fI[1] == strtox
+
+
+Input: 1.23e+20
+
+strtox consumes 8 bytes and returns 1
+with bits = #4041 d55e f90a 2da1 8000
+g_xfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIx returns 1, consuming 8 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.23e-20
+
+strtox consumes 8 bytes and returns 17
+with bits = #3fbc e857 267b b3a9 84f2
+g_xfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #3fbc e857 267b b3a9 84f2
+fI[1] = #3fbc e857 267b b3a9 84f2
+fI[0] == strtox
+
+
+Input: 1.23456789
+
+strtox consumes 10 bytes and returns 33
+with bits = #3fff 9e06 5214 1ef0 dbf6
+g_xfmt(0) gives 10 bytes: "1.23456789"
+
+strtoIx returns 33, consuming 10 bytes.
+fI[0] = #3fff 9e06 5214 1ef0 dbf5
+fI[1] = #3fff 9e06 5214 1ef0 dbf5
+fI[1] == strtox
+
+
+Input: 1.23456589e+20
+
+strtox consumes 14 bytes and returns 1
+with bits = #4041 d629 bd33 5cc ba00
+g_xfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoIx returns 1, consuming 14 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.23e+30
+
+strtox consumes 8 bytes and returns 17
+with bits = #4062 f865 8274 7dbc 824a
+g_xfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #4062 f865 8274 7dbc 824a
+fI[1] = #4062 f865 8274 7dbc 824a
+fI[0] == strtox
+
+
+Input: 1.23e-30
+
+strtox consumes 8 bytes and returns 17
+with bits = #3f9b c794 337a 8085 54eb
+g_xfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #3f9b c794 337a 8085 54eb
+fI[1] = #3f9b c794 337a 8085 54eb
+fI[0] == strtox
+
+
+Input: 1.23456789e-20
+
+strtox consumes 14 bytes and returns 17
+with bits = #3fbc e934 a38 f3d6 d352
+g_xfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoIx returns 17, consuming 14 bytes.
+fI[0] = #3fbc e934 a38 f3d6 d352
+fI[1] = #3fbc e934 a38 f3d6 d352
+fI[0] == strtox
+
+
+Input: 1.23456789e-30
+
+strtox consumes 14 bytes and returns 17
+with bits = #3f9b c851 f19d decc a8fc
+g_xfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoIx returns 17, consuming 14 bytes.
+fI[0] = #3f9b c851 f19d decc a8fc
+fI[1] = #3f9b c851 f19d decc a8fc
+fI[0] == strtox
+
+
+Input: 1.234567890123456789
+
+strtox consumes 20 bytes and returns 17
+with bits = #3fff 9e06 5214 62cf db8d
+g_xfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIx returns 17, consuming 20 bytes.
+fI[0] = #3fff 9e06 5214 62cf db8d
+fI[1] = #3fff 9e06 5214 62cf db8d
+fI[0] == strtox
+
+
+Input: 1.23456789012345678901234567890123456789
+
+strtox consumes 40 bytes and returns 17
+with bits = #3fff 9e06 5214 62cf db8d
+g_xfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIx returns 17, consuming 40 bytes.
+fI[0] = #3fff 9e06 5214 62cf db8d
+fI[1] = #3fff 9e06 5214 62cf db8d
+fI[0] == strtox
+
+
+Input: 1.23e306
+
+strtox consumes 8 bytes and returns 17
+with bits = #43f7 e033 b668 e30f a6d5
+g_xfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #43f7 e033 b668 e30f a6d5
+fI[1] = #43f7 e033 b668 e30f a6d5
+fI[0] == strtox
+
+
+Input: 1.23e-306
+
+strtox consumes 9 bytes and returns 33
+with bits = #3c06 dd1d c2ed 1cb7 3f25
+g_xfmt(0) gives 9 bytes: "1.23e-306"
+
+strtoIx returns 33, consuming 9 bytes.
+fI[0] = #3c06 dd1d c2ed 1cb7 3f24
+fI[1] = #3c06 dd1d c2ed 1cb7 3f24
+fI[1] == strtox
+
+
+Input: 1.23e-320
+
+strtox consumes 9 bytes and returns 33
+with bits = #3bd8 9b98 c371 844c 3f1a
+g_xfmt(0) gives 9 bytes: "1.23e-320"
+
+strtoIx returns 33, consuming 9 bytes.
+fI[0] = #3bd8 9b98 c371 844c 3f19
+fI[1] = #3bd8 9b98 c371 844c 3f19
+fI[1] == strtox
+
+
+Input: 1.23e-20
+
+strtox consumes 8 bytes and returns 17
+with bits = #3fbc e857 267b b3a9 84f2
+g_xfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #3fbc e857 267b b3a9 84f2
+fI[1] = #3fbc e857 267b b3a9 84f2
+fI[0] == strtox
+
+
+Input: 1.23456789e307
+
+strtox consumes 14 bytes and returns 17
+with bits = #43fb 8ca5 8a5e d766 de75
+g_xfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoIx returns 17, consuming 14 bytes.
+fI[0] = #43fb 8ca5 8a5e d766 de75
+fI[1] = #43fb 8ca5 8a5e d766 de75
+fI[0] == strtox
+
+
+Input: 1.23456589e-307
+
+strtox consumes 15 bytes and returns 17
+with bits = #3c03 b18c b5dc c22f d369
+g_xfmt(0) gives 15 bytes: "1.23456589e-307"
+
+strtoIx returns 17, consuming 15 bytes.
+fI[0] = #3c03 b18c b5dc c22f d369
+fI[1] = #3c03 b18c b5dc c22f d369
+fI[0] == strtox
+
+
+Input: 1.234567890123456789
+
+strtox consumes 20 bytes and returns 17
+with bits = #3fff 9e06 5214 62cf db8d
+g_xfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIx returns 17, consuming 20 bytes.
+fI[0] = #3fff 9e06 5214 62cf db8d
+fI[1] = #3fff 9e06 5214 62cf db8d
+fI[0] == strtox
+
+
+Input: 1.234567890123456789e301
+
+strtox consumes 24 bytes and returns 33
+with bits = #43e7 937a 8baf ab20 980c
+g_xfmt(0) gives 25 bytes: "1.234567890123456789e+301"
+
+strtoIx returns 33, consuming 24 bytes.
+fI[0] = #43e7 937a 8baf ab20 980b
+fI[1] = #43e7 937a 8baf ab20 980b
+fI[1] == strtox
+
+
+Input: 1.234567890123456789e-301
+
+strtox consumes 25 bytes and returns 33
+with bits = #3c17 a953 271a 5d06 9ad9
+g_xfmt(0) gives 25 bytes: "1.234567890123456789e-301"
+
+strtoIx returns 33, consuming 25 bytes.
+fI[0] = #3c17 a953 271a 5d06 9ad8
+fI[1] = #3c17 a953 271a 5d06 9ad8
+fI[1] == strtox
+
+
+Input: 1.234567890123456789e-321
+
+strtox consumes 25 bytes and returns 33
+with bits = #3bd4 f9e1 1b4c ea6d cce9
+g_xfmt(0) gives 25 bytes: "1.234567890123456789e-321"
+
+strtoIx returns 33, consuming 25 bytes.
+fI[0] = #3bd4 f9e1 1b4c ea6d cce8
+fI[1] = #3bd4 f9e1 1b4c ea6d cce8
+fI[1] == strtox
+
+
+Input: 1e23
+
+strtox consumes 4 bytes and returns 1
+with bits = #404b a968 163f a57 b400
+g_xfmt(0) gives 5 bytes: "1e+23"
+
+strtoIx returns 1, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1e310
+
+strtox consumes 5 bytes and returns 33
+with bits = #4404 de81 e40a 34b cf50
+g_xfmt(0) gives 6 bytes: "1e+310"
+
+strtoIx returns 33, consuming 5 bytes.
+fI[0] = #4404 de81 e40a 34b cf4f
+fI[1] = #4404 de81 e40a 34b cf4f
+fI[1] == strtox
+
+
+Input: 9.0259718793241475e-277
+
+strtox consumes 23 bytes and returns 33
+with bits = #3c69 ffff ffff ffff fcf7
+g_xfmt(0) gives 23 bytes: "9.0259718793241475e-277"
+
+strtoIx returns 33, consuming 23 bytes.
+fI[0] = #3c69 ffff ffff ffff fcf6
+fI[1] = #3c69 ffff ffff ffff fcf6
+fI[1] == strtox
+
+
+Input: 9.025971879324147880346310405869e-277
+
+strtox consumes 37 bytes and returns 17
+with bits = #3c6a 8000 0 0 0
+g_xfmt(0) gives 26 bytes: "9.0259718793241478803e-277"
+
+strtoIx returns 17, consuming 37 bytes.
+fI[0] = #3c6a 8000 0 0 0
+fI[1] = #3c6a 8000 0 0 0
+fI[0] == strtox
+
+
+Input: 9.025971879324147880346310405868e-277
+
+strtox consumes 37 bytes and returns 33
+with bits = #3c6a 8000 0 0 0
+g_xfmt(0) gives 26 bytes: "9.0259718793241478803e-277"
+
+strtoIx returns 33, consuming 37 bytes.
+fI[0] = #3c69 ffff ffff ffff ffff
+fI[1] = #3c6a 8000 0 ffff ffff
+fI[1] == strtox
+
+
+Input: 2.2250738585072014e-308
+
+strtox consumes 23 bytes and returns 17
+with bits = #3c01 8000 0 0 46
+g_xfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoIx returns 17, consuming 23 bytes.
+fI[0] = #3c01 8000 0 0 46
+fI[1] = #3c01 8000 0 0 46
+fI[0] == strtox
+
+
+Input: 2.2250738585072013e-308
+
+strtox consumes 23 bytes and returns 17
+with bits = #3c00 ffff ffff ffff fd4f
+g_xfmt(0) gives 23 bytes: "2.2250738585072013e-308"
+
+strtoIx returns 17, consuming 23 bytes.
+fI[0] = #3c00 ffff ffff ffff fd4f
+fI[1] = #3c00 ffff ffff ffff fd4f
+fI[0] == strtox
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff 8ccc cccc cccc cccc
+g_xfmt(0) gives 21 bytes: "1.0999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 8ccc cccc cccc cccc
+fI[1] = #3fff 8ccc cccc cccc cccc
+fI[0] == strtox
+
+
+Input: -1.1
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff 8ccc cccc cccc cccc
+g_xfmt(0) gives 22 bytes: "-1.0999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 8ccc cccc cccc cccd
+fI[1] = #bfff 8ccc cccc cccc cccd
+fI[1] == strtox
+
+
+Input: 1.2
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff 9999 9999 9999 9999
+g_xfmt(0) gives 21 bytes: "1.1999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 9999 9999 9999 9999
+fI[1] = #3fff 9999 9999 9999 9999
+fI[0] == strtox
+
+
+Input: -1.2
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff 9999 9999 9999 9999
+g_xfmt(0) gives 22 bytes: "-1.1999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 9999 9999 9999 999a
+fI[1] = #bfff 9999 9999 9999 999a
+fI[1] == strtox
+
+
+Input: 1.3
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff a666 6666 6666 6666
+g_xfmt(0) gives 3 bytes: "1.3"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff a666 6666 6666 6666
+fI[1] = #3fff a666 6666 6666 6666
+fI[0] == strtox
+
+
+Input: -1.3
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff a666 6666 6666 6666
+g_xfmt(0) gives 4 bytes: "-1.3"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff a666 6666 6666 6667
+fI[1] = #bfff a666 6666 6666 6667
+fI[1] == strtox
+
+
+Input: 1.4
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff b333 3333 3333 3333
+g_xfmt(0) gives 3 bytes: "1.4"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff b333 3333 3333 3333
+fI[1] = #3fff b333 3333 3333 3333
+fI[0] == strtox
+
+
+Input: -1.4
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff b333 3333 3333 3333
+g_xfmt(0) gives 4 bytes: "-1.4"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff b333 3333 3333 3334
+fI[1] = #bfff b333 3333 3333 3334
+fI[1] == strtox
+
+
+Input: 1.5
+
+strtox consumes 3 bytes and returns 1
+with bits = #3fff c000 0 0 0
+g_xfmt(0) gives 3 bytes: "1.5"
+
+strtoIx returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: -1.5
+
+strtox consumes 4 bytes and returns 9
+with bits = #bfff c000 0 0 0
+g_xfmt(0) gives 4 bytes: "-1.5"
+
+strtoIx returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.6
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff cccc cccc cccc cccc
+g_xfmt(0) gives 21 bytes: "1.5999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff cccc cccc cccc cccc
+fI[1] = #3fff cccc cccc cccc cccc
+fI[0] == strtox
+
+
+Input: -1.6
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff cccc cccc cccc cccc
+g_xfmt(0) gives 22 bytes: "-1.5999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff cccc cccc cccc cccd
+fI[1] = #bfff cccc cccc cccc cccd
+fI[1] == strtox
+
+
+Input: 1.7
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff d999 9999 9999 9999
+g_xfmt(0) gives 21 bytes: "1.6999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff d999 9999 9999 9999
+fI[1] = #3fff d999 9999 9999 9999
+fI[0] == strtox
+
+
+Input: -1.7
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff d999 9999 9999 9999
+g_xfmt(0) gives 22 bytes: "-1.6999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff d999 9999 9999 999a
+fI[1] = #bfff d999 9999 9999 999a
+fI[1] == strtox
+
+
+Input: 1.8
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff e666 6666 6666 6666
+g_xfmt(0) gives 3 bytes: "1.8"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff e666 6666 6666 6666
+fI[1] = #3fff e666 6666 6666 6666
+fI[0] == strtox
+
+
+Input: -1.8
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff e666 6666 6666 6666
+g_xfmt(0) gives 4 bytes: "-1.8"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff e666 6666 6666 6667
+fI[1] = #bfff e666 6666 6666 6667
+fI[1] == strtox
+
+
+Input: 1.9
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff f333 3333 3333 3333
+g_xfmt(0) gives 3 bytes: "1.9"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff f333 3333 3333 3333
+fI[1] = #3fff f333 3333 3333 3333
+fI[0] == strtox
+
+
+Input: -1.9
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff f333 3333 3333 3333
+g_xfmt(0) gives 4 bytes: "-1.9"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff f333 3333 3333 3334
+fI[1] = #bfff f333 3333 3333 3334
+fI[1] == strtox
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff 8ccc cccc cccc cccd
+g_xfmt(0) gives 3 bytes: "1.1"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 8ccc cccc cccc cccc
+fI[1] = #3fff 8ccc cccc cccc cccc
+fI[1] == strtox
+
+
+Input: -1.1
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff 8ccc cccc cccc cccd
+g_xfmt(0) gives 4 bytes: "-1.1"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 8ccc cccc cccc cccd
+fI[1] = #bfff 8ccc cccc cccc cccd
+fI[0] == strtox
+
+
+Input: 1.2
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff 9999 9999 9999 999a
+g_xfmt(0) gives 3 bytes: "1.2"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 9999 9999 9999 9999
+fI[1] = #3fff 9999 9999 9999 9999
+fI[1] == strtox
+
+
+Input: -1.2
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff 9999 9999 9999 999a
+g_xfmt(0) gives 4 bytes: "-1.2"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 9999 9999 9999 999a
+fI[1] = #bfff 9999 9999 9999 999a
+fI[0] == strtox
+
+
+Input: 1.3
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff a666 6666 6666 6666
+g_xfmt(0) gives 3 bytes: "1.3"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff a666 6666 6666 6666
+fI[1] = #3fff a666 6666 6666 6666
+fI[0] == strtox
+
+
+Input: -1.3
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff a666 6666 6666 6666
+g_xfmt(0) gives 4 bytes: "-1.3"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff a666 6666 6666 6667
+fI[1] = #bfff a666 6666 6666 6667
+fI[1] == strtox
+
+
+Input: 1.4
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff b333 3333 3333 3333
+g_xfmt(0) gives 3 bytes: "1.4"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff b333 3333 3333 3333
+fI[1] = #3fff b333 3333 3333 3333
+fI[0] == strtox
+
+
+Input: -1.4
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff b333 3333 3333 3333
+g_xfmt(0) gives 4 bytes: "-1.4"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff b333 3333 3333 3334
+fI[1] = #bfff b333 3333 3333 3334
+fI[1] == strtox
+
+
+Input: 1.5
+
+strtox consumes 3 bytes and returns 1
+with bits = #3fff c000 0 0 0
+g_xfmt(0) gives 3 bytes: "1.5"
+
+strtoIx returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: -1.5
+
+strtox consumes 4 bytes and returns 9
+with bits = #bfff c000 0 0 0
+g_xfmt(0) gives 4 bytes: "-1.5"
+
+strtoIx returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.6
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff cccc cccc cccc cccd
+g_xfmt(0) gives 3 bytes: "1.6"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff cccc cccc cccc cccc
+fI[1] = #3fff cccc cccc cccc cccc
+fI[1] == strtox
+
+
+Input: -1.6
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff cccc cccc cccc cccd
+g_xfmt(0) gives 4 bytes: "-1.6"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff cccc cccc cccc cccd
+fI[1] = #bfff cccc cccc cccc cccd
+fI[0] == strtox
+
+
+Input: 1.7
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff d999 9999 9999 999a
+g_xfmt(0) gives 3 bytes: "1.7"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff d999 9999 9999 9999
+fI[1] = #3fff d999 9999 9999 9999
+fI[1] == strtox
+
+
+Input: -1.7
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff d999 9999 9999 999a
+g_xfmt(0) gives 4 bytes: "-1.7"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff d999 9999 9999 999a
+fI[1] = #bfff d999 9999 9999 999a
+fI[0] == strtox
+
+
+Input: 1.8
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff e666 6666 6666 6666
+g_xfmt(0) gives 3 bytes: "1.8"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff e666 6666 6666 6666
+fI[1] = #3fff e666 6666 6666 6666
+fI[0] == strtox
+
+
+Input: -1.8
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff e666 6666 6666 6666
+g_xfmt(0) gives 4 bytes: "-1.8"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff e666 6666 6666 6667
+fI[1] = #bfff e666 6666 6666 6667
+fI[1] == strtox
+
+
+Input: 1.9
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff f333 3333 3333 3333
+g_xfmt(0) gives 3 bytes: "1.9"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff f333 3333 3333 3333
+fI[1] = #3fff f333 3333 3333 3333
+fI[0] == strtox
+
+
+Input: -1.9
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff f333 3333 3333 3333
+g_xfmt(0) gives 4 bytes: "-1.9"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff f333 3333 3333 3334
+fI[1] = #bfff f333 3333 3333 3334
+fI[1] == strtox
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff 8ccc cccc cccc cccd
+g_xfmt(0) gives 3 bytes: "1.1"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 8ccc cccc cccc cccc
+fI[1] = #3fff 8ccc cccc cccc cccc
+fI[1] == strtox
+
+
+Input: -1.1
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff 8ccc cccc cccc cccc
+g_xfmt(0) gives 22 bytes: "-1.0999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 8ccc cccc cccc cccd
+fI[1] = #bfff 8ccc cccc cccc cccd
+fI[1] == strtox
+
+
+Input: 1.2
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff 9999 9999 9999 999a
+g_xfmt(0) gives 3 bytes: "1.2"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 9999 9999 9999 9999
+fI[1] = #3fff 9999 9999 9999 9999
+fI[1] == strtox
+
+
+Input: -1.2
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff 9999 9999 9999 9999
+g_xfmt(0) gives 22 bytes: "-1.1999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 9999 9999 9999 999a
+fI[1] = #bfff 9999 9999 9999 999a
+fI[1] == strtox
+
+
+Input: 1.3
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff a666 6666 6666 6667
+g_xfmt(0) gives 21 bytes: "1.3000000000000000001"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff a666 6666 6666 6666
+fI[1] = #3fff a666 6666 6666 6666
+fI[1] == strtox
+
+
+Input: -1.3
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff a666 6666 6666 6666
+g_xfmt(0) gives 4 bytes: "-1.3"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff a666 6666 6666 6667
+fI[1] = #bfff a666 6666 6666 6667
+fI[1] == strtox
+
+
+Input: 1.4
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff b333 3333 3333 3334
+g_xfmt(0) gives 21 bytes: "1.4000000000000000001"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff b333 3333 3333 3333
+fI[1] = #3fff b333 3333 3333 3333
+fI[1] == strtox
+
+
+Input: -1.4
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff b333 3333 3333 3333
+g_xfmt(0) gives 4 bytes: "-1.4"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff b333 3333 3333 3334
+fI[1] = #bfff b333 3333 3333 3334
+fI[1] == strtox
+
+
+Input: 1.5
+
+strtox consumes 3 bytes and returns 1
+with bits = #3fff c000 0 0 0
+g_xfmt(0) gives 3 bytes: "1.5"
+
+strtoIx returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: -1.5
+
+strtox consumes 4 bytes and returns 9
+with bits = #bfff c000 0 0 0
+g_xfmt(0) gives 4 bytes: "-1.5"
+
+strtoIx returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.6
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff cccc cccc cccc cccd
+g_xfmt(0) gives 3 bytes: "1.6"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff cccc cccc cccc cccc
+fI[1] = #3fff cccc cccc cccc cccc
+fI[1] == strtox
+
+
+Input: -1.6
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff cccc cccc cccc cccc
+g_xfmt(0) gives 22 bytes: "-1.5999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff cccc cccc cccc cccd
+fI[1] = #bfff cccc cccc cccc cccd
+fI[1] == strtox
+
+
+Input: 1.7
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff d999 9999 9999 999a
+g_xfmt(0) gives 3 bytes: "1.7"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff d999 9999 9999 9999
+fI[1] = #3fff d999 9999 9999 9999
+fI[1] == strtox
+
+
+Input: -1.7
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff d999 9999 9999 9999
+g_xfmt(0) gives 22 bytes: "-1.6999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff d999 9999 9999 999a
+fI[1] = #bfff d999 9999 9999 999a
+fI[1] == strtox
+
+
+Input: 1.8
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff e666 6666 6666 6667
+g_xfmt(0) gives 21 bytes: "1.8000000000000000001"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff e666 6666 6666 6666
+fI[1] = #3fff e666 6666 6666 6666
+fI[1] == strtox
+
+
+Input: -1.8
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff e666 6666 6666 6666
+g_xfmt(0) gives 4 bytes: "-1.8"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff e666 6666 6666 6667
+fI[1] = #bfff e666 6666 6666 6667
+fI[1] == strtox
+
+
+Input: 1.9
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff f333 3333 3333 3334
+g_xfmt(0) gives 21 bytes: "1.9000000000000000001"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff f333 3333 3333 3333
+fI[1] = #3fff f333 3333 3333 3333
+fI[1] == strtox
+
+
+Input: -1.9
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff f333 3333 3333 3333
+g_xfmt(0) gives 4 bytes: "-1.9"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff f333 3333 3333 3334
+fI[1] = #bfff f333 3333 3333 3334
+fI[1] == strtox
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff 8ccc cccc cccc cccc
+g_xfmt(0) gives 21 bytes: "1.0999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 8ccc cccc cccc cccc
+fI[1] = #3fff 8ccc cccc cccc cccc
+fI[0] == strtox
+
+
+Input: -1.1
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff 8ccc cccc cccc cccd
+g_xfmt(0) gives 4 bytes: "-1.1"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 8ccc cccc cccc cccd
+fI[1] = #bfff 8ccc cccc cccc cccd
+fI[0] == strtox
+
+
+Input: 1.2
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff 9999 9999 9999 9999
+g_xfmt(0) gives 21 bytes: "1.1999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 9999 9999 9999 9999
+fI[1] = #3fff 9999 9999 9999 9999
+fI[0] == strtox
+
+
+Input: -1.2
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff 9999 9999 9999 999a
+g_xfmt(0) gives 4 bytes: "-1.2"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 9999 9999 9999 999a
+fI[1] = #bfff 9999 9999 9999 999a
+fI[0] == strtox
+
+
+Input: 1.3
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff a666 6666 6666 6666
+g_xfmt(0) gives 3 bytes: "1.3"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff a666 6666 6666 6666
+fI[1] = #3fff a666 6666 6666 6666
+fI[0] == strtox
+
+
+Input: -1.3
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff a666 6666 6666 6667
+g_xfmt(0) gives 22 bytes: "-1.3000000000000000001"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff a666 6666 6666 6667
+fI[1] = #bfff a666 6666 6666 6667
+fI[0] == strtox
+
+
+Input: 1.4
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff b333 3333 3333 3333
+g_xfmt(0) gives 3 bytes: "1.4"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff b333 3333 3333 3333
+fI[1] = #3fff b333 3333 3333 3333
+fI[0] == strtox
+
+
+Input: -1.4
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff b333 3333 3333 3334
+g_xfmt(0) gives 22 bytes: "-1.4000000000000000001"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff b333 3333 3333 3334
+fI[1] = #bfff b333 3333 3333 3334
+fI[0] == strtox
+
+
+Input: 1.5
+
+strtox consumes 3 bytes and returns 1
+with bits = #3fff c000 0 0 0
+g_xfmt(0) gives 3 bytes: "1.5"
+
+strtoIx returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: -1.5
+
+strtox consumes 4 bytes and returns 9
+with bits = #bfff c000 0 0 0
+g_xfmt(0) gives 4 bytes: "-1.5"
+
+strtoIx returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.6
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff cccc cccc cccc cccc
+g_xfmt(0) gives 21 bytes: "1.5999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff cccc cccc cccc cccc
+fI[1] = #3fff cccc cccc cccc cccc
+fI[0] == strtox
+
+
+Input: -1.6
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff cccc cccc cccc cccd
+g_xfmt(0) gives 4 bytes: "-1.6"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff cccc cccc cccc cccd
+fI[1] = #bfff cccc cccc cccc cccd
+fI[0] == strtox
+
+
+Input: 1.7
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff d999 9999 9999 9999
+g_xfmt(0) gives 21 bytes: "1.6999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff d999 9999 9999 9999
+fI[1] = #3fff d999 9999 9999 9999
+fI[0] == strtox
+
+
+Input: -1.7
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff d999 9999 9999 999a
+g_xfmt(0) gives 4 bytes: "-1.7"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff d999 9999 9999 999a
+fI[1] = #bfff d999 9999 9999 999a
+fI[0] == strtox
+
+
+Input: 1.8
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff e666 6666 6666 6666
+g_xfmt(0) gives 3 bytes: "1.8"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff e666 6666 6666 6666
+fI[1] = #3fff e666 6666 6666 6666
+fI[0] == strtox
+
+
+Input: -1.8
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff e666 6666 6666 6667
+g_xfmt(0) gives 22 bytes: "-1.8000000000000000001"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff e666 6666 6666 6667
+fI[1] = #bfff e666 6666 6666 6667
+fI[0] == strtox
+
+
+Input: 1.9
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff f333 3333 3333 3333
+g_xfmt(0) gives 3 bytes: "1.9"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff f333 3333 3333 3333
+fI[1] = #3fff f333 3333 3333 3333
+fI[0] == strtox
+
+
+Input: -1.9
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff f333 3333 3333 3334
+g_xfmt(0) gives 22 bytes: "-1.9000000000000000001"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff f333 3333 3333 3334
+fI[1] = #bfff f333 3333 3333 3334
+fI[0] == strtox
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/x.ou1
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/x.ou1	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/x.ou1	(revision 2448)
@@ -0,0 +1,1460 @@
+
+Input: 1.23
+
+strtox consumes 4 bytes and returns 33
+with bits = #3fff 9d70 a3d7 a3d 70a4
+printf("%.21Lg") gives 1.23000000000000000002
+g_xfmt(0) gives 4 bytes: "1.23"
+
+strtoIx returns 33, consuming 4 bytes.
+fI[0] = #3fff 9d70 a3d7 a3d 70a3
+= 1.22999999999999999991
+fI[1] = #3fff 9d70 a3d7 a3d 70a3
+= 1.23000000000000000002
+fI[1] == strtox
+
+
+Input: 1.23e+20
+
+strtox consumes 8 bytes and returns 1
+with bits = #4041 d55e f90a 2da1 8000
+printf("%.21Lg") gives 123000000000000000000
+g_xfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIx returns 1, consuming 8 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.23e-20
+
+strtox consumes 8 bytes and returns 17
+with bits = #3fbc e857 267b b3a9 84f2
+printf("%.21Lg") gives 1.22999999999999999997e-20
+g_xfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #3fbc e857 267b b3a9 84f2
+= 1.22999999999999999997e-20
+fI[1] = #3fbc e857 267b b3a9 84f2
+= 1.23000000000000000004e-20
+fI[0] == strtox
+
+
+Input: 1.23456789
+
+strtox consumes 10 bytes and returns 33
+with bits = #3fff 9e06 5214 1ef0 dbf6
+printf("%.21Lg") gives 1.23456789000000000003
+g_xfmt(0) gives 10 bytes: "1.23456789"
+
+strtoIx returns 33, consuming 10 bytes.
+fI[0] = #3fff 9e06 5214 1ef0 dbf5
+= 1.23456788999999999992
+fI[1] = #3fff 9e06 5214 1ef0 dbf5
+= 1.23456789000000000003
+fI[1] == strtox
+
+
+Input: 1.23456589e+20
+
+strtox consumes 14 bytes and returns 1
+with bits = #4041 d629 bd33 5cc ba00
+printf("%.21Lg") gives 123456589000000000000
+g_xfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoIx returns 1, consuming 14 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.23e+30
+
+strtox consumes 8 bytes and returns 17
+with bits = #4062 f865 8274 7dbc 824a
+printf("%.21Lg") gives 1.22999999999999999999e+30
+g_xfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #4062 f865 8274 7dbc 824a
+= 1.22999999999999999999e+30
+fI[1] = #4062 f865 8274 7dbc 824a
+= 1.23000000000000000006e+30
+fI[0] == strtox
+
+
+Input: 1.23e-30
+
+strtox consumes 8 bytes and returns 17
+with bits = #3f9b c794 337a 8085 54eb
+printf("%.21Lg") gives 1.22999999999999999999e-30
+g_xfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #3f9b c794 337a 8085 54eb
+= 1.22999999999999999999e-30
+fI[1] = #3f9b c794 337a 8085 54eb
+= 1.23000000000000000007e-30
+fI[0] == strtox
+
+
+Input: 1.23456789e-20
+
+strtox consumes 14 bytes and returns 17
+with bits = #3fbc e934 a38 f3d6 d352
+printf("%.21Lg") gives 1.23456788999999999998e-20
+g_xfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoIx returns 17, consuming 14 bytes.
+fI[0] = #3fbc e934 a38 f3d6 d352
+= 1.23456788999999999998e-20
+fI[1] = #3fbc e934 a38 f3d6 d352
+= 1.23456789000000000005e-20
+fI[0] == strtox
+
+
+Input: 1.23456789e-30
+
+strtox consumes 14 bytes and returns 17
+with bits = #3f9b c851 f19d decc a8fc
+printf("%.21Lg") gives 1.23456788999999999999e-30
+g_xfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoIx returns 17, consuming 14 bytes.
+fI[0] = #3f9b c851 f19d decc a8fc
+= 1.23456788999999999999e-30
+fI[1] = #3f9b c851 f19d decc a8fc
+= 1.23456789000000000007e-30
+fI[0] == strtox
+
+
+Input: 1.234567890123456789
+
+strtox consumes 20 bytes and returns 17
+with bits = #3fff 9e06 5214 62cf db8d
+printf("%.21Lg") gives 1.23456789012345678899
+g_xfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIx returns 17, consuming 20 bytes.
+fI[0] = #3fff 9e06 5214 62cf db8d
+= 1.23456789012345678899
+fI[1] = #3fff 9e06 5214 62cf db8d
+= 1.23456789012345678909
+fI[0] == strtox
+
+
+Input: 1.23456789012345678901234567890123456789
+
+strtox consumes 40 bytes and returns 17
+with bits = #3fff 9e06 5214 62cf db8d
+printf("%.21Lg") gives 1.23456789012345678899
+g_xfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIx returns 17, consuming 40 bytes.
+fI[0] = #3fff 9e06 5214 62cf db8d
+= 1.23456789012345678899
+fI[1] = #3fff 9e06 5214 62cf db8d
+= 1.23456789012345678909
+fI[0] == strtox
+
+
+Input: 1.23e306
+
+strtox consumes 8 bytes and returns 17
+with bits = #43f7 e033 b668 e30f a6d5
+printf("%.21Lg") gives 1.22999999999999999997e+306
+g_xfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #43f7 e033 b668 e30f a6d5
+= 1.22999999999999999997e+306
+fI[1] = #43f7 e033 b668 e30f a6d5
+= 1.23000000000000000005e+306
+fI[0] == strtox
+
+
+Input: 1.23e-306
+
+strtox consumes 9 bytes and returns 33
+with bits = #3c06 dd1d c2ed 1cb7 3f25
+printf("%.21Lg") gives 1.23000000000000000002e-306
+g_xfmt(0) gives 9 bytes: "1.23e-306"
+
+strtoIx returns 33, consuming 9 bytes.
+fI[0] = #3c06 dd1d c2ed 1cb7 3f24
+= 1.22999999999999999995e-306
+fI[1] = #3c06 dd1d c2ed 1cb7 3f24
+= 1.23000000000000000002e-306
+fI[1] == strtox
+
+
+Input: 1.23e-320
+
+strtox consumes 9 bytes and returns 33
+with bits = #3bd8 9b98 c371 844c 3f1a
+printf("%.21Lg") gives 1.23000000000000000002e-320
+g_xfmt(0) gives 9 bytes: "1.23e-320"
+
+strtoIx returns 33, consuming 9 bytes.
+fI[0] = #3bd8 9b98 c371 844c 3f19
+= 1.22999999999999999991e-320
+fI[1] = #3bd8 9b98 c371 844c 3f19
+= 1.23000000000000000002e-320
+fI[1] == strtox
+
+
+Input: 1.23e-20
+
+strtox consumes 8 bytes and returns 17
+with bits = #3fbc e857 267b b3a9 84f2
+printf("%.21Lg") gives 1.22999999999999999997e-20
+g_xfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIx returns 17, consuming 8 bytes.
+fI[0] = #3fbc e857 267b b3a9 84f2
+= 1.22999999999999999997e-20
+fI[1] = #3fbc e857 267b b3a9 84f2
+= 1.23000000000000000004e-20
+fI[0] == strtox
+
+
+Input: 1.23456789e307
+
+strtox consumes 14 bytes and returns 17
+with bits = #43fb 8ca5 8a5e d766 de75
+printf("%.21Lg") gives 1.23456788999999999998e+307
+g_xfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoIx returns 17, consuming 14 bytes.
+fI[0] = #43fb 8ca5 8a5e d766 de75
+= 1.23456788999999999998e+307
+fI[1] = #43fb 8ca5 8a5e d766 de75
+= 1.23456789000000000011e+307
+fI[0] == strtox
+
+
+Input: 1.23456589e-307
+
+strtox consumes 15 bytes and returns 17
+with bits = #3c03 b18c b5dc c22f d369
+printf("%.21Lg") gives 1.23456588999999999999e-307
+g_xfmt(0) gives 15 bytes: "1.23456589e-307"
+
+strtoIx returns 17, consuming 15 bytes.
+fI[0] = #3c03 b18c b5dc c22f d369
+= 1.23456588999999999999e-307
+fI[1] = #3c03 b18c b5dc c22f d369
+= 1.23456589000000000009e-307
+fI[0] == strtox
+
+
+Input: 1.234567890123456789
+
+strtox consumes 20 bytes and returns 17
+with bits = #3fff 9e06 5214 62cf db8d
+printf("%.21Lg") gives 1.23456789012345678899
+g_xfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIx returns 17, consuming 20 bytes.
+fI[0] = #3fff 9e06 5214 62cf db8d
+= 1.23456789012345678899
+fI[1] = #3fff 9e06 5214 62cf db8d
+= 1.23456789012345678909
+fI[0] == strtox
+
+
+Input: 1.234567890123456789e301
+
+strtox consumes 24 bytes and returns 33
+with bits = #43e7 937a 8baf ab20 980c
+printf("%.21Lg") gives 1.234567890123456789e+301
+g_xfmt(0) gives 25 bytes: "1.234567890123456789e+301"
+
+strtoIx returns 33, consuming 24 bytes.
+fI[0] = #43e7 937a 8baf ab20 980b
+= 1.23456789012345678889e+301
+fI[1] = #43e7 937a 8baf ab20 980b
+= 1.234567890123456789e+301
+fI[1] == strtox
+
+
+Input: 1.234567890123456789e-301
+
+strtox consumes 25 bytes and returns 33
+with bits = #3c17 a953 271a 5d06 9ad9
+printf("%.21Lg") gives 1.23456789012345678902e-301
+g_xfmt(0) gives 25 bytes: "1.234567890123456789e-301"
+
+strtoIx returns 33, consuming 25 bytes.
+fI[0] = #3c17 a953 271a 5d06 9ad8
+= 1.23456789012345678892e-301
+fI[1] = #3c17 a953 271a 5d06 9ad8
+= 1.23456789012345678902e-301
+fI[1] == strtox
+
+
+Input: 1.234567890123456789e-321
+
+strtox consumes 25 bytes and returns 33
+with bits = #3bd4 f9e1 1b4c ea6d cce9
+printf("%.21Lg") gives 1.234567890123456789e-321
+g_xfmt(0) gives 25 bytes: "1.234567890123456789e-321"
+
+strtoIx returns 33, consuming 25 bytes.
+fI[0] = #3bd4 f9e1 1b4c ea6d cce8
+= 1.23456789012345678893e-321
+fI[1] = #3bd4 f9e1 1b4c ea6d cce8
+= 1.234567890123456789e-321
+fI[1] == strtox
+
+
+Input: 1e23
+
+strtox consumes 4 bytes and returns 1
+with bits = #404b a968 163f a57 b400
+printf("%.21Lg") gives 1e+23
+g_xfmt(0) gives 5 bytes: "1e+23"
+
+strtoIx returns 1, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1e310
+
+strtox consumes 5 bytes and returns 33
+with bits = #4404 de81 e40a 34b cf50
+printf("%.21Lg") gives 1e+310
+g_xfmt(0) gives 6 bytes: "1e+310"
+
+strtoIx returns 33, consuming 5 bytes.
+fI[0] = #4404 de81 e40a 34b cf4f
+= 9.9999999999999999994e+309
+fI[1] = #4404 de81 e40a 34b cf4f
+= 1e+310
+fI[1] == strtox
+
+
+Input: 9.0259718793241475e-277
+
+strtox consumes 23 bytes and returns 33
+with bits = #3c69 ffff ffff ffff fcf7
+printf("%.21Lg") gives 9.02597187932414750016e-277
+g_xfmt(0) gives 23 bytes: "9.0259718793241475e-277"
+
+strtoIx returns 33, consuming 23 bytes.
+fI[0] = #3c69 ffff ffff ffff fcf6
+= 9.02597187932414749967e-277
+fI[1] = #3c69 ffff ffff ffff fcf6
+= 9.02597187932414750016e-277
+fI[1] == strtox
+
+
+Input: 9.025971879324147880346310405869e-277
+
+strtox consumes 37 bytes and returns 17
+with bits = #3c6a 8000 0 0 0
+printf("%.21Lg") gives 9.02597187932414788035e-277
+g_xfmt(0) gives 26 bytes: "9.0259718793241478803e-277"
+
+strtoIx returns 17, consuming 37 bytes.
+fI[0] = #3c6a 8000 0 0 0
+= 9.02597187932414788035e-277
+fI[1] = #3c6a 8000 0 0 0
+= 9.02597187932414788132e-277
+fI[0] == strtox
+
+
+Input: 9.025971879324147880346310405868e-277
+
+strtox consumes 37 bytes and returns 33
+with bits = #3c6a 8000 0 0 0
+printf("%.21Lg") gives 9.02597187932414788035e-277
+g_xfmt(0) gives 26 bytes: "9.0259718793241478803e-277"
+
+strtoIx returns 33, consuming 37 bytes.
+fI[0] = #3c69 ffff ffff ffff ffff
+= 9.02597187932414787986e-277
+fI[1] = #3c6a 8000 0 ffff ffff
+= 9.02597187932414788035e-277
+fI[1] == strtox
+
+
+Input: 2.2250738585072014e-308
+
+strtox consumes 23 bytes and returns 17
+with bits = #3c01 8000 0 0 46
+printf("%.21Lg") gives 2.22507385850720139998e-308
+g_xfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoIx returns 17, consuming 23 bytes.
+fI[0] = #3c01 8000 0 0 46
+= 2.22507385850720139998e-308
+fI[1] = #3c01 8000 0 0 46
+= 2.22507385850720140022e-308
+fI[0] == strtox
+
+
+Input: 2.2250738585072013e-308
+
+strtox consumes 23 bytes and returns 17
+with bits = #3c00 ffff ffff ffff fd4f
+printf("%.21Lg") gives 2.22507385850720129998e-308
+g_xfmt(0) gives 23 bytes: "2.2250738585072013e-308"
+
+strtoIx returns 17, consuming 23 bytes.
+fI[0] = #3c00 ffff ffff ffff fd4f
+= 2.22507385850720129998e-308
+fI[1] = #3c00 ffff ffff ffff fd4f
+= 2.2250738585072013001e-308
+fI[0] == strtox
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff 8ccc cccc cccc cccc
+printf("%.21Lg") gives 1.09999999999999999991
+g_xfmt(0) gives 21 bytes: "1.0999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 8ccc cccc cccc cccc
+= 1.09999999999999999991
+fI[1] = #3fff 8ccc cccc cccc cccc
+= 1.10000000000000000002
+fI[0] == strtox
+
+
+Input: -1.1
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff 8ccc cccc cccc cccc
+printf("%.21Lg") gives -1.09999999999999999991
+g_xfmt(0) gives 22 bytes: "-1.0999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 8ccc cccc cccc cccd
+= -1.10000000000000000002
+fI[1] = #bfff 8ccc cccc cccc cccd
+= -1.09999999999999999991
+fI[1] == strtox
+
+
+Input: 1.2
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff 9999 9999 9999 9999
+printf("%.21Lg") gives 1.19999999999999999993
+g_xfmt(0) gives 21 bytes: "1.1999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 9999 9999 9999 9999
+= 1.19999999999999999993
+fI[1] = #3fff 9999 9999 9999 9999
+= 1.20000000000000000004
+fI[0] == strtox
+
+
+Input: -1.2
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff 9999 9999 9999 9999
+printf("%.21Lg") gives -1.19999999999999999993
+g_xfmt(0) gives 22 bytes: "-1.1999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 9999 9999 9999 999a
+= -1.20000000000000000004
+fI[1] = #bfff 9999 9999 9999 999a
+= -1.19999999999999999993
+fI[1] == strtox
+
+
+Input: 1.3
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff a666 6666 6666 6666
+printf("%.21Lg") gives 1.29999999999999999996
+g_xfmt(0) gives 3 bytes: "1.3"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff a666 6666 6666 6666
+= 1.29999999999999999996
+fI[1] = #3fff a666 6666 6666 6666
+= 1.30000000000000000007
+fI[0] == strtox
+
+
+Input: -1.3
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff a666 6666 6666 6666
+printf("%.21Lg") gives -1.29999999999999999996
+g_xfmt(0) gives 4 bytes: "-1.3"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff a666 6666 6666 6667
+= -1.30000000000000000007
+fI[1] = #bfff a666 6666 6666 6667
+= -1.29999999999999999996
+fI[1] == strtox
+
+
+Input: 1.4
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff b333 3333 3333 3333
+printf("%.21Lg") gives 1.39999999999999999998
+g_xfmt(0) gives 3 bytes: "1.4"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff b333 3333 3333 3333
+= 1.39999999999999999998
+fI[1] = #3fff b333 3333 3333 3333
+= 1.40000000000000000009
+fI[0] == strtox
+
+
+Input: -1.4
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff b333 3333 3333 3333
+printf("%.21Lg") gives -1.39999999999999999998
+g_xfmt(0) gives 4 bytes: "-1.4"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff b333 3333 3333 3334
+= -1.40000000000000000009
+fI[1] = #bfff b333 3333 3333 3334
+= -1.39999999999999999998
+fI[1] == strtox
+
+
+Input: 1.5
+
+strtox consumes 3 bytes and returns 1
+with bits = #3fff c000 0 0 0
+printf("%.21Lg") gives 1.5
+g_xfmt(0) gives 3 bytes: "1.5"
+
+strtoIx returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: -1.5
+
+strtox consumes 4 bytes and returns 9
+with bits = #bfff c000 0 0 0
+printf("%.21Lg") gives -1.5
+g_xfmt(0) gives 4 bytes: "-1.5"
+
+strtoIx returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.6
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff cccc cccc cccc cccc
+printf("%.21Lg") gives 1.59999999999999999991
+g_xfmt(0) gives 21 bytes: "1.5999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff cccc cccc cccc cccc
+= 1.59999999999999999991
+fI[1] = #3fff cccc cccc cccc cccc
+= 1.60000000000000000002
+fI[0] == strtox
+
+
+Input: -1.6
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff cccc cccc cccc cccc
+printf("%.21Lg") gives -1.59999999999999999991
+g_xfmt(0) gives 22 bytes: "-1.5999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff cccc cccc cccc cccd
+= -1.60000000000000000002
+fI[1] = #bfff cccc cccc cccc cccd
+= -1.59999999999999999991
+fI[1] == strtox
+
+
+Input: 1.7
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff d999 9999 9999 9999
+printf("%.21Lg") gives 1.69999999999999999993
+g_xfmt(0) gives 21 bytes: "1.6999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff d999 9999 9999 9999
+= 1.69999999999999999993
+fI[1] = #3fff d999 9999 9999 9999
+= 1.70000000000000000004
+fI[0] == strtox
+
+
+Input: -1.7
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff d999 9999 9999 9999
+printf("%.21Lg") gives -1.69999999999999999993
+g_xfmt(0) gives 22 bytes: "-1.6999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff d999 9999 9999 999a
+= -1.70000000000000000004
+fI[1] = #bfff d999 9999 9999 999a
+= -1.69999999999999999993
+fI[1] == strtox
+
+
+Input: 1.8
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff e666 6666 6666 6666
+printf("%.21Lg") gives 1.79999999999999999996
+g_xfmt(0) gives 3 bytes: "1.8"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff e666 6666 6666 6666
+= 1.79999999999999999996
+fI[1] = #3fff e666 6666 6666 6666
+= 1.80000000000000000007
+fI[0] == strtox
+
+
+Input: -1.8
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff e666 6666 6666 6666
+printf("%.21Lg") gives -1.79999999999999999996
+g_xfmt(0) gives 4 bytes: "-1.8"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff e666 6666 6666 6667
+= -1.80000000000000000007
+fI[1] = #bfff e666 6666 6666 6667
+= -1.79999999999999999996
+fI[1] == strtox
+
+
+Input: 1.9
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff f333 3333 3333 3333
+printf("%.21Lg") gives 1.89999999999999999998
+g_xfmt(0) gives 3 bytes: "1.9"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff f333 3333 3333 3333
+= 1.89999999999999999998
+fI[1] = #3fff f333 3333 3333 3333
+= 1.90000000000000000009
+fI[0] == strtox
+
+
+Input: -1.9
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff f333 3333 3333 3333
+printf("%.21Lg") gives -1.89999999999999999998
+g_xfmt(0) gives 4 bytes: "-1.9"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff f333 3333 3333 3334
+= -1.90000000000000000009
+fI[1] = #bfff f333 3333 3333 3334
+= -1.89999999999999999998
+fI[1] == strtox
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff 8ccc cccc cccc cccd
+printf("%.21Lg") gives 1.10000000000000000002
+g_xfmt(0) gives 3 bytes: "1.1"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 8ccc cccc cccc cccc
+= 1.09999999999999999991
+fI[1] = #3fff 8ccc cccc cccc cccc
+= 1.10000000000000000002
+fI[1] == strtox
+
+
+Input: -1.1
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff 8ccc cccc cccc cccd
+printf("%.21Lg") gives -1.10000000000000000002
+g_xfmt(0) gives 4 bytes: "-1.1"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 8ccc cccc cccc cccd
+= -1.10000000000000000002
+fI[1] = #bfff 8ccc cccc cccc cccd
+= -1.09999999999999999991
+fI[0] == strtox
+
+
+Input: 1.2
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff 9999 9999 9999 999a
+printf("%.21Lg") gives 1.20000000000000000004
+g_xfmt(0) gives 3 bytes: "1.2"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 9999 9999 9999 9999
+= 1.19999999999999999993
+fI[1] = #3fff 9999 9999 9999 9999
+= 1.20000000000000000004
+fI[1] == strtox
+
+
+Input: -1.2
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff 9999 9999 9999 999a
+printf("%.21Lg") gives -1.20000000000000000004
+g_xfmt(0) gives 4 bytes: "-1.2"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 9999 9999 9999 999a
+= -1.20000000000000000004
+fI[1] = #bfff 9999 9999 9999 999a
+= -1.19999999999999999993
+fI[0] == strtox
+
+
+Input: 1.3
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff a666 6666 6666 6666
+printf("%.21Lg") gives 1.29999999999999999996
+g_xfmt(0) gives 3 bytes: "1.3"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff a666 6666 6666 6666
+= 1.29999999999999999996
+fI[1] = #3fff a666 6666 6666 6666
+= 1.30000000000000000007
+fI[0] == strtox
+
+
+Input: -1.3
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff a666 6666 6666 6666
+printf("%.21Lg") gives -1.29999999999999999996
+g_xfmt(0) gives 4 bytes: "-1.3"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff a666 6666 6666 6667
+= -1.30000000000000000007
+fI[1] = #bfff a666 6666 6666 6667
+= -1.29999999999999999996
+fI[1] == strtox
+
+
+Input: 1.4
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff b333 3333 3333 3333
+printf("%.21Lg") gives 1.39999999999999999998
+g_xfmt(0) gives 3 bytes: "1.4"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff b333 3333 3333 3333
+= 1.39999999999999999998
+fI[1] = #3fff b333 3333 3333 3333
+= 1.40000000000000000009
+fI[0] == strtox
+
+
+Input: -1.4
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff b333 3333 3333 3333
+printf("%.21Lg") gives -1.39999999999999999998
+g_xfmt(0) gives 4 bytes: "-1.4"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff b333 3333 3333 3334
+= -1.40000000000000000009
+fI[1] = #bfff b333 3333 3333 3334
+= -1.39999999999999999998
+fI[1] == strtox
+
+
+Input: 1.5
+
+strtox consumes 3 bytes and returns 1
+with bits = #3fff c000 0 0 0
+printf("%.21Lg") gives 1.5
+g_xfmt(0) gives 3 bytes: "1.5"
+
+strtoIx returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: -1.5
+
+strtox consumes 4 bytes and returns 9
+with bits = #bfff c000 0 0 0
+printf("%.21Lg") gives -1.5
+g_xfmt(0) gives 4 bytes: "-1.5"
+
+strtoIx returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.6
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff cccc cccc cccc cccd
+printf("%.21Lg") gives 1.60000000000000000002
+g_xfmt(0) gives 3 bytes: "1.6"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff cccc cccc cccc cccc
+= 1.59999999999999999991
+fI[1] = #3fff cccc cccc cccc cccc
+= 1.60000000000000000002
+fI[1] == strtox
+
+
+Input: -1.6
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff cccc cccc cccc cccd
+printf("%.21Lg") gives -1.60000000000000000002
+g_xfmt(0) gives 4 bytes: "-1.6"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff cccc cccc cccc cccd
+= -1.60000000000000000002
+fI[1] = #bfff cccc cccc cccc cccd
+= -1.59999999999999999991
+fI[0] == strtox
+
+
+Input: 1.7
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff d999 9999 9999 999a
+printf("%.21Lg") gives 1.70000000000000000004
+g_xfmt(0) gives 3 bytes: "1.7"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff d999 9999 9999 9999
+= 1.69999999999999999993
+fI[1] = #3fff d999 9999 9999 9999
+= 1.70000000000000000004
+fI[1] == strtox
+
+
+Input: -1.7
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff d999 9999 9999 999a
+printf("%.21Lg") gives -1.70000000000000000004
+g_xfmt(0) gives 4 bytes: "-1.7"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff d999 9999 9999 999a
+= -1.70000000000000000004
+fI[1] = #bfff d999 9999 9999 999a
+= -1.69999999999999999993
+fI[0] == strtox
+
+
+Input: 1.8
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff e666 6666 6666 6666
+printf("%.21Lg") gives 1.79999999999999999996
+g_xfmt(0) gives 3 bytes: "1.8"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff e666 6666 6666 6666
+= 1.79999999999999999996
+fI[1] = #3fff e666 6666 6666 6666
+= 1.80000000000000000007
+fI[0] == strtox
+
+
+Input: -1.8
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff e666 6666 6666 6666
+printf("%.21Lg") gives -1.79999999999999999996
+g_xfmt(0) gives 4 bytes: "-1.8"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff e666 6666 6666 6667
+= -1.80000000000000000007
+fI[1] = #bfff e666 6666 6666 6667
+= -1.79999999999999999996
+fI[1] == strtox
+
+
+Input: 1.9
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff f333 3333 3333 3333
+printf("%.21Lg") gives 1.89999999999999999998
+g_xfmt(0) gives 3 bytes: "1.9"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff f333 3333 3333 3333
+= 1.89999999999999999998
+fI[1] = #3fff f333 3333 3333 3333
+= 1.90000000000000000009
+fI[0] == strtox
+
+
+Input: -1.9
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff f333 3333 3333 3333
+printf("%.21Lg") gives -1.89999999999999999998
+g_xfmt(0) gives 4 bytes: "-1.9"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff f333 3333 3333 3334
+= -1.90000000000000000009
+fI[1] = #bfff f333 3333 3333 3334
+= -1.89999999999999999998
+fI[1] == strtox
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff 8ccc cccc cccc cccd
+printf("%.21Lg") gives 1.10000000000000000002
+g_xfmt(0) gives 3 bytes: "1.1"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 8ccc cccc cccc cccc
+= 1.09999999999999999991
+fI[1] = #3fff 8ccc cccc cccc cccc
+= 1.10000000000000000002
+fI[1] == strtox
+
+
+Input: -1.1
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff 8ccc cccc cccc cccc
+printf("%.21Lg") gives -1.09999999999999999991
+g_xfmt(0) gives 22 bytes: "-1.0999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 8ccc cccc cccc cccd
+= -1.10000000000000000002
+fI[1] = #bfff 8ccc cccc cccc cccd
+= -1.09999999999999999991
+fI[1] == strtox
+
+
+Input: 1.2
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff 9999 9999 9999 999a
+printf("%.21Lg") gives 1.20000000000000000004
+g_xfmt(0) gives 3 bytes: "1.2"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 9999 9999 9999 9999
+= 1.19999999999999999993
+fI[1] = #3fff 9999 9999 9999 9999
+= 1.20000000000000000004
+fI[1] == strtox
+
+
+Input: -1.2
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff 9999 9999 9999 9999
+printf("%.21Lg") gives -1.19999999999999999993
+g_xfmt(0) gives 22 bytes: "-1.1999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 9999 9999 9999 999a
+= -1.20000000000000000004
+fI[1] = #bfff 9999 9999 9999 999a
+= -1.19999999999999999993
+fI[1] == strtox
+
+
+Input: 1.3
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff a666 6666 6666 6667
+printf("%.21Lg") gives 1.30000000000000000007
+g_xfmt(0) gives 21 bytes: "1.3000000000000000001"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff a666 6666 6666 6666
+= 1.29999999999999999996
+fI[1] = #3fff a666 6666 6666 6666
+= 1.30000000000000000007
+fI[1] == strtox
+
+
+Input: -1.3
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff a666 6666 6666 6666
+printf("%.21Lg") gives -1.29999999999999999996
+g_xfmt(0) gives 4 bytes: "-1.3"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff a666 6666 6666 6667
+= -1.30000000000000000007
+fI[1] = #bfff a666 6666 6666 6667
+= -1.29999999999999999996
+fI[1] == strtox
+
+
+Input: 1.4
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff b333 3333 3333 3334
+printf("%.21Lg") gives 1.40000000000000000009
+g_xfmt(0) gives 21 bytes: "1.4000000000000000001"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff b333 3333 3333 3333
+= 1.39999999999999999998
+fI[1] = #3fff b333 3333 3333 3333
+= 1.40000000000000000009
+fI[1] == strtox
+
+
+Input: -1.4
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff b333 3333 3333 3333
+printf("%.21Lg") gives -1.39999999999999999998
+g_xfmt(0) gives 4 bytes: "-1.4"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff b333 3333 3333 3334
+= -1.40000000000000000009
+fI[1] = #bfff b333 3333 3333 3334
+= -1.39999999999999999998
+fI[1] == strtox
+
+
+Input: 1.5
+
+strtox consumes 3 bytes and returns 1
+with bits = #3fff c000 0 0 0
+printf("%.21Lg") gives 1.5
+g_xfmt(0) gives 3 bytes: "1.5"
+
+strtoIx returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: -1.5
+
+strtox consumes 4 bytes and returns 9
+with bits = #bfff c000 0 0 0
+printf("%.21Lg") gives -1.5
+g_xfmt(0) gives 4 bytes: "-1.5"
+
+strtoIx returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.6
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff cccc cccc cccc cccd
+printf("%.21Lg") gives 1.60000000000000000002
+g_xfmt(0) gives 3 bytes: "1.6"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff cccc cccc cccc cccc
+= 1.59999999999999999991
+fI[1] = #3fff cccc cccc cccc cccc
+= 1.60000000000000000002
+fI[1] == strtox
+
+
+Input: -1.6
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff cccc cccc cccc cccc
+printf("%.21Lg") gives -1.59999999999999999991
+g_xfmt(0) gives 22 bytes: "-1.5999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff cccc cccc cccc cccd
+= -1.60000000000000000002
+fI[1] = #bfff cccc cccc cccc cccd
+= -1.59999999999999999991
+fI[1] == strtox
+
+
+Input: 1.7
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff d999 9999 9999 999a
+printf("%.21Lg") gives 1.70000000000000000004
+g_xfmt(0) gives 3 bytes: "1.7"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff d999 9999 9999 9999
+= 1.69999999999999999993
+fI[1] = #3fff d999 9999 9999 9999
+= 1.70000000000000000004
+fI[1] == strtox
+
+
+Input: -1.7
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff d999 9999 9999 9999
+printf("%.21Lg") gives -1.69999999999999999993
+g_xfmt(0) gives 22 bytes: "-1.6999999999999999999"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff d999 9999 9999 999a
+= -1.70000000000000000004
+fI[1] = #bfff d999 9999 9999 999a
+= -1.69999999999999999993
+fI[1] == strtox
+
+
+Input: 1.8
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff e666 6666 6666 6667
+printf("%.21Lg") gives 1.80000000000000000007
+g_xfmt(0) gives 21 bytes: "1.8000000000000000001"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff e666 6666 6666 6666
+= 1.79999999999999999996
+fI[1] = #3fff e666 6666 6666 6666
+= 1.80000000000000000007
+fI[1] == strtox
+
+
+Input: -1.8
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff e666 6666 6666 6666
+printf("%.21Lg") gives -1.79999999999999999996
+g_xfmt(0) gives 4 bytes: "-1.8"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff e666 6666 6666 6667
+= -1.80000000000000000007
+fI[1] = #bfff e666 6666 6666 6667
+= -1.79999999999999999996
+fI[1] == strtox
+
+
+Input: 1.9
+
+strtox consumes 3 bytes and returns 33
+with bits = #3fff f333 3333 3333 3334
+printf("%.21Lg") gives 1.90000000000000000009
+g_xfmt(0) gives 21 bytes: "1.9000000000000000001"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff f333 3333 3333 3333
+= 1.89999999999999999998
+fI[1] = #3fff f333 3333 3333 3333
+= 1.90000000000000000009
+fI[1] == strtox
+
+
+Input: -1.9
+
+strtox consumes 4 bytes and returns 25
+with bits = #bfff f333 3333 3333 3333
+printf("%.21Lg") gives -1.89999999999999999998
+g_xfmt(0) gives 4 bytes: "-1.9"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff f333 3333 3333 3334
+= -1.90000000000000000009
+fI[1] = #bfff f333 3333 3333 3334
+= -1.89999999999999999998
+fI[1] == strtox
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff 8ccc cccc cccc cccc
+printf("%.21Lg") gives 1.09999999999999999991
+g_xfmt(0) gives 21 bytes: "1.0999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 8ccc cccc cccc cccc
+= 1.09999999999999999991
+fI[1] = #3fff 8ccc cccc cccc cccc
+= 1.10000000000000000002
+fI[0] == strtox
+
+
+Input: -1.1
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff 8ccc cccc cccc cccd
+printf("%.21Lg") gives -1.10000000000000000002
+g_xfmt(0) gives 4 bytes: "-1.1"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 8ccc cccc cccc cccd
+= -1.10000000000000000002
+fI[1] = #bfff 8ccc cccc cccc cccd
+= -1.09999999999999999991
+fI[0] == strtox
+
+
+Input: 1.2
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff 9999 9999 9999 9999
+printf("%.21Lg") gives 1.19999999999999999993
+g_xfmt(0) gives 21 bytes: "1.1999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff 9999 9999 9999 9999
+= 1.19999999999999999993
+fI[1] = #3fff 9999 9999 9999 9999
+= 1.20000000000000000004
+fI[0] == strtox
+
+
+Input: -1.2
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff 9999 9999 9999 999a
+printf("%.21Lg") gives -1.20000000000000000004
+g_xfmt(0) gives 4 bytes: "-1.2"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff 9999 9999 9999 999a
+= -1.20000000000000000004
+fI[1] = #bfff 9999 9999 9999 999a
+= -1.19999999999999999993
+fI[0] == strtox
+
+
+Input: 1.3
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff a666 6666 6666 6666
+printf("%.21Lg") gives 1.29999999999999999996
+g_xfmt(0) gives 3 bytes: "1.3"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff a666 6666 6666 6666
+= 1.29999999999999999996
+fI[1] = #3fff a666 6666 6666 6666
+= 1.30000000000000000007
+fI[0] == strtox
+
+
+Input: -1.3
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff a666 6666 6666 6667
+printf("%.21Lg") gives -1.30000000000000000007
+g_xfmt(0) gives 22 bytes: "-1.3000000000000000001"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff a666 6666 6666 6667
+= -1.30000000000000000007
+fI[1] = #bfff a666 6666 6666 6667
+= -1.29999999999999999996
+fI[0] == strtox
+
+
+Input: 1.4
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff b333 3333 3333 3333
+printf("%.21Lg") gives 1.39999999999999999998
+g_xfmt(0) gives 3 bytes: "1.4"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff b333 3333 3333 3333
+= 1.39999999999999999998
+fI[1] = #3fff b333 3333 3333 3333
+= 1.40000000000000000009
+fI[0] == strtox
+
+
+Input: -1.4
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff b333 3333 3333 3334
+printf("%.21Lg") gives -1.40000000000000000009
+g_xfmt(0) gives 22 bytes: "-1.4000000000000000001"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff b333 3333 3333 3334
+= -1.40000000000000000009
+fI[1] = #bfff b333 3333 3333 3334
+= -1.39999999999999999998
+fI[0] == strtox
+
+
+Input: 1.5
+
+strtox consumes 3 bytes and returns 1
+with bits = #3fff c000 0 0 0
+printf("%.21Lg") gives 1.5
+g_xfmt(0) gives 3 bytes: "1.5"
+
+strtoIx returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: -1.5
+
+strtox consumes 4 bytes and returns 9
+with bits = #bfff c000 0 0 0
+printf("%.21Lg") gives -1.5
+g_xfmt(0) gives 4 bytes: "-1.5"
+
+strtoIx returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtox
+
+
+Input: 1.6
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff cccc cccc cccc cccc
+printf("%.21Lg") gives 1.59999999999999999991
+g_xfmt(0) gives 21 bytes: "1.5999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff cccc cccc cccc cccc
+= 1.59999999999999999991
+fI[1] = #3fff cccc cccc cccc cccc
+= 1.60000000000000000002
+fI[0] == strtox
+
+
+Input: -1.6
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff cccc cccc cccc cccd
+printf("%.21Lg") gives -1.60000000000000000002
+g_xfmt(0) gives 4 bytes: "-1.6"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff cccc cccc cccc cccd
+= -1.60000000000000000002
+fI[1] = #bfff cccc cccc cccc cccd
+= -1.59999999999999999991
+fI[0] == strtox
+
+
+Input: 1.7
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff d999 9999 9999 9999
+printf("%.21Lg") gives 1.69999999999999999993
+g_xfmt(0) gives 21 bytes: "1.6999999999999999999"
+
+strtoIx returns 33, consuming 3 bytes.
+fI[0] = #3fff d999 9999 9999 9999
+= 1.69999999999999999993
+fI[1] = #3fff d999 9999 9999 9999
+= 1.70000000000000000004
+fI[0] == strtox
+
+
+Input: -1.7
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff d999 9999 9999 999a
+printf("%.21Lg") gives -1.70000000000000000004
+g_xfmt(0) gives 4 bytes: "-1.7"
+
+strtoIx returns 41, consuming 4 bytes.
+fI[0] = #bfff d999 9999 9999 999a
+= -1.70000000000000000004
+fI[1] = #bfff d999 9999 9999 999a
+= -1.69999999999999999993
+fI[0] == strtox
+
+
+Input: 1.8
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff e666 6666 6666 6666
+printf("%.21Lg") gives 1.79999999999999999996
+g_xfmt(0) gives 3 bytes: "1.8"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff e666 6666 6666 6666
+= 1.79999999999999999996
+fI[1] = #3fff e666 6666 6666 6666
+= 1.80000000000000000007
+fI[0] == strtox
+
+
+Input: -1.8
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff e666 6666 6666 6667
+printf("%.21Lg") gives -1.80000000000000000007
+g_xfmt(0) gives 22 bytes: "-1.8000000000000000001"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff e666 6666 6666 6667
+= -1.80000000000000000007
+fI[1] = #bfff e666 6666 6666 6667
+= -1.79999999999999999996
+fI[0] == strtox
+
+
+Input: 1.9
+
+strtox consumes 3 bytes and returns 17
+with bits = #3fff f333 3333 3333 3333
+printf("%.21Lg") gives 1.89999999999999999998
+g_xfmt(0) gives 3 bytes: "1.9"
+
+strtoIx returns 17, consuming 3 bytes.
+fI[0] = #3fff f333 3333 3333 3333
+= 1.89999999999999999998
+fI[1] = #3fff f333 3333 3333 3333
+= 1.90000000000000000009
+fI[0] == strtox
+
+
+Input: -1.9
+
+strtox consumes 4 bytes and returns 41
+with bits = #bfff f333 3333 3333 3334
+printf("%.21Lg") gives -1.90000000000000000009
+g_xfmt(0) gives 22 bytes: "-1.9000000000000000001"
+
+strtoIx returns 25, consuming 4 bytes.
+fI[0] = #bfff f333 3333 3333 3334
+= -1.90000000000000000009
+fI[1] = #bfff f333 3333 3333 3334
+= -1.89999999999999999998
+fI[0] == strtox
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/xL.ou0
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/xL.ou0	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/xL.ou0	(revision 2448)
@@ -0,0 +1,1182 @@
+
+Input: 1.23
+
+strtoxL consumes 4 bytes and returns 33
+with bits = #3fff0000 9d70a3d7 a3d70a4
+g_xLfmt(0) gives 4 bytes: "1.23"
+
+strtoIxL returns 33, consuming 4 bytes.
+fI[0] = #3fff0000 9d70a3d7 a3d70a3
+fI[1] = #3fff0000 9d70a3d7 a3d70a4
+fI[1] == strtoxL
+
+
+Input: 1.23e+20
+
+strtoxL consumes 8 bytes and returns 1
+with bits = #40410000 d55ef90a 2da18000
+g_xLfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIxL returns 1, consuming 8 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.23e-20
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #3fbc0000 e857267b b3a984f2
+g_xLfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #3fbc0000 e857267b b3a984f2
+fI[1] = #3fbc0000 e857267b b3a984f3
+fI[0] == strtoxL
+
+
+Input: 1.23456789
+
+strtoxL consumes 10 bytes and returns 33
+with bits = #3fff0000 9e065214 1ef0dbf6
+g_xLfmt(0) gives 10 bytes: "1.23456789"
+
+strtoIxL returns 33, consuming 10 bytes.
+fI[0] = #3fff0000 9e065214 1ef0dbf5
+fI[1] = #3fff0000 9e065214 1ef0dbf6
+fI[1] == strtoxL
+
+
+Input: 1.23456589e+20
+
+strtoxL consumes 14 bytes and returns 1
+with bits = #40410000 d629bd33 5ccba00
+g_xLfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoIxL returns 1, consuming 14 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.23e+30
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #40620000 f8658274 7dbc824a
+g_xLfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #40620000 f8658274 7dbc824a
+fI[1] = #40620000 f8658274 7dbc824b
+fI[0] == strtoxL
+
+
+Input: 1.23e-30
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #3f9b0000 c794337a 808554eb
+g_xLfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #3f9b0000 c794337a 808554eb
+fI[1] = #3f9b0000 c794337a 808554ec
+fI[0] == strtoxL
+
+
+Input: 1.23456789e-20
+
+strtoxL consumes 14 bytes and returns 17
+with bits = #3fbc0000 e9340a38 f3d6d352
+g_xLfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoIxL returns 17, consuming 14 bytes.
+fI[0] = #3fbc0000 e9340a38 f3d6d352
+fI[1] = #3fbc0000 e9340a38 f3d6d353
+fI[0] == strtoxL
+
+
+Input: 1.23456789e-30
+
+strtoxL consumes 14 bytes and returns 17
+with bits = #3f9b0000 c851f19d decca8fc
+g_xLfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoIxL returns 17, consuming 14 bytes.
+fI[0] = #3f9b0000 c851f19d decca8fc
+fI[1] = #3f9b0000 c851f19d decca8fd
+fI[0] == strtoxL
+
+
+Input: 1.234567890123456789
+
+strtoxL consumes 20 bytes and returns 17
+with bits = #3fff0000 9e065214 62cfdb8d
+g_xLfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIxL returns 17, consuming 20 bytes.
+fI[0] = #3fff0000 9e065214 62cfdb8d
+fI[1] = #3fff0000 9e065214 62cfdb8e
+fI[0] == strtoxL
+
+
+Input: 1.23456789012345678901234567890123456789
+
+strtoxL consumes 40 bytes and returns 17
+with bits = #3fff0000 9e065214 62cfdb8d
+g_xLfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIxL returns 17, consuming 40 bytes.
+fI[0] = #3fff0000 9e065214 62cfdb8d
+fI[1] = #3fff0000 9e065214 62cfdb8e
+fI[0] == strtoxL
+
+
+Input: 1.23e306
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #43f70000 e033b668 e30fa6d5
+g_xLfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #43f70000 e033b668 e30fa6d5
+fI[1] = #43f70000 e033b668 e30fa6d6
+fI[0] == strtoxL
+
+
+Input: 1.23e-306
+
+strtoxL consumes 9 bytes and returns 33
+with bits = #3c060000 dd1dc2ed 1cb73f25
+g_xLfmt(0) gives 9 bytes: "1.23e-306"
+
+strtoIxL returns 33, consuming 9 bytes.
+fI[0] = #3c060000 dd1dc2ed 1cb73f24
+fI[1] = #3c060000 dd1dc2ed 1cb73f25
+fI[1] == strtoxL
+
+
+Input: 1.23e-320
+
+strtoxL consumes 9 bytes and returns 33
+with bits = #3bd80000 9b98c371 844c3f1a
+g_xLfmt(0) gives 9 bytes: "1.23e-320"
+
+strtoIxL returns 33, consuming 9 bytes.
+fI[0] = #3bd80000 9b98c371 844c3f19
+fI[1] = #3bd80000 9b98c371 844c3f1a
+fI[1] == strtoxL
+
+
+Input: 1.23e-20
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #3fbc0000 e857267b b3a984f2
+g_xLfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #3fbc0000 e857267b b3a984f2
+fI[1] = #3fbc0000 e857267b b3a984f3
+fI[0] == strtoxL
+
+
+Input: 1.23456789e307
+
+strtoxL consumes 14 bytes and returns 17
+with bits = #43fb0000 8ca58a5e d766de75
+g_xLfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoIxL returns 17, consuming 14 bytes.
+fI[0] = #43fb0000 8ca58a5e d766de75
+fI[1] = #43fb0000 8ca58a5e d766de76
+fI[0] == strtoxL
+
+
+Input: 1.23456589e-307
+
+strtoxL consumes 15 bytes and returns 17
+with bits = #3c030000 b18cb5dc c22fd369
+g_xLfmt(0) gives 15 bytes: "1.23456589e-307"
+
+strtoIxL returns 17, consuming 15 bytes.
+fI[0] = #3c030000 b18cb5dc c22fd369
+fI[1] = #3c030000 b18cb5dc c22fd36a
+fI[0] == strtoxL
+
+
+Input: 1.234567890123456789
+
+strtoxL consumes 20 bytes and returns 17
+with bits = #3fff0000 9e065214 62cfdb8d
+g_xLfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIxL returns 17, consuming 20 bytes.
+fI[0] = #3fff0000 9e065214 62cfdb8d
+fI[1] = #3fff0000 9e065214 62cfdb8e
+fI[0] == strtoxL
+
+
+Input: 1.234567890123456789e301
+
+strtoxL consumes 24 bytes and returns 33
+with bits = #43e70000 937a8baf ab20980c
+g_xLfmt(0) gives 25 bytes: "1.234567890123456789e+301"
+
+strtoIxL returns 33, consuming 24 bytes.
+fI[0] = #43e70000 937a8baf ab20980b
+fI[1] = #43e70000 937a8baf ab20980c
+fI[1] == strtoxL
+
+
+Input: 1.234567890123456789e-301
+
+strtoxL consumes 25 bytes and returns 33
+with bits = #3c170000 a953271a 5d069ad9
+g_xLfmt(0) gives 25 bytes: "1.234567890123456789e-301"
+
+strtoIxL returns 33, consuming 25 bytes.
+fI[0] = #3c170000 a953271a 5d069ad8
+fI[1] = #3c170000 a953271a 5d069ad9
+fI[1] == strtoxL
+
+
+Input: 1.234567890123456789e-321
+
+strtoxL consumes 25 bytes and returns 33
+with bits = #3bd40000 f9e11b4c ea6dcce9
+g_xLfmt(0) gives 25 bytes: "1.234567890123456789e-321"
+
+strtoIxL returns 33, consuming 25 bytes.
+fI[0] = #3bd40000 f9e11b4c ea6dcce8
+fI[1] = #3bd40000 f9e11b4c ea6dcce9
+fI[1] == strtoxL
+
+
+Input: 1e23
+
+strtoxL consumes 4 bytes and returns 1
+with bits = #404b0000 a968163f a57b400
+g_xLfmt(0) gives 5 bytes: "1e+23"
+
+strtoIxL returns 1, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1e310
+
+strtoxL consumes 5 bytes and returns 33
+with bits = #44040000 de81e40a 34bcf50
+g_xLfmt(0) gives 6 bytes: "1e+310"
+
+strtoIxL returns 33, consuming 5 bytes.
+fI[0] = #44040000 de81e40a 34bcf4f
+fI[1] = #44040000 de81e40a 34bcf50
+fI[1] == strtoxL
+
+
+Input: 9.0259718793241475e-277
+
+strtoxL consumes 23 bytes and returns 33
+with bits = #3c690000 ffffffff fffffcf7
+g_xLfmt(0) gives 23 bytes: "9.0259718793241475e-277"
+
+strtoIxL returns 33, consuming 23 bytes.
+fI[0] = #3c690000 ffffffff fffffcf6
+fI[1] = #3c690000 ffffffff fffffcf7
+fI[1] == strtoxL
+
+
+Input: 9.025971879324147880346310405869e-277
+
+strtoxL consumes 37 bytes and returns 17
+with bits = #3c6a0000 80000000 0
+g_xLfmt(0) gives 26 bytes: "9.0259718793241478803e-277"
+
+strtoIxL returns 17, consuming 37 bytes.
+fI[0] = #3c6a0000 80000000 0
+fI[1] = #3c6a0000 80000000 1
+fI[0] == strtoxL
+
+
+Input: 9.025971879324147880346310405868e-277
+
+strtoxL consumes 37 bytes and returns 33
+with bits = #3c6a0000 80000000 0
+g_xLfmt(0) gives 26 bytes: "9.0259718793241478803e-277"
+
+strtoIxL returns 33, consuming 37 bytes.
+fI[0] = #3c690000 ffffffff ffffffff
+fI[1] = #3c6a0000 80000000 0
+fI[1] == strtoxL
+
+
+Input: 2.2250738585072014e-308
+
+strtoxL consumes 23 bytes and returns 17
+with bits = #3c010000 80000000 46
+g_xLfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoIxL returns 17, consuming 23 bytes.
+fI[0] = #3c010000 80000000 46
+fI[1] = #3c010000 80000000 47
+fI[0] == strtoxL
+
+
+Input: 2.2250738585072013e-308
+
+strtoxL consumes 23 bytes and returns 17
+with bits = #3c000000 ffffffff fffffd4f
+g_xLfmt(0) gives 23 bytes: "2.2250738585072013e-308"
+
+strtoIxL returns 17, consuming 23 bytes.
+fI[0] = #3c000000 ffffffff fffffd4f
+fI[1] = #3c000000 ffffffff fffffd50
+fI[0] == strtoxL
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 8ccccccc cccccccc
+g_xLfmt(0) gives 21 bytes: "1.0999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 8ccccccc cccccccc
+fI[1] = #3fff0000 8ccccccc cccccccd
+fI[0] == strtoxL
+
+
+Input: -1.1
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 8ccccccc cccccccc
+g_xLfmt(0) gives 22 bytes: "-1.0999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 8ccccccc cccccccd
+fI[1] = #bfff0000 8ccccccc cccccccc
+fI[1] == strtoxL
+
+
+Input: 1.2
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 99999999 99999999
+g_xLfmt(0) gives 21 bytes: "1.1999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 99999999 99999999
+fI[1] = #3fff0000 99999999 9999999a
+fI[0] == strtoxL
+
+
+Input: -1.2
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 99999999 99999999
+g_xLfmt(0) gives 22 bytes: "-1.1999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 99999999 9999999a
+fI[1] = #bfff0000 99999999 99999999
+fI[1] == strtoxL
+
+
+Input: 1.3
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 a6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.3"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 a6666666 66666666
+fI[1] = #3fff0000 a6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.3
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 a6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.3"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 a6666666 66666667
+fI[1] = #bfff0000 a6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.4
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 b3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.4"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 b3333333 33333333
+fI[1] = #3fff0000 b3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.4
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 b3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.4"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 b3333333 33333334
+fI[1] = #bfff0000 b3333333 33333333
+fI[1] == strtoxL
+
+
+Input: 1.5
+
+strtoxL consumes 3 bytes and returns 1
+with bits = #3fff0000 c0000000 0
+g_xLfmt(0) gives 3 bytes: "1.5"
+
+strtoIxL returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: -1.5
+
+strtoxL consumes 4 bytes and returns 9
+with bits = #bfff0000 c0000000 0
+g_xLfmt(0) gives 4 bytes: "-1.5"
+
+strtoIxL returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.6
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 cccccccc cccccccc
+g_xLfmt(0) gives 21 bytes: "1.5999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 cccccccc cccccccc
+fI[1] = #3fff0000 cccccccc cccccccd
+fI[0] == strtoxL
+
+
+Input: -1.6
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 cccccccc cccccccc
+g_xLfmt(0) gives 22 bytes: "-1.5999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 cccccccc cccccccd
+fI[1] = #bfff0000 cccccccc cccccccc
+fI[1] == strtoxL
+
+
+Input: 1.7
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 d9999999 99999999
+g_xLfmt(0) gives 21 bytes: "1.6999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 d9999999 99999999
+fI[1] = #3fff0000 d9999999 9999999a
+fI[0] == strtoxL
+
+
+Input: -1.7
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 d9999999 99999999
+g_xLfmt(0) gives 22 bytes: "-1.6999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 d9999999 9999999a
+fI[1] = #bfff0000 d9999999 99999999
+fI[1] == strtoxL
+
+
+Input: 1.8
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 e6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.8"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 e6666666 66666666
+fI[1] = #3fff0000 e6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.8
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 e6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.8"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 e6666666 66666667
+fI[1] = #bfff0000 e6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.9
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 f3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.9"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 f3333333 33333333
+fI[1] = #3fff0000 f3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.9
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 f3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.9"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 f3333333 33333334
+fI[1] = #bfff0000 f3333333 33333333
+fI[1] == strtoxL
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 8ccccccc cccccccd
+g_xLfmt(0) gives 3 bytes: "1.1"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 8ccccccc cccccccc
+fI[1] = #3fff0000 8ccccccc cccccccd
+fI[1] == strtoxL
+
+
+Input: -1.1
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 8ccccccc cccccccd
+g_xLfmt(0) gives 4 bytes: "-1.1"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 8ccccccc cccccccd
+fI[1] = #bfff0000 8ccccccc cccccccc
+fI[0] == strtoxL
+
+
+Input: 1.2
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 99999999 9999999a
+g_xLfmt(0) gives 3 bytes: "1.2"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 99999999 99999999
+fI[1] = #3fff0000 99999999 9999999a
+fI[1] == strtoxL
+
+
+Input: -1.2
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 99999999 9999999a
+g_xLfmt(0) gives 4 bytes: "-1.2"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 99999999 9999999a
+fI[1] = #bfff0000 99999999 99999999
+fI[0] == strtoxL
+
+
+Input: 1.3
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 a6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.3"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 a6666666 66666666
+fI[1] = #3fff0000 a6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.3
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 a6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.3"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 a6666666 66666667
+fI[1] = #bfff0000 a6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.4
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 b3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.4"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 b3333333 33333333
+fI[1] = #3fff0000 b3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.4
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 b3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.4"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 b3333333 33333334
+fI[1] = #bfff0000 b3333333 33333333
+fI[1] == strtoxL
+
+
+Input: 1.5
+
+strtoxL consumes 3 bytes and returns 1
+with bits = #3fff0000 c0000000 0
+g_xLfmt(0) gives 3 bytes: "1.5"
+
+strtoIxL returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: -1.5
+
+strtoxL consumes 4 bytes and returns 9
+with bits = #bfff0000 c0000000 0
+g_xLfmt(0) gives 4 bytes: "-1.5"
+
+strtoIxL returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.6
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 cccccccc cccccccd
+g_xLfmt(0) gives 3 bytes: "1.6"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 cccccccc cccccccc
+fI[1] = #3fff0000 cccccccc cccccccd
+fI[1] == strtoxL
+
+
+Input: -1.6
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 cccccccc cccccccd
+g_xLfmt(0) gives 4 bytes: "-1.6"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 cccccccc cccccccd
+fI[1] = #bfff0000 cccccccc cccccccc
+fI[0] == strtoxL
+
+
+Input: 1.7
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 d9999999 9999999a
+g_xLfmt(0) gives 3 bytes: "1.7"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 d9999999 99999999
+fI[1] = #3fff0000 d9999999 9999999a
+fI[1] == strtoxL
+
+
+Input: -1.7
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 d9999999 9999999a
+g_xLfmt(0) gives 4 bytes: "-1.7"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 d9999999 9999999a
+fI[1] = #bfff0000 d9999999 99999999
+fI[0] == strtoxL
+
+
+Input: 1.8
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 e6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.8"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 e6666666 66666666
+fI[1] = #3fff0000 e6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.8
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 e6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.8"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 e6666666 66666667
+fI[1] = #bfff0000 e6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.9
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 f3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.9"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 f3333333 33333333
+fI[1] = #3fff0000 f3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.9
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 f3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.9"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 f3333333 33333334
+fI[1] = #bfff0000 f3333333 33333333
+fI[1] == strtoxL
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 8ccccccc cccccccd
+g_xLfmt(0) gives 3 bytes: "1.1"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 8ccccccc cccccccc
+fI[1] = #3fff0000 8ccccccc cccccccd
+fI[1] == strtoxL
+
+
+Input: -1.1
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 8ccccccc cccccccc
+g_xLfmt(0) gives 22 bytes: "-1.0999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 8ccccccc cccccccd
+fI[1] = #bfff0000 8ccccccc cccccccc
+fI[1] == strtoxL
+
+
+Input: 1.2
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 99999999 9999999a
+g_xLfmt(0) gives 3 bytes: "1.2"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 99999999 99999999
+fI[1] = #3fff0000 99999999 9999999a
+fI[1] == strtoxL
+
+
+Input: -1.2
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 99999999 99999999
+g_xLfmt(0) gives 22 bytes: "-1.1999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 99999999 9999999a
+fI[1] = #bfff0000 99999999 99999999
+fI[1] == strtoxL
+
+
+Input: 1.3
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 a6666666 66666667
+g_xLfmt(0) gives 21 bytes: "1.3000000000000000001"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 a6666666 66666666
+fI[1] = #3fff0000 a6666666 66666667
+fI[1] == strtoxL
+
+
+Input: -1.3
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 a6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.3"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 a6666666 66666667
+fI[1] = #bfff0000 a6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.4
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 b3333333 33333334
+g_xLfmt(0) gives 21 bytes: "1.4000000000000000001"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 b3333333 33333333
+fI[1] = #3fff0000 b3333333 33333334
+fI[1] == strtoxL
+
+
+Input: -1.4
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 b3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.4"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 b3333333 33333334
+fI[1] = #bfff0000 b3333333 33333333
+fI[1] == strtoxL
+
+
+Input: 1.5
+
+strtoxL consumes 3 bytes and returns 1
+with bits = #3fff0000 c0000000 0
+g_xLfmt(0) gives 3 bytes: "1.5"
+
+strtoIxL returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: -1.5
+
+strtoxL consumes 4 bytes and returns 9
+with bits = #bfff0000 c0000000 0
+g_xLfmt(0) gives 4 bytes: "-1.5"
+
+strtoIxL returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.6
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 cccccccc cccccccd
+g_xLfmt(0) gives 3 bytes: "1.6"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 cccccccc cccccccc
+fI[1] = #3fff0000 cccccccc cccccccd
+fI[1] == strtoxL
+
+
+Input: -1.6
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 cccccccc cccccccc
+g_xLfmt(0) gives 22 bytes: "-1.5999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 cccccccc cccccccd
+fI[1] = #bfff0000 cccccccc cccccccc
+fI[1] == strtoxL
+
+
+Input: 1.7
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 d9999999 9999999a
+g_xLfmt(0) gives 3 bytes: "1.7"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 d9999999 99999999
+fI[1] = #3fff0000 d9999999 9999999a
+fI[1] == strtoxL
+
+
+Input: -1.7
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 d9999999 99999999
+g_xLfmt(0) gives 22 bytes: "-1.6999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 d9999999 9999999a
+fI[1] = #bfff0000 d9999999 99999999
+fI[1] == strtoxL
+
+
+Input: 1.8
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 e6666666 66666667
+g_xLfmt(0) gives 21 bytes: "1.8000000000000000001"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 e6666666 66666666
+fI[1] = #3fff0000 e6666666 66666667
+fI[1] == strtoxL
+
+
+Input: -1.8
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 e6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.8"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 e6666666 66666667
+fI[1] = #bfff0000 e6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.9
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 f3333333 33333334
+g_xLfmt(0) gives 21 bytes: "1.9000000000000000001"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 f3333333 33333333
+fI[1] = #3fff0000 f3333333 33333334
+fI[1] == strtoxL
+
+
+Input: -1.9
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 f3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.9"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 f3333333 33333334
+fI[1] = #bfff0000 f3333333 33333333
+fI[1] == strtoxL
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 8ccccccc cccccccc
+g_xLfmt(0) gives 21 bytes: "1.0999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 8ccccccc cccccccc
+fI[1] = #3fff0000 8ccccccc cccccccd
+fI[0] == strtoxL
+
+
+Input: -1.1
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 8ccccccc cccccccd
+g_xLfmt(0) gives 4 bytes: "-1.1"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 8ccccccc cccccccd
+fI[1] = #bfff0000 8ccccccc cccccccc
+fI[0] == strtoxL
+
+
+Input: 1.2
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 99999999 99999999
+g_xLfmt(0) gives 21 bytes: "1.1999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 99999999 99999999
+fI[1] = #3fff0000 99999999 9999999a
+fI[0] == strtoxL
+
+
+Input: -1.2
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 99999999 9999999a
+g_xLfmt(0) gives 4 bytes: "-1.2"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 99999999 9999999a
+fI[1] = #bfff0000 99999999 99999999
+fI[0] == strtoxL
+
+
+Input: 1.3
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 a6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.3"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 a6666666 66666666
+fI[1] = #3fff0000 a6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.3
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 a6666666 66666667
+g_xLfmt(0) gives 22 bytes: "-1.3000000000000000001"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 a6666666 66666667
+fI[1] = #bfff0000 a6666666 66666666
+fI[0] == strtoxL
+
+
+Input: 1.4
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 b3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.4"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 b3333333 33333333
+fI[1] = #3fff0000 b3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.4
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 b3333333 33333334
+g_xLfmt(0) gives 22 bytes: "-1.4000000000000000001"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 b3333333 33333334
+fI[1] = #bfff0000 b3333333 33333333
+fI[0] == strtoxL
+
+
+Input: 1.5
+
+strtoxL consumes 3 bytes and returns 1
+with bits = #3fff0000 c0000000 0
+g_xLfmt(0) gives 3 bytes: "1.5"
+
+strtoIxL returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: -1.5
+
+strtoxL consumes 4 bytes and returns 9
+with bits = #bfff0000 c0000000 0
+g_xLfmt(0) gives 4 bytes: "-1.5"
+
+strtoIxL returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.6
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 cccccccc cccccccc
+g_xLfmt(0) gives 21 bytes: "1.5999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 cccccccc cccccccc
+fI[1] = #3fff0000 cccccccc cccccccd
+fI[0] == strtoxL
+
+
+Input: -1.6
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 cccccccc cccccccd
+g_xLfmt(0) gives 4 bytes: "-1.6"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 cccccccc cccccccd
+fI[1] = #bfff0000 cccccccc cccccccc
+fI[0] == strtoxL
+
+
+Input: 1.7
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 d9999999 99999999
+g_xLfmt(0) gives 21 bytes: "1.6999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 d9999999 99999999
+fI[1] = #3fff0000 d9999999 9999999a
+fI[0] == strtoxL
+
+
+Input: -1.7
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 d9999999 9999999a
+g_xLfmt(0) gives 4 bytes: "-1.7"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 d9999999 9999999a
+fI[1] = #bfff0000 d9999999 99999999
+fI[0] == strtoxL
+
+
+Input: 1.8
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 e6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.8"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 e6666666 66666666
+fI[1] = #3fff0000 e6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.8
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 e6666666 66666667
+g_xLfmt(0) gives 22 bytes: "-1.8000000000000000001"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 e6666666 66666667
+fI[1] = #bfff0000 e6666666 66666666
+fI[0] == strtoxL
+
+
+Input: 1.9
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 f3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.9"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 f3333333 33333333
+fI[1] = #3fff0000 f3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.9
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 f3333333 33333334
+g_xLfmt(0) gives 22 bytes: "-1.9000000000000000001"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 f3333333 33333334
+fI[1] = #bfff0000 f3333333 33333333
+fI[0] == strtoxL
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/xL.ou1
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/xL.ou1	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/xL.ou1	(revision 2448)
@@ -0,0 +1,1183 @@
+***** This file is not right.  It needs to be generated on a
+***** system with a Motorla 68881 or the equivalent.
+Input: 1.23
+
+strtoxL consumes 4 bytes and returns 33
+with bits = #3fff0000 9d70a3d7 a3d70a4
+g_xLfmt(0) gives 4 bytes: "1.23"
+
+strtoIxL returns 33, consuming 4 bytes.
+fI[0] = #3fff0000 9d70a3d7 a3d70a3
+fI[1] = #3fff0000 9d70a3d7 a3d70a4
+fI[1] == strtoxL
+
+
+Input: 1.23e+20
+
+strtoxL consumes 8 bytes and returns 1
+with bits = #40410000 d55ef90a 2da18000
+g_xLfmt(0) gives 8 bytes: "1.23e+20"
+
+strtoIxL returns 1, consuming 8 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.23e-20
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #3fbc0000 e857267b b3a984f2
+g_xLfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #3fbc0000 e857267b b3a984f2
+fI[1] = #3fbc0000 e857267b b3a984f3
+fI[0] == strtoxL
+
+
+Input: 1.23456789
+
+strtoxL consumes 10 bytes and returns 33
+with bits = #3fff0000 9e065214 1ef0dbf6
+g_xLfmt(0) gives 10 bytes: "1.23456789"
+
+strtoIxL returns 33, consuming 10 bytes.
+fI[0] = #3fff0000 9e065214 1ef0dbf5
+fI[1] = #3fff0000 9e065214 1ef0dbf6
+fI[1] == strtoxL
+
+
+Input: 1.23456589e+20
+
+strtoxL consumes 14 bytes and returns 1
+with bits = #40410000 d629bd33 5ccba00
+g_xLfmt(0) gives 14 bytes: "1.23456589e+20"
+
+strtoIxL returns 1, consuming 14 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.23e+30
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #40620000 f8658274 7dbc824a
+g_xLfmt(0) gives 8 bytes: "1.23e+30"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #40620000 f8658274 7dbc824a
+fI[1] = #40620000 f8658274 7dbc824b
+fI[0] == strtoxL
+
+
+Input: 1.23e-30
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #3f9b0000 c794337a 808554eb
+g_xLfmt(0) gives 8 bytes: "1.23e-30"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #3f9b0000 c794337a 808554eb
+fI[1] = #3f9b0000 c794337a 808554ec
+fI[0] == strtoxL
+
+
+Input: 1.23456789e-20
+
+strtoxL consumes 14 bytes and returns 17
+with bits = #3fbc0000 e9340a38 f3d6d352
+g_xLfmt(0) gives 14 bytes: "1.23456789e-20"
+
+strtoIxL returns 17, consuming 14 bytes.
+fI[0] = #3fbc0000 e9340a38 f3d6d352
+fI[1] = #3fbc0000 e9340a38 f3d6d353
+fI[0] == strtoxL
+
+
+Input: 1.23456789e-30
+
+strtoxL consumes 14 bytes and returns 17
+with bits = #3f9b0000 c851f19d decca8fc
+g_xLfmt(0) gives 14 bytes: "1.23456789e-30"
+
+strtoIxL returns 17, consuming 14 bytes.
+fI[0] = #3f9b0000 c851f19d decca8fc
+fI[1] = #3f9b0000 c851f19d decca8fd
+fI[0] == strtoxL
+
+
+Input: 1.234567890123456789
+
+strtoxL consumes 20 bytes and returns 17
+with bits = #3fff0000 9e065214 62cfdb8d
+g_xLfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIxL returns 17, consuming 20 bytes.
+fI[0] = #3fff0000 9e065214 62cfdb8d
+fI[1] = #3fff0000 9e065214 62cfdb8e
+fI[0] == strtoxL
+
+
+Input: 1.23456789012345678901234567890123456789
+
+strtoxL consumes 40 bytes and returns 17
+with bits = #3fff0000 9e065214 62cfdb8d
+g_xLfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIxL returns 17, consuming 40 bytes.
+fI[0] = #3fff0000 9e065214 62cfdb8d
+fI[1] = #3fff0000 9e065214 62cfdb8e
+fI[0] == strtoxL
+
+
+Input: 1.23e306
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #43f70000 e033b668 e30fa6d5
+g_xLfmt(0) gives 9 bytes: "1.23e+306"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #43f70000 e033b668 e30fa6d5
+fI[1] = #43f70000 e033b668 e30fa6d6
+fI[0] == strtoxL
+
+
+Input: 1.23e-306
+
+strtoxL consumes 9 bytes and returns 33
+with bits = #3c060000 dd1dc2ed 1cb73f25
+g_xLfmt(0) gives 9 bytes: "1.23e-306"
+
+strtoIxL returns 33, consuming 9 bytes.
+fI[0] = #3c060000 dd1dc2ed 1cb73f24
+fI[1] = #3c060000 dd1dc2ed 1cb73f25
+fI[1] == strtoxL
+
+
+Input: 1.23e-320
+
+strtoxL consumes 9 bytes and returns 33
+with bits = #3bd80000 9b98c371 844c3f1a
+g_xLfmt(0) gives 9 bytes: "1.23e-320"
+
+strtoIxL returns 33, consuming 9 bytes.
+fI[0] = #3bd80000 9b98c371 844c3f19
+fI[1] = #3bd80000 9b98c371 844c3f1a
+fI[1] == strtoxL
+
+
+Input: 1.23e-20
+
+strtoxL consumes 8 bytes and returns 17
+with bits = #3fbc0000 e857267b b3a984f2
+g_xLfmt(0) gives 8 bytes: "1.23e-20"
+
+strtoIxL returns 17, consuming 8 bytes.
+fI[0] = #3fbc0000 e857267b b3a984f2
+fI[1] = #3fbc0000 e857267b b3a984f3
+fI[0] == strtoxL
+
+
+Input: 1.23456789e307
+
+strtoxL consumes 14 bytes and returns 17
+with bits = #43fb0000 8ca58a5e d766de75
+g_xLfmt(0) gives 15 bytes: "1.23456789e+307"
+
+strtoIxL returns 17, consuming 14 bytes.
+fI[0] = #43fb0000 8ca58a5e d766de75
+fI[1] = #43fb0000 8ca58a5e d766de76
+fI[0] == strtoxL
+
+
+Input: 1.23456589e-307
+
+strtoxL consumes 15 bytes and returns 17
+with bits = #3c030000 b18cb5dc c22fd369
+g_xLfmt(0) gives 15 bytes: "1.23456589e-307"
+
+strtoIxL returns 17, consuming 15 bytes.
+fI[0] = #3c030000 b18cb5dc c22fd369
+fI[1] = #3c030000 b18cb5dc c22fd36a
+fI[0] == strtoxL
+
+
+Input: 1.234567890123456789
+
+strtoxL consumes 20 bytes and returns 17
+with bits = #3fff0000 9e065214 62cfdb8d
+g_xLfmt(0) gives 20 bytes: "1.234567890123456789"
+
+strtoIxL returns 17, consuming 20 bytes.
+fI[0] = #3fff0000 9e065214 62cfdb8d
+fI[1] = #3fff0000 9e065214 62cfdb8e
+fI[0] == strtoxL
+
+
+Input: 1.234567890123456789e301
+
+strtoxL consumes 24 bytes and returns 33
+with bits = #43e70000 937a8baf ab20980c
+g_xLfmt(0) gives 25 bytes: "1.234567890123456789e+301"
+
+strtoIxL returns 33, consuming 24 bytes.
+fI[0] = #43e70000 937a8baf ab20980b
+fI[1] = #43e70000 937a8baf ab20980c
+fI[1] == strtoxL
+
+
+Input: 1.234567890123456789e-301
+
+strtoxL consumes 25 bytes and returns 33
+with bits = #3c170000 a953271a 5d069ad9
+g_xLfmt(0) gives 25 bytes: "1.234567890123456789e-301"
+
+strtoIxL returns 33, consuming 25 bytes.
+fI[0] = #3c170000 a953271a 5d069ad8
+fI[1] = #3c170000 a953271a 5d069ad9
+fI[1] == strtoxL
+
+
+Input: 1.234567890123456789e-321
+
+strtoxL consumes 25 bytes and returns 33
+with bits = #3bd40000 f9e11b4c ea6dcce9
+g_xLfmt(0) gives 25 bytes: "1.234567890123456789e-321"
+
+strtoIxL returns 33, consuming 25 bytes.
+fI[0] = #3bd40000 f9e11b4c ea6dcce8
+fI[1] = #3bd40000 f9e11b4c ea6dcce9
+fI[1] == strtoxL
+
+
+Input: 1e23
+
+strtoxL consumes 4 bytes and returns 1
+with bits = #404b0000 a968163f a57b400
+g_xLfmt(0) gives 5 bytes: "1e+23"
+
+strtoIxL returns 1, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1e310
+
+strtoxL consumes 5 bytes and returns 33
+with bits = #44040000 de81e40a 34bcf50
+g_xLfmt(0) gives 6 bytes: "1e+310"
+
+strtoIxL returns 33, consuming 5 bytes.
+fI[0] = #44040000 de81e40a 34bcf4f
+fI[1] = #44040000 de81e40a 34bcf50
+fI[1] == strtoxL
+
+
+Input: 9.0259718793241475e-277
+
+strtoxL consumes 23 bytes and returns 33
+with bits = #3c690000 ffffffff fffffcf7
+g_xLfmt(0) gives 23 bytes: "9.0259718793241475e-277"
+
+strtoIxL returns 33, consuming 23 bytes.
+fI[0] = #3c690000 ffffffff fffffcf6
+fI[1] = #3c690000 ffffffff fffffcf7
+fI[1] == strtoxL
+
+
+Input: 9.025971879324147880346310405869e-277
+
+strtoxL consumes 37 bytes and returns 17
+with bits = #3c6a0000 80000000 0
+g_xLfmt(0) gives 26 bytes: "9.0259718793241478803e-277"
+
+strtoIxL returns 17, consuming 37 bytes.
+fI[0] = #3c6a0000 80000000 0
+fI[1] = #3c6a0000 80000000 1
+fI[0] == strtoxL
+
+
+Input: 9.025971879324147880346310405868e-277
+
+strtoxL consumes 37 bytes and returns 33
+with bits = #3c6a0000 80000000 0
+g_xLfmt(0) gives 26 bytes: "9.0259718793241478803e-277"
+
+strtoIxL returns 33, consuming 37 bytes.
+fI[0] = #3c690000 ffffffff ffffffff
+fI[1] = #3c6a0000 80000000 0
+fI[1] == strtoxL
+
+
+Input: 2.2250738585072014e-308
+
+strtoxL consumes 23 bytes and returns 17
+with bits = #3c010000 80000000 46
+g_xLfmt(0) gives 23 bytes: "2.2250738585072014e-308"
+
+strtoIxL returns 17, consuming 23 bytes.
+fI[0] = #3c010000 80000000 46
+fI[1] = #3c010000 80000000 47
+fI[0] == strtoxL
+
+
+Input: 2.2250738585072013e-308
+
+strtoxL consumes 23 bytes and returns 17
+with bits = #3c000000 ffffffff fffffd4f
+g_xLfmt(0) gives 23 bytes: "2.2250738585072013e-308"
+
+strtoIxL returns 17, consuming 23 bytes.
+fI[0] = #3c000000 ffffffff fffffd4f
+fI[1] = #3c000000 ffffffff fffffd50
+fI[0] == strtoxL
+
+Rounding mode for strtor... changed from 1 (nearest) to 0 (toward zero)
+
+Input: 1.1
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 8ccccccc cccccccc
+g_xLfmt(0) gives 21 bytes: "1.0999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 8ccccccc cccccccc
+fI[1] = #3fff0000 8ccccccc cccccccd
+fI[0] == strtoxL
+
+
+Input: -1.1
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 8ccccccc cccccccc
+g_xLfmt(0) gives 22 bytes: "-1.0999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 8ccccccc cccccccd
+fI[1] = #bfff0000 8ccccccc cccccccc
+fI[1] == strtoxL
+
+
+Input: 1.2
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 99999999 99999999
+g_xLfmt(0) gives 21 bytes: "1.1999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 99999999 99999999
+fI[1] = #3fff0000 99999999 9999999a
+fI[0] == strtoxL
+
+
+Input: -1.2
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 99999999 99999999
+g_xLfmt(0) gives 22 bytes: "-1.1999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 99999999 9999999a
+fI[1] = #bfff0000 99999999 99999999
+fI[1] == strtoxL
+
+
+Input: 1.3
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 a6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.3"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 a6666666 66666666
+fI[1] = #3fff0000 a6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.3
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 a6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.3"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 a6666666 66666667
+fI[1] = #bfff0000 a6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.4
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 b3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.4"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 b3333333 33333333
+fI[1] = #3fff0000 b3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.4
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 b3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.4"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 b3333333 33333334
+fI[1] = #bfff0000 b3333333 33333333
+fI[1] == strtoxL
+
+
+Input: 1.5
+
+strtoxL consumes 3 bytes and returns 1
+with bits = #3fff0000 c0000000 0
+g_xLfmt(0) gives 3 bytes: "1.5"
+
+strtoIxL returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: -1.5
+
+strtoxL consumes 4 bytes and returns 9
+with bits = #bfff0000 c0000000 0
+g_xLfmt(0) gives 4 bytes: "-1.5"
+
+strtoIxL returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.6
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 cccccccc cccccccc
+g_xLfmt(0) gives 21 bytes: "1.5999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 cccccccc cccccccc
+fI[1] = #3fff0000 cccccccc cccccccd
+fI[0] == strtoxL
+
+
+Input: -1.6
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 cccccccc cccccccc
+g_xLfmt(0) gives 22 bytes: "-1.5999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 cccccccc cccccccd
+fI[1] = #bfff0000 cccccccc cccccccc
+fI[1] == strtoxL
+
+
+Input: 1.7
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 d9999999 99999999
+g_xLfmt(0) gives 21 bytes: "1.6999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 d9999999 99999999
+fI[1] = #3fff0000 d9999999 9999999a
+fI[0] == strtoxL
+
+
+Input: -1.7
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 d9999999 99999999
+g_xLfmt(0) gives 22 bytes: "-1.6999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 d9999999 9999999a
+fI[1] = #bfff0000 d9999999 99999999
+fI[1] == strtoxL
+
+
+Input: 1.8
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 e6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.8"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 e6666666 66666666
+fI[1] = #3fff0000 e6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.8
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 e6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.8"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 e6666666 66666667
+fI[1] = #bfff0000 e6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.9
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 f3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.9"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 f3333333 33333333
+fI[1] = #3fff0000 f3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.9
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 f3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.9"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 f3333333 33333334
+fI[1] = #bfff0000 f3333333 33333333
+fI[1] == strtoxL
+
+Rounding mode for strtor... changed from 0 (toward zero) to 1 (nearest)
+
+Input: 1.1
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 8ccccccc cccccccd
+g_xLfmt(0) gives 3 bytes: "1.1"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 8ccccccc cccccccc
+fI[1] = #3fff0000 8ccccccc cccccccd
+fI[1] == strtoxL
+
+
+Input: -1.1
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 8ccccccc cccccccd
+g_xLfmt(0) gives 4 bytes: "-1.1"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 8ccccccc cccccccd
+fI[1] = #bfff0000 8ccccccc cccccccc
+fI[0] == strtoxL
+
+
+Input: 1.2
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 99999999 9999999a
+g_xLfmt(0) gives 3 bytes: "1.2"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 99999999 99999999
+fI[1] = #3fff0000 99999999 9999999a
+fI[1] == strtoxL
+
+
+Input: -1.2
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 99999999 9999999a
+g_xLfmt(0) gives 4 bytes: "-1.2"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 99999999 9999999a
+fI[1] = #bfff0000 99999999 99999999
+fI[0] == strtoxL
+
+
+Input: 1.3
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 a6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.3"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 a6666666 66666666
+fI[1] = #3fff0000 a6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.3
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 a6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.3"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 a6666666 66666667
+fI[1] = #bfff0000 a6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.4
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 b3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.4"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 b3333333 33333333
+fI[1] = #3fff0000 b3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.4
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 b3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.4"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 b3333333 33333334
+fI[1] = #bfff0000 b3333333 33333333
+fI[1] == strtoxL
+
+
+Input: 1.5
+
+strtoxL consumes 3 bytes and returns 1
+with bits = #3fff0000 c0000000 0
+g_xLfmt(0) gives 3 bytes: "1.5"
+
+strtoIxL returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: -1.5
+
+strtoxL consumes 4 bytes and returns 9
+with bits = #bfff0000 c0000000 0
+g_xLfmt(0) gives 4 bytes: "-1.5"
+
+strtoIxL returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.6
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 cccccccc cccccccd
+g_xLfmt(0) gives 3 bytes: "1.6"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 cccccccc cccccccc
+fI[1] = #3fff0000 cccccccc cccccccd
+fI[1] == strtoxL
+
+
+Input: -1.6
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 cccccccc cccccccd
+g_xLfmt(0) gives 4 bytes: "-1.6"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 cccccccc cccccccd
+fI[1] = #bfff0000 cccccccc cccccccc
+fI[0] == strtoxL
+
+
+Input: 1.7
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 d9999999 9999999a
+g_xLfmt(0) gives 3 bytes: "1.7"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 d9999999 99999999
+fI[1] = #3fff0000 d9999999 9999999a
+fI[1] == strtoxL
+
+
+Input: -1.7
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 d9999999 9999999a
+g_xLfmt(0) gives 4 bytes: "-1.7"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 d9999999 9999999a
+fI[1] = #bfff0000 d9999999 99999999
+fI[0] == strtoxL
+
+
+Input: 1.8
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 e6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.8"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 e6666666 66666666
+fI[1] = #3fff0000 e6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.8
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 e6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.8"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 e6666666 66666667
+fI[1] = #bfff0000 e6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.9
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 f3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.9"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 f3333333 33333333
+fI[1] = #3fff0000 f3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.9
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 f3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.9"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 f3333333 33333334
+fI[1] = #bfff0000 f3333333 33333333
+fI[1] == strtoxL
+
+Rounding mode for strtor... changed from 1 (nearest) to 2 (toward +Infinity)
+
+Input: 1.1
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 8ccccccc cccccccd
+g_xLfmt(0) gives 3 bytes: "1.1"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 8ccccccc cccccccc
+fI[1] = #3fff0000 8ccccccc cccccccd
+fI[1] == strtoxL
+
+
+Input: -1.1
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 8ccccccc cccccccc
+g_xLfmt(0) gives 22 bytes: "-1.0999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 8ccccccc cccccccd
+fI[1] = #bfff0000 8ccccccc cccccccc
+fI[1] == strtoxL
+
+
+Input: 1.2
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 99999999 9999999a
+g_xLfmt(0) gives 3 bytes: "1.2"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 99999999 99999999
+fI[1] = #3fff0000 99999999 9999999a
+fI[1] == strtoxL
+
+
+Input: -1.2
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 99999999 99999999
+g_xLfmt(0) gives 22 bytes: "-1.1999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 99999999 9999999a
+fI[1] = #bfff0000 99999999 99999999
+fI[1] == strtoxL
+
+
+Input: 1.3
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 a6666666 66666667
+g_xLfmt(0) gives 21 bytes: "1.3000000000000000001"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 a6666666 66666666
+fI[1] = #3fff0000 a6666666 66666667
+fI[1] == strtoxL
+
+
+Input: -1.3
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 a6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.3"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 a6666666 66666667
+fI[1] = #bfff0000 a6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.4
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 b3333333 33333334
+g_xLfmt(0) gives 21 bytes: "1.4000000000000000001"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 b3333333 33333333
+fI[1] = #3fff0000 b3333333 33333334
+fI[1] == strtoxL
+
+
+Input: -1.4
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 b3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.4"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 b3333333 33333334
+fI[1] = #bfff0000 b3333333 33333333
+fI[1] == strtoxL
+
+
+Input: 1.5
+
+strtoxL consumes 3 bytes and returns 1
+with bits = #3fff0000 c0000000 0
+g_xLfmt(0) gives 3 bytes: "1.5"
+
+strtoIxL returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: -1.5
+
+strtoxL consumes 4 bytes and returns 9
+with bits = #bfff0000 c0000000 0
+g_xLfmt(0) gives 4 bytes: "-1.5"
+
+strtoIxL returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.6
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 cccccccc cccccccd
+g_xLfmt(0) gives 3 bytes: "1.6"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 cccccccc cccccccc
+fI[1] = #3fff0000 cccccccc cccccccd
+fI[1] == strtoxL
+
+
+Input: -1.6
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 cccccccc cccccccc
+g_xLfmt(0) gives 22 bytes: "-1.5999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 cccccccc cccccccd
+fI[1] = #bfff0000 cccccccc cccccccc
+fI[1] == strtoxL
+
+
+Input: 1.7
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 d9999999 9999999a
+g_xLfmt(0) gives 3 bytes: "1.7"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 d9999999 99999999
+fI[1] = #3fff0000 d9999999 9999999a
+fI[1] == strtoxL
+
+
+Input: -1.7
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 d9999999 99999999
+g_xLfmt(0) gives 22 bytes: "-1.6999999999999999999"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 d9999999 9999999a
+fI[1] = #bfff0000 d9999999 99999999
+fI[1] == strtoxL
+
+
+Input: 1.8
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 e6666666 66666667
+g_xLfmt(0) gives 21 bytes: "1.8000000000000000001"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 e6666666 66666666
+fI[1] = #3fff0000 e6666666 66666667
+fI[1] == strtoxL
+
+
+Input: -1.8
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 e6666666 66666666
+g_xLfmt(0) gives 4 bytes: "-1.8"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 e6666666 66666667
+fI[1] = #bfff0000 e6666666 66666666
+fI[1] == strtoxL
+
+
+Input: 1.9
+
+strtoxL consumes 3 bytes and returns 33
+with bits = #3fff0000 f3333333 33333334
+g_xLfmt(0) gives 21 bytes: "1.9000000000000000001"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 f3333333 33333333
+fI[1] = #3fff0000 f3333333 33333334
+fI[1] == strtoxL
+
+
+Input: -1.9
+
+strtoxL consumes 4 bytes and returns 25
+with bits = #bfff0000 f3333333 33333333
+g_xLfmt(0) gives 4 bytes: "-1.9"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 f3333333 33333334
+fI[1] = #bfff0000 f3333333 33333333
+fI[1] == strtoxL
+
+Rounding mode for strtor... changed from 2 (toward +Infinity) to 3 (toward -Infinity)
+
+Input: 1.1
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 8ccccccc cccccccc
+g_xLfmt(0) gives 21 bytes: "1.0999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 8ccccccc cccccccc
+fI[1] = #3fff0000 8ccccccc cccccccd
+fI[0] == strtoxL
+
+
+Input: -1.1
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 8ccccccc cccccccd
+g_xLfmt(0) gives 4 bytes: "-1.1"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 8ccccccc cccccccd
+fI[1] = #bfff0000 8ccccccc cccccccc
+fI[0] == strtoxL
+
+
+Input: 1.2
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 99999999 99999999
+g_xLfmt(0) gives 21 bytes: "1.1999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 99999999 99999999
+fI[1] = #3fff0000 99999999 9999999a
+fI[0] == strtoxL
+
+
+Input: -1.2
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 99999999 9999999a
+g_xLfmt(0) gives 4 bytes: "-1.2"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 99999999 9999999a
+fI[1] = #bfff0000 99999999 99999999
+fI[0] == strtoxL
+
+
+Input: 1.3
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 a6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.3"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 a6666666 66666666
+fI[1] = #3fff0000 a6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.3
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 a6666666 66666667
+g_xLfmt(0) gives 22 bytes: "-1.3000000000000000001"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 a6666666 66666667
+fI[1] = #bfff0000 a6666666 66666666
+fI[0] == strtoxL
+
+
+Input: 1.4
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 b3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.4"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 b3333333 33333333
+fI[1] = #3fff0000 b3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.4
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 b3333333 33333334
+g_xLfmt(0) gives 22 bytes: "-1.4000000000000000001"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 b3333333 33333334
+fI[1] = #bfff0000 b3333333 33333333
+fI[0] == strtoxL
+
+
+Input: 1.5
+
+strtoxL consumes 3 bytes and returns 1
+with bits = #3fff0000 c0000000 0
+g_xLfmt(0) gives 3 bytes: "1.5"
+
+strtoIxL returns 1, consuming 3 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: -1.5
+
+strtoxL consumes 4 bytes and returns 9
+with bits = #bfff0000 c0000000 0
+g_xLfmt(0) gives 4 bytes: "-1.5"
+
+strtoIxL returns 9, consuming 4 bytes.
+fI[0] == fI[1] == strtoxL
+
+
+Input: 1.6
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 cccccccc cccccccc
+g_xLfmt(0) gives 21 bytes: "1.5999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 cccccccc cccccccc
+fI[1] = #3fff0000 cccccccc cccccccd
+fI[0] == strtoxL
+
+
+Input: -1.6
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 cccccccc cccccccd
+g_xLfmt(0) gives 4 bytes: "-1.6"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 cccccccc cccccccd
+fI[1] = #bfff0000 cccccccc cccccccc
+fI[0] == strtoxL
+
+
+Input: 1.7
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 d9999999 99999999
+g_xLfmt(0) gives 21 bytes: "1.6999999999999999999"
+
+strtoIxL returns 33, consuming 3 bytes.
+fI[0] = #3fff0000 d9999999 99999999
+fI[1] = #3fff0000 d9999999 9999999a
+fI[0] == strtoxL
+
+
+Input: -1.7
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 d9999999 9999999a
+g_xLfmt(0) gives 4 bytes: "-1.7"
+
+strtoIxL returns 41, consuming 4 bytes.
+fI[0] = #bfff0000 d9999999 9999999a
+fI[1] = #bfff0000 d9999999 99999999
+fI[0] == strtoxL
+
+
+Input: 1.8
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 e6666666 66666666
+g_xLfmt(0) gives 3 bytes: "1.8"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 e6666666 66666666
+fI[1] = #3fff0000 e6666666 66666667
+fI[0] == strtoxL
+
+
+Input: -1.8
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 e6666666 66666667
+g_xLfmt(0) gives 22 bytes: "-1.8000000000000000001"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 e6666666 66666667
+fI[1] = #bfff0000 e6666666 66666666
+fI[0] == strtoxL
+
+
+Input: 1.9
+
+strtoxL consumes 3 bytes and returns 17
+with bits = #3fff0000 f3333333 33333333
+g_xLfmt(0) gives 3 bytes: "1.9"
+
+strtoIxL returns 17, consuming 3 bytes.
+fI[0] = #3fff0000 f3333333 33333333
+fI[1] = #3fff0000 f3333333 33333334
+fI[0] == strtoxL
+
+
+Input: -1.9
+
+strtoxL consumes 4 bytes and returns 41
+with bits = #bfff0000 f3333333 33333334
+g_xLfmt(0) gives 22 bytes: "-1.9000000000000000001"
+
+strtoIxL returns 25, consuming 4 bytes.
+fI[0] = #bfff0000 f3333333 33333334
+fI[1] = #bfff0000 f3333333 33333333
+fI[0] == strtoxL
+
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/xLtest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/xLtest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/xLtest.c	(revision 2448)
@@ -0,0 +1,169 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* Test program for g_xLfmt, strtoIxL, strtopxL, and strtorxL.
+ *
+ * Inputs (on stdin):
+ *		r rounding_mode
+ *		n ndig
+ *		number
+ *		#hex0 hex1 hex2
+ *
+ *	rounding_mode values:
+ *		0 = toward zero
+ *		1 = nearest
+ *		2 = toward +Infinity
+ *		3 = toward -Infinity
+ *
+ * where number is a decimal floating-point number,
+ * hex0 is a string of <= 8 Hex digits for the most significant
+ * word of the number, hex1 is a similar string for the next
+ * word, etc., and ndig is a parameters to g_xLfmt.
+ */
+
+#include "gdtoa.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+ extern int getround ANSI((int,char*));
+
+ static char ibuf[2048], obuf[2048];
+
+#define U (unsigned long)
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#endif
+#ifdef IEEE_8087
+#define _0 2
+#define _1 1
+#define _2 0
+#endif
+
+ int
+main(Void)
+{
+	char *s, *se, *se1;
+	int dItry, i, ndig = 0, r = 1;
+	union { long double d; ULong bits[3]; } u, v[2];
+
+	while(s = fgets(ibuf, sizeof(ibuf), stdin)) {
+		while(*s <= ' ')
+			if (!*s++)
+				continue;
+		dItry = 0;
+		switch(*s) {
+		  case 'r':
+			r = getround(r, s);
+			continue;
+		  case 'n':
+			i = s[1];
+			if (i <= ' ' || i >= '0' && i <= '9') {
+				ndig = atoi(s+1);
+				continue;
+				}
+			break; /* nan? */
+		  case '#':
+			sscanf(s+1, "%lx %lx %lx", &u.bits[_0],
+				&u.bits[_1], &u.bits[_2]);
+			printf("\nInput: %s", ibuf);
+			printf(" --> f = #%lx %lx %lx\n", u.bits[_0],
+				u.bits[_1], u.bits[_2]);
+			goto fmt_test;
+			}
+		dItry = 1;
+		printf("\nInput: %s", ibuf);
+		i = strtorxL(ibuf, &se, r, u.bits);
+		if (r == 1 && (i != strtopxL(ibuf, &se1, v[0].bits) || se1 != se
+		 || memcmp(u.bits, v[0].bits, 12)))
+			printf("***strtoxL and strtorxL disagree!!\n:");
+		printf("\nstrtoxL consumes %d bytes and returns %d\n",
+				(int)(se-ibuf), i);
+		printf("with bits = #%lx %lx %lx\n",
+			U u.bits[_0], U u.bits[_1], U u.bits[_2]);
+		if (sizeof(long double) == 12)
+			printf("printf(\"%%.21Lg\") gives %.21Lg\n", u.d);
+ fmt_test:
+		se = g_xLfmt(obuf, u.bits, ndig, sizeof(obuf));
+		printf("g_xLfmt(%d) gives %d bytes: \"%s\"\n\n",
+			ndig, (int)(se-obuf), se ? obuf : "<null>");
+		if (!dItry)
+			continue;
+		printf("strtoIxL returns %d,",
+			strtoIxL(ibuf, &se, v[0].bits, v[1].bits));
+		printf(" consuming %d bytes.\n", (int)(se-ibuf));
+		if (!memcmp(v[0].bits, v[1].bits, 12)) {
+			if (!memcmp(u.bits, v[0].bits, 12))
+				printf("fI[0] == fI[1] == strtoxL\n");
+			else {
+				printf("fI[0] == fI[1] = #%lx %lx %lx\n",
+					U v[0].bits[_0], U v[0].bits[_1],
+					U v[0].bits[_2]);
+				if (sizeof(long double) == 12)
+				    printf("= %.21Lg\n", v[0].d);
+				}
+			}
+		else {
+			printf("fI[0] = #%lx %lx %lx\n",
+					U v[0].bits[_0], U v[0].bits[_1],
+					U v[0].bits[_2]);
+			if (sizeof(long double) == 12)
+				printf("= %.21Lg\n", v[0].d);
+			printf("fI[1] = #%lx %lx %lx\n",
+					U v[1].bits[_0], U v[1].bits[_1],
+					U v[1].bits[_2]);
+			if (sizeof(long double) == 12)
+				printf("= %.21Lg\n", v[1].d);
+			if (!memcmp(v[0].bits, u.bits, 12))
+				printf("fI[0] == strtoxL\n");
+			else if (!memcmp(v[1].bits, u.bits, 12))
+				printf("fI[1] == strtoxL\n");
+			else
+				printf("**** Both differ from strtod ****\n");
+			}
+		printf("\n");
+		}
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/xQtest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/xQtest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/xQtest.c	(revision 2448)
@@ -0,0 +1,46 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 2002 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+#include <stdio.h>
+
+ int
+main(void)
+{
+	switch(sizeof(long double)) {
+	  case 10:
+	  case 12:
+		printf("cp x.ou1 x.out; cp xL.ou1 xL.out; cp Q.ou0 Q.out\n");
+		break;
+	  case 16:
+		printf("cp x.ou0 x.out; cp xL.ou0 xL.out; cp Q.ou1 Q.out\n");
+		break;
+	  default:
+		printf("cp x.ou0 x.out; cp xL.ou0 xL.out; cp Q.ou0 Q.out\n");
+	  }
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/xsum0.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/xsum0.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/xsum0.out	(revision 2448)
@@ -0,0 +1,35 @@
+README	e6ebdc91	2429
+Qtest.c	140625e2	4778
+dItest.c	8689031	2401
+ddtest.c	ea24d330	4943
+dtest.c	900d971	4071
+dt.c	addb61c	6198
+ftest.c	f609ce43	3958
+getround.c	f471599	2041
+strtoIdSI.c	7bfb88b	49
+strtoIddSI.c	72e8852	50
+strtodISI.c	ed08b740	49
+strtodt.c	17aca428	3213
+strtopddSI.c	13e7138d	50
+strtorddSI.c	f7e4b1d5	50
+xLtest.c	faca328f	4646
+xQtest.c	efdea3a2	1549
+xtest.c	1f19b87	4858
+rtestnos	f94bcdf6	336
+testnos	e89999d6	485
+testnos1	7e16229	294
+testnos3	fa5c8aca	11998
+dI.out	d522eef	4369
+dIsi.out	1dd6d02f	4350
+ddsi.out	1f94bbe2	10251
+dd.out	e262456e	40923
+dtst.out	ee75f6b9	23308
+d.out	f271efc9	28131
+f.out	4b0bd51	21207
+x.ou0	1cfc5d22	25378
+xL.ou0	faa3a741	26363
+x.ou1	1a7e9dd4	34587
+xL.ou1	418057a	26476
+Q.ou0	e4592b85	28742
+Q.ou1	ea0b344d	39572
+makefile	ebbea1e1	4191
Index: /trunk/libc/src/fbsdlibc/gdtoa/test/xtest.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/test/xtest.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/test/xtest.c	(revision 2448)
@@ -0,0 +1,176 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+/* Test program for g_xfmt, strtoIx, strtopx, and strtorx.
+ *
+ * Inputs (on stdin):
+ *		r rounding_mode
+ *		n ndig
+ *		number
+ *		#hex0 hex1 hex2 hex3 hex4
+ *
+ *	rounding_mode values:
+ *		0 = toward zero
+ *		1 = nearest
+ *		2 = toward +Infinity
+ *		3 = toward -Infinity
+ *
+ * where number is a decimal floating-point number,
+ * hex0 is a string of <= 4 Hex digits for the most significant
+ * half-word of the number, hex1 is a similar string for the next
+ * half-word, etc., and ndig is a parameters to g_xfmt.
+ */
+
+#include "gdtoa.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+ extern int getround ANSI((int,char*));
+
+ static char ibuf[2048], obuf[2048];
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#define _4 4
+#endif
+#ifdef IEEE_8087
+#define _0 4
+#define _1 3
+#define _2 2
+#define _3 1
+#define _4 0
+#endif
+
+ int
+main(Void)
+{
+	char *s, *se, *se1;
+	int i, dItry, ndig = 0, r = 1;
+	union { long double d; UShort bits[5]; } u, v[2];
+
+	while(s = fgets(ibuf, sizeof(ibuf), stdin)) {
+		while(*s <= ' ')
+			if (!*s++)
+				continue;
+		dItry = 0;
+		switch(*s) {
+		  case 'r':
+			r = getround(r, s);
+			continue;
+		  case 'n':
+			i = s[1];
+			if (i <= ' ' || i >= '0' && i <= '9') {
+				ndig = atoi(s+1);
+				continue;
+				}
+			break; /* nan? */
+		  case '#':
+			sscanf(s+1, "%hx %hx %hx %hx hx", &u.bits[_0],
+				&u.bits[_1], &u.bits[_2], &u.bits[_3],
+				&u.bits[_4]);
+			printf("\nInput: %s", ibuf);
+			printf(" --> f = #%x %x %x %x %x\n", u.bits[_0],
+				u.bits[_1], u.bits[_2], u.bits[_3], u.bits[4]);
+			goto fmt_test;
+			}
+		dItry = 1;
+		printf("\nInput: %s", ibuf);
+		i = strtorx(ibuf, &se, r, u.bits);
+		if (r == 1 && (i != strtopx(ibuf, &se1, v[0].bits) || se1 != se
+		 || memcmp(u.bits, v[0].bits, 10)))
+			printf("***strtox and strtorx disagree!!\n:");
+		printf("\nstrtox consumes %d bytes and returns %d\n",
+				(int)(se-ibuf), i);
+		printf("with bits = #%x %x %x %x %x\n",
+			u.bits[_0], u.bits[_1], u.bits[_2],
+			u.bits[_3], u.bits[_4]);
+		if (sizeof(long double) == 12)
+			printf("printf(\"%%.21Lg\") gives %.21Lg\n", u.d);
+ fmt_test:
+		se = g_xfmt(obuf, u.bits, ndig, sizeof(obuf));
+		printf("g_xfmt(%d) gives %d bytes: \"%s\"\n\n",
+			ndig, (int)(se-obuf), se ? obuf : "<null>");
+		if (!dItry)
+			continue;
+		printf("strtoIx returns %d,",
+			strtoIx(ibuf, &se, v[0].bits, v[1].bits));
+		printf(" consuming %d bytes.\n", (int)(se-ibuf));
+		if (!memcmp(v[0].bits, v[1].bits, 10)) {
+			if (!memcmp(u.bits, v[0].bits, 10))
+				printf("fI[0] == fI[1] == strtox\n");
+			else {
+				printf("fI[0] == fI[1] = #%x %x %x %x %x\n",
+					v[0].bits[_0], v[0].bits[_1],
+					v[0].bits[_2], v[0].bits[_3],
+					v[0].bits[_4]);
+				if (sizeof(long double) == 12)
+				    printf("= %.21Lg\n", v[0].d);
+				}
+			}
+		else {
+			printf("fI[0] = #%x %x %x %x %x\n",
+					v[0].bits[_0], v[0].bits[_1],
+					v[0].bits[_2], v[0].bits[_3],
+					v[0].bits[_4]);
+			if (sizeof(long double) == 12)
+				printf("= %.21Lg\n", v[0].d);
+			printf("fI[1] = #%x %x %x %x %x\n",
+					v[1].bits[_0], v[1].bits[_1],
+					v[1].bits[_2], v[0].bits[_3],
+					v[0].bits[_4]);
+			if (sizeof(long double) == 12)
+				printf("= %.21Lg\n", v[1].d);
+			if (!memcmp(v[0].bits, u.bits, 10))
+				printf("fI[0] == strtox\n");
+			else if (!memcmp(v[1].bits, u.bits, 10))
+				printf("fI[1] == strtox\n");
+			else
+				printf("**** Both differ from strtod ****\n");
+			}
+		printf("\n");
+		}
+	return 0;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/ulp.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/ulp.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/ulp.c	(revision 2448)
@@ -0,0 +1,76 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to
+	David M. Gay
+	Bell Laboratories, Room 2C-463
+	600 Mountain Avenue
+	Murray Hill, NJ 07974-0636
+	U.S.A.
+	dmg@bell-labs.com
+ */
+
+#include "gdtoaimp.h"
+
+ double
+ulp
+#ifdef KR_headers
+	(x) double x;
+#else
+	(double x)
+#endif
+{
+	Long L;
+	double a;
+
+	L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
+#ifndef Sudden_Underflow
+	if (L > 0) {
+#endif
+#ifdef IBM
+		L |= Exp_msk1 >> 4;
+#endif
+		word0(a) = L;
+		word1(a) = 0;
+#ifndef Sudden_Underflow
+		}
+	else {
+		L = -L >> Exp_shift;
+		if (L < Exp_shift) {
+			word0(a) = 0x80000 >> L;
+			word1(a) = 0;
+			}
+		else {
+			word0(a) = 0;
+			L -= Exp_shift;
+			word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+			}
+		}
+#endif
+	return a;
+	}
Index: /trunk/libc/src/fbsdlibc/gdtoa/xsum0.out
===================================================================
--- /trunk/libc/src/fbsdlibc/gdtoa/xsum0.out	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gdtoa/xsum0.out	(revision 2448)
@@ -0,0 +1,46 @@
+README	c9c34c1	13153
+arithchk.c	e37b8a75	4070
+dmisc.c	e8d262b6	4712
+dtoa.c	f3c132b3	16905
+g_Qfmt.c	e5847e9	2870
+g__fmt.c	ee5f9be0	2439
+g_ddfmt.c	fcf94527	3790
+g_dfmt.c	f30e55a9	2533
+g_ffmt.c	7c4ea96	2459
+g_xLfmt.c	36ee116	2716
+g_xfmt.c	c20a5e4	2795
+gdtoa.c	364a0d2	17017
+gdtoa.h	1eb440de	4810
+gdtoaimp.h	6a955ba	19106
+gethex.c	1c586a03	5075
+gmisc.c	e1a268ea	2114
+hd_init.c	cf9a94e	1827
+hexnan.c	f53be1da	2988
+makefile	e84d078f	2802
+misc.c	ea539bdb	14168
+smisc.c	f659f036	3685
+strtoIQ.c	13ac9f44	1969
+strtoId.c	d05a7a6	1961
+strtoIdd.c	fa36260d	2135
+strtoIf.c	eb75ac99	1905
+strtoIg.c	ec59c2fa	3484
+strtoIx.c	8f8c9d	1990
+strtoIxL.c	1313ff7f	1961
+strtod.c	fd6556c8	19985
+strtodI.c	e58338e0	4062
+strtodg.c	e04b9254	19458
+strtof.c	1e7a787a	2202
+strtopQ.c	e232c542	2685
+strtopd.c	e865dc64	1701
+strtopdd.c	1c240126	4540
+strtopf.c	1c762782	2196
+strtopx.c	17c3fafb	2665
+strtopxL.c	ed474cdb	2505
+strtorQ.c	126cc92b	2898
+strtord.c	1fce44b9	2528
+strtordd.c	c32bca0	4979
+strtorf.c	fe6a2687	2430
+strtorx.c	18389f0c	2888
+strtorxL.c	f63fc249	2730
+sum.c	dc07b9b	2524
+ulp.c	f6db0b4d	1894
Index: /trunk/libc/src/fbsdlibc/gen/_rand48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/_rand48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/_rand48.c	(revision 2448)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/_rand48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+unsigned short _rand48_seed[3] = {
+	RAND48_SEED_0,
+	RAND48_SEED_1,
+	RAND48_SEED_2
+};
+unsigned short _rand48_mult[3] = {
+	RAND48_MULT_0,
+	RAND48_MULT_1,
+	RAND48_MULT_2
+};
+unsigned short _rand48_add = RAND48_ADD;
+
+void
+_dorand48(unsigned short xseed[3])
+{
+	unsigned long accu;
+	unsigned short temp[2];
+
+	accu = (unsigned long) _rand48_mult[0] * (unsigned long) xseed[0] +
+	 (unsigned long) _rand48_add;
+	temp[0] = (unsigned short) accu;	/* lower 16 bits */
+	accu >>= sizeof(unsigned short) * 8;
+	accu += (unsigned long) _rand48_mult[0] * (unsigned long) xseed[1] +
+	 (unsigned long) _rand48_mult[1] * (unsigned long) xseed[0];
+	temp[1] = (unsigned short) accu;	/* middle 16 bits */
+	accu >>= sizeof(unsigned short) * 8;
+	accu += _rand48_mult[0] * xseed[2] + _rand48_mult[1] * xseed[1] + _rand48_mult[2] * xseed[0];
+	xseed[0] = temp[0];
+	xseed[1] = temp[1];
+	xseed[2] = (unsigned short) accu;
+}
Index: /trunk/libc/src/fbsdlibc/gen/alarm.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/alarm.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/alarm.c	(revision 2448)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)alarm.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/alarm.c,v 1.2 2002/02/01 01:08:47 obrien Exp $");
+
+/*
+ * Backwards compatible alarm.
+ */
+#include <sys/time.h>
+#include <unistd.h>
+
+unsigned int
+_STD(alarm)(secs)                       /* bird */
+	unsigned int secs;
+{
+	struct itimerval it, oitv;
+	struct itimerval *itp = &it;
+
+	timerclear(&itp->it_interval);
+	itp->it_value.tv_sec = secs;
+	itp->it_value.tv_usec = 0;
+	if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
+		return (-1);
+	if (oitv.it_value.tv_usec)
+		oitv.it_value.tv_sec++;
+	return (oitv.it_value.tv_sec);
+}
Index: /trunk/libc/src/fbsdlibc/gen/arc4random.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/arc4random.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/arc4random.c	(revision 2448)
@@ -0,0 +1,248 @@
+/*
+ * Arc4 random number generator for OpenBSD.
+ * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
+ *
+ * Modification and redistribution in source and binary forms is
+ * permitted provided that due credit is given to the author and the
+ * OpenBSD project (for instance by leaving this copyright notice
+ * intact).
+ */
+
+/*
+ * This code is derived from section 17.1 of Applied Cryptography,
+ * second edition, which describes a stream cipher allegedly
+ * compatible with RSA Labs "RC4" cipher (the actual description of
+ * which is a trade secret).  The same algorithm is used as a stream
+ * cipher called "arcfour" in Tatu Ylonen's ssh package.
+ *
+ * Here the stream cipher has been modified always to include the time
+ * when initializing the state.  That makes it impossible to
+ * regenerate the same random sequence twice, so this can't be used
+ * for encryption, but will generate good random numbers.
+ *
+ * RC4 is a registered trademark of RSA Laboratories.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/arc4random.c,v 1.10 2004/03/24 14:44:57 green Exp $");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef __EMX__
+#include <sys/fmutex.h>
+#else
+#include <pthread.h>
+#endif
+
+#include "libc_private.h"
+#include "un-namespace.h"
+
+struct arc4_stream {
+	u_int8_t i;
+	u_int8_t j;
+	u_int8_t s[256];
+};
+
+#ifdef __EMX__
+static _fmutex	arc4random_mtx = _FMUTEX_INITIALIZER;
+#else
+static pthread_mutex_t	arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#define	RANDOMDEV	"/dev/urandom"
+#ifdef __EMX__
+#define	THREAD_LOCK()   _fmutex_request(&arc4random_mtx, 0)
+#define	THREAD_UNLOCK()	_fmutex_release(&arc4random_mtx)
+#else /* !__EMX__ */
+#define	THREAD_LOCK()						\
+	do {							\
+		if (__isthreaded)				\
+			_pthread_mutex_lock(&arc4random_mtx);	\
+	} while (0)
+
+#define	THREAD_UNLOCK()						\
+	do {							\
+		if (__isthreaded)				\
+			_pthread_mutex_unlock(&arc4random_mtx);	\
+	} while (0)
+#endif
+
+static struct arc4_stream rs;
+static int rs_initialized;
+static int rs_stired;
+
+static inline u_int8_t arc4_getbyte(struct arc4_stream *);
+static void arc4_stir(struct arc4_stream *);
+
+static inline void
+arc4_init(as)
+	struct arc4_stream *as;
+{
+	int     n;
+
+	for (n = 0; n < 256; n++)
+		as->s[n] = n;
+	as->i = 0;
+	as->j = 0;
+}
+
+static inline void
+arc4_addrandom(as, dat, datlen)
+	struct arc4_stream *as;
+	u_char *dat;
+	int     datlen;
+{
+	int     n;
+	u_int8_t si;
+
+	as->i--;
+	for (n = 0; n < 256; n++) {
+		as->i = (as->i + 1);
+		si = as->s[as->i];
+		as->j = (as->j + si + dat[n % datlen]);
+		as->s[as->i] = as->s[as->j];
+		as->s[as->j] = si;
+	}
+}
+
+static void
+arc4_stir(as)
+	struct arc4_stream *as;
+{
+	int     fd, n;
+	struct {
+		struct timeval tv;
+		pid_t pid;
+		u_int8_t rnd[128 - sizeof(struct timeval) - sizeof(pid_t)];
+	}       rdat;
+
+	gettimeofday(&rdat.tv, NULL);
+	rdat.pid = getpid();
+	fd = _open(RANDOMDEV, O_RDONLY, 0);
+	if (fd >= 0) {
+		(void) _read(fd, rdat.rnd, sizeof(rdat.rnd));
+		_close(fd);
+	}
+	/* fd < 0?  Ah, what the heck. We'll just take whatever was on the
+	 * stack... */
+
+	arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
+
+	/*
+	 * Throw away the first N bytes of output, as suggested in the
+	 * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
+	 * by Fluher, Mantin, and Shamir.  N=1024 is based on
+	 * suggestions in the paper "(Not So) Random Shuffles of RC4"
+	 * by Ilya Mironov.
+	 */
+	for (n = 0; n < 1024; n++)
+		arc4_getbyte(as);
+}
+
+static inline u_int8_t
+arc4_getbyte(as)
+	struct arc4_stream *as;
+{
+	u_int8_t si, sj;
+
+	as->i = (as->i + 1);
+	si = as->s[as->i];
+	as->j = (as->j + si);
+	sj = as->s[as->j];
+	as->s[as->i] = sj;
+	as->s[as->j] = si;
+
+	return (as->s[(si + sj) & 0xff]);
+}
+
+static inline u_int32_t
+arc4_getword(as)
+	struct arc4_stream *as;
+{
+	u_int32_t val;
+
+	val = arc4_getbyte(as) << 24;
+	val |= arc4_getbyte(as) << 16;
+	val |= arc4_getbyte(as) << 8;
+	val |= arc4_getbyte(as);
+
+	return (val);
+}
+
+static void
+arc4_check_init(void)
+{
+	if (!rs_initialized) {
+		arc4_init(&rs);
+		rs_initialized = 1;
+	}
+}
+
+static void
+arc4_check_stir(void)
+{
+	if (!rs_stired) {
+		arc4_stir(&rs);
+		rs_stired = 1;
+	}
+}
+
+void
+arc4random_stir()
+{
+	THREAD_LOCK();
+	arc4_check_init();
+	arc4_stir(&rs);
+	THREAD_UNLOCK();
+}
+
+void
+arc4random_addrandom(dat, datlen)
+	u_char *dat;
+	int     datlen;
+{
+	THREAD_LOCK();
+	arc4_check_init();
+	arc4_check_stir();
+	arc4_addrandom(&rs, dat, datlen);
+	THREAD_UNLOCK();
+}
+
+u_int32_t
+arc4random()
+{
+	u_int32_t rnd;
+
+	THREAD_LOCK();
+	arc4_check_init();
+	arc4_check_stir();
+	rnd = arc4_getword(&rs);
+	THREAD_UNLOCK();
+
+	return (rnd);
+}
+
+#if 0
+/*-------- Test code for i386 --------*/
+#include <stdio.h>
+#include <machine/pctr.h>
+int
+main(int argc, char **argv)
+{
+	const int iter = 1000000;
+	int     i;
+	pctrval v;
+
+	v = rdtsc();
+	for (i = 0; i < iter; i++)
+		arc4random();
+	v = rdtsc() - v;
+	v /= iter;
+
+	printf("%qd cycles\n", v);
+}
+#endif
Index: /trunk/libc/src/fbsdlibc/gen/drand48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/drand48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/drand48.c	(revision 2448)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/drand48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+
+double
+_STD(drand48)(void)
+{
+	return erand48(_rand48_seed);
+}
Index: /trunk/libc/src/fbsdlibc/gen/erand48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/erand48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/erand48.c	(revision 2448)
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/erand48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+double
+_STD(erand48)(unsigned short xseed[3])
+{
+	_dorand48(xseed);
+	return ldexp((double) xseed[0], -48) +
+	       ldexp((double) xseed[1], -32) +
+	       ldexp((double) xseed[2], -16);
+}
Index: /trunk/libc/src/fbsdlibc/gen/err.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/err.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/err.c	(revision 2448)
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)err.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.13 2002/03/29 22:43:41 markm Exp $");
+
+#include "namespace.h"
+#include <err.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+static FILE *err_file; /* file to use for error output */
+static void (*err_exit)(int);
+
+/*
+ * This is declared to take a `void *' so that the caller is not required
+ * to include <stdio.h> first.  However, it is really a `FILE *', and the
+ * manual page documents it as such.
+ */
+void
+err_set_file(void *fp)
+{
+	if (fp)
+		err_file = fp;
+	else
+		err_file = stderr;
+}
+
+void
+err_set_exit(void (*ef)(int))
+{
+	err_exit = ef;
+}
+
+__weak_reference(_err, err);
+
+void
+_err(int eval, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	verrc(eval, errno, fmt, ap);
+	va_end(ap);
+}
+
+void
+verr(eval, fmt, ap)
+	int eval;
+	const char *fmt;
+	va_list ap;
+{
+	verrc(eval, errno, fmt, ap);
+}
+
+void
+errc(int eval, int code, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	verrc(eval, code, fmt, ap);
+	va_end(ap);
+}
+
+void
+verrc(eval, code, fmt, ap)
+	int eval;
+	int code;
+	const char *fmt;
+	va_list ap;
+{
+	if (err_file == 0)
+		err_set_file((FILE *)0);
+	fprintf(err_file, "%s: ", _getprogname());
+	if (fmt != NULL) {
+		vfprintf(err_file, fmt, ap);
+		fprintf(err_file, ": ");
+	}
+	fprintf(err_file, "%s\n", strerror(code));
+	if (err_exit)
+		err_exit(eval);
+	exit(eval);
+}
+
+void
+errx(int eval, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	verrx(eval, fmt, ap);
+	va_end(ap);
+}
+
+void
+verrx(eval, fmt, ap)
+	int eval;
+	const char *fmt;
+	va_list ap;
+{
+	if (err_file == 0)
+		err_set_file((FILE *)0);
+	fprintf(err_file, "%s: ", _getprogname());
+	if (fmt != NULL)
+		vfprintf(err_file, fmt, ap);
+	fprintf(err_file, "\n");
+	if (err_exit)
+		err_exit(eval);
+	exit(eval);
+}
+
+__weak_reference(_warn, warn);
+
+void
+_warn(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vwarnc(errno, fmt, ap);
+	va_end(ap);
+}
+
+void
+vwarn(fmt, ap)
+	const char *fmt;
+	va_list ap;
+{
+	vwarnc(errno, fmt, ap);
+}
+
+void
+warnc(int code, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vwarnc(code, fmt, ap);
+	va_end(ap);
+}
+
+void
+vwarnc(code, fmt, ap)
+	int code;
+	const char *fmt;
+	va_list ap;
+{
+	if (err_file == 0)
+		err_set_file((FILE *)0);
+	fprintf(err_file, "%s: ", _getprogname());
+	if (fmt != NULL) {
+		vfprintf(err_file, fmt, ap);
+		fprintf(err_file, ": ");
+	}
+	fprintf(err_file, "%s\n", strerror(code));
+}
+
+void
+warnx(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vwarnx(fmt, ap);
+	va_end(ap);
+}
+
+void
+vwarnx(fmt, ap)
+	const char *fmt;
+	va_list ap;
+{
+	if (err_file == 0)
+		err_set_file((FILE *)0);
+	fprintf(err_file, "%s: ", _getprogname());
+	if (fmt != NULL)
+		vfprintf(err_file, fmt, ap);
+	fprintf(err_file, "\n");
+}
Index: /trunk/libc/src/fbsdlibc/gen/fpclassify.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/fpclassify.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/fpclassify.c	(revision 2448)
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/gen/fpclassify.c,v 1.2 2005/02/06 03:23:31 das Exp $
+ */
+
+#include "namespace.h"
+#include <sys/endian.h>
+
+#include <math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+
+int
+__fpclassifyf(float f)
+{
+	union IEEEf2bits u;
+
+	u.f = f;
+	if (u.bits.exp == 0) {
+		if (u.bits.man == 0)
+			return (FP_ZERO);
+		return (FP_SUBNORMAL);
+	}
+	if (u.bits.exp == 255) {
+		if (u.bits.man == 0)
+			return (FP_INFINITE);
+		return (FP_NAN);
+	}
+	return (FP_NORMAL);
+}
+
+int
+__fpclassifyd(double d)
+{
+	union IEEEd2bits u;
+
+	u.d = d;
+	if (u.bits.exp == 0) {
+		if ((u.bits.manl | u.bits.manh) == 0)
+			return (FP_ZERO);
+		return (FP_SUBNORMAL);
+	}
+	if (u.bits.exp == 2047) {
+		if ((u.bits.manl | u.bits.manh) == 0)
+			return (FP_INFINITE);
+		return (FP_NAN);
+	}
+	return (FP_NORMAL);
+}
+
+int
+__fpclassifyl(long double e)
+{
+	union IEEEl2bits u;
+
+	u.e = e;
+	if (u.bits.exp == 0) {
+		if ((u.bits.manl | u.bits.manh) == 0)
+			return (FP_ZERO);
+		return (FP_SUBNORMAL);
+	}
+	mask_nbit_l(u);		/* Mask normalization bit if applicable. */
+	if (u.bits.exp == 32767) {
+		if ((u.bits.manl | u.bits.manh) == 0)
+			return (FP_INFINITE);
+		return (FP_NAN);
+	}
+	return (FP_NORMAL);
+}
Index: /trunk/libc/src/fbsdlibc/gen/ftok.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/ftok.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/ftok.c	(revision 2448)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/lib/libc/gen/ftok.c,v 1.7 2004/06/01 06:53:07 tjr Exp $");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+
+key_t
+_STD(ftok)(path, id)
+	const char *path;
+	int id;
+{
+	struct stat st;
+
+	if (stat(path, &st) < 0)
+		return (key_t)-1;
+
+	return (key_t) (id << 24 | (st.st_dev & 0xff) << 16 | (st.st_ino & 0xffff));
+}
Index: /trunk/libc/src/fbsdlibc/gen/fts.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/fts.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/fts.c	(revision 2448)
@@ -0,0 +1,1267 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $OpenBSD: fts.c,v 1.22 1999/10/03 19:22:22 millert Exp $
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fts.c	8.6 (Berkeley) 8/14/94";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#ifndef __EMX__
+# define IS_SLASH(ch)   ( (ch) == '/' )
+#else
+# define NEED_STRRSLASH
+# define IS_SLASH(ch)   ( (ch) == '/' || (ch) == '\\' )
+#endif
+
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/lib/libc/gen/fts.c,v 1.27 2004/06/08 06:23:23 das Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+static FTSENT	*fts_alloc(FTS *, char *, int);
+static FTSENT	*fts_build(FTS *, int);
+static void	 fts_lfree(FTSENT *);
+static void	 fts_load(FTS *, FTSENT *);
+static size_t	 fts_maxarglen(char * const *);
+static void	 fts_padjust(FTS *, FTSENT *);
+static int	 fts_palloc(FTS *, size_t);
+static FTSENT	*fts_sort(FTS *, FTSENT *, int);
+static u_short	 fts_stat(FTS *, FTSENT *, int);
+static int	 fts_safe_changedir(FTS *, FTSENT *, int, char *);
+static int	 fts_ufslinks(FTS *, const FTSENT *);
+
+#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))
+
+#ifdef HAVE_FCHDIR
+#define	FCHDIR(sp, fd)	(!ISSET(FTS_NOCHDIR) && fchdir(fd))
+#else
+#define	FCHDIR(sp, rdir) (!ISSET(FTS_NOCHDIR) && chdir(rdir))
+#endif
+
+/* fts_build flags */
+#define	BCHILD		1		/* fts_children */
+#define	BNAMES		2		/* fts_children, names only */
+#define	BREAD		3		/* fts_read */
+
+/*
+ * Internal representation of an FTS, including extra implementation
+ * details.  The FTS returned from fts_open points to this structure's
+ * ftsp_fts member (and can be cast to an _fts_private as required)
+ */
+struct _fts_private {
+	FTS		ftsp_fts;
+	struct statfs	ftsp_statfs;
+	dev_t		ftsp_dev;
+	int		ftsp_linksreliable;
+};
+
+#ifndef __EMX__
+/*
+ * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it
+ * knows that a directory could not possibly have subdirectories.  This
+ * is decided by looking at the link count: a subdirectory would
+ * increment its parent's link count by virtue of its own ".." entry.
+ * This assumption only holds for UFS-like filesystems that implement
+ * links and directories this way, so we must punt for others.
+ */
+
+static const char *ufslike_filesystems[] = {
+	"ufs",
+	"nfs",
+	"nfs4",
+	"ext2fs",
+	0
+};
+#endif /* !__EMX__ */
+
+FTS *
+fts_open(argv, options, compar)
+	char * const *argv;
+	int options;
+	int (*compar)(const FTSENT * const *, const FTSENT * const *);
+{
+	struct _fts_private *priv;
+	FTS *sp;
+	FTSENT *p, *root;
+	int nitems;
+	FTSENT *parent, *tmp;
+	int len;
+
+	/* Options check. */
+	if (options & ~FTS_OPTIONMASK) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/* Allocate/initialize the stream. */
+	if ((priv = malloc(sizeof(*priv))) == NULL)
+		return (NULL);
+	memset(priv, 0, sizeof(*priv));
+	sp = &priv->ftsp_fts;
+	sp->fts_compar = compar;
+	sp->fts_options = options;
+
+	/* Shush, GCC. */
+	tmp = NULL;
+
+	/* 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.
+	 */
+	if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+		goto mem1;
+
+	/* Allocate/initialize root's parent. */
+	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. */
+		if ((len = strlen(*argv)) == 0) {
+			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);
+}
+
+#ifdef NEED_STRRSLASH
+static char *strrslash(register char *psz)
+{
+    register char ch;
+    char *pszLast = NULL;
+    for (; (ch = *psz); psz++)
+        switch (ch)
+        {
+            case '/':
+            case '\\':
+            case ':':
+                pszLast = psz;
+                break;
+        }
+    return pszLast;
+}
+#endif
+
+static void
+fts_load(sp, p)
+	FTS *sp;
+	FTSENT *p;
+{
+	int len;
+	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);
+#ifdef NEED_STRRSLASH
+	if ((cp = strrslash(p->fts_name)) && (cp != p->fts_name || cp[1])) {
+#else
+	if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+#endif
+		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(sp)
+	FTS *sp;
+{
+	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);
+	if (sp->fts_array)
+		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);
+			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)							\
+	(IS_SLASH(p->fts_path[p->fts_pathlen - 1])			\
+	    ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+FTSENT *
+fts_read(sp)
+	FTS *sp;
+{
+	FTSENT *p, *tmp;
+	int instr;
+	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;
+		goto name;
+	}
+
+	/* Move to the next node on this level. */
+next:	tmp = p;
+	if ((p = p->fts_link) != NULL) {
+		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 (sp->fts_cur = 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 (sp->fts_cur = p);
+	}
+
+	/* Move up to the parent node. */
+	p = tmp->fts_parent;
+	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);
+		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);
+			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 (sp->fts_cur = 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(sp, p, instr)
+	FTS *sp;
+	FTSENT *p;
+	int instr;
+{
+	if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
+		errno = EINVAL;
+		return (1);
+	}
+	p->fts_instr = instr;
+	return (0);
+}
+
+FTSENT *
+fts_children(sp, instr)
+	FTS *sp;
+	int instr;
+{
+	FTSENT *p;
+	int fd;
+
+	if (instr != 0 && instr != FTS_NAMEONLY) {
+		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.
+	 */
+	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 || IS_SLASH(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);
+}
+
+#ifndef fts_get_clientptr
+#error "fts_get_clientptr not defined"
+#endif
+
+void *
+(fts_get_clientptr)(FTS *sp)
+{
+
+	return (fts_get_clientptr(sp));
+}
+
+#ifndef fts_get_stream
+#error "fts_get_stream not defined"
+#endif
+
+FTS *
+(fts_get_stream)(FTSENT *p)
+{
+	return (fts_get_stream(p));
+}
+
+void
+fts_set_clientptr(FTS *sp, void *clientptr)
+{
+
+	sp->fts_clientptr = clientptr;
+}
+
+/*
+ * 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 *
+fts_build(sp, type)
+	FTS *sp;
+	int type;
+{
+	struct dirent *dp;
+	FTSENT *p, *head;
+	int nitems;
+	FTSENT *cur, *tail;
+	DIR *dirp;
+	void *oldaddr;
+	size_t dnamlen;
+	int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno,
+	    nostat, doadjust;
+	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) && !defined(__EMX__)
+	if (ISSET(FTS_WHITEOUT))
+		oflag = DTF_NODUP | DTF_REWIND;
+	else
+		oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND;
+#else
+        (void)(oflag);
+#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)) {
+		if (fts_ufslinks(sp, cur))
+			nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+		else
+			nlinks = -1;
+		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;
+		} 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));) {
+		dnamlen = dp->d_namlen;
+		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+			continue;
+
+		if ((p = fts_alloc(sp, dp->d_name, (int)dnamlen)) == NULL)
+			goto mem1;
+		if (dnamlen >= maxlen) {	/* include space for NUL */
+			oldaddr = sp->fts_path;
+			if (fts_palloc(sp, dnamlen + 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;
+				if (p)
+					free(p);
+				fts_lfree(head);
+				(void)closedir(dirp);
+				cur->fts_info = FTS_ERR;
+				SET(FTS_STOP);
+				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 + dnamlen >= 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);
+			errno = ENAMETOOLONG;
+			return (NULL);
+		}
+		p->fts_level = level;
+		p->fts_parent = sp->fts_cur;
+		p->fts_pathlen = len + dnamlen;
+
+#ifdef FTS_WHITEOUT
+		if (dp->d_type == DT_WHT)
+			p->fts_flags |= FTS_ISW;
+#endif
+
+		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 if (nlinks == 0
+#ifdef DT_DIR
+		    || (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);
+		return (NULL);
+	}
+
+	/* If didn't find anything, return NULL. */
+	if (!nitems) {
+		if (type == BREAD)
+			cur->fts_info = FTS_DP;
+		return (NULL);
+	}
+
+	/* Sort the entries. */
+	if (sp->fts_compar && nitems > 1)
+		head = fts_sort(sp, head, nitems);
+	return (head);
+}
+
+static u_short
+fts_stat(sp, p, follow)
+	FTS *sp;
+	FTSENT *p;
+	int follow;
+{
+	FTSENT *t;
+	dev_t dev;
+	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;
+
+#ifdef FTS_WHITEOUT
+	/* 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)) {
+				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);
+}
+
+/*
+ * The comparison function takes pointers to pointers to FTSENT structures.
+ * Qsort wants a comparison function that takes pointers to void.
+ * (Both with appropriate levels of const-poisoning, of course!)
+ * Use a trampoline function to deal with the difference.
+ */
+static int
+fts_compar(const void *a, const void *b)
+{
+	FTS *parent;
+
+	parent = (*(const FTSENT * const *)a)->fts_fts;
+	return (*parent->fts_compar)(a, b);
+}
+
+static FTSENT *
+fts_sort(sp, head, nitems)
+	FTS *sp;
+	FTSENT *head;
+	int nitems;
+{
+	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) {
+		sp->fts_nitems = nitems + 40;
+		if ((sp->fts_array = reallocf(sp->fts_array,
+		    sp->fts_nitems * sizeof(FTSENT *))) == NULL) {
+			sp->fts_nitems = 0;
+			return (head);
+		}
+	}
+	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+		*ap++ = p;
+	qsort(sp->fts_array, nitems, sizeof(FTSENT *), 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 *
+fts_alloc(sp, name, namelen)
+	FTS *sp;
+	char *name;
+	int namelen;
+{
+	FTSENT *p;
+	size_t len;
+
+	struct ftsent_withstat {
+		FTSENT	ent;
+		struct	stat statbuf;
+	};
+
+	/*
+	 * 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.
+	 */
+	if (ISSET(FTS_NOSTAT))
+		len = sizeof(FTSENT) + namelen + 1;
+	else
+		len = sizeof(struct ftsent_withstat) + namelen + 1;
+
+	if ((p = malloc(len)) == NULL)
+		return (NULL);
+
+	if (ISSET(FTS_NOSTAT)) {
+		p->fts_name = (char *)(p + 1);
+		p->fts_statp = NULL;
+	} else {
+		p->fts_name = (char *)((struct ftsent_withstat *)p + 1);
+		p->fts_statp = &((struct ftsent_withstat *)p)->statbuf;
+	}
+
+	/* Copy the name and guarantee NUL termination. */
+	memcpy(p->fts_name, name, namelen);
+	p->fts_name[namelen] = '\0';
+	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;
+	p->fts_fts = sp;
+	return (p);
+}
+
+static void
+fts_lfree(head)
+	FTSENT *head;
+{
+	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
+fts_palloc(sp, more)
+	FTS *sp;
+	size_t more;
+{
+
+	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) {
+		if (sp->fts_path)
+			free(sp->fts_path);
+		sp->fts_path = NULL;
+		errno = ENAMETOOLONG;
+		return (1);
+	}
+	sp->fts_path = reallocf(sp->fts_path, sp->fts_pathlen);
+	return (sp->fts_path == NULL);
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+fts_padjust(sp, head)
+	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
+fts_maxarglen(argv)
+	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
+fts_safe_changedir(sp, p, fd, path)
+	FTS *sp;
+	FTSENT *p;
+	int fd;
+	char *path;
+{
+	int ret, oerrno, newfd;
+	struct stat sb;
+
+	newfd = fd;
+	if (ISSET(FTS_NOCHDIR))
+		return (0);
+	if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
+		return (-1);
+	if (_fstat(newfd, &sb)) {
+		ret = -1;
+		goto bail;
+	}
+	if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
+		errno = ENOENT;		/* disinformation */
+		ret = -1;
+		goto bail;
+	}
+	ret = fchdir(newfd);
+bail:
+	oerrno = errno;
+	if (fd < 0)
+		(void)_close(newfd);
+	errno = oerrno;
+	return (ret);
+}
+
+/*
+ * Check if the filesystem for "ent" has UFS-style links.
+ */
+static int
+fts_ufslinks(FTS *sp, const FTSENT *ent)
+{
+	struct _fts_private *priv;
+	const char **cpp;
+
+	priv = (struct _fts_private *)sp;
+#ifdef __EMX__
+        /* we don't have reliable links */
+        priv->ftsp_linksreliable = 0;
+        (void)cpp;
+#else
+	/*
+	 * If this node's device is different from the previous, grab
+	 * the filesystem information, and decide on the reliability
+	 * of the link information from this filesystem for stat(2)
+	 * avoidance.
+	 */
+	if (priv->ftsp_dev != ent->fts_dev) {
+		if (statfs(ent->fts_path, &priv->ftsp_statfs) != -1) {
+			priv->ftsp_dev = ent->fts_dev;
+			priv->ftsp_linksreliable = 0;
+			for (cpp = ufslike_filesystems; *cpp; cpp++) {
+				if (strcmp(priv->ftsp_statfs.f_fstypename,
+				    *cpp) == 0) {
+					priv->ftsp_linksreliable = 1;
+					break;
+				}
+			}
+		} else {
+			priv->ftsp_linksreliable = 0;
+		}
+	}
+#endif
+	return (priv->ftsp_linksreliable);
+}
Index: /trunk/libc/src/fbsdlibc/gen/ftw.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/ftw.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/ftw.c	(revision 2448)
@@ -0,0 +1,99 @@
+/*	$OpenBSD: ftw.c,v 1.4 2004/07/07 16:05:23 millert Exp $	*/
+
+/*
+ * Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$OpenBSD: ftw.c,v 1.4 2004/07/07 16:05:23 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/ftw.c,v 1.4 2004/08/24 13:00:55 tjr Exp $");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fts.h>
+#include <ftw.h>
+#include <limits.h>
+
+int
+_STD(ftw)(const char *path, int (*fn)(const char *, const struct stat *, int),
+    int nfds)
+{
+	char * const paths[2] = { (char *)path, NULL };
+	FTSENT *cur;
+	FTS *ftsp;
+	int error = 0, fnflag, sverrno;
+
+	/* XXX - nfds is currently unused */
+	if (nfds < 1 || nfds > OPEN_MAX) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	ftsp = fts_open(paths, FTS_LOGICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL);
+	if (ftsp == NULL)
+		return (-1);
+	while ((cur = fts_read(ftsp)) != NULL) {
+		switch (cur->fts_info) {
+		case FTS_D:
+			fnflag = FTW_D;
+			break;
+		case FTS_DNR:
+			fnflag = FTW_DNR;
+			break;
+		case FTS_DP:
+			/* we only visit in preorder */
+			continue;
+		case FTS_F:
+		case FTS_DEFAULT:
+			fnflag = FTW_F;
+			break;
+		case FTS_NS:
+		case FTS_NSOK:
+		case FTS_SLNONE:
+			fnflag = FTW_NS;
+			break;
+		case FTS_SL:
+			fnflag = FTW_SL;
+			break;
+		case FTS_DC:
+			errno = ELOOP;
+			/* FALLTHROUGH */
+		default:
+			error = -1;
+			goto done;
+		}
+		error = fn(cur->fts_path, cur->fts_statp, fnflag);
+		if (error != 0)
+			break;
+	}
+done:
+	sverrno = errno;
+	if (fts_close(ftsp) != 0 && error == 0)
+		error = -1;
+	else
+		errno = sverrno;
+	return (error);
+}
Index: /trunk/libc/src/fbsdlibc/gen/gen.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/gen.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/gen.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/fbsdlibc/gen/*.c)
Index: /trunk/libc/src/fbsdlibc/gen/getgrent.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/getgrent.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/getgrent.c	(revision 2448)
@@ -0,0 +1,1168 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getgrent.c,v 1.32 2004/05/17 22:15:49 kientzle Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#ifdef HESIOD
+#include <hesiod.h>
+#endif
+#include <grp.h>
+#include <nsswitch.h>
+#ifndef __EMX__
+#include <pthread.h>
+#include <pthread_np.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "nss_tls.h"
+
+
+enum constants {
+	GRP_STORAGE_INITIAL	= 1 << 10, /* 1 KByte */
+	GRP_STORAGE_MAX		= 1 << 20, /* 1 MByte */
+	SETGRENT		= 1,
+	ENDGRENT		= 2,
+	HESIOD_NAME_MAX		= 256,
+};
+
+static const ns_src defaultsrc[] = {
+	{ NSSRC_COMPAT, NS_SUCCESS },
+	{ NULL, 0 }
+};
+
+int	 __gr_match_entry(const char *, size_t, enum nss_lookup_type,
+	    const char *, gid_t);
+int	 __gr_parse_entry(char *, size_t, struct group *, char *, size_t,
+	    int *);
+
+static	int	 is_comment_line(const char *, size_t);
+
+union key {
+	const char	*name;
+	gid_t		 gid;
+};
+static	struct group *getgr(int (*)(union key, struct group *, char *, size_t,
+		    struct group **), union key);
+static	int	 wrap_getgrnam_r(union key, struct group *, char *, size_t,
+		    struct group **);
+static	int	 wrap_getgrgid_r(union key, struct group *, char *, size_t,
+		    struct group **);
+static	int	 wrap_getgrent_r(union key, struct group *, char *, size_t,
+		    struct group **);
+
+struct files_state {
+	FILE	*fp;
+	int	 stayopen;
+};
+static	void	 files_endstate(void *);
+NSS_TLS_HANDLING(files);
+static	int	 files_setgrent(void *, void *, va_list);
+static	int	 files_group(void *, void *, va_list);
+
+
+#ifdef HESIOD
+struct dns_state {
+	long	counter;
+};
+static	void	 dns_endstate(void *);
+NSS_TLS_HANDLING(dns);
+static	int	 dns_setgrent(void *, void *, va_list);
+static	int	 dns_group(void *, void *, va_list);
+#endif
+
+
+#ifdef YP
+struct nis_state {
+	char	 domain[MAXHOSTNAMELEN];
+	int	 done;
+	char	*key;
+	int	 keylen;
+};
+static	void	 nis_endstate(void *);
+NSS_TLS_HANDLING(nis);
+static	int	 nis_setgrent(void *, void *, va_list);
+static	int	 nis_group(void *, void *, va_list);
+#endif
+
+struct compat_state {
+	FILE	*fp;
+	int	 stayopen;
+	char	*name;
+	enum _compat {
+		COMPAT_MODE_OFF = 0,
+		COMPAT_MODE_ALL,
+		COMPAT_MODE_NAME
+	}	 compat;
+};
+static	void	 compat_endstate(void *);
+NSS_TLS_HANDLING(compat);
+static	int	 compat_setgrent(void *, void *, va_list);
+static	int	 compat_group(void *, void *, va_list);
+
+
+/* XXX IEEE Std 1003.1, 2003 specifies `void setgrent(void)' */
+int				
+setgrent(void)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_setgrent, (void *)SETGRENT },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_setgrent, (void *)SETGRENT },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_setgrent, (void *)SETGRENT },
+#endif
+		{ NSSRC_COMPAT, compat_setgrent, (void *)SETGRENT },
+		{ NULL, NULL, NULL }
+	};
+	(void)_nsdispatch(NULL, dtab, NSDB_GROUP, "setgrent", defaultsrc, 0);
+	return (1);
+}
+
+
+int
+setgroupent(int stayopen)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_setgrent, (void *)SETGRENT },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_setgrent, (void *)SETGRENT },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_setgrent, (void *)SETGRENT },
+#endif
+		{ NSSRC_COMPAT, compat_setgrent, (void *)SETGRENT },
+		{ NULL, NULL, NULL }
+	};
+	(void)_nsdispatch(NULL, dtab, NSDB_GROUP, "setgrent", defaultsrc,
+	    stayopen);
+	return (1);
+}
+
+
+void
+endgrent(void)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_setgrent, (void *)ENDGRENT },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_setgrent, (void *)ENDGRENT },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_setgrent, (void *)ENDGRENT },
+#endif
+		{ NSSRC_COMPAT, compat_setgrent, (void *)ENDGRENT },
+		{ NULL, NULL, NULL }
+	};
+	(void)_nsdispatch(NULL, dtab, NSDB_GROUP, "endgrent", defaultsrc);
+}
+
+
+int
+getgrent_r(struct group *grp, char *buffer, size_t bufsize,
+    struct group **result)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_group, (void *)nss_lt_all },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_group, (void *)nss_lt_all },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_group, (void *)nss_lt_all },
+#endif
+		{ NSSRC_COMPAT, compat_group, (void *)nss_lt_all },
+		{ NULL, NULL, NULL }
+	};
+	int	rv, ret_errno;
+
+	ret_errno = 0;
+	*result = NULL;
+	rv = _nsdispatch(result, dtab, NSDB_GROUP, "getgrent_r", defaultsrc,
+	    grp, buffer, bufsize, &ret_errno);
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+
+int
+getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize,
+    struct group **result)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_group, (void *)nss_lt_name },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_group, (void *)nss_lt_name },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_group, (void *)nss_lt_name },
+#endif
+		{ NSSRC_COMPAT, compat_group, (void *)nss_lt_name },
+		{ NULL, NULL, NULL }
+	};
+	int	rv, ret_errno;
+
+	ret_errno = 0;
+	*result = NULL;
+	rv = _nsdispatch(result, dtab, NSDB_GROUP, "getgrnam_r", defaultsrc,
+	    name, grp, buffer, bufsize, &ret_errno);
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+
+int
+getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize,
+    struct group **result)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_group, (void *)nss_lt_id },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_group, (void *)nss_lt_id },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_group, (void *)nss_lt_id },
+#endif
+		{ NSSRC_COMPAT, compat_group, (void *)nss_lt_id },
+		{ NULL, NULL, NULL }
+	};
+	int	rv, ret_errno;
+
+	ret_errno = 0;
+	*result = NULL;
+	rv = _nsdispatch(result, dtab, NSDB_GROUP, "getgrgid_r", defaultsrc,
+	    gid, grp, buffer, bufsize, &ret_errno);
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+
+static struct group	 grp;
+static char		*grp_storage;
+static size_t		 grp_storage_size;
+
+static struct group *
+getgr(int (*fn)(union key, struct group *, char *, size_t, struct group **),
+    union key key)
+{
+	int		 rv;
+	struct group	*res;
+
+	if (grp_storage == NULL) {
+		grp_storage = malloc(GRP_STORAGE_INITIAL);
+		if (grp_storage == NULL)
+			return (NULL);
+		grp_storage_size = GRP_STORAGE_INITIAL;
+	}
+	do {
+		rv = fn(key, &grp, grp_storage, grp_storage_size, &res);
+		if (res == NULL && rv == ERANGE) {
+			free(grp_storage);
+			if ((grp_storage_size << 1) > GRP_STORAGE_MAX) {
+				grp_storage = NULL;
+				errno = ERANGE;
+				return (NULL);
+			}
+			grp_storage_size <<= 1;
+			grp_storage = malloc(grp_storage_size);
+			if (grp_storage == NULL)
+				return (NULL);
+		}
+	} while (res == NULL && rv == ERANGE);
+	if (rv != 0)
+		errno = rv;
+	return (res);
+}
+
+
+static int
+wrap_getgrnam_r(union key key, struct group *grp, char *buffer, size_t bufsize,
+    struct group **res)
+{
+	return (getgrnam_r(key.name, grp, buffer, bufsize, res));
+}
+
+
+static int
+wrap_getgrgid_r(union key key, struct group *grp, char *buffer, size_t bufsize,
+    struct group **res)
+{
+	return (getgrgid_r(key.gid, grp, buffer, bufsize, res));
+}
+
+
+static int
+wrap_getgrent_r(union key key __unused, struct group *grp, char *buffer,
+    size_t bufsize, struct group **res)
+{
+	return (getgrent_r(grp, buffer, bufsize, res));
+}
+
+
+struct group *
+_STD(getgrnam)(const char *name)
+{
+	union key key;
+
+	key.name = name;
+	return (getgr(wrap_getgrnam_r, key));
+}
+
+
+struct group *
+getgrgid(gid_t gid)
+{
+	union key key;
+
+	key.gid = gid;
+	return (getgr(wrap_getgrgid_r, key));
+}
+
+
+struct group *
+getgrent(void)
+{
+	union key key;
+
+	key.gid = 0; /* not used */
+	return (getgr(wrap_getgrent_r, key));
+}
+
+
+static int
+is_comment_line(const char *s, size_t n)
+{
+	const char	*eom;
+
+	eom = &s[n];
+
+	for (; s < eom; s++)
+		if (*s == '#' || !isspace((unsigned char)*s))
+			break;
+	return (*s == '#' || s == eom);
+}
+
+
+/*
+ * files backend
+ */
+static void
+files_endstate(void *p)
+{
+
+	if (p == NULL)
+		return;
+	if (((struct files_state *)p)->fp != NULL)
+		fclose(((struct files_state *)p)->fp);
+	free(p);
+}
+
+
+static int
+files_setgrent(void *retval, void *mdata, va_list ap)
+{
+	struct files_state *st;
+	int		 rv, stayopen;
+
+	rv = files_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+	switch ((enum constants)mdata) {
+	case SETGRENT:
+		stayopen = va_arg(ap, int);
+		if (st->fp != NULL)
+			rewind(st->fp);
+		else if (stayopen)
+			st->fp = fopen(_PATH_GROUP, "r");
+		break;
+	case ENDGRENT:
+		if (st->fp != NULL) {
+			fclose(st->fp);
+			st->fp = NULL;
+		}
+		break;
+	default:
+		break;
+	}
+	return (NS_UNAVAIL);
+}
+
+
+static int
+files_group(void *retval, void *mdata, va_list ap)
+{
+	struct files_state	*st;
+	enum nss_lookup_type	 how;
+	const char		*name, *line;
+	struct group		*grp;
+	gid_t			 gid;
+	char			*buffer;
+	size_t			 bufsize, linesize;
+	int			 rv, stayopen, *errnop;
+
+	name = NULL;
+	gid = (gid_t)-1;
+	how = (enum nss_lookup_type)mdata;
+	switch (how) {
+	case nss_lt_name:
+		name = va_arg(ap, const char *);
+		break;
+	case nss_lt_id:
+		gid = va_arg(ap, gid_t);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		return (NS_NOTFOUND);
+	}
+	grp = va_arg(ap, struct group *);
+	buffer = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop = va_arg(ap, int *);
+	*errnop = files_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+	if (st->fp == NULL &&
+	    ((st->fp = fopen(_PATH_GROUP, "r")) == NULL)) {
+		*errnop = errno;
+		return (NS_UNAVAIL);
+	}
+	if (how == nss_lt_all)
+		stayopen = 1;
+	else {
+		rewind(st->fp);
+		stayopen = st->stayopen;
+	}
+	rv = NS_NOTFOUND;
+#ifndef __EMX__
+	while ((line = fgetln(st->fp, &linesize)) != NULL) {
+#else
+        char szLine[4096];
+        while ((line = fgets(szLine, sizeof(szLine), st->fp)) != NULL) {
+                linesize = strlen(szLine);
+#endif
+		if (line[linesize-1] == '\n')
+			linesize--;
+		rv = __gr_match_entry(line, linesize, how, name, gid);
+		if (rv != NS_SUCCESS)
+			continue;
+		/* We need room at least for the line, a string NUL
+		 * terminator, alignment padding, and one (char *)
+		 * pointer for the member list terminator.
+		 */
+		if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			break;
+		}
+		memcpy(buffer, line, linesize);
+		buffer[linesize] = '\0';
+		rv = __gr_parse_entry(buffer, linesize, grp,
+		    &buffer[linesize + 1], bufsize - linesize - 1, errnop);
+		if (rv & NS_TERMINATE)
+			break;
+	}
+	if (!stayopen && st->fp != NULL) {
+		fclose(st->fp);
+		st->fp = NULL;
+	}
+	if (rv == NS_SUCCESS && retval != NULL)
+		*(struct group **)retval = grp;
+	return (rv);
+}
+
+
+#ifdef HESIOD
+/*
+ * dns backend
+ */
+static void
+dns_endstate(void *p)
+{
+
+	free(p);
+}
+
+
+static int
+dns_setgrent(void *retval, void *cb_data, va_list ap)
+{
+	struct dns_state	*st;
+	int			 rv;
+
+	rv = dns_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+	st->counter = 0;
+	return (NS_UNAVAIL);
+}
+
+
+static int
+dns_group(void *retval, void *mdata, va_list ap)
+{
+	char			 buf[HESIOD_NAME_MAX];
+	struct dns_state	*st;
+	struct group		*grp;
+	const char		*name, *label;
+	void			*ctx;
+	char			*buffer, **hes;
+	size_t			 bufsize, adjsize, linesize;
+	gid_t			 gid;
+	enum nss_lookup_type	 how;
+	int			 rv, *errnop;
+
+	ctx = NULL;
+	hes = NULL;
+	name = NULL;
+	gid = (gid_t)-1;
+	how = (enum nss_lookup_type)mdata;
+	switch (how) {
+	case nss_lt_name:
+		name = va_arg(ap, const char *);
+		break;
+	case nss_lt_id:
+		gid = va_arg(ap, gid_t);
+		break;
+	case nss_lt_all:
+		break;
+	}
+	grp     = va_arg(ap, struct group *);
+	buffer  = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop  = va_arg(ap, int *);
+	*errnop = dns_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+	if (hesiod_init(&ctx) != 0) {
+		*errnop = errno;
+		rv = NS_UNAVAIL;
+		goto fin;
+	}
+	do {
+		rv = NS_NOTFOUND;
+		switch (how) {
+		case nss_lt_name:
+			label = name;
+			break;
+		case nss_lt_id:
+			if (snprintf(buf, sizeof(buf), "%lu",
+			    (unsigned long)gid) >= sizeof(buf))
+				goto fin;
+			label = buf;
+			break;
+		case nss_lt_all:
+			if (st->counter < 0)
+				goto fin;
+			if (snprintf(buf, sizeof(buf), "group-%ld",
+			    st->counter++) >= sizeof(buf))
+				goto fin;
+			label = buf;
+			break;
+		}
+		hes = hesiod_resolve(ctx, label,
+		    how == nss_lt_id ? "gid" : "group");
+		if ((how == nss_lt_id && hes == NULL &&
+		    (hes = hesiod_resolve(ctx, buf, "group")) == NULL) ||
+		    hes == NULL) {
+			if (how == nss_lt_all)
+				st->counter = -1;
+			if (errno != ENOENT)
+				*errnop = errno;
+			goto fin;
+		}
+		rv = __gr_match_entry(hes[0], strlen(hes[0]), how, name, gid);
+		if (rv != NS_SUCCESS) {
+			hesiod_free_list(ctx, hes);
+			hes = NULL;
+			continue;
+		}
+		/* We need room at least for the line, a string NUL
+		 * terminator, alignment padding, and one (char *)
+		 * pointer for the member list terminator.
+		 */
+		adjsize = bufsize - _ALIGNBYTES - sizeof(char *);
+		linesize = strlcpy(buffer, hes[0], adjsize);
+		if (linesize >= adjsize) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			goto fin;
+		}
+		hesiod_free_list(ctx, hes);
+		hes = NULL;
+		rv = __gr_parse_entry(buffer, linesize, grp,
+		    &buffer[linesize + 1], bufsize - linesize - 1, errnop);
+	} while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+	if (hes != NULL)
+		hesiod_free_list(ctx, hes);
+	if (ctx != NULL)
+		hesiod_end(ctx);
+	if (rv == NS_SUCCESS && retval != NULL)
+		*(struct group **)retval = grp;
+	return (rv);
+}
+#endif /* HESIOD */
+
+
+#ifdef YP
+/*
+ * nis backend
+ */
+static void
+nis_endstate(void *p)
+{
+
+	if (p == NULL)
+		return;
+	free(((struct nis_state *)p)->key);
+	free(p);
+}
+
+
+static int
+nis_setgrent(void *retval, void *cb_data, va_list ap)
+{
+	struct nis_state	*st;
+	int			 rv;
+
+	rv = nis_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+	st->done = 0;
+	free(st->key);
+	st->key = NULL;
+	return (NS_UNAVAIL);
+}
+
+
+static int
+nis_group(void *retval, void *mdata, va_list ap)
+{
+	char		 *map;
+	struct nis_state *st;
+	struct group	*grp;
+	const char	*name;
+	char		*buffer, *key, *result;
+	size_t		 bufsize;
+	gid_t		 gid;
+	enum nss_lookup_type how;
+	int		*errnop, keylen, resultlen, rv;
+	
+	name = NULL;
+	gid = (gid_t)-1;
+	how = (enum nss_lookup_type)mdata;
+	switch (how) {
+	case nss_lt_name:
+		name = va_arg(ap, const char *);
+		map = "group.byname";
+		break;
+	case nss_lt_id:
+		gid = va_arg(ap, gid_t);
+		map = "group.bygid";
+		break;
+	case nss_lt_all:
+		map = "group.byname";
+		break;
+	}
+	grp     = va_arg(ap, struct group *);
+	buffer  = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop  = va_arg(ap, int *);
+	*errnop = nis_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+	if (st->domain[0] == '\0') {
+		if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
+			*errnop = errno;
+			return (NS_UNAVAIL);
+		}
+	}
+	result = NULL;
+	do {
+		rv = NS_NOTFOUND;
+		switch (how) {
+		case nss_lt_name:
+			if (strlcpy(buffer, name, bufsize) >= bufsize)
+				goto erange;
+			break;
+		case nss_lt_id:
+			if (snprintf(buffer, bufsize, "%lu",
+			    (unsigned long)gid) >= bufsize)
+				goto erange;
+			break;
+		case nss_lt_all:
+			if (st->done)
+				goto fin;
+			break;
+		}
+		result = NULL;
+		if (how == nss_lt_all) {
+			if (st->key == NULL)
+				rv = yp_first(st->domain, map, &st->key,
+				    &st->keylen, &result, &resultlen);
+			else {
+				key = st->key;
+				keylen = st->keylen;
+				st->key = NULL;
+				rv = yp_next(st->domain, map, key, keylen,
+				    &st->key, &st->keylen, &result,
+				    &resultlen);
+				free(key);
+			}
+			if (rv != 0) {
+				free(result);
+				free(st->key);
+				st->key = NULL;
+				if (rv == YPERR_NOMORE) {
+					st->done = 1;
+					rv = NS_NOTFOUND;
+				} else
+					rv = NS_UNAVAIL;
+				goto fin;
+			}
+		} else {
+			rv = yp_match(st->domain, map, buffer, strlen(buffer),
+			    &result, &resultlen);
+			if (rv == YPERR_KEY) {
+				rv = NS_NOTFOUND;
+				continue;
+			} else if (rv != 0) {
+				free(result);
+				rv = NS_UNAVAIL;
+				continue;
+			}
+		}
+		/* We need room at least for the line, a string NUL
+		 * terminator, alignment padding, and one (char *)
+		 * pointer for the member list terminator.
+		 */
+		if (resultlen >= bufsize - _ALIGNBYTES - sizeof(char *))
+			goto erange;
+		memcpy(buffer, result, resultlen);
+		buffer[resultlen] = '\0';
+		free(result);
+		rv = __gr_match_entry(buffer, resultlen, how, name, gid);
+		if (rv == NS_SUCCESS)
+			rv = __gr_parse_entry(buffer, resultlen, grp,
+			    &buffer[resultlen+1], bufsize - resultlen - 1,
+			    errnop);
+	} while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+	if (rv == NS_SUCCESS && retval != NULL)
+		*(struct group **)retval = grp;
+	return (rv);	
+erange:
+	*errnop = ERANGE;
+	return (NS_RETURN);
+}
+#endif /* YP */
+
+
+
+/*
+ * compat backend
+ */
+static void
+compat_endstate(void *p)
+{
+	struct compat_state *st;
+
+	if (p == NULL)
+		return;
+	st = (struct compat_state *)p;
+	free(st->name);
+	if (st->fp != NULL)
+		fclose(st->fp);
+	free(p);
+}
+
+
+static int
+compat_setgrent(void *retval, void *mdata, va_list ap)
+{
+	static const ns_src compatsrc[] = {
+#ifdef YP
+		{ NSSRC_NIS, NS_SUCCESS },
+#endif
+		{ NULL, 0 }
+	};
+	ns_dtab dtab[] = {
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_setgrent, NULL },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_setgrent, NULL },
+#endif
+		{ NULL, NULL, NULL }
+	};
+	struct compat_state *st;
+	int		 rv, stayopen;
+
+#define set_setent(x, y) do {	 				\
+	int i;							\
+								\
+	for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++)	\
+		x[i].mdata = (void *)y;				\
+} while (0)
+
+	rv = compat_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+	switch ((enum constants)mdata) {
+	case SETGRENT:
+		stayopen = va_arg(ap, int);
+		if (st->fp != NULL)
+			rewind(st->fp);
+		else if (stayopen)
+			st->fp = fopen(_PATH_GROUP, "r");
+		set_setent(dtab, mdata);
+		(void)_nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "setgrent",
+		    compatsrc, 0);
+		break;
+	case ENDGRENT:
+		if (st->fp != NULL) {
+			fclose(st->fp);
+			st->fp = NULL;
+		}
+		set_setent(dtab, mdata);
+		(void)_nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "endgrent",
+		    compatsrc, 0);
+		break;
+	default:
+		break;
+	}
+	st->compat = COMPAT_MODE_OFF;
+	free(st->name);
+	st->name = NULL;
+	return (NS_UNAVAIL);
+#undef set_setent
+}
+
+
+static int
+compat_group(void *retval, void *mdata, va_list ap)
+{
+	static const ns_src compatsrc[] = {
+#ifdef YP
+		{ NSSRC_NIS, NS_SUCCESS },
+#endif
+		{ NULL, 0 }
+	};
+	ns_dtab dtab[] = {
+#ifdef YP
+		{ NSSRC_NIS, nis_group, NULL },
+#endif
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_group, NULL },
+#endif
+		{ NULL, NULL, NULL }
+	};
+	struct compat_state	*st;
+	enum nss_lookup_type	 how;
+	const char		*name, *line;
+	struct group		*grp;
+	gid_t			 gid;
+	char			*buffer, *p;
+	void			*discard;
+	size_t			 bufsize, linesize;
+	int			 rv = 0, stayopen = 0, *errnop; /* bird: initialized to shut up GCC. */
+
+#define set_lookup_type(x, y) do { 				\
+	int i;							\
+								\
+	for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++)	\
+		x[i].mdata = (void *)y;				\
+} while (0)
+
+	name = NULL;
+	gid = (gid_t)-1;
+	how = (enum nss_lookup_type)mdata;
+	switch (how) {
+	case nss_lt_name:
+		name = va_arg(ap, const char *);
+		break;
+	case nss_lt_id:
+		gid = va_arg(ap, gid_t);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		return (NS_NOTFOUND);
+	}
+	grp = va_arg(ap, struct group *);
+	buffer = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop = va_arg(ap, int *);
+	*errnop = compat_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+	if (st->fp == NULL &&
+	    ((st->fp = fopen(_PATH_GROUP, "r")) == NULL)) {
+		*errnop = errno;
+		rv = NS_UNAVAIL;
+		goto fin;
+	}
+	if (how == nss_lt_all)
+		stayopen = 1;
+	else {
+		rewind(st->fp);
+		stayopen = st->stayopen;
+	}
+docompat:
+	switch (st->compat) {
+	case COMPAT_MODE_ALL:
+		set_lookup_type(dtab, how);
+		switch (how) {
+		case nss_lt_all:
+			rv = _nsdispatch(&discard, dtab, NSDB_GROUP_COMPAT,
+			    "getgrent_r", compatsrc, grp, buffer, bufsize,
+			    errnop);
+			break;
+		case nss_lt_id:
+			rv = _nsdispatch(&discard, dtab, NSDB_GROUP_COMPAT,
+			    "getgrgid_r", compatsrc, gid, grp, buffer, bufsize,
+			    errnop);
+			break;
+		case nss_lt_name:
+			rv = _nsdispatch(&discard, dtab, NSDB_GROUP_COMPAT,
+			    "getgrnam_r", compatsrc, name, grp, buffer,
+			    bufsize, errnop);
+			break;
+		}
+		if (rv & NS_TERMINATE)
+			goto fin;
+		st->compat = COMPAT_MODE_OFF;
+		break;
+	case COMPAT_MODE_NAME:
+		set_lookup_type(dtab, nss_lt_name);
+		rv = _nsdispatch(&discard, dtab, NSDB_GROUP_COMPAT,
+		    "getgrnam_r", compatsrc, st->name, grp, buffer, bufsize,
+		    errnop);
+		switch (rv) {
+		case NS_SUCCESS:
+			switch (how) {
+			case nss_lt_name:
+				if (strcmp(name, grp->gr_name) != 0)
+					rv = NS_NOTFOUND;
+				break;
+			case nss_lt_id:
+				if (gid != grp->gr_gid)
+					rv = NS_NOTFOUND;
+				break;
+			default:
+				break;
+			}
+			break;
+		case NS_RETURN:
+			goto fin;
+		default:
+			break;
+		}
+		free(st->name);
+		st->name = NULL;
+		st->compat = COMPAT_MODE_OFF;
+		if (rv == NS_SUCCESS)
+			goto fin;
+		break;
+	default:
+		break;
+	}
+	rv = NS_NOTFOUND;
+#ifndef __EMX__
+	while ((line = fgetln(st->fp, &linesize)) != NULL) {
+#else
+        char szLine[4096];
+        while ((line = fgets(szLine, sizeof(szLine), st->fp)) != NULL) {
+               linesize = strlen(szLine);
+#endif
+		if (line[linesize-1] == '\n')
+			linesize--;
+		if (linesize > 2 && line[0] == '+') {
+			p = memchr(&line[1], ':', linesize);
+			if (p == NULL || p == &line[1])
+				st->compat = COMPAT_MODE_ALL;
+			else {
+				st->name = malloc(p - line);
+				if (st->name == NULL) {
+#ifndef __EMX__
+					syslog(LOG_ERR,
+					 "getgrent memory allocation failure");
+#endif
+					*errnop = ENOMEM;
+					rv = NS_UNAVAIL;
+					break;
+				}
+				memcpy(st->name, &line[1], p - line - 1);
+				st->name[p - line - 1] = '\0';
+				st->compat = COMPAT_MODE_NAME;
+			}
+			goto docompat;
+		}
+		rv = __gr_match_entry(line, linesize, how, name, gid);
+		if (rv != NS_SUCCESS)
+			continue;
+		/* We need room at least for the line, a string NUL
+		 * terminator, alignment padding, and one (char *)
+		 * pointer for the member list terminator.
+		 */
+		if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			break;
+		}
+		memcpy(buffer, line, linesize);
+		buffer[linesize] = '\0';
+		rv = __gr_parse_entry(buffer, linesize, grp,
+		    &buffer[linesize + 1], bufsize - linesize - 1, errnop);
+		if (rv & NS_TERMINATE)
+			break;
+	}
+fin:
+	if (!stayopen && st->fp != NULL) {
+		fclose(st->fp);
+		st->fp = NULL;
+	}
+	if (rv == NS_SUCCESS && retval != NULL)
+		*(struct group **)retval = grp;
+	return (rv);
+#undef set_lookup_type
+}
+
+
+/*
+ * common group line matching and parsing
+ */
+int
+__gr_match_entry(const char *line, size_t linesize, enum nss_lookup_type how,
+    const char *name, gid_t gid)
+{
+	size_t		 namesize;
+	const char	*p, *eol;
+	char		*q;
+	unsigned long	 n;
+	int		 i, needed;
+
+	if (linesize == 0 || is_comment_line(line, linesize))
+		return (NS_NOTFOUND);
+	switch (how) {
+	case nss_lt_name:	needed = 1; break;
+	case nss_lt_id:		needed = 2; break;
+	default:		needed = 2; break;
+	}
+	eol = &line[linesize];
+	for (p = line, i = 0; i < needed && p < eol; p++)
+		if (*p == ':')
+			i++;
+	if (i < needed)
+		return (NS_NOTFOUND);
+	switch (how) {
+	case nss_lt_name:
+		namesize = strlen(name);
+		if (namesize + 1 == (size_t)(p - line) &&
+		    memcmp(line, name, namesize) == 0)
+			return (NS_SUCCESS);
+		break;
+	case nss_lt_id:
+		n = strtoul(p, &q, 10);
+		if (q < eol && *q == ':' && gid == (gid_t)n)
+			return (NS_SUCCESS);
+		break;
+	case nss_lt_all:
+		return (NS_SUCCESS);
+	default:
+		break;
+	}
+	return (NS_NOTFOUND);
+}
+
+
+int
+__gr_parse_entry(char *line, size_t linesize, struct group *grp, char *membuf,
+    size_t membufsize, int *errnop)
+{
+	char	       *s_gid, *s_mem, *p, **members;
+	unsigned long	n;
+	int		maxmembers;
+
+	memset(grp, 0, sizeof(*grp));
+	members = (char **)_ALIGN(membuf);
+	membufsize -= (char *)members - membuf;
+	maxmembers = membufsize / sizeof(*members);
+	if (maxmembers <= 0 ||
+	    (grp->gr_name = strsep(&line, ":")) == NULL ||
+	    grp->gr_name[0] == '\0' ||
+	    (grp->gr_passwd = strsep(&line, ":")) == NULL ||
+	    (s_gid = strsep(&line, ":")) == NULL ||
+	    s_gid[0] == '\0')
+		return (NS_NOTFOUND);
+	s_mem = line;
+	n = strtoul(s_gid, &s_gid, 10);
+	if (s_gid[0] != '\0')
+		return (NS_NOTFOUND);
+	grp->gr_gid = (gid_t)n;
+	grp->gr_mem = members;
+	while (maxmembers > 1 && s_mem != NULL) {
+		p = strsep(&s_mem, ",");
+		if (p != NULL && *p != '\0') {
+			*members++ = p;
+			maxmembers--;
+		}
+	}
+	*members = NULL;
+	if (s_mem == NULL)
+		return (NS_SUCCESS);
+	else {
+		*errnop = ERANGE;
+		return (NS_RETURN);
+	}
+}
Index: /trunk/libc/src/fbsdlibc/gen/getgrouplist.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/getgrouplist.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/getgrouplist.c	(revision 2448)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1991, 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getgrouplist.c	8.2 (Berkeley) 12/8/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getgrouplist.c,v 1.13 2003/02/16 17:29:09 nectar Exp $");
+
+/*
+ * get credential
+ */
+#include <sys/types.h>
+#include <string.h>
+#include <grp.h>
+
+int
+getgrouplist(uname, agroup, groups, grpcnt)
+	const char *uname;
+	gid_t agroup;
+	gid_t *groups;
+	int *grpcnt;
+{
+	struct group *grp;
+	int i, maxgroups, ngroups, ret;
+
+	ret = 0;
+	ngroups = 0;
+	maxgroups = *grpcnt;
+	/*
+	 * When installing primary group, duplicate it;
+	 * the first element of groups is the effective gid
+	 * and will be overwritten when a setgid file is executed.
+	 */
+	groups[ngroups++] = agroup;
+	if (maxgroups > 1)
+		groups[ngroups++] = agroup;
+	/*
+	 * Scan the group file to find additional groups.
+	 */
+	setgrent();
+	while ((grp = getgrent()) != NULL) {
+		for (i = 0; i < ngroups; i++) {
+			if (grp->gr_gid == groups[i])
+				goto skip;
+		}
+		for (i = 0; grp->gr_mem[i]; i++) {
+			if (!strcmp(grp->gr_mem[i], uname)) {
+				if (ngroups >= maxgroups) {
+					ret = -1;
+					break;
+				}
+				groups[ngroups++] = grp->gr_gid;
+				break;
+			}
+		}
+skip:
+		;
+	}
+	endgrent();
+	*grpcnt = ngroups;
+	return (ret);
+}
Index: /trunk/libc/src/fbsdlibc/gen/getmntinfo.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/getmntinfo.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/getmntinfo.c	(revision 2448)
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getmntinfo.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getmntinfo.c,v 1.4 2002/02/01 00:57:29 obrien Exp $");
+
+#include <sys/param.h>
+#ifndef __EMX__
+#include <sys/ucred.h>
+#endif
+#include <sys/mount.h>
+#include <stdlib.h>
+
+/*
+ * Return information about mounted filesystems.
+ */
+int
+getmntinfo(mntbufp, flags)
+	struct statfs **mntbufp;
+	int flags;
+{
+	static struct statfs *mntbuf;
+	static int mntsize;
+	static long bufsize;
+
+	if (mntsize <= 0 && (mntsize = getfsstat(0, 0, MNT_NOWAIT)) < 0)
+		return (0);
+	if (bufsize > 0 && (mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
+		return (0);
+	while (bufsize <= mntsize * sizeof(struct statfs)) {
+		if (mntbuf)
+			free(mntbuf);
+		bufsize = (mntsize + 1) * sizeof(struct statfs);
+		if ((mntbuf = (struct statfs *)malloc(bufsize)) == 0)
+			return (0);
+		if ((mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
+			return (0);
+	}
+	*mntbufp = mntbuf;
+	return (mntsize);
+}
Index: /trunk/libc/src/fbsdlibc/gen/getnetgrent.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/getnetgrent.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/getnetgrent.c	(revision 2448)
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetgrent.c	8.2 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getnetgrent.c,v 1.31 2004/07/28 11:56:03 des Exp $");
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef __EMX__
+#include <netdb.h>
+#endif
+
+#ifdef YP
+/*
+ * Notes:
+ * We want to be able to use NIS netgroups properly while retaining
+ * the ability to use a local /etc/netgroup file. Unfortunately, you
+ * can't really do both at the same time - at least, not efficiently.
+ * NetBSD deals with this problem by creating a netgroup database
+ * using Berkeley DB (just like the password database) that allows
+ * for lookups using netgroup, netgroup.byuser or netgroup.byhost
+ * searches. This is a neat idea, but I don't have time to implement
+ * something like that now. (I think ultimately it would be nice
+ * if we DB-fied the group and netgroup stuff all in one shot, but
+ * for now I'm satisfied just to have something that works well
+ * without requiring massive code changes.)
+ *
+ * Therefore, to still permit the use of the local file and maintain
+ * optimum NIS performance, we allow for the following conditions:
+ *
+ * - If /etc/netgroup does not exist and NIS is turned on, we use
+ *   NIS netgroups only.
+ *
+ * - If /etc/netgroup exists but is empty, we use NIS netgroups
+ *   only.
+ *
+ * - If /etc/netgroup exists and contains _only_ a '+', we use
+ *   NIS netgroups only.
+ *
+ * - If /etc/netgroup exists, contains locally defined netgroups
+ *   and a '+', we use a mixture of NIS and the local entries.
+ *   This method should return the same NIS data as just using
+ *   NIS alone, but it will be slower if the NIS netgroup database
+ *   is large (innetgr() in particular will suffer since extra
+ *   processing has to be done in order to determine memberships
+ *   using just the raw netgroup data).
+ *
+ * - If /etc/netgroup exists and contains only locally defined
+ *   netgroup entries, we use just those local entries and ignore
+ *   NIS (this is the original, pre-NIS behavior).
+ */
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+static char *_netgr_yp_domain;
+int _use_only_yp;
+static int _netgr_yp_enabled;
+static int _yp_innetgr;
+#endif
+
+#ifndef _PATH_NETGROUP
+#define _PATH_NETGROUP "/etc/netgroup"
+#endif
+
+/*
+ * Static Variables and functions used by setnetgrent(), getnetgrent() and
+ * endnetgrent().
+ * There are two linked lists:
+ * - linelist is just used by setnetgrent() to parse the net group file via.
+ *   parse_netgrp()
+ * - netgrp is the list of entries for the current netgroup
+ */
+struct linelist {
+	struct linelist	*l_next;	/* Chain ptr. */
+	int		l_parsed;	/* Flag for cycles */
+	char		*l_groupname;	/* Name of netgroup */
+	char		*l_line;	/* Netgroup entrie(s) to be parsed */
+};
+
+struct netgrp {
+	struct netgrp	*ng_next;	/* Chain ptr */
+	char		*ng_str[3];	/* Field pointers, see below */
+};
+#define NG_HOST		0	/* Host name */
+#define NG_USER		1	/* User name */
+#define NG_DOM		2	/* and Domain name */
+
+static struct linelist	*linehead = (struct linelist *)0;
+static struct netgrp	*nextgrp = (struct netgrp *)0;
+static struct {
+	struct netgrp	*gr;
+	char		*grname;
+} grouphead = {
+	(struct netgrp *)0,
+	(char *)0,
+};
+static FILE *netf = (FILE *)0;
+
+static int parse_netgrp(const char *);
+static struct linelist *read_for_group(const char *);
+void setnetgrent(const char *);
+void endnetgrent(void);
+int getnetgrent(char **, char **, char **);
+int innetgr(const char *, const char *, const char *, const char *);
+
+#define	LINSIZ	1024	/* Length of netgroup file line */
+
+/*
+ * setnetgrent()
+ * Parse the netgroup file looking for the netgroup and build the list
+ * of netgrp structures. Let parse_netgrp() and read_for_group() do
+ * most of the work.
+ */
+void
+setnetgrent(const char *group)
+{
+#ifdef YP
+	struct stat _yp_statp;
+	char _yp_plus;
+#endif
+
+	/* Sanity check */
+
+	if (group == NULL || !strlen(group))
+		return;
+
+	if (grouphead.gr == (struct netgrp *)0 ||
+		strcmp(group, grouphead.grname)) {
+		endnetgrent();
+#ifdef YP
+		/* Presumed guilty until proven innocent. */
+		_use_only_yp = 0;
+		/*
+		 * If /etc/netgroup doesn't exist or is empty,
+		 * use NIS exclusively.
+		 */
+		if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) &&
+			errno == ENOENT) || _yp_statp.st_size == 0)
+			_use_only_yp = _netgr_yp_enabled = 1;
+		if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){
+		/*
+		 * Icky: grab the first character of the netgroup file
+		 * and turn on NIS if it's a '+'. rewind the stream
+		 * afterwards so we don't goof up read_for_group() later.
+		 */
+			if (netf) {
+				fscanf(netf, "%c", &_yp_plus);
+				rewind(netf);
+				if (_yp_plus == '+')
+					_use_only_yp = _netgr_yp_enabled = 1;
+			}
+		/*
+		 * If we were called specifically for an innetgr()
+		 * lookup and we're in NIS-only mode, short-circuit
+		 * parse_netgroup() and cut directly to the chase.
+		 */
+			if (_use_only_yp && _yp_innetgr) {
+				/* dohw! */
+				if (netf != NULL)
+					fclose(netf);
+				return;
+			}
+#else
+		if ((netf = fopen(_PATH_NETGROUP, "r"))) { /* bird: shutting up GCC */
+#endif
+			if (parse_netgrp(group))
+				endnetgrent();
+			else {
+				grouphead.grname = (char *)
+					malloc(strlen(group) + 1);
+				strcpy(grouphead.grname, group);
+			}
+			if (netf)
+				fclose(netf);
+		}
+	}
+	nextgrp = grouphead.gr;
+}
+
+/*
+ * Get the next netgroup off the list.
+ */
+int
+getnetgrent(char **hostp, char **userp, char **domp)
+{
+#ifdef YP
+	_yp_innetgr = 0;
+#endif
+
+	if (nextgrp) {
+		*hostp = nextgrp->ng_str[NG_HOST];
+		*userp = nextgrp->ng_str[NG_USER];
+		*domp = nextgrp->ng_str[NG_DOM];
+		nextgrp = nextgrp->ng_next;
+		return (1);
+	}
+	return (0);
+}
+
+/*
+ * endnetgrent() - cleanup
+ */
+void
+endnetgrent(void)
+{
+	struct linelist *lp, *olp;
+	struct netgrp *gp, *ogp;
+
+	lp = linehead;
+	while (lp) {
+		olp = lp;
+		lp = lp->l_next;
+		free(olp->l_groupname);
+		free(olp->l_line);
+		free((char *)olp);
+	}
+	linehead = (struct linelist *)0;
+	if (grouphead.grname) {
+		free(grouphead.grname);
+		grouphead.grname = (char *)0;
+	}
+	gp = grouphead.gr;
+	while (gp) {
+		ogp = gp;
+		gp = gp->ng_next;
+		if (ogp->ng_str[NG_HOST])
+			free(ogp->ng_str[NG_HOST]);
+		if (ogp->ng_str[NG_USER])
+			free(ogp->ng_str[NG_USER]);
+		if (ogp->ng_str[NG_DOM])
+			free(ogp->ng_str[NG_DOM]);
+		free((char *)ogp);
+	}
+	grouphead.gr = (struct netgrp *)0;
+#ifdef YP
+	_netgr_yp_enabled = 0;
+#endif
+}
+
+#ifdef YP
+static int
+_listmatch(const char *list, const char *group, int len)
+{
+	const char *ptr = list;
+	const char *cptr;
+	int glen = strlen(group);
+
+	/* skip possible leading whitespace */
+	while(isspace((unsigned char)*ptr))
+		ptr++;
+
+	while (ptr < list + len) {
+		cptr = ptr;
+		while(*ptr != ','  && *ptr != '\0' && !isspace((unsigned char)*ptr))
+			ptr++;
+		if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr))
+			return(1);
+		while(*ptr == ','  || isspace((unsigned char)*ptr))
+			ptr++;
+	}
+
+	return(0);
+}
+
+static int
+_buildkey(char *key, const char *str, const char *dom, int *rotation)
+{
+	(*rotation)++;
+	if (*rotation > 4)
+		return(0);
+	switch(*rotation) {
+		case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*");
+			 break;
+		case(2): sprintf((char *)key, "%s.*", str);
+			 break;
+		case(3): sprintf((char *)key, "*.%s", dom ? dom : "*");
+			 break;
+		case(4): sprintf((char *)key, "*.*");
+			 break;
+	}
+	return(1);
+}
+#endif
+
+/*
+ * Search for a match in a netgroup.
+ */
+int
+innetgr(const char *group, const char *host, const char *user, const char *dom)
+{
+	char *hst, *usr, *dm;
+#ifdef YP
+	char *result;
+	int resultlen;
+	int rv;
+#endif
+	/* Sanity check */
+	
+	if (group == NULL || !strlen(group))
+		return (0);
+
+#ifdef YP
+	_yp_innetgr = 1;
+#endif
+	setnetgrent(group);
+#ifdef YP
+	_yp_innetgr = 0;
+	/*
+	 * If we're in NIS-only mode, do the search using
+	 * NIS 'reverse netgroup' lookups.
+	 */
+	if (_use_only_yp) {
+		char _key[MAXHOSTNAMELEN];
+		int rot = 0, y = 0;
+
+		if(yp_get_default_domain(&_netgr_yp_domain))
+			return(0);
+		while(_buildkey(_key, user ? user : host, dom, &rot)) {
+			y = yp_match(_netgr_yp_domain, user? "netgroup.byuser":
+			    "netgroup.byhost", _key, strlen(_key), &result,
+			    	&resultlen);
+			if (y) {
+				/*
+				 * If we get an error other than 'no
+				 * such key in map' then something is
+				 * wrong and we should stop the search.
+				 */
+				if (y != YPERR_KEY)
+					break;
+			} else {
+				rv = _listmatch(result, group, resultlen);
+				free(result);
+				if (rv)
+					return(1);
+				else
+					return(0);
+			}
+		}
+		/*
+		 * Couldn't match using NIS-exclusive mode. If the error
+	 	 * was YPERR_MAP, then the failure happened because there
+	 	 * was no netgroup.byhost or netgroup.byuser map. The odds
+		 * are we are talking to a Sun NIS+ server in YP emulation
+		 * mode; if this is the case, then we have to do the check
+		 * the 'old-fashioned' way by grovelling through the netgroup
+		 * map and resolving memberships on the fly.
+		 */
+		if (y != YPERR_MAP)
+			return(0);
+	}
+
+	setnetgrent(group);
+#endif /* YP */
+
+	while (getnetgrent(&hst, &usr, &dm))
+		if ((host == NULL || hst == NULL || !strcmp(host, hst)) &&
+		    (user == NULL || usr == NULL || !strcmp(user, usr)) &&
+		    ( dom == NULL ||  dm == NULL || !strcmp(dom, dm))) {
+			endnetgrent();
+			return (1);
+		}
+	endnetgrent();
+	return (0);
+}
+
+/*
+ * Parse the netgroup file setting up the linked lists.
+ */
+static int
+parse_netgrp(const char *group)
+{
+	char *spos, *epos;
+	int len, strpos;
+#ifdef DEBUG
+	int fields;
+#endif
+	char *pos, *gpos;
+	struct netgrp *grp;
+	struct linelist *lp = linehead;
+
+	/*
+	 * First, see if the line has already been read in.
+	 */
+	while (lp) {
+		if (!strcmp(group, lp->l_groupname))
+			break;
+		lp = lp->l_next;
+	}
+	if (lp == (struct linelist *)0 &&
+	    (lp = read_for_group(group)) == (struct linelist *)0)
+		return (1);
+	if (lp->l_parsed) {
+#ifdef DEBUG
+		/*
+		 * This error message is largely superflous since the
+		 * code handles the error condition sucessfully, and
+		 * spewing it out from inside libc can actually hose
+		 * certain programs.
+		 */
+		fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
+#endif
+		return (1);
+	} else
+		lp->l_parsed = 1;
+	pos = lp->l_line;
+	/* Watch for null pointer dereferences, dammit! */
+	while (pos != NULL && *pos != '\0') {
+		if (*pos == '(') {
+			grp = (struct netgrp *)malloc(sizeof (struct netgrp));
+			bzero((char *)grp, sizeof (struct netgrp));
+			grp->ng_next = grouphead.gr;
+			grouphead.gr = grp;
+			pos++;
+			gpos = strsep(&pos, ")");
+#ifdef DEBUG
+			fields = 0;
+#endif
+			for (strpos = 0; strpos < 3; strpos++) {
+				if ((spos = strsep(&gpos, ","))) {
+#ifdef DEBUG
+					fields++;
+#endif
+					while (*spos == ' ' || *spos == '\t')
+						spos++;
+					if ((epos = strpbrk(spos, " \t"))) {
+						*epos = '\0';
+						len = epos - spos;
+					} else
+						len = strlen(spos);
+					if (len > 0) {
+						grp->ng_str[strpos] =  (char *)
+							malloc(len + 1);
+						bcopy(spos, grp->ng_str[strpos],
+							len + 1);
+					}
+				} else {
+					/*
+					 * All other systems I've tested
+					 * return NULL for empty netgroup
+					 * fields. It's up to user programs
+					 * to handle the NULLs appropriately.
+					 */
+					grp->ng_str[strpos] = NULL;
+				}
+			}
+#ifdef DEBUG
+			/*
+			 * Note: on other platforms, malformed netgroup
+			 * entries are not normally flagged. While we
+			 * can catch bad entries and report them, we should
+			 * stay silent by default for compatibility's sake.
+			 */
+			if (fields < 3)
+					fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n",
+						grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST],
+						grp->ng_str[NG_USER] == NULL ? "" : ",",
+						grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER],
+						grp->ng_str[NG_DOM] == NULL ? "" : ",",
+						grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM],
+						lp->l_groupname);
+#endif
+		} else {
+			spos = strsep(&pos, ", \t");
+			if (parse_netgrp(spos))
+				continue;
+		}
+		if (pos == NULL)
+			break;
+		while (*pos == ' ' || *pos == ',' || *pos == '\t')
+			pos++;
+	}
+	return (0);
+}
+
+/*
+ * Read the netgroup file and save lines until the line for the netgroup
+ * is found. Return 1 if eof is encountered.
+ */
+static struct linelist *
+read_for_group(const char *group)
+{
+	char *pos, *spos, *linep = NULL, *olinep = NULL; /* bird: shutting up GCC. */
+	int len, olen;
+	int cont;
+	struct linelist *lp;
+	char line[LINSIZ + 2];
+#ifdef YP
+	char *result;
+	int resultlen;
+
+	while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) {
+		if (_netgr_yp_enabled) {
+			if(!_netgr_yp_domain)
+				if(yp_get_default_domain(&_netgr_yp_domain))
+					continue;
+			if (yp_match(_netgr_yp_domain, "netgroup", group,
+					strlen(group), &result, &resultlen)) {
+				free(result);
+				if (_use_only_yp)
+					return ((struct linelist *)0);
+				else {
+					_netgr_yp_enabled = 0;
+					continue;
+				}
+			}
+			snprintf(line, LINSIZ, "%s %s", group, result);
+			free(result);
+		}
+#else
+	while (fgets(line, LINSIZ, netf) != NULL) {
+#endif
+		pos = (char *)&line;
+#ifdef YP
+		if (*pos == '+') {
+			_netgr_yp_enabled = 1;
+			continue;
+		}
+#endif
+		if (*pos == '#')
+			continue;
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		spos = pos;
+		while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
+			*pos != '\0')
+			pos++;
+		len = pos - spos;
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		if (*pos != '\n' && *pos != '\0') {
+			lp = (struct linelist *)malloc(sizeof (*lp));
+			lp->l_parsed = 0;
+			lp->l_groupname = (char *)malloc(len + 1);
+			bcopy(spos, lp->l_groupname, len);
+			*(lp->l_groupname + len) = '\0';
+			len = strlen(pos);
+			olen = 0;
+
+			/*
+			 * Loop around handling line continuations.
+			 */
+			do {
+				if (*(pos + len - 1) == '\n')
+					len--;
+				if (*(pos + len - 1) == '\\') {
+					len--;
+					cont = 1;
+				} else
+					cont = 0;
+				if (len > 0) {
+					linep = (char *)malloc(olen + len + 1);
+					if (olen > 0) {
+						bcopy(olinep, linep, olen);
+						free(olinep);
+					}
+					bcopy(pos, linep + olen, len);
+					olen += len;
+					*(linep + olen) = '\0';
+					olinep = linep;
+				}
+				if (cont) {
+					if (fgets(line, LINSIZ, netf)) {
+						pos = line;
+						len = strlen(pos);
+					} else
+						cont = 0;
+				}
+			} while (cont);
+			lp->l_line = linep;
+			lp->l_next = linehead;
+			linehead = lp;
+
+			/*
+			 * If this is the one we wanted, we are done.
+			 */
+			if (!strcmp(lp->l_groupname, group))
+				return (lp);
+		}
+	}
+#ifdef YP
+	/*
+	 * Yucky. The recursive nature of this whole mess might require
+	 * us to make more than one pass through the netgroup file.
+	 * This might be best left outside the #ifdef YP, but YP is
+	 * defined by default anyway, so I'll leave it like this
+	 * until I know better.
+	 */
+	rewind(netf);
+#endif
+	return ((struct linelist *)0);
+}
Index: /trunk/libc/src/fbsdlibc/gen/getprogname.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/getprogname.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/getprogname.c	(revision 2448)
@@ -0,0 +1,56 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getprogname.c,v 1.4 2002/03/29 22:43:41 markm Exp $");
+
+#include "namespace.h"
+#include <stdlib.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+#ifdef __EMX__
+#define INCL_BASE
+#define INCL_FSMACROS
+#include <os2emx.h>
+#include <string.h>
+const char *__progname = NULL;
+#endif
+
+__weak_reference(_getprogname, getprogname);
+
+
+const char *
+_getprogname(void)
+{
+#ifdef __EMX__
+    /*
+     * On demand initiation.
+     * THREADS: The assignment isn't safe.
+     * THREADS: pib_pchcmd is pointing into environment space which in theory
+     *          can be changed by any other thread while we're parsing it.
+     */
+    if (!__progname)
+    {
+        char *psz, *psz2;
+        PTIB ptib;
+        PPIB ppib;
+        FS_VAR();
+
+        FS_SAVE();
+        DosGetInfoBlocks(&ptib, &ppib);
+        FS_RESTORE();
+
+        psz = ppib->pib_pchcmd;
+        psz2 = strlen(psz) + psz;
+        while (psz2 >= psz)
+        {
+            if (*psz2 == '\\' || *psz2 == '/' || *psz2 == ':')
+                break;
+            psz2--;
+        }
+        psz2++;
+        /* This is in the volatile env. block - dupe it. */
+        __progname = strdup(psz2);
+    }
+#endif
+	return (__progname);
+}
Index: /trunk/libc/src/fbsdlibc/gen/getpwent.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/getpwent.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/getpwent.c	(revision 2448)
@@ -0,0 +1,1742 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getpwent.c,v 1.89 2004/05/17 18:27:05 kientzle Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HESIOD
+#include <hesiod.h>
+#endif
+#include <netdb.h>
+#include <nsswitch.h>
+#ifndef __EMX__
+#include <pthread.h>
+#include <pthread_np.h>
+#endif
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include <db.h>
+#include "libc_private.h"
+#include "pw_scan.h"
+#include "nss_tls.h"
+
+#ifndef CTASSERT
+#define CTASSERT(x)		_CTASSERT(x, __LINE__)
+#define _CTASSERT(x, y)		__CTASSERT(x, y)
+#define __CTASSERT(x, y)	typedef char __assert_ ## y [(x) ? 1 : -1]
+#endif
+
+/* Counter as stored in /etc/pwd.db */
+typedef	int		pwkeynum;
+
+CTASSERT(MAXLOGNAME > sizeof(uid_t));
+CTASSERT(MAXLOGNAME > sizeof(pwkeynum));
+
+enum constants {
+	PWD_STORAGE_INITIAL	= 1 << 10, /* 1 KByte */
+	PWD_STORAGE_MAX		= 1 << 20, /* 1 MByte */
+	SETPWENT		= 1,
+	ENDPWENT		= 2,
+	HESIOD_NAME_MAX		= 256
+};
+
+static const ns_src defaultsrc[] = {
+	{ NSSRC_COMPAT, NS_SUCCESS },
+	{ NULL, 0 }
+};
+
+int	__pw_match_entry(const char *, size_t, enum nss_lookup_type,
+	    const char *, uid_t);
+int	__pw_parse_entry(char *, size_t, struct passwd *, int, int *errnop);
+
+static	void	 pwd_init(struct passwd *);
+
+union key {
+	const char	*name;
+	uid_t		 uid;
+};
+
+static	struct passwd *getpw(int (*fn)(union key, struct passwd *, char *,
+		    size_t, struct passwd **), union key);
+static	int	 wrap_getpwnam_r(union key, struct passwd *, char *,
+		    size_t, struct passwd **);
+static	int	 wrap_getpwuid_r(union key, struct passwd *, char *, size_t,
+		    struct passwd **);
+static	int	 wrap_getpwent_r(union key, struct passwd *, char *, size_t,
+		    struct passwd **);
+
+static	int	 pwdb_match_entry_v3(char *, size_t, enum nss_lookup_type,
+		    const char *, uid_t);
+static	int	 pwdb_parse_entry_v3(char *, size_t, struct passwd *, int *);
+static	int	 pwdb_match_entry_v4(char *, size_t, enum nss_lookup_type,
+		    const char *, uid_t);
+static	int	 pwdb_parse_entry_v4(char *, size_t, struct passwd *, int *);
+
+
+struct {
+	int	(*match)(char *, size_t, enum nss_lookup_type, const char *,
+		    uid_t);
+	int	(*parse)(char *, size_t, struct passwd *, int *);
+} pwdb_versions[] = {
+	{ NULL, NULL },					/* version 0 */
+	{ NULL, NULL },					/* version 1 */
+	{ NULL, NULL },					/* version 2 */
+	{ pwdb_match_entry_v3, pwdb_parse_entry_v3 },	/* version 3 */
+	{ pwdb_match_entry_v4, pwdb_parse_entry_v4 },	/* version 4 */
+};
+
+
+struct files_state {
+	DB		*db;
+	pwkeynum	 keynum;
+	int		 stayopen;
+	int		 version;
+};
+static	void	files_endstate(void *);
+NSS_TLS_HANDLING(files);
+static	DB	*pwdbopen(int *);
+static	void	 files_endstate(void *);
+static	int	 files_setpwent(void *, void *, va_list);
+static	int	 files_passwd(void *, void *, va_list);
+
+
+#ifdef HESIOD
+struct dns_state {
+	long	counter;
+};
+static	void	dns_endstate(void *);
+NSS_TLS_HANDLING(dns);
+static	int	 dns_setpwent(void *, void *, va_list);
+static	int	 dns_passwd(void *, void *, va_list);
+#endif
+
+
+#ifdef YP
+struct nis_state {
+	char	 domain[MAXHOSTNAMELEN];
+	int	 done;
+	char	*key;
+	int	 keylen;
+};
+static	void	 nis_endstate(void *);
+NSS_TLS_HANDLING(nis);
+static	int	 nis_setpwent(void *, void *, va_list);
+static	int	 nis_passwd(void *, void *, va_list);
+static	int	 nis_map(char *, enum nss_lookup_type, char *, size_t, int *);
+static	int	 nis_adjunct(char *, const char *, char *, size_t);
+#endif
+
+
+struct compat_state {
+	DB		*db;
+	pwkeynum	 keynum;
+	int		 stayopen;
+	int		 version;
+	DB		*exclude;
+	struct passwd	 template;
+	char		*name;
+	enum _compat {
+		COMPAT_MODE_OFF = 0,
+		COMPAT_MODE_ALL,
+		COMPAT_MODE_NAME,
+		COMPAT_MODE_NETGROUP
+	}		 compat;
+};
+static	void	 compat_endstate(void *);
+NSS_TLS_HANDLING(compat);
+static	int	 compat_setpwent(void *, void *, va_list);
+static	int	 compat_passwd(void *, void *, va_list);
+static	void	 compat_clear_template(struct passwd *);
+static	int	 compat_set_template(struct passwd *, struct passwd *);
+static	int	 compat_use_template(struct passwd *, struct passwd *, char *,
+		    size_t);
+static	int	 compat_redispatch(struct compat_state *, enum nss_lookup_type,
+		    enum nss_lookup_type, const char *, const char *, uid_t,
+		    struct passwd *, char *, size_t, int *);
+void
+_STD(setpwent)(void)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_setpwent, (void *)SETPWENT },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_setpwent, (void *)SETPWENT },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_setpwent, (void *)SETPWENT },
+#endif
+		{ NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT },
+		{ NULL, NULL, NULL }
+	};
+	(void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc, 0);
+}
+
+
+int
+_STD(setpassent)(int stayopen)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_setpwent, (void *)SETPWENT },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_setpwent, (void *)SETPWENT },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_setpwent, (void *)SETPWENT },
+#endif
+		{ NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT },
+		{ NULL, NULL, NULL }
+	};
+	(void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc,
+	    stayopen);
+	return (1);
+}
+
+
+void
+_STD(endpwent)(void)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_setpwent, (void *)ENDPWENT },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_setpwent, (void *)ENDPWENT },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_setpwent, (void *)ENDPWENT },
+#endif
+		{ NSSRC_COMPAT, compat_setpwent, (void *)ENDPWENT },
+		{ NULL, NULL, NULL }
+	};
+	(void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "endpwent", defaultsrc);
+}
+
+
+int
+getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
+    struct passwd **result)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_passwd, (void *)nss_lt_all },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_passwd, (void *)nss_lt_all },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_passwd, (void *)nss_lt_all },
+#endif
+		{ NSSRC_COMPAT, compat_passwd, (void *)nss_lt_all },
+		{ NULL, NULL, NULL }
+	};
+	int	rv, ret_errno;
+
+	pwd_init(pwd);
+	ret_errno = 0;
+	*result = NULL;
+	rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwent_r", defaultsrc,
+	    pwd, buffer, bufsize, &ret_errno);
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+
+int
+getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize,
+    struct passwd **result)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_passwd, (void *)nss_lt_name },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_passwd, (void *)nss_lt_name },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_passwd, (void *)nss_lt_name },
+#endif
+		{ NSSRC_COMPAT, compat_passwd, (void *)nss_lt_name },
+		{ NULL, NULL, NULL }
+	};
+	int	rv, ret_errno;
+
+	pwd_init(pwd);
+	ret_errno = 0;
+	*result = NULL;
+	rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwnam_r", defaultsrc,
+	    name, pwd, buffer, bufsize, &ret_errno);
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+
+int
+getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize,
+    struct passwd **result)
+{
+	static const ns_dtab dtab[] = {
+		{ NSSRC_FILES, files_passwd, (void *)nss_lt_id },
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_passwd, (void *)nss_lt_id },
+#endif
+#ifdef YP
+		{ NSSRC_NIS, nis_passwd, (void *)nss_lt_id },
+#endif
+		{ NSSRC_COMPAT, compat_passwd, (void *)nss_lt_id },
+		{ NULL, NULL, NULL }
+	};
+	int	rv, ret_errno;
+
+	pwd_init(pwd);
+	ret_errno = 0;
+	*result = NULL;
+	rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwuid_r", defaultsrc,
+	    uid, pwd, buffer, bufsize, &ret_errno);
+	if (rv == NS_SUCCESS)
+		return (0);
+	else
+		return (ret_errno);
+}
+
+
+static void
+pwd_init(struct passwd *pwd)
+{
+	static char nul[] = "";
+
+	memset(pwd, 0, sizeof(*pwd));
+	pwd->pw_uid = (uid_t)-1;  /* Considered least likely to lead to */
+	pwd->pw_gid = (gid_t)-1;  /* a security issue.                  */
+	pwd->pw_name = nul;
+	pwd->pw_passwd = nul;
+	pwd->pw_class = nul;
+	pwd->pw_gecos = nul;
+	pwd->pw_dir = nul;
+	pwd->pw_shell = nul;
+}
+
+
+static struct passwd	 pwd;
+static char		*pwd_storage;
+static size_t		 pwd_storage_size;
+
+
+static struct passwd *
+getpw(int (*fn)(union key, struct passwd *, char *, size_t, struct passwd **),
+    union key key)
+{
+	int		 rv;
+	struct passwd	*res;
+
+	if (pwd_storage == NULL) {
+		pwd_storage = malloc(PWD_STORAGE_INITIAL);
+		if (pwd_storage == NULL)
+			return (NULL);
+		pwd_storage_size = PWD_STORAGE_INITIAL;
+	}
+	do {
+		rv = fn(key, &pwd, pwd_storage, pwd_storage_size, &res);
+		if (res == NULL && rv == ERANGE) {
+			free(pwd_storage);
+			if ((pwd_storage_size << 1) > PWD_STORAGE_MAX) {
+				pwd_storage = NULL;
+				errno = ERANGE;
+				return (NULL);
+			}
+			pwd_storage_size <<= 1;
+			pwd_storage = malloc(pwd_storage_size);
+			if (pwd_storage == NULL)
+				return (NULL);
+		}
+	} while (res == NULL && rv == ERANGE);
+	if (rv != 0)
+		errno = rv;
+	return (res);
+}
+
+
+static int
+wrap_getpwnam_r(union key key, struct passwd *pwd, char *buffer,
+    size_t bufsize, struct passwd **res)
+{
+	return (getpwnam_r(key.name, pwd, buffer, bufsize, res));
+}
+
+
+static int
+wrap_getpwuid_r(union key key, struct passwd *pwd, char *buffer,
+    size_t bufsize, struct passwd **res)
+{
+	return (getpwuid_r(key.uid, pwd, buffer, bufsize, res));
+}
+
+
+static int
+wrap_getpwent_r(union key key __unused, struct passwd *pwd, char *buffer,
+    size_t bufsize, struct passwd **res)
+{
+	return (getpwent_r(pwd, buffer, bufsize, res));
+}
+
+
+struct passwd *
+getpwnam(const char *name)
+{
+	union key key;
+
+	key.name = name;
+	return (getpw(wrap_getpwnam_r, key));
+}
+
+
+struct passwd *
+getpwuid(uid_t uid)
+{
+	union key key;
+
+	key.uid = uid;
+	return (getpw(wrap_getpwuid_r, key));
+}
+
+
+struct passwd *
+_STD(getpwent)(void)
+{
+	union key key;
+
+	key.uid = 0; /* not used */
+	return (getpw(wrap_getpwent_r, key));
+}
+
+
+/*
+ * files backend
+ */
+static DB *
+pwdbopen(int *version)
+{
+	DB	*res;
+	DBT	 key, entry;
+	int	 rv;
+
+	if (geteuid() != 0 ||
+	    (res = dbopen(_PATH_SMP_DB, O_RDONLY, 0, DB_HASH, NULL)) == NULL)
+		res = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL);
+	if (res == NULL)
+		return (NULL);
+	key.data = _PWD_VERSION_KEY;
+	key.size = strlen(_PWD_VERSION_KEY);
+	rv = res->get(res, &key, &entry, 0);
+	if (rv == 0)
+		*version = *(unsigned char *)entry.data;
+	else
+		*version = 3;
+	if (*version < 3 ||
+	    *version >= sizeof(pwdb_versions)/sizeof(pwdb_versions[0])) {
+#ifndef __EMX__
+		syslog(LOG_CRIT, "Unsupported password database version %d",
+		    *version);
+#endif
+		res->close(res);
+		res = NULL;
+	}
+	return (res);
+}
+
+
+static void
+files_endstate(void *p)
+{
+	DB	*db;
+
+	if (p == NULL)
+		return;
+	db = ((struct files_state *)p)->db;
+	if (db != NULL)
+		db->close(db);
+	free(p);
+}
+
+
+static int
+files_setpwent(void *retval, void *mdata, va_list ap)
+{
+	struct files_state	*st;
+	int			 rv, stayopen;
+
+	rv = files_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+	switch ((enum constants)mdata) {
+	case SETPWENT:
+		stayopen = va_arg(ap, int);
+		st->keynum = 0;
+		if (stayopen)
+			st->db = pwdbopen(&st->version);
+		st->stayopen = stayopen;
+		break;
+	case ENDPWENT:
+		if (st->db != NULL) {
+			(void)st->db->close(st->db);
+			st->db = NULL;
+		}
+		break;
+	default:
+		break;
+	}
+	return (NS_UNAVAIL);
+}
+
+
+static int
+files_passwd(void *retval, void *mdata, va_list ap)
+{
+	char			 keybuf[MAXLOGNAME + 1];
+	DBT			 key, entry;
+	struct files_state	*st;
+	enum nss_lookup_type	 how;
+	const char		*name;
+	struct passwd		*pwd = NULL;                    /* bird: shut up GCC */
+	char			*buffer;
+	size_t			 bufsize, namesize;
+	uid_t			 uid;
+	uint32_t		 store;
+	int			 rv, stayopen = 0, *errnop;     /* bird: shut up GCC */
+
+	name = NULL;
+	uid = (uid_t)-1;
+	how = (enum nss_lookup_type)mdata;
+	switch (how) {
+	case nss_lt_name:
+		name = va_arg(ap, const char *);
+		keybuf[0] = _PW_KEYBYNAME;
+		break;
+	case nss_lt_id:
+		uid = va_arg(ap, uid_t);
+		keybuf[0] = _PW_KEYBYUID;
+		break;
+	case nss_lt_all:
+		keybuf[0] = _PW_KEYBYNUM;
+		break;
+	default:
+		rv = NS_NOTFOUND;
+		goto fin;
+	}
+	pwd = va_arg(ap, struct passwd *);
+	buffer = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop = va_arg(ap, int *);
+	*errnop = files_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+	if (how == nss_lt_all && st->keynum < 0) {
+		rv = NS_NOTFOUND;
+		goto fin;
+	}
+	if (st->db == NULL &&
+	    (st->db = pwdbopen(&st->version)) == NULL) {
+		*errnop = errno;
+		rv = NS_UNAVAIL;
+		goto fin;
+	}
+	if (how == nss_lt_all)
+		stayopen = 1;
+	else
+		stayopen = st->stayopen;
+	key.data = keybuf;
+	do {
+		switch (how) {
+		case nss_lt_name:
+			/* MAXLOGNAME includes NUL byte, but we do not
+			 * include the NUL byte in the key.
+			 */
+			namesize = strlcpy(&keybuf[1], name, sizeof(keybuf)-1);
+			if (namesize >= sizeof(keybuf)-1) {
+				*errnop = EINVAL;
+				rv = NS_NOTFOUND;
+				goto fin;
+			}
+			key.size = namesize + 1;
+			break;
+		case nss_lt_id:
+			if (st->version < _PWD_CURRENT_VERSION) {
+				memcpy(&keybuf[1], &uid, sizeof(uid));
+				key.size = sizeof(uid) + 1;
+			} else {
+				store = htonl(uid);
+				memcpy(&keybuf[1], &store, sizeof(store));
+				key.size = sizeof(store) + 1;
+			}
+			break;
+		case nss_lt_all:
+			st->keynum++;
+			if (st->version < _PWD_CURRENT_VERSION) {
+				memcpy(&keybuf[1], &st->keynum,
+				    sizeof(st->keynum));
+				key.size = sizeof(st->keynum) + 1;
+			} else {
+				store = htonl(st->keynum);
+				memcpy(&keybuf[1], &store, sizeof(store));
+				key.size = sizeof(store) + 1;
+			}
+			break;
+		}
+		keybuf[0] = _PW_VERSIONED(keybuf[0], st->version);
+		rv = st->db->get(st->db, &key, &entry, 0);
+		if (rv < 0 || rv > 1) { /* should never return > 1 */
+			*errnop = errno;
+			rv = NS_UNAVAIL;
+			goto fin;
+		} else if (rv == 1) {
+			if (how == nss_lt_all)
+				st->keynum = -1;
+			rv = NS_NOTFOUND;
+			goto fin;
+		}
+		rv = pwdb_versions[st->version].match(entry.data, entry.size,
+		    how, name, uid);
+		if (rv != NS_SUCCESS)
+			continue;
+		if (entry.size > bufsize) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			break;
+		}
+		memcpy(buffer, entry.data, entry.size);
+		rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd,
+		    errnop);
+	} while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+	if (!stayopen && st->db != NULL) {
+		(void)st->db->close(st->db);
+		st->db = NULL;
+	}
+	if (rv == NS_SUCCESS) {
+		pwd->pw_fields &= ~_PWF_SOURCE;
+		pwd->pw_fields |= _PWF_FILES;
+		if (retval != NULL)
+			*(struct passwd **)retval = pwd;
+	}
+	return (rv);
+}
+
+
+static int
+pwdb_match_entry_v3(char *entry, size_t entrysize, enum nss_lookup_type how,
+    const char *name, uid_t uid)
+{
+	const char	*p, *eom;
+	uid_t		 uid2;
+
+	eom = &entry[entrysize];
+	for (p = entry; p < eom; p++)
+		if (*p == '\0')
+			break;
+	if (*p != '\0')
+		return (NS_NOTFOUND);
+	if (how == nss_lt_all)
+		return (NS_SUCCESS);
+	if (how == nss_lt_name)
+		return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND);
+	for (p++; p < eom; p++)
+		if (*p == '\0')
+			break;
+	if (*p != '\0' || (++p) + sizeof(uid) >= eom)
+		return (NS_NOTFOUND);
+	memcpy(&uid2, p, sizeof(uid2));
+	return (uid == uid2 ? NS_SUCCESS : NS_NOTFOUND);
+}
+
+
+static int
+pwdb_parse_entry_v3(char *buffer, size_t bufsize, struct passwd *pwd,
+    int *errnop)
+{
+	char		*p, *eom;
+	int32_t		 pw_change, pw_expire;
+
+	/* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
+	p = buffer;
+	eom = &buffer[bufsize];
+#define STRING(field)	do {			\
+		(field) = p;			\
+		while (p < eom && *p != '\0')	\
+			p++;			\
+		if (p >= eom)			\
+			return (NS_NOTFOUND);	\
+		p++;				\
+	} while (0)
+#define SCALAR(field)	do {				\
+		if (p + sizeof(field) > eom)		\
+			return (NS_NOTFOUND);		\
+		memcpy(&(field), p, sizeof(field));	\
+		p += sizeof(field);			\
+	} while (0)
+	STRING(pwd->pw_name);
+	STRING(pwd->pw_passwd);
+	SCALAR(pwd->pw_uid);
+	SCALAR(pwd->pw_gid);
+	SCALAR(pw_change);
+	STRING(pwd->pw_class);
+	STRING(pwd->pw_gecos);
+	STRING(pwd->pw_dir);
+	STRING(pwd->pw_shell);
+	SCALAR(pw_expire);
+	SCALAR(pwd->pw_fields);
+#undef STRING
+#undef SCALAR
+	pwd->pw_change = pw_change;
+	pwd->pw_expire = pw_expire;
+	return (NS_SUCCESS);
+}
+
+
+static int
+pwdb_match_entry_v4(char *entry, size_t entrysize, enum nss_lookup_type how,
+    const char *name, uid_t uid)
+{
+	const char	*p, *eom;
+	uint32_t	 uid2;
+
+	eom = &entry[entrysize];
+	for (p = entry; p < eom; p++)
+		if (*p == '\0')
+			break;
+	if (*p != '\0')
+		return (NS_NOTFOUND);
+	if (how == nss_lt_all)
+		return (NS_SUCCESS);
+	if (how == nss_lt_name)
+		return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND);
+	for (p++; p < eom; p++)
+		if (*p == '\0')
+			break;
+	if (*p != '\0' || (++p) + sizeof(uid) >= eom)
+		return (NS_NOTFOUND);
+	memcpy(&uid2, p, sizeof(uid2));
+	uid2 = ntohl(uid2);
+	return (uid == (uid_t)uid2 ? NS_SUCCESS : NS_NOTFOUND);
+}
+
+
+static int
+pwdb_parse_entry_v4(char *buffer, size_t bufsize, struct passwd *pwd,
+    int *errnop)
+{
+	char		*p, *eom;
+	uint32_t	 n;
+
+	/* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
+	p = buffer;
+	eom = &buffer[bufsize];
+#define STRING(field)	do {			\
+		(field) = p;			\
+		while (p < eom && *p != '\0')	\
+			p++;			\
+		if (p >= eom)			\
+			return (NS_NOTFOUND);	\
+		p++;				\
+	} while (0)
+#define SCALAR(field)	do {				\
+		if (p + sizeof(n) > eom)		\
+			return (NS_NOTFOUND);		\
+		memcpy(&n, p, sizeof(n));		\
+		(field) = ntohl(n);			\
+		p += sizeof(n);				\
+	} while (0)
+	STRING(pwd->pw_name);
+	STRING(pwd->pw_passwd);
+	SCALAR(pwd->pw_uid);
+	SCALAR(pwd->pw_gid);
+	SCALAR(pwd->pw_change);
+	STRING(pwd->pw_class);
+	STRING(pwd->pw_gecos);
+	STRING(pwd->pw_dir);
+	STRING(pwd->pw_shell);
+	SCALAR(pwd->pw_expire);
+	SCALAR(pwd->pw_fields);
+#undef STRING
+#undef SCALAR
+	return (NS_SUCCESS);
+}
+
+
+#ifdef HESIOD
+/*
+ * dns backend
+ */
+static void
+dns_endstate(void *p)
+{
+	free(p);
+}
+
+
+static int
+dns_setpwent(void *retval, void *mdata, va_list ap)
+{
+	struct dns_state	*st;
+	int			 rv;
+
+	rv = dns_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+	st->counter = 0;
+	return (NS_UNAVAIL);
+}
+
+
+static int
+dns_passwd(void *retval, void *mdata, va_list ap)
+{
+	char			 buf[HESIOD_NAME_MAX];
+	struct dns_state	*st;
+	struct passwd		*pwd;
+	const char		*name, *label;
+	void			*ctx;
+	char			*buffer, **hes;
+	size_t			 bufsize, linesize;
+	uid_t			 uid;
+	enum nss_lookup_type	 how;
+	int			 rv, *errnop;
+
+	ctx = NULL;
+	hes = NULL;
+	name = NULL;
+	uid = (uid_t)-1;
+	how = (enum nss_lookup_type)mdata;
+	switch (how) {
+	case nss_lt_name:
+		name = va_arg(ap, const char *);
+		break;
+	case nss_lt_id:
+		uid = va_arg(ap, uid_t);
+		break;
+	case nss_lt_all:
+		break;
+	}
+	pwd     = va_arg(ap, struct passwd *);
+	buffer  = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop  = va_arg(ap, int *);
+	*errnop = dns_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+	if (hesiod_init(&ctx) != 0) {
+		*errnop = errno;
+		rv = NS_UNAVAIL;
+		goto fin;
+	}
+	do {
+		rv = NS_NOTFOUND;
+		switch (how) {
+		case nss_lt_name:
+			label = name;
+			break;
+		case nss_lt_id:
+			if (snprintf(buf, sizeof(buf), "%lu",
+			    (unsigned long)uid) >= sizeof(buf))
+				goto fin;
+			label = buf;
+			break;
+		case nss_lt_all:
+			if (st->counter < 0)
+				goto fin;
+			if (snprintf(buf, sizeof(buf), "passwd-%ld",
+			    st->counter++) >= sizeof(buf))
+				goto fin;
+			label = buf;
+			break;
+		}
+		hes = hesiod_resolve(ctx, label,
+		    how == nss_lt_id ? "uid" : "passwd");
+		if (hes == NULL) {
+			if (how == nss_lt_all)
+				st->counter = -1;
+			if (errno != ENOENT)
+				*errnop = errno;
+			goto fin;
+		}
+		rv = __pw_match_entry(hes[0], strlen(hes[0]), how, name, uid);
+		if (rv != NS_SUCCESS) {
+			hesiod_free_list(ctx, hes);
+			hes = NULL;
+			continue;
+		}
+		linesize = strlcpy(buffer, hes[0], bufsize);
+		if (linesize >= bufsize) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			continue;
+		}
+		hesiod_free_list(ctx, hes);
+		hes = NULL;
+		rv = __pw_parse_entry(buffer, bufsize, pwd, 0, errnop);
+	} while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+	if (hes != NULL)
+		hesiod_free_list(ctx, hes);
+	if (ctx != NULL)
+		hesiod_end(ctx);
+	if (rv == NS_SUCCESS) {
+		pwd->pw_fields &= ~_PWF_SOURCE;
+		pwd->pw_fields |= _PWF_HESIOD;
+		if (retval != NULL)
+			*(struct passwd **)retval = pwd;
+	}
+	return (rv);
+}
+#endif /* HESIOD */
+
+
+#ifdef YP
+/*
+ * nis backend
+ */
+static void
+nis_endstate(void *p)
+{
+	free(((struct nis_state *)p)->key);
+	free(p);
+}
+
+/*
+ * Test for the presence of special FreeBSD-specific master.passwd.by*
+ * maps. We do this using yp_order(). If it fails, then either the server
+ * doesn't have the map, or the YPPROC_ORDER procedure isn't supported by
+ * the server (Sun NIS+ servers in YP compat mode behave this way). If
+ * the master.passwd.by* maps don't exist, then let the lookup routine try
+ * the regular passwd.by* maps instead. If the lookup routine fails, it
+ * can return an error as needed.
+ */
+static int
+nis_map(char *domain, enum nss_lookup_type how, char *buffer, size_t bufsize,
+    int *master)
+{
+	int	rv, order;
+
+	*master = 0;
+	if (geteuid() == 0) {
+		if (snprintf(buffer, bufsize, "master.passwd.by%s",
+		    (how == nss_lt_id) ? "uid" : "name") >= bufsize)
+			return (NS_UNAVAIL);
+		rv = yp_order(domain, buffer, &order);
+		if (rv == 0) {
+			*master = 1;
+			return (NS_SUCCESS);
+		}
+	}
+
+	if (snprintf(buffer, bufsize, "passwd.by%s",
+	    (how == nss_lt_id) ? "uid" : "name") >= bufsize)
+		return (NS_UNAVAIL);
+
+	return (NS_SUCCESS);
+}
+
+
+static int
+nis_adjunct(char *domain, const char *name, char *buffer, size_t bufsize)
+{
+	int	 rv;
+	char	*result, *p, *q, *eor;
+	int	 resultlen;
+
+	result = NULL;
+	rv = yp_match(domain, "passwd.adjunct.byname", name, strlen(name),
+	    &result, &resultlen);
+	if (rv != 0)
+		rv = 1;
+	else {
+		eor = &result[resultlen];
+		p = memchr(result, ':', eor - result);
+		if (p != NULL && ++p < eor &&
+		    (q = memchr(p, ':', eor - p)) != NULL) {
+			if (q - p >= bufsize)
+				rv = -1;
+			else {
+				memcpy(buffer, p, q - p);
+				buffer[q - p] ='\0';
+			}
+		} else
+			rv = 1;
+	}
+	free(result);
+	return (rv);
+}
+
+
+static int
+nis_setpwent(void *retval, void *mdata, va_list ap)
+{
+	struct nis_state	*st;
+	int			 rv;
+
+	rv = nis_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+	st->done = 0;
+	free(st->key);
+	st->key = NULL;
+	return (NS_UNAVAIL);
+}
+
+
+static int
+nis_passwd(void *retval, void *mdata, va_list ap)
+{
+	char		 map[YPMAXMAP];
+	struct nis_state *st;
+	struct passwd	*pwd;
+	const char	*name;
+	char		*buffer, *key, *result;
+	size_t		 bufsize;
+	uid_t		 uid;
+	enum nss_lookup_type how;
+	int		*errnop, keylen, resultlen, rv, master;
+
+	name = NULL;
+	uid = (uid_t)-1;
+	how = (enum nss_lookup_type)mdata;
+	switch (how) {
+	case nss_lt_name:
+		name = va_arg(ap, const char *);
+		break;
+	case nss_lt_id:
+		uid = va_arg(ap, uid_t);
+		break;
+	case nss_lt_all:
+		break;
+	}
+	pwd     = va_arg(ap, struct passwd *);
+	buffer  = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop  = va_arg(ap, int *);
+	*errnop = nis_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+	if (st->domain[0] == '\0') {
+		if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
+			*errnop = errno;
+			return (NS_UNAVAIL);
+		}
+	}
+	rv = nis_map(st->domain, how, map, sizeof(map), &master);
+	if (rv != NS_SUCCESS)
+		return (rv);
+	result = NULL;
+	do {
+		rv = NS_NOTFOUND;
+		switch (how) {
+		case nss_lt_name:
+			if (strlcpy(buffer, name, bufsize) >= bufsize)
+				goto erange;
+			break;
+		case nss_lt_id:
+			if (snprintf(buffer, bufsize, "%lu",
+			    (unsigned long)uid) >= bufsize)
+				goto erange;
+			break;
+		case nss_lt_all:
+			if (st->done)
+				goto fin;
+			break;
+		}
+		result = NULL;
+		if (how == nss_lt_all) {
+			if (st->key == NULL)
+				rv = yp_first(st->domain, map, &st->key,
+				    &st->keylen, &result, &resultlen);
+			else {
+				key = st->key;
+				keylen = st->keylen;
+				st->key = NULL;
+				rv = yp_next(st->domain, map, key, keylen,
+				    &st->key, &st->keylen, &result,
+				    &resultlen);
+				free(key);
+			}
+			if (rv != 0) {
+				free(result);
+				free(st->key);
+				st->key = NULL;
+				if (rv == YPERR_NOMORE)
+					st->done = 1;
+				else
+					rv = NS_UNAVAIL;
+				goto fin;
+			}
+		} else {
+			rv = yp_match(st->domain, map, buffer, strlen(buffer),
+			    &result, &resultlen);
+			if (rv == YPERR_KEY) {
+				rv = NS_NOTFOUND;
+				continue;
+			} else if (rv != 0) {
+				free(result);
+				rv = NS_UNAVAIL;
+				continue;
+			}
+		}
+		if (resultlen >= bufsize)
+			goto erange;
+		memcpy(buffer, result, resultlen);
+		buffer[resultlen] = '\0';
+		free(result);
+		rv = __pw_match_entry(buffer, resultlen, how, name, uid);
+		if (rv == NS_SUCCESS)
+			rv = __pw_parse_entry(buffer, resultlen, pwd, master,
+			    errnop);
+	} while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+	if (rv == NS_SUCCESS) {
+		if (strstr(pwd->pw_passwd, "##") != NULL) {
+			rv = nis_adjunct(st->domain, pwd->pw_name,
+			    &buffer[resultlen+1], bufsize-resultlen-1);
+			if (rv < 0)
+				goto erange;
+			else if (rv == 0)
+				pwd->pw_passwd = &buffer[resultlen+1];
+		}
+		pwd->pw_fields &= ~_PWF_SOURCE;
+		pwd->pw_fields |= _PWF_NIS;
+		if (retval != NULL)
+			*(struct passwd **)retval = pwd;
+		rv = NS_SUCCESS;
+	}
+	return (rv);
+erange:
+	*errnop = ERANGE;
+	return (NS_RETURN);
+}
+#endif /* YP */
+
+
+/*
+ * compat backend
+ */
+static void
+compat_clear_template(struct passwd *template)
+{
+
+	free(template->pw_passwd);
+	free(template->pw_gecos);
+	free(template->pw_dir);
+	free(template->pw_shell);
+	memset(template, 0, sizeof(*template));
+}
+
+
+static int
+compat_set_template(struct passwd *src, struct passwd *template)
+{
+
+	compat_clear_template(template);
+#ifdef PW_OVERRIDE_PASSWD
+	if ((src->pw_fields & _PWF_PASSWD) &&
+	    (template->pw_passwd = strdup(src->pw_passwd)) == NULL)
+		goto enomem;
+#endif
+	if (src->pw_fields & _PWF_UID)
+		template->pw_uid = src->pw_uid;
+	if (src->pw_fields & _PWF_GID)
+		template->pw_gid = src->pw_gid;
+	if ((src->pw_fields & _PWF_GECOS) &&
+	    (template->pw_gecos = strdup(src->pw_gecos)) == NULL)
+		goto enomem;
+	if ((src->pw_fields & _PWF_DIR) &&
+	    (template->pw_dir = strdup(src->pw_dir)) == NULL)
+		goto enomem;
+	if ((src->pw_fields & _PWF_SHELL) &&
+	    (template->pw_shell = strdup(src->pw_shell)) == NULL)
+		goto enomem;
+	template->pw_fields = src->pw_fields;
+	return (0);
+enomem:
+#ifndef __EMX__
+	syslog(LOG_ERR, "getpwent memory allocation failure");
+#endif
+	return (-1);
+}
+
+
+static int
+compat_use_template(struct passwd *pwd, struct passwd *template, char *buffer,
+    size_t bufsize)
+{
+	struct passwd hold;
+	char	*copy, *p, *q, *eob;
+	size_t	 n;
+
+	/* We cannot know the layout of the password fields in `buffer',
+	 * so we have to copy everything.
+	 */
+	if (template->pw_fields == 0) /* nothing to fill-in */
+		return (0);
+	n = 0;
+	n += pwd->pw_name != NULL ? strlen(pwd->pw_name) + 1 : 0;
+	n += pwd->pw_passwd != NULL ? strlen(pwd->pw_passwd) + 1 : 0;
+	n += pwd->pw_class != NULL ? strlen(pwd->pw_class) + 1 : 0;
+	n += pwd->pw_gecos != NULL ? strlen(pwd->pw_gecos) + 1 : 0;
+	n += pwd->pw_dir != NULL ? strlen(pwd->pw_dir) + 1 : 0;
+	n += pwd->pw_shell != NULL ? strlen(pwd->pw_shell) + 1 : 0;
+	copy = malloc(n);
+	if (copy == NULL) {
+#ifndef __EMX__
+		syslog(LOG_ERR, "getpwent memory allocation failure");
+#endif
+		return (ENOMEM);
+	}
+	p = copy;
+	eob = &copy[n];
+#define COPY(field) do {				\
+	if (pwd->field == NULL)				\
+		hold.field = NULL;			\
+	else {						\
+		hold.field = p;				\
+		p += strlcpy(p, pwd->field, eob-p) + 1;	\
+	}						\
+} while (0)
+	COPY(pw_name);
+	COPY(pw_passwd);
+	COPY(pw_class);
+	COPY(pw_gecos);
+	COPY(pw_dir);
+	COPY(pw_shell);
+#undef COPY
+	p = buffer;
+	eob = &buffer[bufsize];
+#define COPY(field, flag) do {						 \
+	q = (template->pw_fields & flag) ? template->field : hold.field; \
+	if (q == NULL)							 \
+		pwd->field = NULL;					 \
+	else {								 \
+		pwd->field = p;						 \
+		if ((n = strlcpy(p, q, eob-p)) >= eob-p) {		 \
+			free(copy);					 \
+			return (ERANGE);				 \
+		}							 \
+		p += n + 1;						 \
+	}								 \
+} while (0)
+	COPY(pw_name, 0);
+#ifdef PW_OVERRIDE_PASSWD
+	COPY(pw_passwd, _PWF_PASSWD);
+#else
+	COPY(pw_passwd, 0);
+#endif
+	COPY(pw_class, 0);
+	COPY(pw_gecos, _PWF_GECOS);
+	COPY(pw_dir, _PWF_DIR);
+	COPY(pw_shell, _PWF_SHELL);
+#undef COPY
+#define COPY(field, flag) do {			\
+	if (template->pw_fields & flag)		\
+		pwd->field = template->field;	\
+} while (0)
+	COPY(pw_uid, _PWF_UID);
+	COPY(pw_gid, _PWF_GID);
+#undef COPY
+	free(copy);
+	return (0);
+}
+
+
+static int
+compat_exclude(const char *name, DB **db)
+{
+	DBT	key, data;
+
+	if (*db == NULL &&
+	    (*db = dbopen(NULL, O_RDWR, 600, DB_HASH, 0)) == NULL)
+		return (errno);
+	key.size = strlen(name);
+	key.data = (char *)name;
+	data.size = 0;
+	data.data = NULL;
+
+	if ((*db)->put(*db, &key, &data, 0) == -1)
+		return (errno);
+	return (0);
+}
+
+
+static int
+compat_is_excluded(const char *name, DB *db)
+{
+	DBT	key, data;
+
+	if (db == NULL)
+		return (0);
+	key.size = strlen(name);
+	key.data = (char *)name;
+	return (db->get(db, &key, &data, 0) == 0);
+}
+
+
+static int
+compat_redispatch(struct compat_state *st, enum nss_lookup_type how,
+    enum nss_lookup_type lookup_how, const char *name, const char *lookup_name,
+    uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, int *errnop)
+{
+	static const ns_src compatsrc[] = {
+#ifdef YP
+		{ NSSRC_NIS, NS_SUCCESS },
+#endif
+		{ NULL, 0 }
+	};
+	ns_dtab dtab[] = {
+#ifdef YP
+		{ NSSRC_NIS, nis_passwd, NULL },
+#endif
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_passwd, NULL },
+#endif
+		{ NULL, NULL, NULL }
+	};
+	void		*discard;
+	int		 rv, e, i;
+
+	for (i = 0; i < sizeof(dtab)/sizeof(dtab[0]) - 1; i++)
+		dtab[i].mdata = (void *)lookup_how;
+more:
+	pwd_init(pwd);
+	switch (lookup_how) {
+	case nss_lt_all:
+		rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT,
+		    "getpwent_r", compatsrc, pwd, buffer, bufsize,
+		    errnop);
+		break;
+	case nss_lt_id:
+		rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT,
+		    "getpwuid_r", compatsrc, uid, pwd, buffer,
+		    bufsize, errnop);
+		break;
+	case nss_lt_name:
+		rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT,
+		    "getpwnam_r", compatsrc, lookup_name, pwd, buffer,
+		    bufsize, errnop);
+		break;
+	default:
+		return (NS_UNAVAIL);
+	}
+	if (rv != NS_SUCCESS)
+		return (rv);
+	if (compat_is_excluded(pwd->pw_name, st->exclude)) {
+		if (how == nss_lt_all)
+			goto more;
+		return (NS_NOTFOUND);
+	}
+	e = compat_use_template(pwd, &st->template, buffer, bufsize);
+	if (e != 0) {
+		*errnop = e;
+		if (e == ERANGE)
+			return (NS_RETURN);
+		else
+			return (NS_UNAVAIL);
+	}
+	switch (how) {
+	case nss_lt_name:
+		if (strcmp(name, pwd->pw_name) != 0)
+			return (NS_NOTFOUND);
+		break;
+	case nss_lt_id:
+		if (uid != pwd->pw_uid)
+			return (NS_NOTFOUND);
+		break;
+	default:
+		break;
+	}
+	return (NS_SUCCESS);
+}
+
+
+static void
+compat_endstate(void *p)
+{
+	struct compat_state *st;
+
+	if (p == NULL)
+		return;
+	st = (struct compat_state *)p;
+	if (st->db != NULL)
+		st->db->close(st->db);
+	if (st->exclude != NULL)
+		st->exclude->close(st->exclude);
+	compat_clear_template(&st->template);
+	free(p);
+}
+
+
+static int
+compat_setpwent(void *retval, void *mdata, va_list ap)
+{
+	static const ns_src compatsrc[] = {
+#ifdef YP
+		{ NSSRC_NIS, NS_SUCCESS },
+#endif
+		{ NULL, 0 }
+	};
+	ns_dtab dtab[] = {
+#ifdef YP
+		{ NSSRC_NIS, nis_setpwent, NULL },
+#endif
+#ifdef HESIOD
+		{ NSSRC_DNS, dns_setpwent, NULL },
+#endif
+		{ NULL, NULL, NULL }
+	};
+	struct compat_state	*st;
+	int			 rv, stayopen;
+
+#define set_setent(x, y) do {	 				\
+	int i;							\
+								\
+	for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++)	\
+		x[i].mdata = (void *)y;				\
+} while (0)
+
+	rv = compat_getstate(&st);
+	if (rv != 0)
+		return (NS_UNAVAIL);
+	switch ((enum constants)mdata) {
+	case SETPWENT:
+		stayopen = va_arg(ap, int);
+		st->keynum = 0;
+		if (stayopen)
+			st->db = pwdbopen(&st->version);
+		st->stayopen = stayopen;
+		set_setent(dtab, mdata);
+		(void)_nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "setpwent",
+		    compatsrc, 0);
+		break;
+	case ENDPWENT:
+		if (st->db != NULL) {
+			(void)st->db->close(st->db);
+			st->db = NULL;
+		}
+		set_setent(dtab, mdata);
+		(void)_nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "endpwent",
+		    compatsrc, 0);
+		break;
+	default:
+		break;
+	}
+	return (NS_UNAVAIL);
+#undef set_setent
+}
+
+
+static int
+compat_passwd(void *retval, void *mdata, va_list ap)
+{
+	char			 keybuf[MAXLOGNAME + 1];
+	DBT			 key, entry;
+	struct compat_state	*st;
+	enum nss_lookup_type	 how;
+	const char		*name;
+	struct passwd		*pwd = NULL;                    /* bird: shut up gcc.  */
+	char			*buffer, *pw_name;
+	char			*host, *user, *domain;
+	size_t			 bufsize;
+	uid_t			 uid;
+	uint32_t		 store;
+	int			 rv, from_compat, stayopen = 0, *errnop; /* bird: shut up gcc. */
+
+	from_compat = 0;
+	name = NULL;
+	uid = (uid_t)-1;
+	how = (enum nss_lookup_type)mdata;
+	switch (how) {
+	case nss_lt_name:
+		name = va_arg(ap, const char *);
+		break;
+	case nss_lt_id:
+		uid = va_arg(ap, uid_t);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		rv = NS_NOTFOUND;
+		goto fin;
+	}
+	pwd = va_arg(ap, struct passwd *);
+	buffer = va_arg(ap, char *);
+	bufsize = va_arg(ap, size_t);
+	errnop = va_arg(ap, int *);
+	*errnop = compat_getstate(&st);
+	if (*errnop != 0)
+		return (NS_UNAVAIL);
+	if (how == nss_lt_all && st->keynum < 0) {
+		rv = NS_NOTFOUND;
+		goto fin;
+	}
+	if (st->db == NULL &&
+	    (st->db = pwdbopen(&st->version)) == NULL) {
+		*errnop = errno;
+		rv = NS_UNAVAIL;
+		goto fin;
+	}
+	if (how == nss_lt_all) {
+		if (st->keynum < 0) {
+			rv = NS_NOTFOUND;
+			goto fin;
+		}
+		stayopen = 1;
+	} else {
+		st->keynum = 0;
+		stayopen = st->stayopen;
+	}
+docompat:
+	rv = NS_NOTFOUND;
+	switch (st->compat) {
+	case COMPAT_MODE_ALL:
+		rv = compat_redispatch(st, how, how, name, name, uid, pwd,
+		    buffer, bufsize, errnop);
+		if (rv != NS_SUCCESS)
+			st->compat = COMPAT_MODE_OFF;
+		break;
+	case COMPAT_MODE_NETGROUP:
+		/* XXX getnetgrent is not thread-safe. */
+		do {
+			rv = getnetgrent(&host, &user, &domain);
+			if (rv == 0) {
+				endnetgrent();
+				st->compat = COMPAT_MODE_OFF;
+				rv = NS_NOTFOUND;
+				continue;
+			} else if (user == NULL || user[0] == '\0')
+				continue;
+			rv = compat_redispatch(st, how, nss_lt_name, name,
+			    user, uid, pwd, buffer, bufsize, errnop);
+		} while (st->compat == COMPAT_MODE_NETGROUP &&
+		    !(rv & NS_TERMINATE));
+		break;
+	case COMPAT_MODE_NAME:
+		rv = compat_redispatch(st, how, nss_lt_name, name, st->name,
+		    uid, pwd, buffer, bufsize, errnop);
+		free(st->name);
+		st->name = NULL;
+		st->compat = COMPAT_MODE_OFF;
+		break;
+	default:
+		break;
+	}
+	if (rv & NS_TERMINATE) {
+		from_compat = 1;
+		goto fin;
+	}
+	key.data = keybuf;
+	rv = NS_NOTFOUND;
+	while (st->keynum >= 0) {
+		st->keynum++;
+		if (st->version < _PWD_CURRENT_VERSION) {
+			memcpy(&keybuf[1], &st->keynum, sizeof(st->keynum));
+			key.size = sizeof(st->keynum) + 1;
+		} else {
+			store = htonl(st->keynum);
+			memcpy(&keybuf[1], &store, sizeof(store));
+			key.size = sizeof(store) + 1;
+		}
+		keybuf[0] = _PW_VERSIONED(_PW_KEYBYNUM, st->version);
+		rv = st->db->get(st->db, &key, &entry, 0);
+		if (rv < 0 || rv > 1) { /* should never return > 1 */
+			*errnop = errno;
+			rv = NS_UNAVAIL;
+			goto fin;
+		} else if (rv == 1) {
+			st->keynum = -1;
+			rv = NS_NOTFOUND;
+			goto fin;
+		}
+		pw_name = (char *)entry.data;
+		switch (pw_name[0]) {
+		case '+':
+			switch (pw_name[1]) {
+			case '\0':
+				st->compat = COMPAT_MODE_ALL;
+				break;
+			case '@':
+				setnetgrent(&pw_name[2]);
+				st->compat = COMPAT_MODE_NETGROUP;
+				break;
+			default:
+				st->name = strdup(&pw_name[1]);
+				if (st->name == NULL) {
+#ifndef __EMX__
+					syslog(LOG_ERR,
+					 "getpwent memory allocation failure");
+#endif
+					*errnop = ENOMEM;
+					rv = NS_UNAVAIL;
+					break;
+				}
+				st->compat = COMPAT_MODE_NAME;
+			}
+			if (entry.size > bufsize) {
+				*errnop = ERANGE;
+				rv = NS_RETURN;
+				goto fin;
+			}
+			memcpy(buffer, entry.data, entry.size);
+			rv = pwdb_versions[st->version].parse(buffer,
+			    entry.size, pwd, errnop);
+			if (rv != NS_SUCCESS)
+				;
+			else if (compat_set_template(pwd, &st->template) < 0) {
+				*errnop = ENOMEM;
+				rv = NS_UNAVAIL;
+				goto fin;
+			}
+			goto docompat;
+		case '-':
+			switch (pw_name[1]) {
+			case '\0':
+				/* XXX Maybe syslog warning */
+				continue;
+			case '@':
+				setnetgrent(&pw_name[2]);
+				while (getnetgrent(&host, &user, &domain) !=
+				    0) {
+					if (user != NULL && user[0] != '\0')
+						compat_exclude(user,
+						    &st->exclude);
+				}
+				endnetgrent();
+				continue;
+			default:
+				compat_exclude(&pw_name[1], &st->exclude);
+				continue;
+			}
+			break;
+		default:
+			break;
+		}
+		if (compat_is_excluded((char *)entry.data, st->exclude))
+			continue;
+		rv = pwdb_versions[st->version].match(entry.data, entry.size,
+		    how, name, uid);
+		if (rv == NS_RETURN)
+			break;
+		else if (rv != NS_SUCCESS)
+			continue;
+		if (entry.size > bufsize) {
+			*errnop = ERANGE;
+			rv = NS_RETURN;
+			break;
+		}
+		memcpy(buffer, entry.data, entry.size);
+		rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd,
+		    errnop);
+		if (rv & NS_TERMINATE)
+			break;
+	}
+fin:
+	if (!stayopen && st->db != NULL) {
+		(void)st->db->close(st->db);
+		st->db = NULL;
+	}
+	if (rv == NS_SUCCESS) {
+		if (!from_compat) {
+			pwd->pw_fields &= ~_PWF_SOURCE;
+			pwd->pw_fields |= _PWF_FILES;
+		}
+		if (retval != NULL)
+			*(struct passwd **)retval = pwd;
+	}
+	return (rv);
+}
+
+
+/*
+ * common passwd line matching and parsing
+ */
+int
+__pw_match_entry(const char *entry, size_t entrysize, enum nss_lookup_type how,
+    const char *name, uid_t uid)
+{
+	const char	*p, *eom;
+	char		*q;
+	size_t		 len;
+	unsigned long	 m;
+
+	eom = entry + entrysize;
+	for (p = entry; p < eom; p++)
+		if (*p == ':')
+			break;
+	if (*p != ':')
+		return (NS_NOTFOUND);
+	if (how == nss_lt_all)
+		return (NS_SUCCESS);
+	if (how == nss_lt_name) {
+		len = strlen(name);
+		if (len == (p - entry) && memcmp(name, entry, len) == 0)
+			return (NS_SUCCESS);
+		else
+			return (NS_NOTFOUND);
+	}
+	for (p++; p < eom; p++)
+		if (*p == ':')
+			break;
+	if (*p != ':')
+		return (NS_NOTFOUND);
+	m = strtoul(++p, &q, 10);
+	if (q[0] != ':' || (uid_t)m != uid)
+		return (NS_NOTFOUND);
+	else
+		return (NS_SUCCESS);
+}
+
+
+/* XXX buffer must be NUL-terminated.  errnop is not set correctly. */
+int
+__pw_parse_entry(char *buffer, size_t bufsize __unused, struct passwd *pwd,
+    int master, int *errnop __unused)
+{
+
+	if (__pw_scan(buffer, pwd, master ? _PWSCAN_MASTER : 0) == 0)
+		return (NS_NOTFOUND);
+	else
+		return (NS_SUCCESS);
+}
Index: /trunk/libc/src/fbsdlibc/gen/getusershell.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/getusershell.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/getusershell.c	(revision 2448)
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 1985, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getusershell.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+/*	$NetBSD: getusershell.c,v 1.17 1999/01/25 01:09:34 lukem Exp $	*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getusershell.c,v 1.9 2003/04/24 20:16:21 nectar Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/file.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <nsswitch.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+
+#ifdef HESIOD
+#include <hesiod.h>
+#endif
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yp_prot.h>
+#endif
+#include "un-namespace.h"
+
+/*
+ * Local shells should NOT be added here.  They should be added in
+ * /etc/shells.
+ */
+
+static const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
+static const char *const *curshell;
+static StringList	 *sl;
+
+static const char *const *initshells(void);
+
+/*
+ * Get a list of shells from "shells" nsswitch database
+ */
+char *
+getusershell(void)
+{
+	char *ret;
+
+	if (curshell == NULL)
+		curshell = initshells();
+	/*LINTED*/
+	ret = (char *)*curshell;
+	if (ret != NULL)
+		curshell++;
+	return (ret);
+}
+
+void
+endusershell(void)
+{
+	if (sl) {
+		sl_free(sl, 1);
+		sl = NULL;
+	}
+	curshell = NULL;
+}
+
+void
+setusershell(void)
+{
+
+	curshell = initshells();
+}
+
+
+static int	_local_initshells(void *, void *, va_list);
+
+/*ARGSUSED*/
+static int
+_local_initshells(rv, cb_data, ap)
+	void	*rv;
+	void	*cb_data;
+	va_list	 ap;
+{
+	char	*sp, *cp;
+	FILE	*fp;
+	char	 line[MAXPATHLEN + 2];
+
+	if (sl)
+		sl_free(sl, 1);
+	sl = sl_init();
+
+	if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
+		return NS_UNAVAIL;
+
+	sp = cp = line;
+	while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
+		while (*cp != '#' && *cp != '/' && *cp != '\0')
+			cp++;
+		if (*cp == '#' || *cp == '\0')
+			continue;
+		sp = cp;
+		while (!isspace(*cp) && *cp != '#' && *cp != '\0')
+			cp++;
+		*cp++ = '\0';
+		sl_add(sl, strdup(sp));
+	}
+	(void)fclose(fp);
+	return NS_SUCCESS;
+}
+
+#ifdef HESIOD
+static int	_dns_initshells(void *, void *, va_list);
+
+/*ARGSUSED*/
+static int
+_dns_initshells(rv, cb_data, ap)
+	void	*rv;
+	void	*cb_data;
+	va_list	 ap;
+{
+	char	  shellname[] = "shells-XXXXX";
+	int	  hsindex, hpi, r;
+	char	**hp;
+	void	 *context;
+
+	if (sl)
+		sl_free(sl, 1);
+	sl = sl_init();
+	r = NS_UNAVAIL;
+	if (hesiod_init(&context) == -1)
+		return (r);
+
+	for (hsindex = 0; ; hsindex++) {
+		snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex);
+		hp = hesiod_resolve(context, shellname, "shells");
+		if (hp == NULL) {
+			if (errno == ENOENT) {
+				if (hsindex == 0)
+					r = NS_NOTFOUND;
+				else
+					r = NS_SUCCESS;
+			}
+			break;
+		} else {
+			for (hpi = 0; hp[hpi]; hpi++)
+				sl_add(sl, hp[hpi]);
+			free(hp);
+		}
+	}
+	hesiod_end(context);
+	return (r);
+}
+#endif /* HESIOD */
+
+#ifdef YP
+static int	_nis_initshells(void *, void *, va_list);
+
+/*ARGSUSED*/
+static int
+_nis_initshells(rv, cb_data, ap)
+	void	*rv;
+	void	*cb_data;
+	va_list	 ap;
+{
+	static char *ypdomain;
+	char	*key, *data;
+	char	*lastkey;
+	int	 keylen, datalen;
+	int	 r;
+
+	if (sl)
+		sl_free(sl, 1);
+	sl = sl_init();
+
+	if (ypdomain == NULL) {
+		switch (yp_get_default_domain(&ypdomain)) {
+		case 0:
+			break;
+		case YPERR_RESRC:
+			return NS_TRYAGAIN;
+		default:
+			return NS_UNAVAIL;
+		}
+	}
+
+	/*
+	 * `key' and `data' point to strings dynamically allocated by
+	 * the yp_... functions.
+	 * `data' is directly put into the stringlist of shells.
+	 */
+	key = data = NULL;
+	if (yp_first(ypdomain, "shells", &key, &keylen, &data, &datalen))
+		return NS_UNAVAIL;
+	do {
+		data[datalen] = '\0';		/* clear trailing \n */
+		sl_add(sl, data);
+
+		lastkey = key;
+		r = yp_next(ypdomain, "shells", lastkey, keylen,
+		    &key, &keylen, &data, &datalen);
+		free(lastkey);
+	} while (r == 0);
+	
+	if (r == YPERR_NOMORE) {
+		/*
+		 * `data' and `key' ought to be NULL - do not try to free them.
+		 */
+		return NS_SUCCESS;
+	}
+
+	return NS_UNAVAIL;
+}
+#endif /* YP */
+
+static const char *const *
+initshells()
+{
+	static const ns_dtab dtab[] = {
+		NS_FILES_CB(_local_initshells, NULL)
+		NS_DNS_CB(_dns_initshells, NULL)
+		NS_NIS_CB(_nis_initshells, NULL)
+		{ 0 }
+	};
+	if (sl)
+		sl_free(sl, 1);
+	sl = sl_init();
+
+	if (_nsdispatch(NULL, dtab, NSDB_SHELLS, "initshells", __nsdefaultsrc)
+	    != NS_SUCCESS) {
+		if (sl)
+			sl_free(sl, 1);
+		sl = NULL;
+		return (okshells);
+	}
+	sl_add(sl, NULL);
+
+	return (const char *const *)(sl->sl_str);
+}
Index: /trunk/libc/src/fbsdlibc/gen/glob.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/glob.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/glob.c	(revision 2448)
@@ -0,0 +1,962 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.22 2004/07/29 03:48:52 tjr Exp $");
+
+/*
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_QUOTE:
+ *	Escaping convention: \ inhibits any special meaning the following
+ *	character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ *	Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ *	Same as GLOB_NOCHECK, but it will only append pattern if it did
+ *	not contain any magic characters.  [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ *	Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ *	expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ *	expand {1,2}{a,b} to 1a 1b 2a 2b
+ * gl_matchc:
+ *	Number of matches in the current invocation of glob.
+ */
+
+/*
+ * Some notes on multibyte character support:
+ * 1. Patterns with illegal byte sequences match nothing - even if
+ *    GLOB_NOCHECK is specified.
+ * 2. Illegal byte sequences in filenames are handled by treating them as
+ *    single-byte characters with a value of the first byte of the sequence
+ *    cast to wchar_t.
+ * 3. State-dependent encodings are not currently supported.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <glob.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include "collate.h"
+
+#define	DOLLAR		'$'
+#define	DOT		'.'
+#define	EOS		'\0'
+#define	LBRACKET	'['
+#define	NOT		'!'
+#define	QUESTION	'?'
+#define	QUOTE		'\\'
+#define	RANGE		'-'
+#define	RBRACKET	']'
+#define	SEP		'/'
+#define	STAR		'*'
+#define	TILDE		'~'
+#define	UNDERSCORE	'_'
+#define	LBRACE		'{'
+#define	RBRACE		'}'
+#define	SLASH		'/'
+#define	COMMA		','
+
+#ifndef BSD_DEBUG /* bird prefixed with BSD */
+
+#define	M_QUOTE		0x8000000000ULL
+#define	M_PROTECT	0x4000000000ULL
+#define	M_MASK		0xffffffffffULL
+#define	M_CHAR		0x00ffffffffULL
+
+typedef uint_fast64_t Char;
+
+#else
+
+#define	M_QUOTE		0x80
+#define	M_PROTECT	0x40
+#define	M_MASK		0xff
+#define	M_CHAR		0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define	CHAR(c)		((Char)((c)&M_CHAR))
+#define	META(c)		((Char)((c)|M_QUOTE))
+#define	M_ALL		META('*')
+#define	M_END		META(']')
+#define	M_NOT		META('!')
+#define	M_ONE		META('?')
+#define	M_RNG		META('-')
+#define	M_SET		META('[')
+#define	ismeta(c)	(((c)&M_QUOTE) != 0)
+
+
+static int	 compare(const void *, const void *);
+static int	 g_Ctoc(const Char *, char *, u_int);
+static int	 g_lstat(Char *, struct stat *, glob_t *);
+static DIR	*g_opendir(Char *, glob_t *);
+static Char	*g_strchr(Char *, wchar_t);
+#ifdef notdef
+static Char	*g_strcat(Char *, const Char *);
+#endif
+static int	 g_stat(Char *, struct stat *, glob_t *);
+static int	 glob0(const Char *, glob_t *, int *);
+static int	 glob1(Char *, glob_t *, int *);
+static int	 glob2(Char *, Char *, Char *, Char *, glob_t *, int *);
+static int	 glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, int *);
+static int	 globextend(const Char *, glob_t *, int *);
+static const Char *	
+		 globtilde(const Char *, Char *, size_t, glob_t *);
+static int	 globexp1(const Char *, glob_t *, int *);
+static int	 globexp2(const Char *, const Char *, glob_t *, int *, int *);
+static int	 match(Char *, Char *, Char *);
+#ifdef BSD_DEBUG /* bird prefixed with BSD */
+static void	 qprintf(const char *, Char *);
+#endif
+
+int
+_STD(glob)(pattern, flags, errfunc, pglob)
+	const char *pattern;
+	int flags, (*errfunc)(const char *, int);
+	glob_t *pglob;
+{
+	const u_char *patnext;
+	int limit;
+	Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
+	mbstate_t mbs;
+	wchar_t wc;
+	size_t clen;
+
+	patnext = (u_char *) pattern;
+	if (!(flags & GLOB_APPEND)) {
+		pglob->gl_pathc = 0;
+		pglob->gl_pathv = NULL;
+		if (!(flags & GLOB_DOOFFS))
+			pglob->gl_offs = 0;
+	}
+	if (flags & GLOB_LIMIT) {
+		limit = pglob->gl_matchc;
+		if (limit == 0)
+			limit = ARG_MAX;
+	} else
+		limit = 0;
+	pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+	pglob->gl_errfunc = errfunc;
+	pglob->gl_matchc = 0;
+
+	bufnext = patbuf;
+	bufend = bufnext + MAXPATHLEN - 1;
+	if (flags & GLOB_NOESCAPE) {
+		memset(&mbs, 0, sizeof(mbs));
+		while (bufend - bufnext >= MB_CUR_MAX) {
+			clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+			if (clen == (size_t)-1 || clen == (size_t)-2)
+				return (GLOB_NOMATCH);
+			else if (clen == 0)
+				break;
+			*bufnext++ = wc;
+			patnext += clen;
+		}
+	} else {
+		/* Protect the quoted characters. */
+		memset(&mbs, 0, sizeof(mbs));
+		while (bufend - bufnext >= MB_CUR_MAX) {
+			if (*patnext == QUOTE) {
+				if (*++patnext == EOS) {
+					*bufnext++ = QUOTE | M_PROTECT;
+					continue;
+				}
+				prot = M_PROTECT;
+			} else
+				prot = 0;
+			clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+			if (clen == (size_t)-1 || clen == (size_t)-2)
+				return (GLOB_NOMATCH);
+			else if (clen == 0)
+				break;
+			*bufnext++ = wc | prot;
+			patnext += clen;
+		}
+	}
+	*bufnext = EOS;
+
+	if (flags & GLOB_BRACE)
+	    return globexp1(patbuf, pglob, &limit);
+	else
+	    return glob0(patbuf, pglob, &limit);
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int
+globexp1(pattern, pglob, limit)
+	const Char *pattern;
+	glob_t *pglob;
+	int *limit;
+{
+	const Char* ptr = pattern;
+	int rv;
+
+	/* Protect a single {}, for find(1), like csh */
+	if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
+		return glob0(pattern, pglob, limit);
+
+	while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
+		if (!globexp2(ptr, pattern, pglob, &rv, limit))
+			return rv;
+
+	return glob0(pattern, pglob, limit);
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int
+globexp2(ptr, pattern, pglob, rv, limit)
+	const Char *ptr, *pattern;
+	glob_t *pglob;
+	int *rv, *limit;
+{
+	int     i;
+	Char   *lm, *ls;
+	const Char *pe, *pm, *pl;
+	Char    patbuf[MAXPATHLEN];
+
+	/* copy part up to the brace */
+	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+		continue;
+	*lm = EOS;
+	ls = lm;
+
+	/* Find the balanced brace */
+	for (i = 0, pe = ++ptr; *pe; pe++)
+		if (*pe == LBRACKET) {
+			/* Ignore everything between [] */
+			for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
+				continue;
+			if (*pe == EOS) {
+				/*
+				 * We could not find a matching RBRACKET.
+				 * Ignore and just look for RBRACE
+				 */
+				pe = pm;
+			}
+		}
+		else if (*pe == LBRACE)
+			i++;
+		else if (*pe == RBRACE) {
+			if (i == 0)
+				break;
+			i--;
+		}
+
+	/* Non matching braces; just glob the pattern */
+	if (i != 0 || *pe == EOS) {
+		*rv = glob0(patbuf, pglob, limit);
+		return 0;
+	}
+
+	for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+		switch (*pm) {
+		case LBRACKET:
+			/* Ignore everything between [] */
+			for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
+				continue;
+			if (*pm == EOS) {
+				/*
+				 * We could not find a matching RBRACKET.
+				 * Ignore and just look for RBRACE
+				 */
+				pm = pl;
+			}
+			break;
+
+		case LBRACE:
+			i++;
+			break;
+
+		case RBRACE:
+			if (i) {
+			    i--;
+			    break;
+			}
+			/* FALLTHROUGH */
+		case COMMA:
+			if (i && *pm == COMMA)
+				break;
+			else {
+				/* Append the current string */
+				for (lm = ls; (pl < pm); *lm++ = *pl++)
+					continue;
+				/*
+				 * Append the rest of the pattern after the
+				 * closing brace
+				 */
+				for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
+					continue;
+
+				/* Expand the current pattern */
+#ifdef BSD_DEBUG /* bird prefixed with BSD */
+				qprintf("globexp2:", patbuf);
+#endif
+				*rv = globexp1(patbuf, pglob, limit);
+
+				/* move after the comma, to the next string */
+				pl = pm + 1;
+			}
+			break;
+
+		default:
+			break;
+		}
+	*rv = 0;
+	return 0;
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(pattern, patbuf, patbuf_len, pglob)
+	const Char *pattern;
+	Char *patbuf;
+	size_t patbuf_len;
+	glob_t *pglob;
+{
+	struct passwd *pwd;
+	char *h;
+	const Char *p;
+	Char *b, *eb;
+
+	if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
+		return pattern;
+
+	/*
+	 * Copy up to the end of the string or /
+	 */
+	eb = &patbuf[patbuf_len - 1];
+	for (p = pattern + 1, h = (char *) patbuf;
+	    h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
+		continue;
+
+	*h = EOS;
+
+	if (((char *) patbuf)[0] == EOS) {
+		/*
+		 * handle a plain ~ or ~/ by expanding $HOME first (iff
+		 * we're not running setuid or setgid) and then trying
+		 * the password file
+		 */
+		if (issetugid() != 0 ||
+		    (h = getenv("HOME")) == NULL) {
+			if (((h = getlogin()) != NULL &&
+			     (pwd = getpwnam(h)) != NULL) ||
+			    (pwd = getpwuid(getuid())) != NULL)
+				h = pwd->pw_dir;
+			else
+				return pattern;
+		}
+	}
+	else {
+		/*
+		 * Expand a ~user
+		 */
+		if ((pwd = getpwnam((char*) patbuf)) == NULL)
+			return pattern;
+		else
+			h = pwd->pw_dir;
+	}
+
+	/* Copy the home directory */
+	for (b = patbuf; b < eb && *h; *b++ = *h++)
+		continue;
+
+	/* Append the rest of the pattern */
+	while (b < eb && (*b++ = *p++) != EOS)
+		continue;
+	*b = EOS;
+
+	return patbuf;
+}
+
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested).  Returns 0
+ * if things went well, nonzero if errors occurred.
+ */
+static int
+glob0(pattern, pglob, limit)
+	const Char *pattern;
+	glob_t *pglob;
+	int *limit;
+{
+	const Char *qpatnext;
+	int c, err, oldpathc;
+	Char *bufnext, patbuf[MAXPATHLEN];
+
+	qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
+	oldpathc = pglob->gl_pathc;
+	bufnext = patbuf;
+
+	/* We don't need to check for buffer overflow any more. */
+	while ((c = *qpatnext++) != EOS) {
+		switch (c) {
+		case LBRACKET:
+			c = *qpatnext;
+			if (c == NOT)
+				++qpatnext;
+			if (*qpatnext == EOS ||
+			    g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
+				*bufnext++ = LBRACKET;
+				if (c == NOT)
+					--qpatnext;
+				break;
+			}
+			*bufnext++ = M_SET;
+			if (c == NOT)
+				*bufnext++ = M_NOT;
+			c = *qpatnext++;
+			do {
+				*bufnext++ = CHAR(c);
+				if (*qpatnext == RANGE &&
+				    (c = qpatnext[1]) != RBRACKET) {
+					*bufnext++ = M_RNG;
+					*bufnext++ = CHAR(c);
+					qpatnext += 2;
+				}
+			} while ((c = *qpatnext++) != RBRACKET);
+			pglob->gl_flags |= GLOB_MAGCHAR;
+			*bufnext++ = M_END;
+			break;
+		case QUESTION:
+			pglob->gl_flags |= GLOB_MAGCHAR;
+			*bufnext++ = M_ONE;
+			break;
+		case STAR:
+			pglob->gl_flags |= GLOB_MAGCHAR;
+			/* collapse adjacent stars to one,
+			 * to avoid exponential behavior
+			 */
+			if (bufnext == patbuf || bufnext[-1] != M_ALL)
+			    *bufnext++ = M_ALL;
+			break;
+		default:
+			*bufnext++ = CHAR(c);
+			break;
+		}
+	}
+	*bufnext = EOS;
+#ifdef BSD_DEBUG /* bird prefixed with BSD */
+	qprintf("glob0:", patbuf);
+#endif
+
+	if ((err = glob1(patbuf, pglob, limit)) != 0)
+		return(err);
+
+	/*
+	 * If there was no match we are going to append the pattern
+	 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+	 * and the pattern did not contain any magic characters
+	 * GLOB_NOMAGIC is there just for compatibility with csh.
+	 */
+	if (pglob->gl_pathc == oldpathc) {
+		if (((pglob->gl_flags & GLOB_NOCHECK) ||
+		    ((pglob->gl_flags & GLOB_NOMAGIC) &&
+			!(pglob->gl_flags & GLOB_MAGCHAR))))
+			return(globextend(pattern, pglob, limit));
+		else
+			return(GLOB_NOMATCH);
+	}
+	if (!(pglob->gl_flags & GLOB_NOSORT))
+		qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+		    pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+	return(0);
+}
+
+static int
+compare(p, q)
+	const void *p, *q;
+{
+	return(strcmp(*(char **)p, *(char **)q));
+}
+
+static int
+glob1(pattern, pglob, limit)
+	Char *pattern;
+	glob_t *pglob;
+	int *limit;
+{
+	Char pathbuf[MAXPATHLEN];
+
+	/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+	if (*pattern == EOS)
+		return(0);
+	return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
+	    pattern, pglob, limit));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+static int
+glob2(pathbuf, pathend, pathend_last, pattern, pglob, limit)
+	Char *pathbuf, *pathend, *pathend_last, *pattern;
+	glob_t *pglob;
+	int *limit;
+{
+	struct stat sb;
+	Char *p, *q;
+	int anymeta;
+
+	/*
+	 * Loop over pattern segments until end of pattern or until
+	 * segment with meta character found.
+	 */
+	for (anymeta = 0;;) {
+		if (*pattern == EOS) {		/* End of pattern? */
+			*pathend = EOS;
+			if (g_lstat(pathbuf, &sb, pglob))
+				return(0);
+
+			if (((pglob->gl_flags & GLOB_MARK) &&
+			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
+			    || (S_ISLNK(sb.st_mode) &&
+			    (g_stat(pathbuf, &sb, pglob) == 0) &&
+			    S_ISDIR(sb.st_mode)))) {
+				if (pathend + 1 > pathend_last)
+					return (GLOB_ABORTED);
+				*pathend++ = SEP;
+				*pathend = EOS;
+			}
+			++pglob->gl_matchc;
+			return(globextend(pathbuf, pglob, limit));
+		}
+
+		/* Find end of next segment, copy tentatively to pathend. */
+		q = pathend;
+		p = pattern;
+		while (*p != EOS && *p != SEP) {
+			if (ismeta(*p))
+				anymeta = 1;
+			if (q + 1 > pathend_last)
+				return (GLOB_ABORTED);
+			*q++ = *p++;
+		}
+
+		if (!anymeta) {		/* No expansion, do next segment. */
+			pathend = q;
+			pattern = p;
+			while (*pattern == SEP) {
+				if (pathend + 1 > pathend_last)
+					return (GLOB_ABORTED);
+				*pathend++ = *pattern++;
+			}
+		} else			/* Need expansion, recurse. */
+			return(glob3(pathbuf, pathend, pathend_last, pattern, p,
+			    pglob, limit));
+	}
+	/* NOTREACHED */
+}
+
+static int
+glob3(pathbuf, pathend, pathend_last, pattern, restpattern, pglob, limit)
+	Char *pathbuf, *pathend, *pathend_last, *pattern, *restpattern;
+	glob_t *pglob;
+	int *limit;
+{
+	struct dirent *dp;
+	DIR *dirp;
+	int err;
+	char buf[MAXPATHLEN];
+
+	/*
+	 * The readdirfunc declaration can't be prototyped, because it is
+	 * assigned, below, to two functions which are prototyped in glob.h
+	 * and dirent.h as taking pointers to differently typed opaque
+	 * structures.
+	 */
+	struct dirent *(*readdirfunc)();
+
+	if (pathend > pathend_last)
+		return (GLOB_ABORTED);
+	*pathend = EOS;
+	errno = 0;
+
+	if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+		/* TODO: don't call for ENOENT or ENOTDIR? */
+		if (pglob->gl_errfunc) {
+			if (g_Ctoc(pathbuf, buf, sizeof(buf)))
+				return (GLOB_ABORTED);
+			if (pglob->gl_errfunc(buf, errno) ||
+			    pglob->gl_flags & GLOB_ERR)
+				return (GLOB_ABORTED);
+		}
+		return(0);
+	}
+
+	err = 0;
+
+	/* Search directory for matching names. */
+	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+		readdirfunc = pglob->gl_readdir;
+	else
+		readdirfunc = readdir;
+	while ((dp = (*readdirfunc)(dirp))) {
+		u_char *sc;
+		Char *dc;
+		wchar_t wc;
+		size_t clen;
+		mbstate_t mbs;
+
+		/* Initial DOT must be matched literally. */
+		if (dp->d_name[0] == DOT && *pattern != DOT)
+			continue;
+		memset(&mbs, 0, sizeof(mbs));
+		dc = pathend;
+		sc = (u_char *) dp->d_name;
+		while (dc < pathend_last) {
+			clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+			if (clen == (size_t)-1 || clen == (size_t)-2) {
+				wc = *sc;
+				clen = 1;
+				memset(&mbs, 0, sizeof(mbs));
+			}
+			if ((*dc++ = wc) == EOS)
+				break;
+			sc += clen;
+		}
+		if (!match(pathend, pattern, restpattern)) {
+			*pathend = EOS;
+			continue;
+		}
+		err = glob2(pathbuf, --dc, pathend_last, restpattern,
+		    pglob, limit);
+		if (err)
+			break;
+	}
+
+	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+		(*pglob->gl_closedir)(dirp);
+	else
+		closedir(dirp);
+	return(err);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ *	Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ *	gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(path, pglob, limit)
+	const Char *path;
+	glob_t *pglob;
+	int *limit;
+{
+	char **pathv;
+	int i;
+	u_int newsize, len;
+	char *copy;
+	const Char *p;
+
+	if (*limit && pglob->gl_pathc > *limit) {
+		errno = 0;
+		return (GLOB_NOSPACE);
+	}
+
+	newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+	pathv = pglob->gl_pathv ?
+		    realloc((char *)pglob->gl_pathv, newsize) :
+		    malloc(newsize);
+	if (pathv == NULL) {
+		if (pglob->gl_pathv) {
+			free(pglob->gl_pathv);
+			pglob->gl_pathv = NULL;
+		}
+		return(GLOB_NOSPACE);
+	}
+
+	if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+		/* first time around -- clear initial gl_offs items */
+		pathv += pglob->gl_offs;
+		for (i = pglob->gl_offs; --i >= 0; )
+			*--pathv = NULL;
+	}
+	pglob->gl_pathv = pathv;
+
+	for (p = path; *p++;)
+		continue;
+	len = MB_CUR_MAX * (size_t)(p - path);	/* XXX overallocation */
+	if ((copy = malloc(len)) != NULL) {
+		if (g_Ctoc(path, copy, len)) {
+			free(copy);
+			return (GLOB_NOSPACE);
+		}
+		pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+	}
+	pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+	return(copy == NULL ? GLOB_NOSPACE : 0);
+}
+
+/*
+ * pattern matching function for filenames.  Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(name, pat, patend)
+	Char *name, *pat, *patend;
+{
+	int ok, negate_range;
+	Char c, k;
+
+	while (pat < patend) {
+		c = *pat++;
+		switch (c & M_MASK) {
+		case M_ALL:
+			if (pat == patend)
+				return(1);
+			do
+			    if (match(name, pat, patend))
+				    return(1);
+			while (*name++ != EOS);
+			return(0);
+		case M_ONE:
+			if (*name++ == EOS)
+				return(0);
+			break;
+		case M_SET:
+			ok = 0;
+			if ((k = *name++) == EOS)
+				return(0);
+			if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
+				++pat;
+			while (((c = *pat++) & M_MASK) != M_END)
+				if ((*pat & M_MASK) == M_RNG) {
+#ifdef __EMX__ /* we don't include all the locale stuff, only standalone stuff like this. */
+					if (   __collate_range_cmp(CHAR(c), CHAR(k)) <= 0
+					    && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0)
+#else
+					if (__collate_load_error ?
+					    CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
+					       __collate_range_cmp(CHAR(c), CHAR(k)) <= 0
+					    && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0
+					   )
+#endif
+						ok = 1;
+					pat += 2;
+				} else if (c == k)
+					ok = 1;
+			if (ok == negate_range)
+				return(0);
+			break;
+		default:
+			if (*name++ != c)
+				return(0);
+			break;
+		}
+	}
+	return(*name == EOS);
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void
+_STD(globfree)(pglob)
+	glob_t *pglob;
+{
+	int i;
+	char **pp;
+
+	if (pglob->gl_pathv != NULL) {
+		pp = pglob->gl_pathv + pglob->gl_offs;
+		for (i = pglob->gl_pathc; i--; ++pp)
+			if (*pp)
+				free(*pp);
+		free(pglob->gl_pathv);
+		pglob->gl_pathv = NULL;
+	}
+}
+
+static DIR *
+g_opendir(str, pglob)
+	Char *str;
+	glob_t *pglob;
+{
+	char buf[MAXPATHLEN];
+
+	if (!*str)
+		strcpy(buf, ".");
+	else {
+		if (g_Ctoc(str, buf, sizeof(buf)))
+			return (NULL);
+	}
+
+	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+		return((*pglob->gl_opendir)(buf));
+
+	return(opendir(buf));
+}
+
+static int
+g_lstat(fn, sb, pglob)
+	Char *fn;
+	struct stat *sb;
+	glob_t *pglob;
+{
+	char buf[MAXPATHLEN];
+
+	if (g_Ctoc(fn, buf, sizeof(buf))) {
+		errno = ENAMETOOLONG;
+		return (-1);
+	}
+	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+		return((*pglob->gl_lstat)(buf, sb));
+	return(lstat(buf, sb));
+}
+
+static int
+g_stat(fn, sb, pglob)
+	Char *fn;
+	struct stat *sb;
+	glob_t *pglob;
+{
+	char buf[MAXPATHLEN];
+
+	if (g_Ctoc(fn, buf, sizeof(buf))) {
+		errno = ENAMETOOLONG;
+		return (-1);
+	}
+	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+		return((*pglob->gl_stat)(buf, sb));
+	return(stat(buf, sb));
+}
+
+static Char *
+g_strchr(str, ch)
+	Char *str;
+	wchar_t ch;
+{
+	do {
+		if (*str == ch)
+			return (str);
+	} while (*str++);
+	return (NULL);
+}
+
+static int
+g_Ctoc(str, buf, len)
+	const Char *str;
+	char *buf;
+	u_int len;
+{
+	mbstate_t mbs;
+	size_t clen;
+
+	memset(&mbs, 0, sizeof(mbs));
+	while (len >= MB_CUR_MAX) {
+		clen = wcrtomb(buf, *str, &mbs);
+		if (clen == (size_t)-1)
+			return (1);
+		if (*str == L'\0')
+			return (0);
+		str++;
+		buf += clen;
+		len -= clen;
+	}
+	return (1);
+}
+
+#ifdef BSD_DEBUG /* bird prefixed with BSD */
+static void
+qprintf(str, s)
+	const char *str;
+	Char *s;
+{
+	Char *p;
+
+	(void)printf("%s:\n", str);
+	for (p = s; *p; p++)
+		(void)printf("%c", CHAR(*p));
+	(void)printf("\n");
+	for (p = s; *p; p++)
+		(void)printf("%c", *p & M_PROTECT ? '"' : ' ');
+	(void)printf("\n");
+	for (p = s; *p; p++)
+		(void)printf("%c", ismeta(*p) ? '_' : ' ');
+	(void)printf("\n");
+}
+#endif
Index: /trunk/libc/src/fbsdlibc/gen/initgroups.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/initgroups.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/initgroups.c	(revision 2448)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)initgroups.c	8.1 (Berkeley) 6/4/93";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/initgroups.c,v 1.8 2003/11/19 15:51:26 dds Exp $");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include "namespace.h"
+#include <err.h>
+#include "un-namespace.h"
+#include <unistd.h>
+
+int
+initgroups(uname, agroup)
+	const char *uname;
+	gid_t agroup;
+{
+	int ngroups;
+	/*
+	 * Provide space for one group more than NGROUPS to allow
+	 * setgroups to fail and set errno.
+	 */
+	gid_t groups[NGROUPS + 1];
+
+	ngroups = NGROUPS + 1;
+	getgrouplist(uname, agroup, groups, &ngroups);
+	return (setgroups(ngroups, groups));
+}
Index: /trunk/libc/src/fbsdlibc/gen/isinf.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/isinf.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/isinf.c	(revision 2448)
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/gen/isinf.c,v 1.2 2004/07/10 15:52:26 marcel Exp $
+ */
+
+#include "namespace.h"
+#include <math.h>
+
+#include "fpmath.h"
+
+/*
+ * XXX These routines belong in libm, but they must remain in libc for
+ *     binary compat until we can bump libm's major version number.
+ */
+
+/* _ _ w e a k _ r e f e r e n c e (__isinf, isinf); */
+
+int
+_STD(isinf)(double d)
+{
+	union IEEEd2bits u;
+
+	u.d = d;
+#ifdef __EMX__
+	return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0)
+	    ? u.bits.sign ? -1 : 1 : 0;
+#else
+	return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0);
+#endif
+}
+
+int
+__isinff(float f)
+{
+	union IEEEf2bits u;
+
+	u.f = f;
+#ifdef __EMX__
+	return (u.bits.exp == 255 && u.bits.man == 0)
+	    ? u.bits.sign ? -1 : 1 : 0;
+#else
+	return (u.bits.exp == 255 && u.bits.man == 0);
+#endif
+}
+
+int
+__isinfl(long double e)
+{
+	union IEEEl2bits u;
+
+	u.e = e;
+	mask_nbit_l(u);
+#ifdef __EMX__
+#ifndef __alpha__
+	return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0)
+#else
+	return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0)
+#endif
+	    ? u.bits.sign ? -1 : 1 : 0;
+#else
+#ifndef __alpha__
+	return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0);
+#else
+	return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0);
+#endif
+#endif
+}
Index: /trunk/libc/src/fbsdlibc/gen/jrand48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/jrand48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/jrand48.c	(revision 2448)
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/jrand48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+long
+_STD(jrand48)(unsigned short xseed[3])
+{
+	_dorand48(xseed);
+	return ((long) xseed[2] << 16) + (long) xseed[1];
+}
Index: /trunk/libc/src/fbsdlibc/gen/lcong48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/lcong48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/lcong48.c	(revision 2448)
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/lcong48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+extern unsigned short _rand48_mult[3];
+extern unsigned short _rand48_add;
+
+void
+_STD(lcong48)(unsigned short p[7])
+{
+	_rand48_seed[0] = p[0];
+	_rand48_seed[1] = p[1];
+	_rand48_seed[2] = p[2];
+	_rand48_mult[0] = p[3];
+	_rand48_mult[1] = p[4];
+	_rand48_mult[2] = p[5];
+	_rand48_add = p[6];
+}
Index: /trunk/libc/src/fbsdlibc/gen/lrand48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/lrand48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/lrand48.c	(revision 2448)
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/lrand48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+
+long
+_STD(lrand48)(void)
+{
+	_dorand48(_rand48_seed);
+	return ((long) _rand48_seed[2] << 15) + ((long) _rand48_seed[1] >> 1);
+}
Index: /trunk/libc/src/fbsdlibc/gen/mrand48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/mrand48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/mrand48.c	(revision 2448)
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/mrand48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+
+long
+_STD(mrand48)(void)
+{
+	_dorand48(_rand48_seed);
+	return ((long) _rand48_seed[2] << 16) + (long) _rand48_seed[1];
+}
Index: /trunk/libc/src/fbsdlibc/gen/nftw.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/nftw.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/nftw.c	(revision 2448)
@@ -0,0 +1,118 @@
+/*	$OpenBSD: nftw.c,v 1.4 2004/07/07 16:05:23 millert Exp $	*/
+
+/*
+ * Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$OpenBSD: nftw.c,v 1.4 2004/07/07 16:05:23 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/nftw.c,v 1.1 2004/08/24 13:00:55 tjr Exp $");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fts.h>
+#include <ftw.h>
+#include <limits.h>
+
+int
+_STD(nftw)(const char *path, int (*fn)(const char *, const struct stat *, int,
+     struct FTW *), int nfds, int ftwflags)
+{
+	char * const paths[2] = { (char *)path, NULL };
+	struct FTW ftw;
+	FTSENT *cur;
+	FTS *ftsp;
+	int error = 0, ftsflags, fnflag, postorder, sverrno;
+
+	/* XXX - nfds is currently unused */
+	if (nfds < 1 || nfds > OPEN_MAX) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	ftsflags = FTS_COMFOLLOW;
+	if (!(ftwflags & FTW_CHDIR))
+		ftsflags |= FTS_NOCHDIR;
+	if (ftwflags & FTW_MOUNT)
+		ftsflags |= FTS_XDEV;
+	if (ftwflags & FTW_PHYS)
+		ftsflags |= FTS_PHYSICAL;
+	else
+		ftsflags |= FTS_LOGICAL;
+	postorder = (ftwflags & FTW_DEPTH) != 0;
+	ftsp = fts_open(paths, ftsflags, NULL);
+	if (ftsp == NULL)
+		return (-1);
+	while ((cur = fts_read(ftsp)) != NULL) {
+		switch (cur->fts_info) {
+		case FTS_D:
+			if (postorder)
+				continue;
+			fnflag = FTW_D;
+			break;
+		case FTS_DNR:
+			fnflag = FTW_DNR;
+			break;
+		case FTS_DP:
+			if (!postorder)
+				continue;
+			fnflag = FTW_DP;
+			break;
+		case FTS_F:
+		case FTS_DEFAULT:
+			fnflag = FTW_F;
+			break;
+		case FTS_NS:
+		case FTS_NSOK:
+			fnflag = FTW_NS;
+			break;
+		case FTS_SL:
+			fnflag = FTW_SL;
+			break;
+		case FTS_SLNONE:
+			fnflag = FTW_SLN;
+			break;
+		case FTS_DC:
+			errno = ELOOP;
+			/* FALLTHROUGH */
+		default:
+			error = -1;
+			goto done;
+		}
+		ftw.base = cur->fts_pathlen - cur->fts_namelen;
+		ftw.level = cur->fts_level;
+		error = fn(cur->fts_path, cur->fts_statp, fnflag, &ftw);
+		if (error != 0)
+			break;
+	}
+done:
+	sverrno = errno;
+	if (fts_close(ftsp) != 0 && error == 0)
+		error = -1;
+	else
+		errno = sverrno;
+	return (error);
+}
Index: /trunk/libc/src/fbsdlibc/gen/nrand48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/nrand48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/nrand48.c	(revision 2448)
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/nrand48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+long
+_STD(nrand48)(unsigned short xseed[3])
+{
+	_dorand48(xseed);
+	return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
+}
Index: /trunk/libc/src/fbsdlibc/gen/pw_scan.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/pw_scan.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/pw_scan.c	(revision 2448)
@@ -0,0 +1,205 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)pw_scan.c	8.3 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/pw_scan.c,v 1.25 2004/01/18 21:33:25 charnier Exp $");
+
+/*
+ * This module is used to "verify" password entries by chpass(1) and
+ * pwd_mkdb(8).
+ */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pw_scan.h"
+
+/*
+ * Some software assumes that IDs are short.  We should emit warnings
+ * for id's which cannot be stored in a short, but we are more liberal
+ * by default, warning for IDs greater than USHRT_MAX.
+ *
+ * If pw_big_ids_warning is -1 on entry to pw_scan(), it will be set based
+ * on the existence of PW_SCAN_BIG_IDS in the environment.
+ */
+static int	pw_big_ids_warning = -1;
+
+int
+__pw_scan(char *bp, struct passwd *pw, int flags)
+{
+	uid_t id;
+	int root;
+	char *ep, *p, *sh;
+
+	if (pw_big_ids_warning == -1)
+		pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0;
+
+	pw->pw_fields = 0;
+	if (!(pw->pw_name = strsep(&bp, ":")))		/* login */
+		goto fmt;
+	root = !strcmp(pw->pw_name, "root");
+	if (pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0'))
+		pw->pw_fields |= _PWF_NAME;
+
+	if (!(pw->pw_passwd = strsep(&bp, ":")))	/* passwd */
+		goto fmt;
+	if (pw->pw_passwd[0])
+		pw->pw_fields |= _PWF_PASSWD;
+
+	if (!(p = strsep(&bp, ":")))			/* uid */
+		goto fmt;
+	if (p[0])
+		pw->pw_fields |= _PWF_UID;
+	else {
+		if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
+			if (flags & _PWSCAN_WARN)
+				warnx("no uid for user %s", pw->pw_name);
+			return (0);
+		}
+	}
+	id = strtoul(p, &ep, 10);
+	if (errno == ERANGE) {
+		if (flags & _PWSCAN_WARN)
+			warnx("%s > max uid value (%lu)", p, ULONG_MAX);
+		return (0);
+	}
+	if (*ep != '\0') {
+		if (flags & _PWSCAN_WARN)
+			warnx("%s uid is incorrect", p);
+		return (0);
+	}
+	if (root && id) {
+		if (flags & _PWSCAN_WARN)
+			warnx("root uid should be 0");
+		return (0);
+	}
+	if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
+		warnx("%s > recommended max uid value (%u)", p, USHRT_MAX);
+		/*return (0);*/ /* THIS SHOULD NOT BE FATAL! */
+	}
+	pw->pw_uid = id;
+
+	if (!(p = strsep(&bp, ":")))			/* gid */
+		goto fmt;
+	if (p[0])
+		pw->pw_fields |= _PWF_GID;
+	else {
+		if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
+			if (flags & _PWSCAN_WARN)
+				warnx("no gid for user %s", pw->pw_name);
+			return (0);
+		}
+	}
+	id = strtoul(p, &ep, 10);
+	if (errno == ERANGE) {
+		if (flags & _PWSCAN_WARN)
+			warnx("%s > max gid value (%lu)", p, ULONG_MAX);
+		return (0);
+	}
+	if (*ep != '\0') {
+		if (flags & _PWSCAN_WARN)
+			warnx("%s gid is incorrect", p);
+		return (0);
+	}
+	if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
+		warnx("%s > recommended max gid value (%u)", p, USHRT_MAX);
+		/* return (0); This should not be fatal! */
+	}
+	pw->pw_gid = id;
+
+	if (flags & _PWSCAN_MASTER ) {
+		if (!(pw->pw_class = strsep(&bp, ":")))	/* class */
+			goto fmt;
+		if (pw->pw_class[0])
+			pw->pw_fields |= _PWF_CLASS;
+		
+		if (!(p = strsep(&bp, ":")))		/* change */
+			goto fmt;
+		if (p[0])
+			pw->pw_fields |= _PWF_CHANGE;
+		pw->pw_change = atol(p);
+		
+		if (!(p = strsep(&bp, ":")))		/* expire */
+			goto fmt;
+		if (p[0])
+			pw->pw_fields |= _PWF_EXPIRE;
+		pw->pw_expire = atol(p);
+	}
+	if (!(pw->pw_gecos = strsep(&bp, ":")))		/* gecos */
+		goto fmt;
+	if (pw->pw_gecos[0])
+		pw->pw_fields |= _PWF_GECOS;
+
+	if (!(pw->pw_dir = strsep(&bp, ":")))		/* directory */
+		goto fmt;
+	if (pw->pw_dir[0])
+		pw->pw_fields |= _PWF_DIR;
+
+	if (!(pw->pw_shell = strsep(&bp, ":")))		/* shell */
+		goto fmt;
+
+	p = pw->pw_shell;
+	if (root && *p) {				/* empty == /bin/sh */
+		for (setusershell();;) {
+			if (!(sh = getusershell())) {
+				if (flags & _PWSCAN_WARN)
+					warnx("warning, unknown root shell");
+				break;
+			}
+			if (!strcmp(p, sh))
+				break;
+		}
+		endusershell();
+	}
+	if (p[0])
+		pw->pw_fields |= _PWF_SHELL;
+
+	if ((p = strsep(&bp, ":"))) {			/* too many */
+fmt:		
+		if (flags & _PWSCAN_WARN)
+			warnx("corrupted entry");
+		return (0);
+	}
+	return (1);
+}
Index: /trunk/libc/src/fbsdlibc/gen/pw_scan.h
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/pw_scan.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/pw_scan.h	(revision 2448)
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 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.
+ *
+ *	@(#)pw_scan.h	8.1 (Berkeley) 4/1/94
+ * $FreeBSD: src/lib/libc/gen/pw_scan.h,v 1.6 2002/03/22 23:41:42 obrien Exp $
+ */
+
+#define _PWSCAN_MASTER 0x01
+#define _PWSCAN_WARN   0x02
+
+extern int	__pw_scan(char *, struct passwd *, int);
Index: /trunk/libc/src/fbsdlibc/gen/rand48.h
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/rand48.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/rand48.h	(revision 2448)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ *
+ * $FreeBSD: src/lib/libc/gen/rand48.h,v 1.2 2002/02/01 01:32:19 obrien Exp $
+ */
+
+#ifndef _RAND48_H_
+#define _RAND48_H_
+
+#include <math.h>
+#include <stdlib.h>
+
+void		_dorand48(unsigned short[3]);
+
+#define	RAND48_SEED_0	(0x330e)
+#define	RAND48_SEED_1	(0xabcd)
+#define	RAND48_SEED_2	(0x1234)
+#define	RAND48_MULT_0	(0xe66d)
+#define	RAND48_MULT_1	(0xdeec)
+#define	RAND48_MULT_2	(0x0005)
+#define	RAND48_ADD	(0x000b)
+
+#endif /* _RAND48_H_ */
Index: /trunk/libc/src/fbsdlibc/gen/seed48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/seed48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/seed48.c	(revision 2448)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/seed48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+extern unsigned short _rand48_mult[3];
+extern unsigned short _rand48_add;
+
+unsigned short *
+_STD(seed48)(unsigned short xseed[3])
+{
+	static unsigned short sseed[3];
+
+	sseed[0] = _rand48_seed[0];
+	sseed[1] = _rand48_seed[1];
+	sseed[2] = _rand48_seed[2];
+	_rand48_seed[0] = xseed[0];
+	_rand48_seed[1] = xseed[1];
+	_rand48_seed[2] = xseed[2];
+	_rand48_mult[0] = RAND48_MULT_0;
+	_rand48_mult[1] = RAND48_MULT_1;
+	_rand48_mult[2] = RAND48_MULT_2;
+	_rand48_add = RAND48_ADD;
+	return sseed;
+}
Index: /trunk/libc/src/fbsdlibc/gen/setmode.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/setmode.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/setmode.c	(revision 2448)
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Dave Borman at Cray Research, Inc.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setmode.c	8.2 (Berkeley) 3/25/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/setmode.c,v 1.10 2005/04/08 21:15:38 stefanf Exp $");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef SETMODE_DEBUG
+#include <stdio.h>
+#endif
+#include "un-namespace.h"
+
+#define	SET_LEN	6		/* initial # of bitcmd struct to malloc */
+#define	SET_LEN_INCR 4		/* # of bitcmd structs to add as needed */
+
+typedef struct bitcmd {
+	char	cmd;
+	char	cmd2;
+	mode_t	bits;
+} BITCMD;
+
+#define	CMD2_CLR	0x01
+#define	CMD2_SET	0x02
+#define	CMD2_GBITS	0x04
+#define	CMD2_OBITS	0x08
+#define	CMD2_UBITS	0x10
+
+static BITCMD	*addcmd(BITCMD *, int, int, int, u_int);
+static void	 compress_mode(BITCMD *);
+#ifdef SETMODE_DEBUG
+static void	 dumpmode(BITCMD *);
+#endif
+
+/*
+ * Given the old mode and an array of bitcmd structures, apply the operations
+ * described in the bitcmd structures to the old mode, and return the new mode.
+ * Note that there is no '=' command; a strict assignment is just a '-' (clear
+ * bits) followed by a '+' (set bits).
+ */
+mode_t
+getmode(const void *bbox, mode_t omode)
+{
+	const BITCMD *set;
+	mode_t clrval, newmode, value;
+
+	set = (const BITCMD *)bbox;
+	newmode = omode;
+	for (value = 0;; set++)
+		switch(set->cmd) {
+		/*
+		 * When copying the user, group or other bits around, we "know"
+		 * where the bits are in the mode so that we can do shifts to
+		 * copy them around.  If we don't use shifts, it gets real
+		 * grundgy with lots of single bit checks and bit sets.
+		 */
+		case 'u':
+			value = (newmode & S_IRWXU) >> 6;
+			goto common;
+
+		case 'g':
+			value = (newmode & S_IRWXG) >> 3;
+			goto common;
+
+		case 'o':
+			value = newmode & S_IRWXO;
+common:			if (set->cmd2 & CMD2_CLR) {
+				clrval =
+				    (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
+				if (set->cmd2 & CMD2_UBITS)
+					newmode &= ~((clrval<<6) & set->bits);
+				if (set->cmd2 & CMD2_GBITS)
+					newmode &= ~((clrval<<3) & set->bits);
+				if (set->cmd2 & CMD2_OBITS)
+					newmode &= ~(clrval & set->bits);
+			}
+			if (set->cmd2 & CMD2_SET) {
+				if (set->cmd2 & CMD2_UBITS)
+					newmode |= (value<<6) & set->bits;
+				if (set->cmd2 & CMD2_GBITS)
+					newmode |= (value<<3) & set->bits;
+				if (set->cmd2 & CMD2_OBITS)
+					newmode |= value & set->bits;
+			}
+			break;
+
+		case '+':
+			newmode |= set->bits;
+			break;
+
+		case '-':
+			newmode &= ~set->bits;
+			break;
+
+		case 'X':
+			if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
+				newmode |= set->bits;
+			break;
+
+		case '\0':
+		default:
+#ifdef SETMODE_DEBUG
+			(void)printf("getmode:%04o -> %04o\n", omode, newmode);
+#endif
+			return (newmode);
+		}
+}
+
+#define	ADDCMD(a, b, c, d)						\
+	if (set >= endset) {						\
+		BITCMD *newset;						\
+		setlen += SET_LEN_INCR;					\
+		newset = realloc(saveset, sizeof(BITCMD) * setlen);	\
+		if (!newset) {						\
+			if (saveset)					\
+				free(saveset);				\
+			saveset = NULL;					\
+			return (NULL);					\
+		}							\
+		set = newset + (set - saveset);				\
+		saveset = newset;					\
+		endset = newset + (setlen - 2);				\
+	}								\
+	set = addcmd(set, (a), (b), (c), (d))
+
+#define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+
+void *
+bsd_setmode(const char *p) /* clashes with PC interface. */
+{
+	int perm, who;
+	char op, *ep;
+	BITCMD *set, *saveset, *endset;
+	sigset_t sigset, sigoset;
+	mode_t mask;
+	int equalopdone=0, permXbits, setlen;
+	long perml;
+
+	if (!*p)
+		return (NULL);
+
+	/*
+	 * Get a copy of the mask for the permissions that are mask relative.
+	 * Flip the bits, we want what's not set.  Since it's possible that
+	 * the caller is opening files inside a signal handler, protect them
+	 * as best we can.
+	 */
+	sigfillset(&sigset);
+        (void)_sigprocmask(SIG_BLOCK, &sigset, &sigoset);
+	(void)umask(mask = umask(0));
+	mask = ~mask;
+        (void)_sigprocmask(SIG_SETMASK, &sigoset, NULL);
+
+	setlen = SET_LEN + 2;
+
+	if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
+		return (NULL);
+	saveset = set;
+	endset = set + (setlen - 2);
+
+	/*
+	 * If an absolute number, get it and return; disallow non-octal digits
+	 * or illegal bits.
+	 */
+	if (isdigit((unsigned char)*p)) {
+		perml = strtol(p, &ep, 8);
+		if (*ep || perml < 0 || perml & ~(STANDARD_BITS|S_ISTXT)) {
+			free(saveset);
+			return (NULL);
+		}
+		perm = (mode_t)perml;
+		ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
+		set->cmd = 0;
+		return (saveset);
+	}
+
+	/*
+	 * Build list of structures to set/clear/copy bits as described by
+	 * each clause of the symbolic mode.
+	 */
+	for (;;) {
+		/* First, find out which bits might be modified. */
+		for (who = 0;; ++p) {
+			switch (*p) {
+			case 'a':
+				who |= STANDARD_BITS;
+				break;
+			case 'u':
+				who |= S_ISUID|S_IRWXU;
+				break;
+			case 'g':
+				who |= S_ISGID|S_IRWXG;
+				break;
+			case 'o':
+				who |= S_IRWXO;
+				break;
+			default:
+				goto getop;
+			}
+		}
+
+getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
+			free(saveset);
+			return (NULL);
+		}
+		if (op == '=')
+			equalopdone = 0;
+
+		who &= ~S_ISTXT;
+		for (perm = 0, permXbits = 0;; ++p) {
+			switch (*p) {
+			case 'r':
+				perm |= S_IRUSR|S_IRGRP|S_IROTH;
+				break;
+			case 's':
+				/* If only "other" bits ignore set-id. */
+				if (!who || who & ~S_IRWXO)
+					perm |= S_ISUID|S_ISGID;
+				break;
+			case 't':
+				/* If only "other" bits ignore sticky. */
+				if (!who || who & ~S_IRWXO) {
+					who |= S_ISTXT;
+					perm |= S_ISTXT;
+				}
+				break;
+			case 'w':
+				perm |= S_IWUSR|S_IWGRP|S_IWOTH;
+				break;
+			case 'X':
+				permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
+				break;
+			case 'x':
+				perm |= S_IXUSR|S_IXGRP|S_IXOTH;
+				break;
+			case 'u':
+			case 'g':
+			case 'o':
+				/*
+				 * When ever we hit 'u', 'g', or 'o', we have
+				 * to flush out any partial mode that we have,
+				 * and then do the copying of the mode bits.
+				 */
+				if (perm) {
+					ADDCMD(op, who, perm, mask);
+					perm = 0;
+				}
+				if (op == '=')
+					equalopdone = 1;
+				if (op == '+' && permXbits) {
+					ADDCMD('X', who, permXbits, mask);
+					permXbits = 0;
+				}
+				ADDCMD(*p, who, op, mask);
+				break;
+
+			default:
+				/*
+				 * Add any permissions that we haven't already
+				 * done.
+				 */
+				if (perm || (op == '=' && !equalopdone)) {
+					if (op == '=')
+						equalopdone = 1;
+					ADDCMD(op, who, perm, mask);
+					perm = 0;
+				}
+				if (permXbits) {
+					ADDCMD('X', who, permXbits, mask);
+					permXbits = 0;
+				}
+				goto apply;
+			}
+		}
+
+apply:		if (!*p)
+			break;
+		if (*p != ',')
+			goto getop;
+		++p;
+	}
+	set->cmd = 0;
+#ifdef SETMODE_DEBUG
+	(void)printf("Before compress_mode()\n");
+	dumpmode(saveset);
+#endif
+	compress_mode(saveset);
+#ifdef SETMODE_DEBUG
+	(void)printf("After compress_mode()\n");
+	dumpmode(saveset);
+#endif
+	return (saveset);
+}
+
+static BITCMD *
+addcmd(BITCMD *set, int op, int who, int oparg, u_int mask)
+{
+	switch (op) {
+	case '=':
+		set->cmd = '-';
+		set->bits = who ? who : STANDARD_BITS;
+		set++;
+
+		op = '+';
+		/* FALLTHROUGH */
+	case '+':
+	case '-':
+	case 'X':
+		set->cmd = op;
+		set->bits = (who ? who : mask) & oparg;
+		break;
+
+	case 'u':
+	case 'g':
+	case 'o':
+		set->cmd = op;
+		if (who) {
+			set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
+				    ((who & S_IRGRP) ? CMD2_GBITS : 0) |
+				    ((who & S_IROTH) ? CMD2_OBITS : 0);
+			set->bits = (mode_t)~0;
+		} else {
+			set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
+			set->bits = mask;
+		}
+
+		if (oparg == '+')
+			set->cmd2 |= CMD2_SET;
+		else if (oparg == '-')
+			set->cmd2 |= CMD2_CLR;
+		else if (oparg == '=')
+			set->cmd2 |= CMD2_SET|CMD2_CLR;
+		break;
+	}
+	return (set + 1);
+}
+
+#ifdef SETMODE_DEBUG
+static void
+dumpmode(BITCMD *set)
+{
+	for (; set->cmd; ++set)
+		(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
+		    set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
+		    set->cmd2 & CMD2_CLR ? " CLR" : "",
+		    set->cmd2 & CMD2_SET ? " SET" : "",
+		    set->cmd2 & CMD2_UBITS ? " UBITS" : "",
+		    set->cmd2 & CMD2_GBITS ? " GBITS" : "",
+		    set->cmd2 & CMD2_OBITS ? " OBITS" : "");
+}
+#endif
+
+/*
+ * Given an array of bitcmd structures, compress by compacting consecutive
+ * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
+ * 'g' and 'o' commands continue to be separate.  They could probably be
+ * compacted, but it's not worth the effort.
+ */
+static void
+compress_mode(BITCMD *set)
+{
+	BITCMD *nset;
+	int setbits, clrbits, Xbits, op;
+
+	for (nset = set;;) {
+		/* Copy over any 'u', 'g' and 'o' commands. */
+		while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
+			*set++ = *nset++;
+			if (!op)
+				return;
+		}
+
+		for (setbits = clrbits = Xbits = 0;; nset++) {
+			if ((op = nset->cmd) == '-') {
+				clrbits |= nset->bits;
+				setbits &= ~nset->bits;
+				Xbits &= ~nset->bits;
+			} else if (op == '+') {
+				setbits |= nset->bits;
+				clrbits &= ~nset->bits;
+				Xbits &= ~nset->bits;
+			} else if (op == 'X')
+				Xbits |= nset->bits & ~setbits;
+			else
+				break;
+		}
+		if (clrbits) {
+			set->cmd = '-';
+			set->cmd2 = 0;
+			set->bits = clrbits;
+			set++;
+		}
+		if (setbits) {
+			set->cmd = '+';
+			set->cmd2 = 0;
+			set->bits = setbits;
+			set++;
+		}
+		if (Xbits) {
+			set->cmd = 'X';
+			set->cmd2 = 0;
+			set->bits = Xbits;
+			set++;
+		}
+	}
+}
Index: /trunk/libc/src/fbsdlibc/gen/setprogname.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/setprogname.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/setprogname.c	(revision 2448)
@@ -0,0 +1,34 @@
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/setprogname.c,v 1.8 2002/03/29 22:43:41 markm Exp $");
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "libc_private.h"
+
+void
+setprogname(const char *progname)
+{
+    const char *p;
+#ifdef __EMX__
+    p = strlen(progname) + progname;
+    while (p >= progname)
+    {
+        if (*p == '\\' || *p == '/' || *p == ':')
+        {
+            __progname = p + 1;
+            return;
+        }
+        p--;
+    }
+    __progname = progname;
+    return;
+#else
+	p = strrchr(progname, '/');
+	if (p != NULL)
+		__progname = p + 1;
+	else
+		__progname = progname;
+#endif
+}
Index: /trunk/libc/src/fbsdlibc/gen/sleep.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/sleep.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/sleep.c	(revision 2448)
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sleep.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/sleep.c,v 1.31 2002/02/01 00:57:29 obrien Exp $");
+
+#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+unsigned int
+_STD(sleep)(seconds)
+	unsigned int seconds;
+{
+	struct timespec time_to_sleep;
+	struct timespec time_remaining;
+
+	/*
+	 * Avoid overflow when `seconds' is huge.  This assumes that
+	 * the maximum value for a time_t is >= INT_MAX.
+	 */
+	if (seconds > INT_MAX)
+		return (seconds - INT_MAX + __sleep(INT_MAX));
+
+	time_to_sleep.tv_sec = seconds;
+	time_to_sleep.tv_nsec = 0;
+	if (_nanosleep(&time_to_sleep, &time_remaining) != -1)
+		return (0);
+	if (errno != EINTR)
+		return (seconds);		/* best guess */
+	return (time_remaining.tv_sec +
+		(time_remaining.tv_nsec != 0)); /* round up */
+}
+
+/*_ _ w e a k  _ r e f e r e n c e (__sleep, sleep);
+ _ _ w e a k _ r e f e r e n c e(__sleep, _sleep); */
Index: /trunk/libc/src/fbsdlibc/gen/srand48.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/srand48.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/srand48.c	(revision 2448)
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "namespace.h" /* bird */
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+extern unsigned short _rand48_mult[3];
+extern unsigned short _rand48_add;
+
+void
+_STD(srand48)(long seed)
+{
+	_rand48_seed[0] = RAND48_SEED_0;
+	_rand48_seed[1] = (unsigned short) seed;
+	_rand48_seed[2] = (unsigned short) (seed >> 16);
+	_rand48_mult[0] = RAND48_MULT_0;
+	_rand48_mult[1] = RAND48_MULT_1;
+	_rand48_mult[2] = RAND48_MULT_2;
+	_rand48_add = RAND48_ADD;
+}
Index: /trunk/libc/src/fbsdlibc/gen/statvfs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/statvfs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/statvfs.c	(revision 2448)
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2002 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/statvfs.c,v 1.2 2002/09/06 11:23:40 tjr Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/statvfs.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+static int	sfs2svfs(const struct statfs *from, struct statvfs *to);
+
+int
+_STD(fstatvfs)(int fd, struct statvfs *result)
+{
+	struct statfs sfs;
+	int rv;
+	long pcval;
+
+	rv = _fstatfs(fd, &sfs);
+	if (rv != 0)
+		return (rv);
+
+	rv = sfs2svfs(&sfs, result);
+	if (rv != 0)
+		return (rv);
+
+	/*
+	 * Whether pathconf's -1 return means error or unlimited does not
+	 * make any difference in this best-effort implementation.
+	 */
+	pcval = _fpathconf(fd, _PC_NAME_MAX);
+	if (pcval == -1)
+		result->f_namemax = ~0UL;
+	else
+		result->f_namemax = (unsigned long)pcval;
+	return (0);
+}
+
+int
+_STD(statvfs)(const char * __restrict path, struct statvfs * __restrict result)
+{
+	struct statfs sfs;
+	int rv;
+	long pcval;
+
+	rv = statfs(path, &sfs);
+	if (rv != 0)
+		return (rv);
+
+	sfs2svfs(&sfs, result);
+
+	/*
+	 * Whether pathconf's -1 return means error or unlimited does not
+	 * make any difference in this best-effort implementation.
+	 */
+	pcval = pathconf(path, _PC_NAME_MAX);
+	if (pcval == -1)
+		result->f_namemax = ~0UL;
+	else
+		result->f_namemax = (unsigned long)pcval;
+	return (0);
+}
+
+static int
+sfs2svfs(const struct statfs *from, struct statvfs *to)
+{
+	static const struct statvfs zvfs;
+
+	*to = zvfs;
+
+	if (from->f_flags & MNT_RDONLY)
+		to->f_flag |= ST_RDONLY;
+	if (from->f_flags & MNT_NOSUID)
+		to->f_flag |= ST_NOSUID;
+
+	/* XXX should we clamp negative values? */
+#define COPY(field) \
+	do { \
+		to->field = from->field; \
+		if (from->field != to->field) { \
+			errno = EOVERFLOW; \
+			return (-1); \
+		} \
+	} while(0)
+
+	COPY(f_bavail);
+	COPY(f_bfree);
+	COPY(f_blocks);
+	COPY(f_ffree);
+	COPY(f_files);
+	to->f_bsize = from->f_iosize;
+	to->f_frsize = from->f_bsize;
+	to->f_favail = to->f_ffree;
+	return (0);
+}
+								
+#ifdef MAIN
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+	struct statvfs buf;
+
+	if (statvfs(argv[1], &buf) < 0)
+		err(1, "statvfs");
+
+#define SHOW(field) \
+	printf(#field ": %ju\n", (uintmax_t)buf.field)
+
+	SHOW(f_bavail);
+	SHOW(f_bfree);
+	SHOW(f_blocks);
+	SHOW(f_favail);
+	SHOW(f_ffree);
+	SHOW(f_files);
+	SHOW(f_bsize);
+	SHOW(f_frsize);
+	SHOW(f_namemax);
+	printf("f_flag: %lx\n", (unsigned long)buf.f_flag);
+
+	return 0;
+}
+
+#endif /* MAIN */
Index: /trunk/libc/src/fbsdlibc/gen/stringlist.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/stringlist.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/stringlist.c	(revision 2448)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * 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 Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$NetBSD: stringlist.c,v 1.2 1997/01/17 07:26:20 lukem Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/stringlist.c,v 1.7 2003/01/19 01:16:01 obrien Exp $");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <stdlib.h>
+#include <stringlist.h>
+#include "un-namespace.h"
+
+#define _SL_CHUNKSIZE	20
+
+/*
+ * sl_init(): Initialize a string list
+ */
+StringList *
+sl_init()
+{
+	StringList *sl;
+
+	sl = malloc(sizeof(StringList));
+	if (sl == NULL)
+		_err(1, "stringlist: %m");
+
+	sl->sl_cur = 0;
+	sl->sl_max = _SL_CHUNKSIZE;
+	sl->sl_str = malloc(sl->sl_max * sizeof(char *));
+	if (sl->sl_str == NULL)
+		_err(1, "stringlist: %m");
+	return sl;
+}
+
+
+/*
+ * sl_add(): Add an item to the string list
+ */
+int
+sl_add(sl, name)
+	StringList *sl;
+	char *name;
+{
+	if (sl->sl_cur == sl->sl_max - 1) {
+		sl->sl_max += _SL_CHUNKSIZE;
+		sl->sl_str = reallocf(sl->sl_str, sl->sl_max * sizeof(char *));
+		if (sl->sl_str == NULL)
+			return (-1);
+	}
+	sl->sl_str[sl->sl_cur++] = name;
+	return (0);
+}
+
+
+/*
+ * sl_free(): Free a stringlist
+ */
+void
+sl_free(sl, all)
+	StringList *sl;
+	int all;
+{
+	size_t i;
+
+	if (sl == NULL)
+		return;
+	if (sl->sl_str) {
+		if (all)
+			for (i = 0; i < sl->sl_cur; i++)
+				free(sl->sl_str[i]);
+		free(sl->sl_str);
+	}
+	free(sl);
+}
+
+
+/*
+ * sl_find(): Find a name in the string list
+ */
+char *
+sl_find(sl, name)
+	StringList *sl;
+	char *name;
+{
+	size_t i;
+
+	for (i = 0; i < sl->sl_cur; i++)
+		if (strcmp(sl->sl_str[i], name) == 0)
+			return sl->sl_str[i];
+
+	return NULL;
+}
Index: /trunk/libc/src/fbsdlibc/gen/sysctlbyname.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/sysctlbyname.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/sysctlbyname.c	(revision 2448)
@@ -0,0 +1,40 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include "libc-alias.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/sysctlbyname.c,v 1.5 2002/02/01 00:57:29 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+int
+_STD(sysctlbyname)(const char *name, void *oldp, size_t *oldlenp, void *newp,
+	     size_t newlen)
+{
+	int name2oid_oid[2];
+	int real_oid[CTL_MAXNAME+2];
+	int error;
+	size_t oidlen;
+
+	name2oid_oid[0] = 0;	/* This is magic & undocumented! */
+	name2oid_oid[1] = 3;
+
+	oidlen = sizeof(real_oid);
+	error = sysctl(name2oid_oid, 2, real_oid, &oidlen, (void *)name,
+		       strlen(name));
+	if (error < 0)
+		return error;
+	oidlen /= sizeof (int);
+	error = sysctl(real_oid, oidlen, oldp, oldlenp, newp, newlen);
+	return (error);
+}
+
Index: /trunk/libc/src/fbsdlibc/gen/sysctlnametomib.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/sysctlnametomib.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/sysctlnametomib.c	(revision 2448)
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2001 The FreeBSD Project. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``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 FREEBSD PROJECT 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 "libc-alias.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/sysctlnametomib.c,v 1.4 2003/01/04 00:11:11 tjr Exp $");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+/*
+ * This function uses a presently undocumented interface to the kernel
+ * to walk the tree and get the type so it can print the value.
+ * This interface is under work and consideration, and should probably
+ * be killed with a big axe by the first person who can find the time.
+ * (be aware though, that the proper interface isn't as obvious as it
+ * may seem, there are various conflicting requirements.
+ */
+int
+sysctlnametomib(const char *name, int *mibp, size_t *sizep)
+{
+	int oid[2];
+	int error;
+
+	oid[0] = 0;
+	oid[1] = 3;
+
+	*sizep *= sizeof (int);
+	error = sysctl(oid, 2, mibp, sizep, (void *)name, strlen(name));
+	*sizep /= sizeof (int);
+	return (error);
+}
Index: /trunk/libc/src/fbsdlibc/gen/ualarm.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/ualarm.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/ualarm.c	(revision 2448)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1985, 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ualarm.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/ualarm.c,v 1.4 2002/12/29 00:59:09 mike Exp $");
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#define	USPS	1000000		/* # of microseconds in a second */
+
+/*
+ * Generate a SIGALRM signal in ``usecs'' microseconds.
+ * If ``reload'' is non-zero, keep generating SIGALRM
+ * every ``reload'' microseconds after the first signal.
+ */
+useconds_t
+_STD(ualarm)(usecs, reload)
+	useconds_t usecs;
+	useconds_t reload;
+{
+	struct itimerval new, old;
+
+	new.it_interval.tv_usec = reload % USPS;
+	new.it_interval.tv_sec = reload / USPS;
+
+	new.it_value.tv_usec = usecs % USPS;
+	new.it_value.tv_sec = usecs / USPS;
+
+	if (setitimer(ITIMER_REAL, &new, &old) == 0)
+		return (old.it_value.tv_sec * USPS + old.it_value.tv_usec);
+	/* else */
+		return (-1);
+}
Index: /trunk/libc/src/fbsdlibc/gen/usleep.c
===================================================================
--- /trunk/libc/src/fbsdlibc/gen/usleep.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/gen/usleep.c	(revision 2448)
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)usleep.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/usleep.c,v 1.28 2002/12/29 00:59:09 mike Exp $");
+
+#include "namespace.h"
+#include <time.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+int
+_STD(usleep)(useconds)
+	useconds_t useconds;
+{
+	struct timespec time_to_sleep;
+
+	time_to_sleep.tv_nsec = (useconds % 1000000) * 1000;
+	time_to_sleep.tv_sec = useconds / 1000000;
+	return (_nanosleep(&time_to_sleep, NULL));
+}
Index: /trunk/libc/src/fbsdlibc/i386/gen/fabs.S
===================================================================
--- /trunk/libc/src/fbsdlibc/i386/gen/fabs.S	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/i386/gen/fabs.S	(revision 2448)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+	.asciz "@(#)fabs.s	5.2 (Berkeley) 12/17/90"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/libc/i386/gen/fabs.S,v 1.9 2002/03/23 02:44:18 obrien Exp $");
+
+STDENTRY(fabs)
+	fldl	4(%esp)
+	fabs
+	ret
Index: /trunk/libc/src/fbsdlibc/i386/gen/flt_rounds.c
===================================================================
--- /trunk/libc/src/fbsdlibc/i386/gen/flt_rounds.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/i386/gen/flt_rounds.c	(revision 2448)
@@ -0,0 +1,26 @@
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/i386/gen/flt_rounds.c,v 1.1 2004/07/19 08:17:24 das Exp $");
+
+#include <float.h>
+
+static const int map[] = {
+	1,	/* round to nearest */
+	3,	/* round to zero */
+	2,	/* round to negative infinity */
+	0	/* round to positive infinity */
+};
+
+int
+__flt_rounds(void)
+{
+	int x;
+
+	__asm("fnstcw %0" : "=m" (x));
+        return (map[(x >> 10) & 0x03]);
+}
Index: /trunk/libc/src/fbsdlibc/i386/gen/infinity.c
===================================================================
--- /trunk/libc/src/fbsdlibc/i386/gen/infinity.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/i386/gen/infinity.c	(revision 2448)
@@ -0,0 +1,15 @@
+/*
+ * infinity.c
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/i386/gen/infinity.c,v 1.10 2003/02/08 20:37:52 mike Exp $");
+
+#include <math.h>
+
+/* bytes for +Infinity on a 387 */
+const union __infinity_un __infinity = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
+
+/* bytes for NaN */
+const union __nan_un __nan = { { 0, 0, 0xc0, 0xff } };
Index: /trunk/libc/src/fbsdlibc/i386/gen/ldexp.c
===================================================================
--- /trunk/libc/src/fbsdlibc/i386/gen/ldexp.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/i386/gen/ldexp.c	(revision 2448)
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Sean Eric Fagan.
+ *
+ * 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.
+ */
+
+#include "namespace.h"
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ldexp.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/i386/gen/ldexp.c,v 1.11 2004/02/16 10:03:02 das Exp $");
+
+/* seems not to be declared anywhere, this shuts up gcc. */
+double _STD(ldexp) (double value, int exp);
+
+/*
+ * ldexp(value, exp): return value * (2 ** exp).
+ *
+ * Written by Sean Eric Fagan (sef@kithrup.COM)
+ * Sun Mar 11 20:27:09 PST 1990
+ */
+
+/*
+ * We do the conversion in C to let gcc optimize it away, if possible.
+ */
+double
+_STD(ldexp) (double value, int exp)
+{
+	double temp, texp, temp2;
+	texp = exp;
+#ifdef __GNUC__
+	__asm ("fscale "
+		: "=u" (temp2), "=t" (temp)
+		: "0" (texp), "1" (value));
+#else
+#error unknown asm
+#endif
+	return (temp);
+}
Index: /trunk/libc/src/fbsdlibc/i386/gen/modf.S
===================================================================
--- /trunk/libc/src/fbsdlibc/i386/gen/modf.S	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/i386/gen/modf.S	(revision 2448)
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Sean Eric Fagan.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+	.asciz "@(#)modf.s	5.5 (Berkeley) 3/18/91"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/libc/i386/gen/modf.S,v 1.9 2002/03/23 02:05:17 obrien Exp $");
+
+/*
+ * modf(value, iptr): return fractional part of value, and stores the
+ * integral part into iptr (a pointer to double).
+ *
+ * Written by Sean Eric Fagan (sef@kithrup.COM)
+ * Sun Mar 11 20:27:30 PST 1990
+ */
+
+/* With CHOP mode on, frndint behaves as TRUNC does.  Useful. */
+
+STDENTRY(modf)
+	pushl %ebp
+	movl %esp,%ebp
+	subl $16,%esp
+	fnstcw -12(%ebp)
+	movw -12(%ebp),%dx
+	orw $3072,%dx
+	movw %dx,-16(%ebp)
+	fldcw -16(%ebp)
+	fldl 8(%ebp)
+	frndint
+	fstpl -8(%ebp)
+	fldcw -12(%ebp)
+	movl 16(%ebp),%eax
+	movl -8(%ebp),%edx
+	movl -4(%ebp),%ecx
+	movl %edx,(%eax)
+	movl %ecx,4(%eax)
+	fldl 8(%ebp)
+	fsubl -8(%ebp)
+	jmp L1
+L1:
+	leave
+	ret
Index: /trunk/libc/src/fbsdlibc/i386/i386.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/i386/i386.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/i386/i386.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC.386 += $(wildcard src/fbsdlibc/i386/*/*.c) $(wildcard src/fbsdlibc/i386/*/*.S)
Index: /trunk/libc/src/fbsdlibc/include/_fpmath.h
===================================================================
--- /trunk/libc/src/fbsdlibc/include/_fpmath.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/include/_fpmath.h	(revision 2448)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/i386/_fpmath.h,v 1.5 2005/03/07 04:55:22 das Exp $
+ */
+
+union IEEEl2bits {
+	long double	e;
+	struct {
+		unsigned int	manl	:32;
+		unsigned int	manh	:32;
+		unsigned int	exp	:15;
+		unsigned int	sign	:1;
+		unsigned int	junk	:16;
+	} bits;
+};
+
+#define	LDBL_NBIT	0x80000000
+#define	mask_nbit_l(u)	((u).bits.manh &= ~LDBL_NBIT)
+
+#define	LDBL_MANH_SIZE	32
+#define	LDBL_MANL_SIZE	32
+
+#define	LDBL_TO_ARRAY32(u, a) do {			\
+	(a)[0] = (uint32_t)(u).bits.manl;		\
+	(a)[1] = (uint32_t)(u).bits.manh;		\
+} while(0)
Index: /trunk/libc/src/fbsdlibc/include/fpmath.h
===================================================================
--- /trunk/libc/src/fbsdlibc/include/fpmath.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/include/fpmath.h	(revision 2448)
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2002 David Schultz <dschultz@uclink.Berkeley.EDU>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/include/fpmath.h,v 1.2 2004/01/18 08:05:21 das Exp $
+ */
+
+#include <sys/endian.h>
+#include "_fpmath.h"
+
+union IEEEf2bits {
+	float	f;
+	struct {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+		unsigned int	man	:23;
+		unsigned int	exp	:8;
+		unsigned int	sign	:1;
+#else /* _BIG_ENDIAN */
+		unsigned int	sign	:1;
+		unsigned int	exp	:8;
+		unsigned int	man	:23;
+#endif
+	} bits;
+};
+
+#define	DBL_MANH_SIZE	20
+#define	DBL_MANL_SIZE	32
+
+union IEEEd2bits {
+	double	d;
+	struct {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+		unsigned int	manl	:32;
+		unsigned int	manh	:20;
+		unsigned int	exp	:11;
+		unsigned int	sign	:1;
+#else /* _BIG_ENDIAN */
+		unsigned int	sign	:1;
+		unsigned int	exp	:11;
+		unsigned int	manh	:20;
+		unsigned int	manl	:32;
+#endif
+	} bits;
+};
Index: /trunk/libc/src/fbsdlibc/include/libc_private.h
===================================================================
--- /trunk/libc/src/fbsdlibc/include/libc_private.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/include/libc_private.h	(revision 2448)
@@ -0,0 +1,3 @@
+/* placeholder */
+extern const char *__progname;
+
Index: /trunk/libc/src/fbsdlibc/include/namespace.h
===================================================================
--- /trunk/libc/src/fbsdlibc/include/namespace.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/include/namespace.h	(revision 2448)
@@ -0,0 +1,41 @@
+/** $Id$ */
+/** @file
+ * Replacement for the BSD namespace wrapper.
+ */
+#ifndef _NAMESPACE_H_
+#define _NAMESPACE_H_
+#include "libc-alias.h"
+/* kill these as they're handled by alias/aliasbsdfuncs.awk */
+#define __weak_reference(a,b)   struct __hack
+#define __make_alias(a,b)       struct __hack
+
+#define err _err
+#define warn _warn
+#define getprogname _getprogname
+
+#define _fsync      _STD(fsync)
+#define _fstat      _STD(fstat)
+#define _fcntl      _STD(fcntl)
+#define _writev     _STD(writev)
+#define _readv      _STD(readv)
+#define _close      _STD(close)
+#define _open       _STD(open)
+#define _read       _STD(read)
+#define _write      _STD(write)
+#define _connect    connect
+#define _socket     socket
+#define __strtok_r  _STD(strtok_r)
+#define _fpathconf  _STD(fpathconf)
+#define _statfs     _STD(statfs)
+#define _fstatfs    _STD(fstatfs)
+#define nsdispatch  _nsdispatch
+#define _sigprocmask _STD(sigprocmask)
+#define _nanosleep   _STD(nanosleep)
+#define _sleep       _STD(sleep)
+#define __sleep      _STD(sleep)
+#define _usleep      _STD(usleep)
+#define feenableexcept __feenableexcept
+#define fedisableexcept __fedisableexcept
+
+#endif
+
Index: /trunk/libc/src/fbsdlibc/include/nss_tls.h
===================================================================
--- /trunk/libc/src/fbsdlibc/include/nss_tls.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/include/nss_tls.h	(revision 2448)
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/include/nss_tls.h,v 1.2 2003/04/21 15:44:25 nectar Exp $
+ *
+ * Macros which generate thread local storage handling code in NSS modules.
+ */
+#ifndef _NSS_TLS_H_
+#define _NSS_TLS_H_
+
+#if 0 /* bird */
+
+#define NSS_TLS_HANDLING(name)					\
+static pthread_key_t name##_state_key;				\
+static	void	 name##_keyinit(void);				\
+static	int	 name##_getstate(struct name##_state **);	\
+\
+static void								\
+name##_keyinit(void)							\
+{									\
+	(void)_pthread_key_create(&name##_state_key, name##_endstate);	\
+}									\
+\
+static int							\
+name##_getstate(struct name##_state **p)			\
+{								\
+	static struct name##_state st;				\
+	static pthread_once_t	keyinit = PTHREAD_ONCE_INIT;	\
+	int			rv;				\
+								\
+	if (!__isthreaded || _pthread_main_np() != 0) {		\
+		*p = &st;					\
+		return (0);					\
+	}							\
+	rv = _pthread_once(&keyinit, name##_keyinit);		\
+	if (rv != 0)						\
+		return (rv);					\
+	*p = _pthread_getspecific(name##_state_key);		\
+	if (*p != NULL)						\
+		return (0);					\
+	*p = calloc(1, sizeof(**p));				\
+	if (*p == NULL)						\
+		return (ENOMEM);				\
+	rv = _pthread_setspecific(name##_state_key, *p);	\
+	if (rv != 0) {						\
+		free(*p);					\
+		*p = NULL;					\
+	}							\
+	return (rv);						\
+}								\
+/* allow the macro invocation to end with a semicolon */	\
+typedef int _##name##_bmVjdGFy
+
+#else
+/* Bird: this is a temporary hack till pthreads are implemented and we can test things. */
+#define NSS_TLS_HANDLING(name)					\
+static	void	 name##_keyinit(void);				\
+static	int	 name##_getstate(struct name##_state **);	\
+\
+static void							\
+name##_keyinit(void)						\
+{								\
+}								\
+\
+static int							\
+name##_getstate(struct name##_state **p)			\
+{								\
+	static struct name##_state st;				\
+	*p = &st;					        \
+	return (0);					        \
+}								\
+/* allow the macro invocation to end with a semicolon */	\
+typedef int _##name##_bmVjdGFy
+
+#endif
+
+#endif /* _NSS_TLS_H_ */
Index: /trunk/libc/src/fbsdlibc/include/un-namespace.h
===================================================================
--- /trunk/libc/src/fbsdlibc/include/un-namespace.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/include/un-namespace.h	(revision 2448)
@@ -0,0 +1,15 @@
+/** $Id$ */
+/** @file
+ * Replacement for the BSD namespace wrapper.
+ */
+
+#ifndef _UN_NAMESPACE_H_
+#define _UN_NAMESPACE_H_
+
+#undef err
+#undef warn
+#undef getprogname
+
+#endif
+
+
Index: /trunk/libc/src/fbsdlibc/locale/btowc.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/btowc.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/btowc.c	(revision 2448)
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2002, 2003 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/btowc.c,v 1.4 2004/05/12 14:26:54 tjr Exp $");
+
+#include <stdio.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+wint_t
+_STD(btowc)(int c)
+{
+	static const mbstate_t initial;
+	mbstate_t mbs = initial;
+	char cc;
+	wchar_t wc;
+
+	if (c == EOF)
+		return (WEOF);
+	/*
+	 * We expect mbrtowc() to return 0 or 1, hence the check for n > 1
+	 * which detects error return values as well as "impossible" byte
+	 * counts.
+	 */
+	cc = (char)c;
+	if (    __mbrtowc(&wc, &cc, 1, &mbs) > 1
+            ||  (wc >= 0xfff8 && wc <= 0xffff)) /* warning is expected */
+		return (WEOF);
+	return wc;
+}
Index: /trunk/libc/src/fbsdlibc/locale/collate.h
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/collate.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/collate.h	(revision 2448)
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ *		at Electronni Visti IA, Kiev, Ukraine.
+ *			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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/locale/collate.h,v 1.14 2002/08/30 20:26:02 ache Exp $
+ */
+
+#ifndef _COLLATE_H_
+#define	_COLLATE_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#define STR_LEN 10
+#define TABLE_SIZE 100
+#define COLLATE_VERSION    "1.0\n"
+#define COLLATE_VERSION1_1 "1.1\n"
+
+struct __collate_st_char_pri {
+	int prim, sec;
+};
+struct __collate_st_chain_pri {
+	u_char str[STR_LEN];
+	int prim, sec;
+};
+
+extern int __collate_load_error;
+extern int __collate_substitute_nontrivial;
+#define __collate_substitute_table (*__collate_substitute_table_ptr)
+extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
+#define __collate_char_pri_table (*__collate_char_pri_table_ptr)
+extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
+extern struct __collate_st_chain_pri *__collate_chain_pri_table;
+
+__BEGIN_DECLS
+u_char	*__collate_strdup(u_char *);
+u_char	*__collate_substitute(const u_char *);
+int	__collate_load_tables(const char *);
+void	__collate_lookup(const u_char *, int *, int *, int *);
+int	__collate_range_cmp(int, int);
+#ifdef COLLATE_DEBUG
+void	__collate_print_tables(void);
+#endif
+__END_DECLS
+
+#endif /* !_COLLATE_H_ */
Index: /trunk/libc/src/fbsdlibc/locale/collcmp.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/collcmp.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/collcmp.c	(revision 2448)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/collcmp.c,v 1.17 2003/08/03 19:28:23 ache Exp $");
+
+#include <string.h>
+#include "collate.h"
+
+/*
+ * Compare two characters using collate
+ */
+
+int __collate_range_cmp(c1, c2)
+	int c1, c2;
+{
+	static char s1[2], s2[2];
+
+	s1[0] = c1;
+	s2[0] = c2;
+	return (strcoll(s1, s2));
+}
Index: /trunk/libc/src/fbsdlibc/locale/ldpart.h
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/ldpart.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/ldpart.h	(revision 2448)
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/locale/ldpart.h,v 1.6 2003/06/13 00:14:07 jkh Exp $
+ */
+
+#ifndef _LDPART_H_
+#define	_LDPART_H_
+
+#define _LDP_LOADED 0
+#define _LDP_ERROR  (-1)
+#define _LDP_CACHE  1
+
+int	__part_load_locale(const char *, int*, char **, const char *,
+		    int, int, const char **);
+
+#endif /* !_LDPART_H_ */
Index: /trunk/libc/src/fbsdlibc/locale/locale.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/locale.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/locale.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/fbsdlibc/locale/*.c)
Index: /trunk/libc/src/fbsdlibc/locale/mblen.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mblen.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mblen.c	(revision 2448)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mblen.c,v 1.9 2004/07/29 06:18:40 tjr Exp $");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+_STD(mblen)(const char *s, size_t n)
+{
+	static const mbstate_t initial;
+	static mbstate_t mbs;
+	size_t rval;
+
+	if (s == NULL) {
+		/* No support for state dependent encodings. */
+		mbs = initial;
+		return (0);
+	}
+	rval = __mbrtowc(NULL, s, n, &mbs);
+	if (rval == (size_t)-1 || rval == (size_t)-2)
+		return (-1);
+	return ((int)rval);
+}
Index: /trunk/libc/src/fbsdlibc/locale/mblocal.h
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mblocal.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mblocal.h	(revision 2448)
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/locale/mblocal.h,v 1.3 2004/07/21 10:54:57 tjr Exp $
+ */
+
+#ifndef _MBLOCAL_H_
+#define	_MBLOCAL_H_
+
+#include <stddef.h>	/* XXX for rune_t */
+
+/*
+ * Conversion function pointers for current encoding.
+ */
+#ifndef __INNOTEK_LIBC__
+extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict,
+    size_t, mbstate_t * __restrict);
+extern int (*__mbsinit)(const mbstate_t *);
+extern size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
+    size_t, size_t, mbstate_t * __restrict);
+extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict);
+extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
+    size_t, size_t, mbstate_t * __restrict);
+#else /* !__INNOTEK_LIBC__ */
+#define __mbrtowc(a,b,c,d)      __libc_GLocaleCtype.CtypeFuncs.pfnmbrtowc(a,b,c,d)
+#define __mbsinit(a)            __libc_GLocaleCtype.CtypeFuncs.pfnmbsinit(a)
+#define __mbsnrtowcs(a,b,c,d,e) __libc_GLocaleCtype.CtypeFuncs.pfnmbsnrtowcs(a,b,c,d,e)
+#define __wcrtomb(a,b,c)        __libc_GLocaleCtype.CtypeFuncs.pfnwcrtomb(a,b,c)
+#define __wcsnrtombs(a,b,c,d,e) __libc_GLocaleCtype.CtypeFuncs.pfnwcsnrtombs(a,b,c,d,e)
+#endif
+
+/*
+ * Conversion functions for "NONE"/C/POSIX encoding.
+ */
+extern size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
+    size_t, mbstate_t * __restrict);
+extern int _none_mbsinit(const mbstate_t *);
+extern size_t _none_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
+    size_t, size_t, mbstate_t * __restrict);
+extern size_t _none_wcrtomb(char * __restrict, wchar_t,
+    mbstate_t * __restrict);
+extern size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+    size_t, size_t, mbstate_t * __restrict);
+
+extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict,
+    size_t, size_t, mbstate_t * __restrict);
+extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict,
+    size_t, size_t, mbstate_t * __restrict);
+
+/*
+ * Rune emulation functions.
+ */
+extern rune_t __emulated_sgetrune(const char *, size_t, const char **);
+extern int __emulated_sputrune(rune_t, char *, size_t, char **);
+
+#endif	/* _MBLOCAL_H_ */
Index: /trunk/libc/src/fbsdlibc/locale/mbrlen.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mbrlen.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mbrlen.c	(revision 2448)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbrlen.c,v 1.4 2004/05/12 14:26:54 tjr Exp $");
+
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(mbrlen)(const char * __restrict s, size_t n, mbstate_t * __restrict ps)
+{
+	static mbstate_t mbs;
+
+	if (ps == NULL)
+		ps = &mbs;
+	return (__mbrtowc(NULL, s, n, ps));
+}
Index: /trunk/libc/src/fbsdlibc/locale/mbrtowc.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mbrtowc.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mbrtowc.c	(revision 2448)
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbrtowc.c,v 1.7 2004/05/12 14:09:04 tjr Exp $");
+
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(mbrtowc)(wchar_t * __restrict pwc, const char * __restrict s,
+    size_t n, mbstate_t * __restrict ps)
+{
+	static mbstate_t mbs;
+
+	if (ps == NULL)
+		ps = &mbs;
+	return (__mbrtowc(pwc, s, n, ps));
+}
Index: /trunk/libc/src/fbsdlibc/locale/mbsinit.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mbsinit.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mbsinit.c	(revision 2448)
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbsinit.c,v 1.3 2004/05/12 14:09:04 tjr Exp $");
+
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+_STD(mbsinit)(const mbstate_t *ps)
+{
+
+	return (__mbsinit(ps));
+}
Index: /trunk/libc/src/fbsdlibc/locale/mbsnrtowcs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mbsnrtowcs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mbsnrtowcs.c	(revision 2448)
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbsnrtowcs.c,v 1.1 2004/07/21 10:54:57 tjr Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(mbsnrtowcs)(wchar_t * __restrict dst, const char ** __restrict src,
+    size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+	static mbstate_t mbs;
+
+	if (ps == NULL)
+		ps = &mbs;
+	return (__mbsnrtowcs(dst, src, nms, len, ps));
+}
+
+size_t
+__mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src,
+    size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+	const char *s;
+	size_t nchr;
+	wchar_t wc;
+	size_t nb;
+
+	s = *src;
+	nchr = 0;
+
+	if (dst == NULL) {
+		for (;;) {
+			if ((nb = __mbrtowc(&wc, s, nms, ps)) == (size_t)-1)
+				/* Invalid sequence - mbrtowc() sets errno. */
+				return ((size_t)-1);
+			else if (nb == 0 || nb == (size_t)-2)
+				return (nchr);
+			s += nb;
+			nms -= nb;
+			nchr++;
+		}
+		/*NOTREACHED*/
+	}
+
+	while (len-- > 0) {
+		if ((nb = __mbrtowc(dst, s, nms, ps)) == (size_t)-1) {
+			*src = s;
+			return ((size_t)-1);
+		} else if (nb == (size_t)-2) {
+			*src = s + nms;
+			return (nchr);
+		} else if (nb == 0) {
+			*src = NULL;
+			return (nchr);
+		}
+		s += nb;
+		nms -= nb;
+		nchr++;
+		dst++;
+	}
+	*src = s;
+	return (nchr);
+}
Index: /trunk/libc/src/fbsdlibc/locale/mbsrtowcs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mbsrtowcs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mbsrtowcs.c	(revision 2448)
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbsrtowcs.c,v 1.6 2004/07/21 10:54:57 tjr Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(mbsrtowcs)(wchar_t * __restrict dst, const char ** __restrict src, size_t len,
+    mbstate_t * __restrict ps)
+{
+	static mbstate_t mbs;
+
+	if (ps == NULL)
+		ps = &mbs;
+	return (__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps));
+}
Index: /trunk/libc/src/fbsdlibc/locale/mbstowcs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mbstowcs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mbstowcs.c	(revision 2448)
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbstowcs.c,v 1.11 2004/07/21 10:54:57 tjr Exp $");
+
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(mbstowcs)(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
+{
+	static const mbstate_t initial;
+	mbstate_t mbs;
+
+	mbs = initial;
+	return (__mbsnrtowcs(pwcs, &s, SIZE_T_MAX, n, &mbs));
+}
Index: /trunk/libc/src/fbsdlibc/locale/mbtowc.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/mbtowc.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/mbtowc.c	(revision 2448)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbtowc.c,v 1.11 2004/07/29 06:18:40 tjr Exp $");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+_STD(mbtowc)(wchar_t * __restrict pwc, const char * __restrict s, size_t n)
+{
+	static const mbstate_t initial;
+	static mbstate_t mbs;
+	size_t rval;
+
+	if (s == NULL) {
+		/* No support for state dependent encodings. */
+		mbs = initial;
+		return (0);
+	}
+	rval = __mbrtowc(pwc, s, n, &mbs);
+	if (rval == (size_t)-1 || rval == (size_t)-2)
+		return (-1);
+	return ((int)rval);
+}
Index: /trunk/libc/src/fbsdlibc/locale/utf8.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/utf8.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/utf8.c	(revision 2448)
@@ -0,0 +1,443 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/param.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.11 2004/07/27 06:29:48 tjr Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#ifdef __INNOTEK_LIBC__
+#include <InnotekLIBC/locale.h>
+#else
+#include <runetype.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t	_UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
+	    mbstate_t * __restrict);
+int	_UTF8_mbsinit(const mbstate_t *);
+size_t	_UTF8_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
+	    size_t, size_t, mbstate_t * __restrict);
+size_t	_UTF8_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+size_t	_UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+	    size_t, size_t, mbstate_t * __restrict);
+
+typedef struct {
+	wchar_t	ch;
+	int	want;
+	wchar_t	lbound;
+} _UTF8State;
+
+#ifndef __INNOTEK_LIBC__
+int
+_UTF8_init(_RuneLocale *rl)
+{
+
+	__mbrtowc = _UTF8_mbrtowc;
+	__wcrtomb = _UTF8_wcrtomb;
+	__mbsinit = _UTF8_mbsinit;
+	__mbsnrtowcs = _UTF8_mbsnrtowcs;
+	__wcsnrtombs = _UTF8_wcsnrtombs;
+	_CurrentRuneLocale = rl;
+	__mb_cur_max = 6;
+
+	return (0);
+}
+#else
+void __libc_localeFuncsUTF8(__LIBC_PLOCALECTYPEFUNCS pFuncs)
+{
+    pFuncs->pfnmbsinit = _UTF8_mbsinit;
+    pFuncs->pfnmbrtowc = _UTF8_mbrtowc;
+    pFuncs->pfnmbsnrtowcs = _UTF8_mbsnrtowcs;
+    pFuncs->pfnwcrtomb = _UTF8_wcrtomb;
+    pFuncs->pfnwcsnrtombs = _UTF8_wcsnrtombs;
+}
+#endif /* __INNOTEK_LIBC__ */
+
+int
+_UTF8_mbsinit(const mbstate_t *ps)
+{
+
+	return (ps == NULL || ((const _UTF8State *)ps)->want == 0);
+}
+
+size_t
+_UTF8_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+    mbstate_t * __restrict ps)
+{
+	_UTF8State *us;
+	int ch, i, mask = 0, want;      /* bird: gcc shut */
+#ifdef __INNOTEK_LIBC__
+	wint_t lbound, wch;
+#else
+	wchar_t lbound, wch;
+#endif
+
+	us = (_UTF8State *)ps;
+
+	if (us->want < 0 || us->want > 6) {
+		errno = EINVAL;
+		return ((size_t)-1);
+	}
+
+	if (s == NULL) {
+		s = "";
+		n = 1;
+		pwc = NULL;
+	}
+
+	if (n == 0)
+		/* Incomplete multibyte sequence */
+		return ((size_t)-2);
+
+	if (us->want == 0 && ((ch = (unsigned char)*s) & ~0x7f) == 0) {
+		/* Fast path for plain ASCII characters. */
+		if (pwc != NULL)
+			*pwc = ch;
+		return (ch != '\0' ? 1 : 0);
+	}
+
+	if (us->want == 0) {
+		/*
+		 * Determine the number of octets that make up this character
+		 * from the first octet, and a mask that extracts the
+		 * interesting bits of the first octet. We already know
+		 * the character is at least two bytes long.
+		 *
+		 * We also specify a lower bound for the character code to
+		 * detect redundant, non-"shortest form" encodings. For
+		 * example, the sequence C0 80 is _not_ a legal representation
+		 * of the null character. This enforces a 1-to-1 mapping
+		 * between character codes and their multibyte representations.
+		 */
+		ch = (unsigned char)*s;
+		if ((ch & 0x80) == 0) {
+			mask = 0x7f;
+			want = 1;
+			lbound = 0;
+		} else if ((ch & 0xe0) == 0xc0) {
+			mask = 0x1f;
+			want = 2;
+			lbound = 0x80;
+		} else if ((ch & 0xf0) == 0xe0) {
+			mask = 0x0f;
+			want = 3;
+			lbound = 0x800;
+		} else if ((ch & 0xf8) == 0xf0) {
+			mask = 0x07;
+			want = 4;
+			lbound = 0x10000;
+		} else if ((ch & 0xfc) == 0xf8) {
+			mask = 0x03;
+			want = 5;
+			lbound = 0x200000;
+		} else if ((ch & 0xfc) == 0xfc) {
+			mask = 0x01;
+			want = 6;
+			lbound = 0x4000000;
+		} else {
+			/*
+			 * Malformed input; input is not UTF-8.
+			 */
+			errno = EILSEQ;
+			return ((size_t)-1);
+		}
+	} else {
+		want = us->want;
+		lbound = us->lbound;
+	}
+
+	/*
+	 * Decode the octet sequence representing the character in chunks
+	 * of 6 bits, most significant first.
+	 */
+	if (us->want == 0)
+		wch = (unsigned char)*s++ & mask;
+	else
+		wch = us->ch;
+	for (i = (us->want == 0) ? 1 : 0; i < MIN(want, n); i++) {
+		if ((*s & 0xc0) != 0x80) {
+			/*
+			 * Malformed input; bad characters in the middle
+			 * of a character.
+			 */
+			errno = EILSEQ;
+			return ((size_t)-1);
+		}
+		wch <<= 6;
+		wch |= *s++ & 0x3f;
+	}
+	if (i < want) {
+		/* Incomplete multibyte sequence. */
+		us->want = want - i;
+		us->lbound = lbound;
+		us->ch = wch;
+		return ((size_t)-2);
+	}
+	if (wch < lbound) {
+		/*
+		 * Malformed input; redundant encoding.
+		 */
+		errno = EILSEQ;
+		return ((size_t)-1);
+	}
+#ifdef __INNOTEK_LIBC__
+        if (wch > 0xffff || wch < 0)
+            wch = 0xffff;
+#endif
+	if (pwc != NULL)
+		*pwc = wch;
+	us->want = 0;
+	return (wch == L'\0' ? 0 : want);
+}
+
+size_t
+_UTF8_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+    size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+	_UTF8State *us;
+	const char *s;
+	size_t nchr;
+	wchar_t wc;
+	size_t nb;
+
+	us = (_UTF8State *)ps;
+
+	s = *src;
+	nchr = 0;
+
+	if (dst == NULL) {
+		/*
+		 * The fast path in the loop below is not safe if an ASCII
+		 * character appears as anything but the first byte of a
+		 * multibyte sequence. Check now to avoid doing it in the loop.
+		 */
+		if (nms > 0 && us->want > 0 && (signed char)*s > 0) {
+			errno = EILSEQ;
+			return ((size_t)-1);
+		}
+		for (;;) {
+			if (nms > 0 && (signed char)*s > 0)
+				/*
+				 * Fast path for plain ASCII characters
+				 * excluding NUL.
+				 */
+				nb = 1;
+			else if ((nb = _UTF8_mbrtowc(&wc, s, nms, ps)) ==
+			    (size_t)-1)
+				/* Invalid sequence - mbrtowc() sets errno. */
+				return ((size_t)-1);
+			else if (nb == 0 || nb == (size_t)-2)
+				return (nchr);
+			s += nb;
+			nms -= nb;
+			nchr++;
+		}
+		/*NOTREACHED*/
+	}
+
+	/*
+	 * The fast path in the loop below is not safe if an ASCII
+	 * character appears as anything but the first byte of a
+	 * multibyte sequence. Check now to avoid doing it in the loop.
+	 */
+	if (nms > 0 && len > 0 && us->want > 0 && (signed char)*s > 0) {
+		errno = EILSEQ;
+		return ((size_t)-1);
+	}
+	while (len-- > 0) {
+		if (nms > 0 && (signed char)*s > 0) {
+			/*
+			 * Fast path for plain ASCII characters
+			 * excluding NUL.
+			 */
+			*dst = (wchar_t)*s;
+			nb = 1;
+		} else if ((nb = _UTF8_mbrtowc(dst, s, nms, ps)) ==
+		    (size_t)-1) {
+			*src = s;
+			return ((size_t)-1);
+		} else if (nb == (size_t)-2) {
+			*src = s + nms;
+			return (nchr);
+		} else if (nb == 0) {
+			*src = NULL;
+			return (nchr);
+		}
+		s += nb;
+		nms -= nb;
+		nchr++;
+		dst++;
+	}
+	*src = s;
+	return (nchr);
+}
+
+size_t
+_UTF8_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+	_UTF8State *us;
+	unsigned char lead;
+	int i, len;
+
+	us = (_UTF8State *)ps;
+
+	if (us->want != 0) {
+		errno = EINVAL;
+		return ((size_t)-1);
+	}
+
+	if (s == NULL)
+		/* Reset to initial shift state (no-op) */
+		return (1);
+
+	if ((wc & ~0x7f) == 0) {
+		/* Fast path for plain ASCII characters. */
+		*s = (char)wc;
+		return (1);
+	}
+
+	/*
+	 * Determine the number of octets needed to represent this character.
+	 * We always output the shortest sequence possible. Also specify the
+	 * first few bits of the first octet, which contains the information
+	 * about the sequence length.
+	 */
+	if ((wc & ~0x7f) == 0) {
+		lead = 0;
+		len = 1;
+	} else if ((wc & ~0x7ff) == 0) {
+		lead = 0xc0;
+		len = 2;
+	} else if ((wc & ~0xffff) == 0) {
+		lead = 0xe0;
+		len = 3;
+	} else if ((wc & ~0x1fffff) == 0) {
+		lead = 0xf0;
+		len = 4;
+	} else if ((wc & ~0x3ffffff) == 0) {
+		lead = 0xf8;
+		len = 5;
+	} else if ((wc & ~0x7fffffff) == 0) {
+		lead = 0xfc;
+		len = 6;
+	} else {
+		errno = EILSEQ;
+		return ((size_t)-1);
+	}
+
+	/*
+	 * Output the octets representing the character in chunks
+	 * of 6 bits, least significant last. The first octet is
+	 * a special case because it contains the sequence length
+	 * information.
+	 */
+	for (i = len - 1; i > 0; i--) {
+		s[i] = (wc & 0x3f) | 0x80;
+		wc >>= 6;
+	}
+	*s = (wc & 0xff) | lead;
+
+	return (len);
+}
+
+size_t
+_UTF8_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+    size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+	_UTF8State *us;
+	char buf[MB_LEN_MAX];
+	const wchar_t *s;
+	size_t nbytes;
+	size_t nb;
+
+	us = (_UTF8State *)ps;
+
+	if (us->want != 0) {
+		errno = EINVAL;
+		return ((size_t)-1);
+	}
+
+	s = *src;
+	nbytes = 0;
+
+	if (dst == NULL) {
+		while (nwc-- > 0) {
+			if (/*0 <= *s &&*/ (unsigned)*s < 0x80)
+				/* Fast path for plain ASCII characters. */
+				nb = 1;
+			else if ((nb = _UTF8_wcrtomb(buf, *s, ps)) ==
+			    (size_t)-1)
+				/* Invalid character - wcrtomb() sets errno. */
+				return ((size_t)-1);
+			if (*s == L'\0')
+				return (nbytes + nb - 1);
+			s++;
+			nbytes += nb;
+		}
+		return (nbytes);
+	}
+
+	while (len > 0 && nwc-- > 0) {
+		if (/*0 <= *s &&*/ (unsigned)*s < 0x80) {
+			/* Fast path for plain ASCII characters. */
+			nb = 1;
+			*dst = *s;
+		} else if (len > (size_t)MB_CUR_MAX) {
+			/* Enough space to translate in-place. */
+			if ((nb = (int)_UTF8_wcrtomb(dst, *s, ps)) < 0) {
+				*src = s;
+				return ((size_t)-1);
+			}
+		} else {
+			/*
+			 * May not be enough space; use temp. buffer.
+			 */
+			if ((nb = (int)_UTF8_wcrtomb(buf, *s, ps)) < 0) {
+				*src = s;
+				return ((size_t)-1);
+			}
+			if (nb > (int)len)
+				/* MB sequence for character won't fit. */
+				break;
+			memcpy(dst, buf, nb);
+		}
+		if (*s == L'\0') {
+			*src = NULL;
+			return (nbytes + nb - 1);
+		}
+		s++;
+		dst += nb;
+		len -= nb;
+		nbytes += nb;
+	}
+	*src = s;
+	return (nbytes);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcrtomb.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcrtomb.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcrtomb.c	(revision 2448)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcrtomb.c,v 1.8 2004/05/12 14:09:04 tjr Exp $");
+
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(wcrtomb)(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+	static mbstate_t mbs;
+
+	if (ps == NULL)
+		ps = &mbs;
+	return (__wcrtomb(s, wc, ps));
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcsftime.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcsftime.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcsftime.c	(revision 2448)
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wchar.h>
+
+/*
+ * Convert date and time to a wide-character string.
+ *
+ * This is the wide-character counterpart of strftime(). So that we do not
+ * have to duplicate the code of strftime(), we convert the format string to
+ * multibyte, call strftime(), then convert the result back into wide
+ * characters.
+ *
+ * This technique loses in the presence of stateful multibyte encoding if any
+ * of the conversions in the format string change conversion state. When
+ * stateful encoding is implemented, we will need to reset the state between
+ * format specifications in the format string.
+ */
+size_t
+_STD(wcsftime)(wchar_t * __restrict wcs, size_t maxsize,
+    const wchar_t * __restrict format, const struct tm * __restrict timeptr)
+{
+	static const mbstate_t initial;
+	mbstate_t mbs;
+	char *dst, *dstp, *sformat;
+	size_t n, sflen;
+	int sverrno;
+
+	sformat = dst = NULL;
+
+	/*
+	 * Convert the supplied format string to a multibyte representation
+	 * for strftime(), which only handles single-byte characters.
+	 */
+	mbs = initial;
+	sflen = wcsrtombs(NULL, &format, 0, &mbs);
+	if (sflen == (size_t)-1)
+		goto error;
+	if ((sformat = malloc(sflen + 1)) == NULL)
+		goto error;
+	mbs = initial;
+	wcsrtombs(sformat, &format, sflen + 1, &mbs);
+
+	/*
+	 * Allocate memory for longest multibyte sequence that will fit
+	 * into the caller's buffer and call strftime() to fill it.
+	 * Then, copy and convert the result back into wide characters in
+	 * the caller's buffer.
+	 */
+	if (SIZE_T_MAX / MB_CUR_MAX <= maxsize) {
+		/* maxsize is prepostorously large - avoid int. overflow. */
+		errno = EINVAL;
+		goto error;
+	}
+	if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL)
+		goto error;
+	if (strftime(dst, maxsize, sformat, timeptr) == 0)
+		goto error;
+	dstp = dst;
+	mbs = initial;
+	n = mbsrtowcs(wcs, (const char **)&dstp, maxsize, &mbs);
+	if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
+		goto error;
+
+	free(sformat);
+	free(dst);
+	return (n);
+
+error:
+	sverrno = errno;
+	free(sformat);
+	free(dst);
+	errno = sverrno;
+	return (0);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcsnrtombs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcsnrtombs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcsnrtombs.c	(revision 2448)
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcsnrtombs.c,v 1.2 2004/07/22 02:57:29 tjr Exp $");
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(wcsnrtombs)(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc,
+    size_t len, mbstate_t * __restrict ps)
+{
+	static mbstate_t mbs;
+
+	if (ps == NULL)
+		ps = &mbs;
+	return (__wcsnrtombs(dst, src, nwc, len, ps));
+}
+
+size_t
+__wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
+    size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+	mbstate_t mbsbak;
+	char buf[MB_LEN_MAX];
+	const wchar_t *s;
+	size_t nbytes;
+	size_t nb;
+
+	s = *src;
+	nbytes = 0;
+
+	if (dst == NULL) {
+		while (nwc-- > 0) {
+			if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1)
+				/* Invalid character - wcrtomb() sets errno. */
+				return ((size_t)-1);
+			else if (*s == L'\0')
+				return (nbytes + nb - 1);
+			s++;
+			nbytes += nb;
+		}
+		return (nbytes);
+	}
+
+	while (len > 0 && nwc-- > 0) {
+		if (len > (size_t)MB_CUR_MAX) {
+			/* Enough space to translate in-place. */
+			if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) {
+				*src = s;
+				return ((size_t)-1);
+			}
+		} else {
+			/*
+			 * May not be enough space; use temp. buffer.
+			 *
+			 * We need to save a copy of the conversion state
+			 * here so we can restore it if the multibyte
+			 * character is too long for the buffer.
+			 */
+			mbsbak = *ps;
+			if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) {
+				*src = s;
+				return ((size_t)-1);
+			}
+			if (nb > (int)len) {
+				/* MB sequence for character won't fit. */
+				*ps = mbsbak;
+				break;
+			}
+			memcpy(dst, buf, nb);
+		}
+		if (*s == L'\0') {
+			*src = NULL;
+			return (nbytes + nb - 1);
+		}
+		s++;
+		dst += nb;
+		len -= nb;
+		nbytes += nb;
+	}
+	*src = s;
+	return (nbytes);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcsrtombs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcsrtombs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcsrtombs.c	(revision 2448)
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcsrtombs.c,v 1.6 2004/07/21 10:54:57 tjr Exp $");
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(wcsrtombs)(char * __restrict dst, const wchar_t ** __restrict src, size_t len,
+    mbstate_t * __restrict ps)
+{
+	static mbstate_t mbs;
+
+	if (ps == NULL)
+		ps = &mbs;
+	return (__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps));
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstod.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstod.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstod.c	(revision 2448)
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstod.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Convert a string to a double-precision number.
+ *
+ * This is the wide-character counterpart of strtod(). So that we do not
+ * have to duplicate the code of strtod() here, we convert the supplied
+ * wide character string to multibyte and call strtod() on the result.
+ * This assumes that the multibyte encoding is compatible with ASCII
+ * for at least the digits, radix character and letters.
+ */
+double
+_STD(wcstod)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
+{
+	static const mbstate_t initial;
+	mbstate_t mbs;
+	double val;
+	char *buf, *end;
+	const wchar_t *wcp;
+	size_t len;
+
+	while (iswspace(*nptr))
+		nptr++;
+
+	/*
+	 * Convert the supplied numeric wide char. string to multibyte.
+	 *
+	 * We could attempt to find the end of the numeric portion of the
+	 * wide char. string to avoid converting unneeded characters but
+	 * choose not to bother; optimising the uncommon case where
+	 * the input string contains a lot of text after the number
+	 * duplicates a lot of strtod()'s functionality and slows down the
+	 * most common cases.
+	 */
+	wcp = nptr;
+	mbs = initial;
+	if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) {
+		if (endptr != NULL)
+			*endptr = (wchar_t *)nptr;
+		return (0.0);
+	}
+	if ((buf = malloc(len + 1)) == NULL)
+		return (0.0);
+	mbs = initial;
+	wcsrtombs(buf, &wcp, len + 1, &mbs);
+
+	/* Let strtod() do most of the work for us. */
+	val = strtod(buf, &end);
+
+	/*
+	 * We only know where the number ended in the _multibyte_
+	 * representation of the string. If the caller wants to know
+	 * where it ended, count multibyte characters to find the
+	 * corresponding position in the wide char string.
+	 */
+	if (endptr != NULL)
+		/* XXX Assume each wide char is one byte. */
+		*endptr = (wchar_t *)nptr + (end - buf);
+
+	free(buf);
+
+	return (val);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstof.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstof.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstof.c	(revision 2448)
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2002, 2003 Tim J. Robbins
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstof.c,v 1.3 2004/04/07 09:47:56 tjr Exp $");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * See wcstod() for comments as to the logic used.
+ */
+float
+_STD(wcstof)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
+{
+	static const mbstate_t initial;
+	mbstate_t mbs;
+	float val;
+	char *buf, *end;
+	const wchar_t *wcp;
+	size_t len;
+
+	while (iswspace(*nptr))
+		nptr++;
+
+	wcp = nptr;
+	mbs = initial;
+	if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) {
+		if (endptr != NULL)
+			*endptr = (wchar_t *)nptr;
+		return (0.0);
+	}
+	if ((buf = malloc(len + 1)) == NULL)
+		return (0.0);
+	mbs = initial;
+	wcsrtombs(buf, &wcp, len + 1, &mbs);
+
+	val = strtof(buf, &end);
+
+	if (endptr != NULL)
+		*endptr = (wchar_t *)nptr + (end - buf);
+
+	free(buf);
+
+	return (val);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstoimax.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstoimax.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstoimax.c	(revision 2448)
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1992, 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.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "from @(#)strtol.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoimax.c,v 1.2 2003/01/01 18:48:43 schweikh Exp $");
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Convert a wide character string to an intmax_t integer.
+ */
+intmax_t
+_STD(wcstoimax)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+    int base)
+{
+	const wchar_t *s;
+	uintmax_t acc;
+	wchar_t c;
+	uintmax_t cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtoimax for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (iswspace(c));
+	if (c == L'-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == L'+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == L'0' && (*s == L'x' || *s == L'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == L'0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = neg ? (uintmax_t)-(INTMAX_MIN + INTMAX_MAX) + INTMAX_MAX
+	    : INTMAX_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+#ifdef notyet
+		if (iswdigit(c))
+			c = digittoint(c); /* bird: need w version. */
+		else
+#endif
+		if (c >= L'0' && c <= L'9')
+			c -= L'0';
+		else if (c >= L'A' && c <= L'Z')
+			c -= L'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= L'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? INTMAX_MIN : INTMAX_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstol.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstol.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstol.c	(revision 2448)
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 1990, 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.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstol.c,v 1.1 2002/09/08 13:27:26 tjr Exp $");
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Convert a string to a long integer.
+ */
+long
+_STD(wcstol)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+	const wchar_t *s;
+	unsigned long acc;
+	wchar_t c;
+	unsigned long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtol for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (iswspace(c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == L'+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == L'0' && (*s == L'x' || *s == L'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == L'0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
+	    : LONG_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+#ifdef notyet
+		if (iswdigit(c))
+			c = digittoint(c); /* bird: need w version. */
+		else
+#endif
+		if (c >= L'0' && c <= L'9')
+			c -= L'0';
+		else if (c >= L'A' && c <= L'Z')
+			c -= L'A' - 10;
+		else if (c >= L'a' && c <= L'z')
+			c -= L'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LONG_MIN : LONG_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstold.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstold.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstold.c	(revision 2448)
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2002, 2003 Tim J. Robbins
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstold.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * See wcstod() for comments as to the logic used.
+ */
+long double
+_STD(wcstold)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
+{
+	static const mbstate_t initial;
+	mbstate_t mbs;
+	long double val;
+	char *buf, *end;
+	const wchar_t *wcp;
+	size_t len;
+
+	while (iswspace(*nptr))
+		nptr++;
+
+	wcp = nptr;
+	mbs = initial;
+	if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) {
+		if (endptr != NULL)
+			*endptr = (wchar_t *)nptr;
+		return (0.0);
+	}
+	if ((buf = malloc(len + 1)) == NULL)
+		return (0.0);
+	mbs = initial;
+	wcsrtombs(buf, &wcp, len + 1, &mbs);
+
+	val = strtold(buf, &end);
+
+	if (endptr != NULL)
+		*endptr = (wchar_t *)nptr + (end - buf);
+
+	free(buf);
+
+	return (val);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstoll.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstoll.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstoll.c	(revision 2448)
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 1992, 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.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoq.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoll.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Convert a wide character string to a long long integer.
+ */
+long long
+_STD(wcstoll)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+	const wchar_t *s;
+	unsigned long long acc;
+	wchar_t c;
+	unsigned long long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtoll for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (iswspace(c));
+	if (c == L'-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == L'+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == L'0' && (*s == L'x' || *s == L'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == L'0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
+	    : LLONG_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+#ifdef notyet
+		if (iswdigit(c))
+			c = digittoint(c); /* bird: need w version! */
+		else
+#endif
+		if (c >= L'0' && c <= L'9')
+			c -= L'0';
+		else if (c >= L'A' && c <= L'Z')
+			c -= L'A' - 10;
+		else if (c >= L'a' && c <= L'z')
+			c -= L'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LLONG_MIN : LLONG_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstombs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstombs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstombs.c	(revision 2448)
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstombs.c,v 1.10 2004/07/21 10:54:57 tjr Exp $");
+
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+_STD(wcstombs)(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
+{
+	static const mbstate_t initial;
+	mbstate_t mbs;
+
+	mbs = initial;
+	return (__wcsnrtombs(s, &pwcs, SIZE_T_MAX, n, &mbs));
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstoul.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstoul.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstoul.c	(revision 2448)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1990, 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.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoul.c,v 1.1 2002/09/08 13:27:26 tjr Exp $");
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Convert a wide character string to an unsigned long integer.
+ */
+unsigned long
+_STD(wcstoul)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+	const wchar_t *s;
+	unsigned long acc;
+	wchar_t c;
+	unsigned long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtol for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (iswspace(c));
+	if (c == L'-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == L'+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == L'0' && (*s == L'x' || *s == L'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == L'0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = ULONG_MAX / base;
+	cutlim = ULONG_MAX % base;
+	for ( ; ; c = *s++) {
+#ifdef notyet
+		if (iswdigit(c))
+			c = digittoint(c);
+		else
+#endif
+		if (c >= L'0' && c <= L'9')
+			c -= L'0';
+		else if (c >= L'A' && c <= L'Z')
+			c -= L'A' - 10;
+		else if (c >= L'a' && c <= L'z')
+			c -= L'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULONG_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstoull.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstoull.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstoull.c	(revision 2448)
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 1992, 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.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtouq.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoull.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Convert a wide character string to an unsigned long long integer.
+ */
+unsigned long long
+_STD(wcstoull)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+    int base)
+{
+	const wchar_t *s;
+	unsigned long long acc;
+	wchar_t c;
+	unsigned long long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtoull for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (iswspace(c));
+	if (c == L'-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == L'+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == L'0' && (*s == L'x' || *s == L'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == L'0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = ULLONG_MAX / base;
+	cutlim = ULLONG_MAX % base;
+	for ( ; ; c = *s++) {
+#ifdef notyet
+		if (iswdigit(c))
+			c = digittoint(c);
+		else
+#endif
+		if (c >= L'0' && c <= L'9')
+			c -= L'0';
+		else if (c >= L'A' && c <= L'Z')
+			c -= L'A' - 10;
+		else if (c >= L'a' && c <= L'z')
+			c -= L'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULLONG_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wcstoumax.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wcstoumax.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wcstoumax.c	(revision 2448)
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 1992, 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.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "from @(#)strtoul.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoumax.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Convert a wide character string to a uintmax_t integer.
+ */
+uintmax_t
+_STD(wcstoumax)(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+    int base)
+{
+	const wchar_t *s;
+	uintmax_t acc;
+	wchar_t c;
+	uintmax_t cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtoimax for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (iswspace(c));
+	if (c == L'-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == L'+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == L'0' && (*s == L'x' || *s == L'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == L'0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = UINTMAX_MAX / base;
+	cutlim = UINTMAX_MAX % base;
+	for ( ; ; c = *s++) {
+#ifdef notyet
+		if (iswdigit(c))
+			c = digittoint(c);
+		else
+#endif
+		if (c >= L'0' && c <= L'9')
+			c -= L'0';
+		else if (c >= L'A' && c <= L'Z')
+			c -= L'A' - 10;
+		else if (c >= L'a' && c <= L'z')
+			c -= L'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = UINTMAX_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wctob.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wctob.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wctob.c	(revision 2448)
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wctob.c,v 1.4 2004/05/12 14:26:54 tjr Exp $");
+
+#include <limits.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+_STD(wctob)(wint_t c)
+{
+	static const mbstate_t initial;
+	mbstate_t mbs = initial;
+	char buf[MB_LEN_MAX];
+
+	if (c == WEOF || __wcrtomb(buf, c, &mbs) != 1)
+		return (EOF);
+	return ((unsigned char)*buf);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wctomb.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wctomb.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wctomb.c	(revision 2448)
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <InnoTekLIBC/locale.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wctomb.c,v 1.8 2004/07/29 06:18:40 tjr Exp $");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+_STD(wctomb)(char *s, wchar_t wchar)
+{
+	static const mbstate_t initial;
+	static mbstate_t mbs;
+	size_t rval;
+
+	if (s == NULL) {
+		/* No support for state dependent encodings. */
+		mbs = initial;
+		return (0);
+	}
+	if ((rval = __wcrtomb(s, wchar, &mbs)) == (size_t)-1)
+		return (-1);
+	return ((int)rval);
+}
Index: /trunk/libc/src/fbsdlibc/locale/wctrans.c
===================================================================
--- /trunk/libc/src/fbsdlibc/locale/wctrans.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/locale/wctrans.c	(revision 2448)
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/wctrans.c,v 1.3 2003/11/01 08:20:58 tjr Exp $");
+
+#include <errno.h>
+#include <string.h>
+#include <wctype.h>
+
+enum {
+	_WCT_ERROR	= 0,
+	_WCT_TOLOWER	= 1,
+	_WCT_TOUPPER	= 2
+};
+
+wint_t
+_STD(towctrans)(wint_t wc, wctrans_t desc)
+{
+
+	switch (desc) {
+	case _WCT_TOLOWER:
+		wc = towlower(wc);
+		break;
+	case _WCT_TOUPPER:
+		wc = towupper(wc);
+		break;
+	case _WCT_ERROR:
+	default:
+		errno = EINVAL;
+		break;
+	}
+
+	return (wc);
+}
+
+wctrans_t
+_STD(wctrans)(const char *charclass)
+{
+	struct {
+		const char	*name;
+		wctrans_t	 trans;
+	} ccls[] = {
+		{ "tolower",	_WCT_TOLOWER },
+		{ "toupper",	_WCT_TOUPPER },
+		{ NULL,		_WCT_ERROR },		/* Default */
+	};
+	int i;
+
+	i = 0;
+	while (ccls[i].name != NULL && strcmp(ccls[i].name, charclass) != 0)
+		i++;
+
+	if (ccls[i].trans == _WCT_ERROR)
+		errno = EINVAL;
+	return (ccls[i].trans);
+}
Index: /trunk/libc/src/fbsdlibc/net/net.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/net/net.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/net/net.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/fbsdlibc/net/*.c)
Index: /trunk/libc/src/fbsdlibc/net/nsdispatch.c
===================================================================
--- /trunk/libc/src/fbsdlibc/net/nsdispatch.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/net/nsdispatch.c	(revision 2448)
@@ -0,0 +1,649 @@
+/*	$NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * 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 NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/net/nsdispatch.c,v 1.12 2004/04/01 19:12:45 nectar Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#ifndef __EMX__
+#include <pthread.h>
+#else  /* bird: temporary hack. */
+#define _pthread_mutex_trylock(lock)    (*lock)
+#define _pthread_mutex_unlock(lock)     (*lock)
+#define _pthread_rwlock_rdlock(lock)    (*lock)
+#define _pthread_rwlock_wrlock(lock)    (*lock)
+#define _pthread_rwlock_unlock(lock)    (*lock)
+#define pthread_rwlock_t                unsigned
+#define PTHREAD_RWLOCK_INITIALIZER      0
+#define pthread_mutex_t                 unsigned
+#define PTHREAD_MUTEX_INITIALIZER       0
+#define  __isthreaded 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+enum _nss_constants {
+	/* Number of elements allocated when we grow a vector */
+	ELEMSPERCHUNK =	8
+};
+
+/*
+ * Global NSS data structures are mostly read-only, but we update
+ * them when we read or re-read the nsswitch.conf.
+ */
+static	pthread_rwlock_t	nss_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/*
+ * Runtime determination of whether we are dynamically linked or not.
+ */
+extern	int		_DYNAMIC __attribute__ ((weak));
+#define	is_dynamic()	(&_DYNAMIC != NULL)
+
+/*
+ * default sourcelist: `files'
+ */
+const ns_src __nsdefaultsrc[] = {
+	{ NSSRC_FILES, NS_SUCCESS },
+	{ 0 },
+};
+
+/* Database, source mappings. */
+static	unsigned int		 _nsmapsize;
+static	ns_dbt			*_nsmap = NULL;
+
+/* NSS modules. */
+static	unsigned int		 _nsmodsize;
+static	ns_mod			*_nsmod;
+
+/* Placeholder for builtin modules' dlopen `handle'. */
+static	int			 __nss_builtin_handle;
+static	void			*nss_builtin_handle = &__nss_builtin_handle;
+
+#ifdef __EMX__
+# define syslog(level, format, ...) do { } while (0)
+#endif
+
+/*
+ * Attempt to spew relatively uniform messages to syslog.
+ */
+#define nss_log(level, fmt, ...) \
+	syslog((level), "NSSWITCH(%s): " fmt, __func__, __VA_ARGS__)
+#define nss_log_simple(level, s) \
+	syslog((level), "NSSWITCH(%s): " s, __func__)
+
+/*
+ * Dynamically growable arrays are used for lists of databases, sources,
+ * and modules.  The following `vector' interface is used to isolate the
+ * common operations.
+ */
+typedef	int	(*vector_comparison)(const void *, const void *);
+typedef	void	(*vector_free_elem)(void *);
+static	void	  vector_sort(void *, unsigned int, size_t,
+		    vector_comparison);
+static	void	  vector_free(void *, unsigned int *, size_t,
+		    vector_free_elem);
+static	void	 *vector_ref(unsigned int, void *, unsigned int, size_t);
+static	void	 *vector_search(const void *, void *, unsigned int, size_t,
+		    vector_comparison);
+static	void	 *vector_append(const void *, void *, unsigned int *, size_t);
+
+
+/*
+ * Internal interfaces.
+ */
+static	int	 string_compare(const void *, const void *);
+static	int	 mtab_compare(const void *, const void *);
+static	int	 nss_configure(void);
+static	void	 ns_dbt_free(ns_dbt *);
+static	void	 ns_mod_free(ns_mod *);
+static	void	 ns_src_free(ns_src **, int);
+static	void	 nss_load_builtin_modules(void);
+static	void	 nss_load_module(const char *, nss_module_register_fn);
+static	void	 nss_atexit(void);
+/* nsparser */
+extern	FILE	*_nsyyin;
+
+
+/*
+ * The vector operations
+ */
+static void
+vector_sort(void *vec, unsigned int count, size_t esize,
+    vector_comparison comparison)
+{
+	qsort(vec, count, esize, comparison);
+}
+
+
+static void *
+vector_search(const void *key, void *vec, unsigned int count, size_t esize,
+    vector_comparison comparison)
+{
+	return (bsearch(key, vec, count, esize, comparison));
+}
+
+
+static void *
+vector_append(const void *elem, void *vec, unsigned int *count, size_t esize)
+{
+	void	*p;
+
+	if ((*count % ELEMSPERCHUNK) == 0) {
+		p = realloc(vec, (*count + ELEMSPERCHUNK) * esize);
+		if (p == NULL) {
+			nss_log_simple(LOG_ERR, "memory allocation failure");
+			return (vec);
+		}
+		vec = p;
+	}
+	memmove((void *)(((uintptr_t)vec) + (*count * esize)), elem, esize);
+	(*count)++;
+	return (vec);
+}
+
+
+static void *
+vector_ref(unsigned int i, void *vec, unsigned int count, size_t esize)
+{
+	if (i < count)
+		return (void *)((uintptr_t)vec + (i * esize));
+	else
+		return (NULL);
+}
+
+
+#define VECTOR_FREE(v, c, s, f) \
+	do { vector_free(v, c, s, f); v = NULL; } while (0)
+static void
+vector_free(void *vec, unsigned int *count, size_t esize,
+    vector_free_elem free_elem)
+{
+	unsigned int	 i;
+	void		*elem;
+
+	for (i = 0; i < *count; i++) {
+		elem = vector_ref(i, vec, *count, esize);
+		if (elem != NULL)
+			free_elem(elem);
+	}
+	free(vec);
+	*count = 0;
+}
+
+
+
+/*
+ * Comparison functions for vector_search.
+ */
+static int
+string_compare(const void *a, const void *b)
+{
+      return (strcasecmp(*(const char * const *)a, *(const char * const *)b));
+}
+
+
+static int
+mtab_compare(const void *a, const void *b)
+{
+      int     cmp;
+
+      cmp = strcmp(((const ns_mtab *)a)->name, ((const ns_mtab *)b)->name);
+      if (cmp != 0)
+	      return (cmp);
+      else
+	      return (strcmp(((const ns_mtab *)a)->database,
+		  ((const ns_mtab *)b)->database));
+}
+
+
+
+/*
+ * NSS nsmap management.
+ */
+void
+_nsdbtaddsrc(ns_dbt *dbt, const ns_src *src)
+{
+	const ns_mod	*modp;
+
+	dbt->srclist = vector_append(src, dbt->srclist, &dbt->srclistsize,
+	    sizeof(*src));
+	modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod),
+	    string_compare);
+	if (modp == NULL)
+		nss_load_module(src->name, NULL);
+}
+
+
+#ifdef _NSS_DEBUG
+void
+_nsdbtdump(const ns_dbt *dbt)
+{
+	int i;
+
+	printf("%s (%d source%s):", dbt->name, dbt->srclistsize,
+	    dbt->srclistsize == 1 ? "" : "s");
+	for (i = 0; i < (int)dbt->srclistsize; i++) {
+		printf(" %s", dbt->srclist[i].name);
+		if (!(dbt->srclist[i].flags &
+		    (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) &&
+		    (dbt->srclist[i].flags & NS_SUCCESS))
+			continue;
+		printf(" [");
+		if (!(dbt->srclist[i].flags & NS_SUCCESS))
+			printf(" SUCCESS=continue");
+		if (dbt->srclist[i].flags & NS_UNAVAIL)
+			printf(" UNAVAIL=return");
+		if (dbt->srclist[i].flags & NS_NOTFOUND)
+			printf(" NOTFOUND=return");
+		if (dbt->srclist[i].flags & NS_TRYAGAIN)
+			printf(" TRYAGAIN=return");
+		printf(" ]");
+	}
+	printf("\n");
+}
+#endif
+
+
+/*
+ * The first time nsdispatch is called (during a process's lifetime,
+ * or after nsswitch.conf has been updated), nss_configure will
+ * prepare global data needed by NSS.
+ */
+static int
+nss_configure(void)
+{
+	static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER;
+	static time_t	 confmod;
+	struct stat	 statbuf;
+	int		 result, isthreaded;
+	const char	*path;
+
+	result = 0;
+	isthreaded = __isthreaded;
+#if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT)
+	/* NOTE WELL:  THIS IS A SECURITY HOLE. This must only be built
+	 * for debugging purposes and MUST NEVER be used in production.
+	 */
+	path = getenv("NSSWITCH_CONF");
+	if (path == NULL)
+#endif
+	path = _PATH_NS_CONF;
+	if (stat(path, &statbuf) != 0)
+		return (0);
+	if (statbuf.st_mtime <= confmod)
+		return (0);
+	if (isthreaded) {
+	    result = _pthread_mutex_trylock(&conf_lock);
+	    if (result != 0)
+		    return (0);
+	    (void)_pthread_rwlock_unlock(&nss_lock);
+	    result = _pthread_rwlock_wrlock(&nss_lock);
+	    if (result != 0)
+		    goto fin2;
+	}
+	_nsyyin = fopen(path, "r");
+	if (_nsyyin == NULL)
+		goto fin;
+	VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
+	    (vector_free_elem)ns_dbt_free);
+	VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
+	    (vector_free_elem)ns_mod_free);
+	nss_load_builtin_modules();
+	_nsyyparse();
+	(void)fclose(_nsyyin);
+	vector_sort(_nsmap, _nsmapsize, sizeof(*_nsmap), string_compare);
+	if (confmod == 0)
+		(void)atexit(nss_atexit);
+	confmod = statbuf.st_mtime;
+fin:
+	if (isthreaded) {
+	    (void)_pthread_rwlock_unlock(&nss_lock);
+	    if (result == 0)
+		    result = _pthread_rwlock_rdlock(&nss_lock);
+	}
+fin2:
+	if (isthreaded)
+		(void)_pthread_mutex_unlock(&conf_lock);
+	return (result);
+}
+
+
+void
+_nsdbtput(const ns_dbt *dbt)
+{
+	unsigned int	 i;
+	ns_dbt		*p;
+
+	for (i = 0; i < _nsmapsize; i++) {
+		p = vector_ref(i, _nsmap, _nsmapsize, sizeof(*_nsmap));
+		if (string_compare(&dbt->name, &p->name) == 0) {
+			/* overwrite existing entry */
+			if (p->srclist != NULL)
+				ns_src_free(&p->srclist, p->srclistsize);
+			memmove(p, dbt, sizeof(*dbt));
+			return;
+		}
+	}
+	_nsmap = vector_append(dbt, _nsmap, &_nsmapsize, sizeof(*_nsmap));
+}
+
+
+static void
+ns_dbt_free(ns_dbt *dbt)
+{
+	ns_src_free(&dbt->srclist, dbt->srclistsize);
+}
+
+
+static void
+ns_src_free(ns_src **src, int srclistsize)
+{
+	int	i;
+
+	for (i = 0; i < srclistsize; i++)
+		if ((*src)[i].name != NULL)
+			/* This one was allocated by nslexer. You'll just
+			 * have to trust me.
+			 */
+			free((void *)((*src)[i].name));
+	free(*src);
+	*src = NULL;
+}
+
+
+
+/*
+ * NSS module management.
+ */
+/* The built-in NSS modules are all loaded at once. */
+#define NSS_BACKEND(name, reg) \
+ns_mtab	*reg(unsigned int *, nss_module_unregister_fn *);
+#include "nss_backends.h"
+#undef NSS_BACKEND
+
+static void
+nss_load_builtin_modules(void)
+{
+#define NSS_BACKEND(name, reg) nss_load_module(#name, reg);
+#include "nss_backends.h"
+#undef NSS_BACKEND
+}
+
+
+/* Load a built-in or dynamically linked module.  If the `reg_fn'
+ * argument is non-NULL, assume a built-in module and use reg_fn to
+ * register it.  Otherwise, search for a dynamic NSS module.
+ */
+static void
+nss_load_module(const char *source, nss_module_register_fn reg_fn)
+{
+	char		 buf[PATH_MAX];
+	ns_mod		 mod;
+	nss_module_register_fn fn;
+
+	memset(&mod, 0, sizeof(mod));
+	mod.name = strdup(source);
+	if (mod.name == NULL) {
+		nss_log_simple(LOG_ERR, "memory allocation failure");
+		return;
+	}
+	if (reg_fn != NULL) {
+		/* The placeholder is required, as a NULL handle
+		 * represents an invalid module.
+		 */
+		mod.handle = nss_builtin_handle;
+		fn = reg_fn;
+	} else if (!is_dynamic())
+		goto fin;
+	else {
+#ifndef __EMX__
+		if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name,
+		    NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf))
+#else
+		if (snprintf(buf, sizeof(buf), "nss%.5s.dll", mod.name) >= (int)sizeof(buf))
+#endif
+			goto fin;
+		mod.handle = dlopen(buf, RTLD_LOCAL|RTLD_LAZY);
+		if (mod.handle == NULL) {
+#ifdef _NSS_DEBUG
+			/* This gets pretty annoying since the built-in
+			 * sources aren't modules yet.
+			 */
+			nss_log(LOG_DEBUG, "%s, %s", mod.name, dlerror());
+#endif
+			goto fin;
+		}
+		fn = (nss_module_register_fn)dlfunc(mod.handle,
+		    "nss_module_register");
+		if (fn == NULL) {
+			(void)dlclose(mod.handle);
+			mod.handle = NULL;
+			nss_log(LOG_ERR, "%s, %s", mod.name, dlerror());
+			goto fin;
+		}
+	}
+	mod.mtab = fn(mod.name, &mod.mtabsize, &mod.unregister);
+	if (mod.mtab == NULL || mod.mtabsize == 0) {
+		if (mod.handle != nss_builtin_handle)
+			(void)dlclose(mod.handle);
+		mod.handle = NULL;
+		nss_log(LOG_ERR, "%s, registration failed", mod.name);
+		goto fin;
+	}
+	if (mod.mtabsize > 1)
+		qsort(mod.mtab, mod.mtabsize, sizeof(mod.mtab[0]),
+		    mtab_compare);
+fin:
+	_nsmod = vector_append(&mod, _nsmod, &_nsmodsize, sizeof(*_nsmod));
+	vector_sort(_nsmod, _nsmodsize, sizeof(*_nsmod), string_compare);
+}
+
+
+
+static void
+ns_mod_free(ns_mod *mod)
+{
+
+	free(mod->name);
+	if (mod->handle == NULL)
+		return;
+	if (mod->unregister != NULL)
+		mod->unregister(mod->mtab, mod->mtabsize);
+	if (mod->handle != nss_builtin_handle)
+		(void)dlclose(mod->handle);
+}
+
+
+
+/*
+ * Cleanup
+ */
+static void
+nss_atexit(void)
+{
+	int isthreaded;
+
+	isthreaded = __isthreaded;
+	if (isthreaded)
+		(void)_pthread_rwlock_wrlock(&nss_lock);
+	VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
+	    (vector_free_elem)ns_dbt_free);
+	VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
+	    (vector_free_elem)ns_mod_free);
+	if (isthreaded)
+		(void)_pthread_rwlock_unlock(&nss_lock);
+}
+
+
+
+/*
+ * Finally, the actual implementation.
+ */
+static nss_method
+nss_method_lookup(const char *source, const char *database,
+    const char *method, const ns_dtab disp_tab[], void **mdata)
+{
+	ns_mod	*mod;
+	ns_mtab	*match, key;
+	int	 i;
+
+	if (disp_tab != NULL)
+		for (i = 0; disp_tab[i].src != NULL; i++)
+			if (strcasecmp(source, disp_tab[i].src) == 0) {
+				*mdata = disp_tab[i].mdata;
+				return (disp_tab[i].method);
+			}
+	mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod),
+	    string_compare);
+	if (mod != NULL && mod->handle != NULL) {
+		key.database = database;
+		key.name = method;
+		match = bsearch(&key, mod->mtab, mod->mtabsize,
+		    sizeof(mod->mtab[0]), mtab_compare);
+		if (match != NULL) {
+			*mdata = match->mdata;
+			return (match->method);
+		}
+	}
+	if (is_dynamic())
+		nss_log(LOG_DEBUG, "%s, %s, %s, not found", source, database,
+		    method);
+	*mdata = NULL;
+	return (NULL);
+}
+
+
+__weak_reference(_nsdispatch, nsdispatch);
+
+int
+_nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
+	    const char *method_name, const ns_src defaults[], ...)
+{
+	va_list		 ap;
+	const ns_dbt	*dbt;
+	const ns_src	*srclist;
+	nss_method	 method;
+	void		*mdata;
+	int		 isthreaded, serrno, i, result, srclistsize;
+
+	isthreaded = __isthreaded;
+	serrno = errno;
+	if (isthreaded) {
+		result = _pthread_rwlock_rdlock(&nss_lock);
+		if (result != 0) {
+			result = NS_UNAVAIL;
+			goto fin;
+		}
+	}
+	result = nss_configure();
+	if (result != 0) {
+		result = NS_UNAVAIL;
+		goto fin;
+	}
+	dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap),
+	    string_compare);
+	if (dbt != NULL) {
+		srclist = dbt->srclist;
+		srclistsize = dbt->srclistsize;
+	} else {
+		srclist = defaults;
+		srclistsize = 0;
+		while (srclist[srclistsize].name != NULL)
+			srclistsize++;
+	}
+	for (i = 0; i < srclistsize; i++) {
+		result = NS_NOTFOUND;
+		method = nss_method_lookup(srclist[i].name, database,
+		    method_name, disp_tab, &mdata);
+		if (method != NULL) {
+			va_start(ap, defaults);
+			result = method(retval, mdata, ap);
+			va_end(ap);
+			if (result & (srclist[i].flags))
+				break;
+		}
+	}
+	if (isthreaded)
+		(void)_pthread_rwlock_unlock(&nss_lock);
+fin:
+	errno = serrno;
+	return (result);
+}
Index: /trunk/libc/src/fbsdlibc/net/nslexer.c
===================================================================
--- /trunk/libc/src/fbsdlibc/net/nslexer.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/net/nslexer.c	(revision 2448)
@@ -0,0 +1,1749 @@
+#define yy_create_buffer _nsyy_create_buffer
+#define yy_delete_buffer _nsyy_delete_buffer
+#define yy_scan_buffer _nsyy_scan_buffer
+#define yy_scan_string _nsyy_scan_string
+#define yy_scan_bytes _nsyy_scan_bytes
+#define yy_flex_debug _nsyy_flex_debug
+#define yy_init_buffer _nsyy_init_buffer
+#define yy_flush_buffer _nsyy_flush_buffer
+#define yy_load_buffer_state _nsyy_load_buffer_state
+#define yy_switch_to_buffer _nsyy_switch_to_buffer
+#define yyin _nsyyin
+#define yyleng _nsyyleng
+#define yylex _nsyylex
+#define yyout _nsyyout
+#define yyrestart _nsyyrestart
+#define yytext _nsyytext
+#define yylineno _nsyylineno
+#define yywrap _nsyywrap
+
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header$
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#ifdef __CRTRSXNT__
+#include <crtrsxnt.h>
+#endif
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 1024
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ * 	if ( condition_holds )
+ *		yyless( 5 );
+ *	else
+ *		do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		*yy_cp = yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+	};
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define YY_USES_REJECT
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern int yylineno;
+int yylineno = 1;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yytext_ptr = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 13
+#define YY_END_OF_BUFFER 14
+static yyconst short int yy_acclist[83] =
+    {   0,
+       14,   12,   13,    1,   12,   13,    4,   13,    2,   12,
+       13,   11,   12,   13,   11,   12,   13,   11,   12,   13,
+       11,   12,   13,   11,   12,   13,   11,   12,   13,   11,
+       12,   13,   12,   13,    1,    2,   11,   11,   11,   11,
+       11,   11,   11,    3,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,    9,   11,   11,   11,   11,   11,
+       11,    5,   11,   11,    6,   11,   10,   11,    7,   11,
+        8,   11
+    } ;
+
+static yyconst short int yy_accept[60] =
+    {   0,
+        1,    1,    1,    2,    4,    7,    9,   12,   15,   18,
+       21,   24,   27,   30,   33,   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,   67,   68,   69,   70,
+       71,   72,   74,   75,   77,   79,   81,   83,   83
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    1,    4,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    1,    1,    1,
+        1,    1,    1,    1,    6,    7,    8,    9,   10,   11,
+       12,    7,   13,    7,    7,   14,    7,   15,   16,    7,
+        7,   17,   18,   19,   20,   21,    7,    7,   22,    7,
+        1,   23,    1,    1,    5,    1,    6,    7,    8,    9,
+
+       10,   11,   12,    7,   13,    7,    7,   14,    7,   15,
+       16,    7,    7,   17,   18,   19,   20,   21,    7,    7,
+       22,    7,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[24] =
+    {   0,
+        1,    1,    2,    1,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    1
+    } ;
+
+static yyconst short int yy_base[61] =
+    {   0,
+        0,    0,   68,   69,   65,   69,    0,    0,   50,   49,
+       54,   43,   45,   46,   57,   57,    0,    0,   43,   38,
+       37,   47,   32,   47,   69,   33,   40,   30,   41,   42,
+       26,   33,   29,   27,   33,   30,   35,   25,   19,   23,
+       19,   30,   22,   14,   18,    0,   14,   18,   16,   19,
+       19,    0,   12,    0,    0,    0,    0,   69,   23,   22
+    } ;
+
+static yyconst short int yy_def[61] =
+    {   0,
+       58,    1,   58,   58,   58,   58,   59,   60,   60,   60,
+       60,   60,   60,   60,   58,   58,   59,   60,   60,   60,
+       60,   60,   60,   60,   58,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,    0,   58,   58
+    } ;
+
+static yyconst short int yy_nxt[93] =
+    {   0,
+        4,    5,    6,    7,    4,    8,    8,    9,    8,    8,
+        8,    8,    8,    8,   10,    8,   11,   12,   13,   14,
+        8,    8,   15,   17,   18,   17,   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,   16,   25,
+       24,   23,   22,   21,   20,   19,   16,   58,    3,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58
+
+    } ;
+
+static yyconst short int yy_chk[93] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,   59,   60,   59,   53,   51,   50,   49,
+       48,   47,   45,   44,   43,   42,   41,   40,   39,   38,
+       37,   36,   35,   34,   33,   32,   31,   30,   29,   28,
+       27,   26,   24,   23,   22,   21,   20,   19,   16,   15,
+       14,   13,   12,   11,   10,    9,    5,    3,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58
+
+    } ;
+
+static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
+static char *yy_full_match;
+static int yy_lp;
+#define REJECT \
+{ \
+*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yy_full_match; /* restore poss. backed-over text */ \
+++yy_lp; \
+goto find_rule; \
+}
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "nslexer.l"
+#define INITIAL 0
+#line 2 "nslexer.l"
+/*	$NetBSD: nslexer.l,v 1.3 1999/01/25 00:16:17 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * 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 NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid =
+  "$FreeBSD: src/lib/libc/net/nslexer.l,v 1.5 2003/04/17 14:14:22 nectar Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+#include <ctype.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+#include "nsparser.h"
+
+#define YY_NO_UNPUT
+
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( yy_current_buffer->yy_is_interactive ) \
+		{ \
+		int c = '*', n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+		  && ferror( yyin ) ) \
+		YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+YY_DECL
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+
+#line 66 "nslexer.l"
+
+
+
+	if ( yy_init )
+		{
+		yy_init = 0;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yy_start )
+			yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! yy_current_buffer )
+			yy_current_buffer =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+
+		yy_load_buffer_state();
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yy_start;
+		yy_state_ptr = yy_state_buf;
+		*yy_state_ptr++ = yy_current_state;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 59 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			*yy_state_ptr++ = yy_current_state;
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 69 );
+
+yy_find_action:
+		yy_current_state = *--yy_state_ptr;
+		yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+		for ( ; ; ) /* until we find what rule we matched */
+			{
+			if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )
+				{
+				yy_act = yy_acclist[yy_lp];
+					{
+					yy_full_match = yy_cp;
+					break;
+					}
+				}
+			--yy_cp;
+			yy_current_state = *--yy_state_ptr;
+			yy_lp = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					++yylineno;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 68 "nslexer.l"
+;			/* skip whitespace */
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 70 "nslexer.l"
+;			/* skip comments */
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 72 "nslexer.l"
+;			/* allow continuation */
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 74 "nslexer.l"
+return NL;
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 76 "nslexer.l"
+return SUCCESS;
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 77 "nslexer.l"
+return UNAVAIL;
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 78 "nslexer.l"
+return NOTFOUND;
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 79 "nslexer.l"
+return TRYAGAIN;
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 81 "nslexer.l"
+return RETURN;
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 82 "nslexer.l"
+return CONTINUE;
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 84 "nslexer.l"
+{
+			char *p;
+			int i;
+
+			if ((p = strdup(yytext)) == NULL) {
+#ifndef __EMX__
+				syslog(LOG_ERR,
+			       "NSSWITCH(nslexer): memory allocation failure");
+#endif
+				return ERRORTOKEN;
+			}
+			for (i = 0; i < strlen(p); i++) {
+				if (isupper((unsigned char)p[i]))
+					p[i] = tolower((unsigned char)p[i]);
+			}
+			_nsyylval.str = p;
+			return STRING;
+		}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 101 "nslexer.l"
+return yytext[0];
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 103 "nslexer.l"
+ECHO;
+	YY_BREAK
+			case YY_STATE_EOF(INITIAL):
+				yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between yy_current_buffer and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yy_n_chars = yy_current_buffer->yy_n_chars;
+			yy_current_buffer->yy_input_file = yyin;
+			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state();
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer() )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap() )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yy_c_buf_p =
+					yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yy_c_buf_p =
+				&yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+	{
+	register char *dest = yy_current_buffer->yy_ch_buf;
+	register char *source = yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( yy_current_buffer->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+	else
+		{
+		int num_to_read =
+			yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+			YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = yy_current_buffer;
+
+			int yy_c_buf_p_offset =
+				(int) (yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yy_flex_realloc( (void *) b->yy_ch_buf,
+							 b->yy_buf_size + 2 );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = yy_current_buffer->yy_buf_size -
+						number_to_move - 1;
+#endif
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+			yy_n_chars, num_to_read );
+
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	if ( yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			yy_current_buffer->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	yy_n_chars += number_to_move;
+	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+	return ret_val;
+	}
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+
+	yy_current_state = yy_start;
+	yy_state_ptr = yy_state_buf;
+	*yy_state_ptr++ = yy_current_state;
+
+	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 59 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		*yy_state_ptr++ = yy_current_state;
+		}
+
+	return yy_current_state;
+	}
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+	{
+	register int yy_is_jam;
+
+	register YY_CHAR yy_c = 1;
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 59 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 58);
+	if ( ! yy_is_jam )
+		*yy_state_ptr++ = yy_current_state;
+
+	return yy_is_jam ? 0 : yy_current_state;
+	}
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+	{
+	register char *yy_cp = yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yy_hold_char;
+
+	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = yy_n_chars + 2;
+		register char *dest = &yy_current_buffer->yy_ch_buf[
+					yy_current_buffer->yy_buf_size + 2];
+		register char *source =
+				&yy_current_buffer->yy_ch_buf[number_to_move];
+
+		while ( source > yy_current_buffer->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		yy_current_buffer->yy_n_chars =
+			yy_n_chars = yy_current_buffer->yy_buf_size;
+
+		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	if ( c == '\n' )
+		--yylineno;
+
+	yytext_ptr = yy_bp;
+	yy_hold_char = *yy_cp;
+	yy_c_buf_p = yy_cp;
+	}
+#endif	/* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+	{
+	int c;
+
+	*yy_c_buf_p = yy_hold_char;
+
+	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			/* This was really a NUL. */
+			*yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yy_c_buf_p - yytext_ptr;
+			++yy_c_buf_p;
+
+			switch ( yy_get_next_buffer() )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/* fall through */
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap() )
+						return EOF;
+
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yy_c_buf_p = yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
+	*yy_c_buf_p = '\0';	/* preserve yytext */
+	yy_hold_char = *++yy_c_buf_p;
+
+	if ( c == '\n' )
+		++yylineno;
+
+	return c;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+	{
+	if ( ! yy_current_buffer )
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+	yy_init_buffer( yy_current_buffer, input_file );
+	yy_load_buffer_state();
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+	{
+	if ( yy_current_buffer == new_buffer )
+		return;
+
+	if ( yy_current_buffer )
+		{
+		/* Flush out information for old buffer. */
+		*yy_c_buf_p = yy_hold_char;
+		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	yy_current_buffer = new_buffer;
+	yy_load_buffer_state();
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yy_did_buffer_switch_on_eof = 1;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+	{
+	yy_n_chars = yy_current_buffer->yy_n_chars;
+	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+	yyin = yy_current_buffer->yy_input_file;
+	yy_hold_char = *yy_c_buf_p;
+	}
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+	{
+	if ( ! b )
+		return;
+
+	if ( b == yy_current_buffer )
+		yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yy_flex_free( (void *) b->yy_ch_buf );
+
+	yy_flex_free( (void *) b );
+	}
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+	{
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+	b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+	b->yy_is_interactive = 0;
+#else
+	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+	{
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == yy_current_buffer )
+		yy_load_buffer_state();
+	}
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer( b );
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+	{
+	int len;
+	for ( len = 0; yy_str[len]; ++len )
+		;
+
+	return yy_scan_bytes( yy_str, len );
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+	{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = len + 2;
+	buf = (char *) yy_flex_alloc( n );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < len; ++i )
+		buf[i] = bytes[i];
+
+	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer( buf, n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+	{
+	if ( yy_start_stack_ptr >= yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yy_start_stack_depth * sizeof( int );
+
+		if ( ! yy_start_stack )
+			yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+		else
+			yy_start_stack = (int *) yy_flex_realloc(
+					(void *) yy_start_stack, new_size );
+
+		if ( ! yy_start_stack )
+			YY_FATAL_ERROR(
+			"out of memory expanding start-condition stack" );
+		}
+
+	yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+	}
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+	{
+	if ( --yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yy_start_stack[yy_start_stack_ptr]);
+	}
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+	{
+	return yy_start_stack[yy_start_stack_ptr - 1];
+	}
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+	{
+	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+	}
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		yytext[yyleng] = yy_hold_char; \
+		yy_c_buf_p = yytext + n; \
+		yy_hold_char = *yy_c_buf_p; \
+		*yy_c_buf_p = '\0'; \
+		yyleng = n; \
+		} \
+	while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+	{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+	}
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+	{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+	}
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+	{
+	return (void *) malloc( size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+	{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+	{
+	free( ptr );
+	}
+
+#if YY_MAIN
+int main()
+	{
+	yylex();
+	return 0;
+	}
+#endif
+#line 103 "nslexer.l"
+
+
+#undef _nsyywrap
+int
+_nsyywrap()
+{
+	return 1;
+} /* _nsyywrap */
+
+void
+_nsyyerror(msg)
+	const char *msg;
+{
+#ifndef __EMX__
+	 syslog(LOG_ERR, "NSSWITCH(nslexer): %s line %d: %s at '%s'",
+	     _PATH_NS_CONF, yylineno, msg, yytext);
+#endif
+} /* _nsyyerror */
+#ifndef BISON_NSPARSER_H
+# define BISON_NSPARSER_H
+
+#ifndef YYSTYPE
+typedef union {
+	char *str;
+	int   mapval;
+} yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+# define	NL	257
+# define	SUCCESS	258
+# define	UNAVAIL	259
+# define	NOTFOUND	260
+# define	TRYAGAIN	261
+# define	RETURN	262
+# define	CONTINUE	263
+# define	ERRORTOKEN	264
+# define	STRING	265
+
+
+extern YYSTYPE _nsyylval;
+
+#endif /* not BISON_NSPARSER_H */
Index: /trunk/libc/src/fbsdlibc/net/nslexer.l
===================================================================
--- /trunk/libc/src/fbsdlibc/net/nslexer.l	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/net/nslexer.l	(revision 2448)
@@ -0,0 +1,122 @@
+%{
+/*	$NetBSD: nslexer.l,v 1.3 1999/01/25 00:16:17 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * 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 NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid =
+  "$FreeBSD: src/lib/libc/net/nslexer.l,v 1.5 2003/04/17 14:14:22 nectar Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+#include <ctype.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+#include "nsparser.h"
+
+#define YY_NO_UNPUT
+
+%}
+
+%option yylineno
+
+BLANK		[ \t]
+CR		\n
+STRING		[a-zA-Z][a-zA-Z0-9_]*
+
+%%
+
+{BLANK}+	;			/* skip whitespace */
+
+#.*		;			/* skip comments */
+
+\\{CR}		;			/* allow continuation */
+
+{CR}		return NL;
+
+[sS][uU][cC][cC][eE][sS][sS]		return SUCCESS;
+[uU][nN][aA][vV][aA][iI][lL]		return UNAVAIL;
+[nN][oO][tT][fF][oO][uU][nN][dD]	return NOTFOUND;
+[tT][rR][yY][aA][gG][aA][iI][nN]	return TRYAGAIN;
+
+[rR][eE][tT][uU][rR][nN]		return RETURN;
+[cC][oO][nN][tT][iI][nN][uU][eE]	return CONTINUE;
+
+{STRING}	{
+			char *p;
+			int i;
+
+			if ((p = strdup(yytext)) == NULL) {
+#ifndef __EMX__
+				syslog(LOG_ERR,
+			       "NSSWITCH(nslexer): memory allocation failure");
+#endif
+				return ERRORTOKEN;
+			}
+			for (i = 0; i < strlen(p); i++) {
+				if (isupper((unsigned char)p[i]))
+					p[i] = tolower((unsigned char)p[i]);
+			}
+			_nsyylval.str = p;
+			return STRING;
+		}
+
+.		return yytext[0];
+
+%%
+
+#undef _nsyywrap
+int
+_nsyywrap()
+{
+	return 1;
+} /* _nsyywrap */
+
+void
+_nsyyerror(msg)
+	const char *msg;
+{
+#ifndef __EMX__
+	 syslog(LOG_ERR, "NSSWITCH(nslexer): %s line %d: %s at '%s'",
+	     _PATH_NS_CONF, yylineno, msg, yytext);
+#endif
+} /* _nsyyerror */
Index: /trunk/libc/src/fbsdlibc/net/nsparser.c
===================================================================
--- /trunk/libc/src/fbsdlibc/net/nsparser.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/net/nsparser.c	(revision 2448)
@@ -0,0 +1,1289 @@
+/* A Bison parser, made from nsparser.y
+   by GNU bison 1.35.  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+#define yyparse _nsyyparse
+#define yylex _nsyylex
+#define yyerror _nsyyerror
+#define yylval _nsyylval
+#define yychar _nsyychar
+#define yydebug _nsyydebug
+#define yynerrs _nsyynerrs
+# define	NL	257
+# define	SUCCESS	258
+# define	UNAVAIL	259
+# define	NOTFOUND	260
+# define	TRYAGAIN	261
+# define	RETURN	262
+# define	CONTINUE	263
+# define	ERRORTOKEN	264
+# define	STRING	265
+
+#line 1 "nsparser.y"
+
+/*	$NetBSD: nsparser.y,v 1.3 1999/01/25 00:16:18 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * 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 NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/net/nsparser.y,v 1.4 2003/04/17 14:14:22 nectar Exp $");
+
+#include "namespace.h"
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+static	void	_nsaddsrctomap(const char *);
+
+static	ns_dbt		curdbt;
+static	ns_src		cursrc;
+
+#line 57 "nsparser.y"
+#ifndef YYSTYPE
+typedef union {
+	char *str;
+	int   mapval;
+} yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+
+
+#define	YYFINAL		33
+#define	YYFLAG		-32768
+#define	YYNTBASE	16
+
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
+#define YYTRANSLATE(x) ((unsigned)(x) <= 265 ? yytranslate[x] : 27)
+
+/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */
+static const char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    12,     2,
+       2,    15,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    13,     2,    14,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     3,     4,     5,
+       6,     7,     8,     9,    10,    11
+};
+
+#if YYDEBUG
+static const short yyprhs[] =
+{
+       0,     0,     1,     3,     5,     8,    10,    14,    19,    22,
+      24,    26,    29,    31,    32,    38,    40,    43,    47,    49,
+      51,    53,    55,    57
+};
+static const short yyrhs[] =
+{
+      -1,    17,     0,    18,     0,    17,    18,     0,     3,     0,
+      19,    12,     3,     0,    19,    12,    20,     3,     0,     1,
+       3,     0,    11,     0,    21,     0,    20,    21,     0,    11,
+       0,     0,    11,    13,    22,    23,    14,     0,    24,     0,
+      23,    24,     0,    25,    15,    26,     0,     4,     0,     5,
+       0,     6,     0,     7,     0,     8,     0,     9,     0
+};
+
+#endif
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const short yyrline[] =
+{
+       0,    73,    74,    78,    79,    83,    84,    85,    89,    96,
+     105,   106,   110,   115,   115,   122,   123,   127,   137,   138,
+     139,   140,   144,   145
+};
+#endif
+
+
+#if (YYDEBUG) || defined YYERROR_VERBOSE
+
+/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */
+static const char *const yytname[] =
+{
+  "$", "error", "$undefined.", "NL", "SUCCESS", "UNAVAIL", "NOTFOUND", 
+  "TRYAGAIN", "RETURN", "CONTINUE", "ERRORTOKEN", "STRING", "':'", "'['", 
+  "']'", "'='", "File", "Lines", "Entry", "Database", "Srclist", "Item", 
+  "@1", "Criteria", "Criterion", "Status", "Action", 0
+};
+#endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const short yyr1[] =
+{
+       0,    16,    16,    17,    17,    18,    18,    18,    18,    19,
+      20,    20,    21,    22,    21,    23,    23,    24,    25,    25,
+      25,    25,    26,    26
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const short yyr2[] =
+{
+       0,     0,     1,     1,     2,     1,     3,     4,     2,     1,
+       1,     2,     1,     0,     5,     1,     2,     3,     1,     1,
+       1,     1,     1,     1
+};
+
+/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
+   doesn't specify something else to do.  Zero means the default is an
+   error. */
+static const short yydefact[] =
+{
+       0,     0,     5,     9,     0,     3,     0,     8,     4,     0,
+       6,    12,     0,    10,    13,     7,    11,     0,    18,    19,
+      20,    21,     0,    15,     0,    14,    16,     0,    22,    23,
+      17,     0,     0,     0
+};
+
+static const short yydefgoto[] =
+{
+      31,     4,     5,     6,    12,    13,    17,    22,    23,    24,
+      30
+};
+
+static const short yypact[] =
+{
+       0,     5,-32768,-32768,     4,-32768,    -3,-32768,-32768,    -1,
+  -32768,    11,     3,-32768,-32768,-32768,-32768,    16,-32768,-32768,
+  -32768,-32768,    12,-32768,    -2,-32768,-32768,    19,-32768,-32768,
+  -32768,    25,    29,-32768
+};
+
+static const short yypgoto[] =
+{
+  -32768,-32768,     8,-32768,-32768,    18,-32768,-32768,     9,-32768,
+  -32768
+};
+
+
+#define	YYLAST		31
+
+
+static const short yytable[] =
+{
+      -1,     1,    10,     2,    -2,     1,    15,     2,     7,     9,
+      11,     3,     8,    27,    11,     3,    18,    19,    20,    21,
+      18,    19,    20,    21,    14,    32,    25,    28,    29,    33,
+      16,    26
+};
+
+static const short yycheck[] =
+{
+       0,     1,     3,     3,     0,     1,     3,     3,     3,    12,
+      11,    11,     4,    15,    11,    11,     4,     5,     6,     7,
+       4,     5,     6,     7,    13,     0,    14,     8,     9,     0,
+      12,    22
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "G:/GCCOS2/TREE/TOOLS/usr/share/bison/bison.simple"
+
+/* Skeleton output parser for bison,
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software
+   Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser when
+   the %semantic_parser declaration is not specified in the grammar.
+   It was written by Richard Stallman by simplifying the hairy parser
+   used when %semantic_parser is specified.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE)
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC malloc
+#  define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+	 || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+# if YYLSP_NEEDED
+  YYLTYPE yyls;
+# endif
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# if YYLSP_NEEDED
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))	\
+      + 2 * YYSTACK_GAP_MAX)
+# else
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
+      + YYSTACK_GAP_MAX)
+# endif
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  register YYSIZE_T yyi;		\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX;	\
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (0)
+
+#endif
+
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		-2
+#define YYEOF		0
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT 	goto yyabortlab
+#define YYERROR		goto yyerrlab1
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL		goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yychar1 = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { 								\
+      yyerror ("syntax error: cannot back up");			\
+      YYERROR;							\
+    }								\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).
+
+   When YYLLOC_DEFAULT is run, CURRENT is set the location of the
+   first token.  By default, to implement support for ranges, extend
+   its range to the last symbol.  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)       	\
+   Current.last_line   = Rhs[N].last_line;	\
+   Current.last_column = Rhs[N].last_column;
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#if YYPURE
+# if YYLSP_NEEDED
+#  ifdef YYLEX_PARAM
+#   define YYLEX		yylex (&yylval, &yylloc, YYLEX_PARAM)
+#  else
+#   define YYLEX		yylex (&yylval, &yylloc)
+#  endif
+# else /* !YYLSP_NEEDED */
+#  ifdef YYLEX_PARAM
+#   define YYLEX		yylex (&yylval, YYLEX_PARAM)
+#  else
+#   define YYLEX		yylex (&yylval)
+#  endif
+# endif /* !YYLSP_NEEDED */
+#else /* !YYPURE */
+# define YYLEX			yylex ()
+#endif /* !YYPURE */
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (0)
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#ifdef YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+#endif
+
+
+#line 315 "G:/GCCOS2/TREE/TOOLS/usr/share/bison/bison.simple"
+
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+# ifdef YYPARSE_PARAM
+int yyparse (void *);
+# else
+int yyparse (void);
+# endif
+#endif
+
+/* YY_DECL_VARIABLES -- depending whether we use a pure parser,
+   variables are global, or local to YYPARSE.  */
+
+#define YY_DECL_NON_LSP_VARIABLES			\
+/* The lookahead symbol.  */				\
+int yychar;						\
+							\
+/* The semantic value of the lookahead symbol. */	\
+YYSTYPE yylval;						\
+							\
+/* Number of parse errors so far.  */			\
+int yynerrs;
+
+#if YYLSP_NEEDED
+# define YY_DECL_VARIABLES			\
+YY_DECL_NON_LSP_VARIABLES			\
+						\
+/* Location data for the lookahead symbol.  */	\
+YYLTYPE yylloc;
+#else
+# define YY_DECL_VARIABLES			\
+YY_DECL_NON_LSP_VARIABLES
+#endif
+
+
+/* If nonreentrant, generate the variables here. */
+
+#if !YYPURE
+YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  /* If reentrant, generate the variables here. */
+#if YYPURE
+  YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack. */
+  short	yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+#if YYLSP_NEEDED
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+#endif
+
+#if YYLSP_NEEDED
+# define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+# define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+#if YYLSP_NEEDED
+  YYLTYPE yyloc;
+#endif
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule. */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+#if YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack. Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	short *yyss1 = yyss;
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  */
+# if YYLSP_NEEDED
+	YYLTYPE *yyls1 = yyls;
+	/* This used to be a conditional around just the two extra args,
+	   but that might be undefined if yyoverflow is a macro.  */
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yyls1, yysize * sizeof (*yylsp),
+		    &yystacksize);
+	yyls = yyls1;
+# else
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yystacksize);
+# endif
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+	goto yyoverflowlab;
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	short *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyoverflowlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+# if YYLSP_NEEDED
+	YYSTACK_RELOCATE (yyls);
+# endif
+# undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+#if YYLSP_NEEDED
+      yylsp = yyls + yysize - 1;
+#endif
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyssp >= yyss + yystacksize - 1)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)		/* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;		/* Don't call YYLEX any more */
+
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE (yychar);
+
+#if YYDEBUG
+     /* We have to keep this `#if YYDEBUG', since we use variables
+	which are defined only if `YYDEBUG' is set.  */
+      if (yydebug)
+	{
+	  YYFPRINTF (stderr, "Next token is %d (%s",
+		     yychar, yytname[yychar1]);
+	  /* Give the individual parser a way to print the precise
+	     meaning of a token, for further debugging info.  */
+# ifdef YYPRINT
+	  YYPRINT (stderr, yychar, yylval);
+# endif
+	  YYFPRINTF (stderr, ")\n");
+	}
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+	      yychar, yytname[yychar1]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to the semantic value of
+     the lookahead token.  This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+#if YYLSP_NEEDED
+  /* Similarly for the default location.  Let the user run additional
+     commands if for instance locations are ranges.  */
+  yyloc = yylsp[1-yylen];
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+#endif
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
+  if (yydebug)
+    {
+      int yyi;
+
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+		 yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++)
+	YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+  switch (yyn) {
+
+case 7:
+#line 86 "nsparser.y"
+{
+			_nsdbtput(&curdbt);
+		}
+    break;
+case 8:
+#line 90 "nsparser.y"
+{
+			yyerrok;
+		}
+    break;
+case 9:
+#line 97 "nsparser.y"
+{
+			curdbt.name = yylval.str;
+			curdbt.srclist = NULL;
+			curdbt.srclistsize = 0;
+		}
+    break;
+case 12:
+#line 111 "nsparser.y"
+{
+			cursrc.flags = NS_TERMINATE;
+			_nsaddsrctomap(yyvsp[0].str);
+		}
+    break;
+case 13:
+#line 115 "nsparser.y"
+{ cursrc.flags = NS_SUCCESS; }
+    break;
+case 14:
+#line 116 "nsparser.y"
+{
+			_nsaddsrctomap(yyvsp[-4].str);
+		}
+    break;
+case 17:
+#line 128 "nsparser.y"
+{
+			if (yyvsp[0].mapval)	     /* if action == RETURN set RETURN bit */
+				cursrc.flags |= yyvsp[-2].mapval;
+			else	     /* else unset it */
+				cursrc.flags &= ~yyvsp[-2].mapval;
+		}
+    break;
+case 18:
+#line 137 "nsparser.y"
+{ yyval.mapval = NS_SUCCESS; }
+    break;
+case 19:
+#line 138 "nsparser.y"
+{ yyval.mapval = NS_UNAVAIL; }
+    break;
+case 20:
+#line 139 "nsparser.y"
+{ yyval.mapval = NS_NOTFOUND; }
+    break;
+case 21:
+#line 140 "nsparser.y"
+{ yyval.mapval = NS_TRYAGAIN; }
+    break;
+case 22:
+#line 144 "nsparser.y"
+{ yyval.mapval = NS_ACTION_RETURN; }
+    break;
+case 23:
+#line 145 "nsparser.y"
+{ yyval.mapval = NS_ACTION_CONTINUE; }
+    break;
+}
+
+#line 705 "G:/GCCOS2/TREE/TOOLS/usr/share/bison/bison.simple"
+
+
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#if YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+	YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+#if YYLSP_NEEDED
+  *++yylsp = yyloc;
+#endif
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+	{
+	  YYSIZE_T yysize = 0;
+	  char *yymsg;
+	  int yyx, yycount;
+
+	  yycount = 0;
+	  /* Start YYX at -YYN if negative to avoid negative indexes in
+	     YYCHECK.  */
+	  for (yyx = yyn < 0 ? -yyn : 0;
+	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+	    if (yycheck[yyx + yyn] == yyx)
+	      yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+	  yysize += yystrlen ("parse error, unexpected ") + 1;
+	  yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);
+	  yymsg = (char *) YYSTACK_ALLOC (yysize);
+	  if (yymsg != 0)
+	    {
+	      char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+	      yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);
+
+	      if (yycount < 5)
+		{
+		  yycount = 0;
+		  for (yyx = yyn < 0 ? -yyn : 0;
+		       yyx < (int) (sizeof (yytname) / sizeof (char *));
+		       yyx++)
+		    if (yycheck[yyx + yyn] == yyx)
+		      {
+			const char *yyq = ! yycount ? ", expecting " : " or ";
+			yyp = yystpcpy (yyp, yyq);
+			yyp = yystpcpy (yyp, yytname[yyx]);
+			yycount++;
+		      }
+		}
+	      yyerror (yymsg);
+	      YYSTACK_FREE (yymsg);
+	    }
+	  else
+	    yyerror ("parse error; also virtual memory exhausted");
+	}
+      else
+#endif /* defined (YYERROR_VERBOSE) */
+	yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*--------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action |
+`--------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+	YYABORT;
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+		  yychar, yytname[yychar1]));
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;		/* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+
+/*-------------------------------------------------------------------.
+| yyerrdefault -- current state does not do anything special for the |
+| error token.                                                       |
+`-------------------------------------------------------------------*/
+yyerrdefault:
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+
+  /* If its default is to accept any token, ok.  Otherwise pop it.  */
+  yyn = yydefact[yystate];
+  if (yyn)
+    goto yydefault;
+#endif
+
+
+/*---------------------------------------------------------------.
+| yyerrpop -- pop the current state because it cannot handle the |
+| error token                                                    |
+`---------------------------------------------------------------*/
+yyerrpop:
+  if (yyssp == yyss)
+    YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#if YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "Error: state stack now");
+      while (yyssp1 != yyssp)
+	YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+/*--------------.
+| yyerrhandle.  |
+`--------------*/
+yyerrhandle:
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+#line 148 "nsparser.y"
+
+
+static void
+_nsaddsrctomap(elem)
+	const char *elem;
+{
+	int		i, lineno;
+	extern int	_nsyylineno;
+	extern char *	_nsyytext;
+
+	lineno = _nsyylineno - (*_nsyytext == '\n' ? 1 : 0);
+	if (curdbt.srclistsize > 0) {
+		if ((strcasecmp(elem, NSSRC_COMPAT) == 0) ||
+		    (strcasecmp(curdbt.srclist[0].name, NSSRC_COMPAT) == 0)) {
+#ifndef __EMX__
+			syslog(LOG_ERR,
+	    "NSSWITCH(nsparser): %s line %d: 'compat' used with other sources",
+			    _PATH_NS_CONF, lineno);
+#endif
+			return;
+		}
+	}
+	for (i = 0; i < curdbt.srclistsize; i++) {
+		if (strcasecmp(curdbt.srclist[i].name, elem) == 0) {
+#ifndef __EMX__
+			syslog(LOG_ERR,
+		       "NSSWITCH(nsparser): %s line %d: duplicate source '%s'",
+			    _PATH_NS_CONF, lineno, elem);
+#endif
+			return;
+		}
+	}
+	cursrc.name = elem;
+	_nsdbtaddsrc(&curdbt, &cursrc);
+}
Index: /trunk/libc/src/fbsdlibc/net/nsparser.h
===================================================================
--- /trunk/libc/src/fbsdlibc/net/nsparser.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/net/nsparser.h	(revision 2448)
@@ -0,0 +1,25 @@
+#ifndef BISON_NSPARSER_H
+# define BISON_NSPARSER_H
+
+#ifndef YYSTYPE
+typedef union {
+	char *str;
+	int   mapval;
+} yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+# define	NL	257
+# define	SUCCESS	258
+# define	UNAVAIL	259
+# define	NOTFOUND	260
+# define	TRYAGAIN	261
+# define	RETURN	262
+# define	CONTINUE	263
+# define	ERRORTOKEN	264
+# define	STRING	265
+
+
+extern YYSTYPE _nsyylval;
+
+#endif /* not BISON_NSPARSER_H */
Index: /trunk/libc/src/fbsdlibc/net/nsparser.y
===================================================================
--- /trunk/libc/src/fbsdlibc/net/nsparser.y	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/net/nsparser.y	(revision 2448)
@@ -0,0 +1,182 @@
+%{
+/*	$NetBSD: nsparser.y,v 1.3 1999/01/25 00:16:18 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * 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 NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/net/nsparser.y,v 1.4 2003/04/17 14:14:22 nectar Exp $");
+
+#include "namespace.h"
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+static	void	_nsaddsrctomap(const char *);
+
+static	ns_dbt		curdbt;
+static	ns_src		cursrc;
+%}
+
+%union {
+	char *str;
+	int   mapval;
+}
+
+%token	NL
+%token	SUCCESS UNAVAIL NOTFOUND TRYAGAIN
+%token	RETURN CONTINUE
+%token  ERRORTOKEN
+%token	<str> STRING
+
+%type	<mapval> Status Action
+
+%%
+
+File
+	:	/* empty */
+	| Lines
+	;
+
+Lines
+	: Entry
+	| Lines Entry
+	;
+
+Entry
+	: NL
+	| Database ':' NL
+	| Database ':' Srclist NL
+		{
+			_nsdbtput(&curdbt);
+		}
+	| error NL
+		{
+			yyerrok;
+		}
+	;
+
+Database
+	: STRING
+		{
+			curdbt.name = yylval.str;
+			curdbt.srclist = NULL;
+			curdbt.srclistsize = 0;
+		}
+	;
+
+Srclist
+	: Item
+	| Srclist Item
+	;
+
+Item
+	: STRING
+		{
+			cursrc.flags = NS_TERMINATE;
+			_nsaddsrctomap($1);
+		}
+	| STRING '[' { cursrc.flags = NS_SUCCESS; } Criteria ']'
+		{
+			_nsaddsrctomap($1);
+		}
+	;
+
+Criteria
+	: Criterion
+	| Criteria Criterion
+	;
+
+Criterion
+	: Status '=' Action
+		{
+			if ($3)	     /* if action == RETURN set RETURN bit */
+				cursrc.flags |= $1;
+			else	     /* else unset it */
+				cursrc.flags &= ~$1;
+		}
+	;
+
+Status
+	: SUCCESS	{ $$ = NS_SUCCESS; }
+	| UNAVAIL	{ $$ = NS_UNAVAIL; }
+	| NOTFOUND	{ $$ = NS_NOTFOUND; }
+	| TRYAGAIN	{ $$ = NS_TRYAGAIN; }
+	;
+
+Action
+	: RETURN	{ $$ = NS_ACTION_RETURN; }
+	| CONTINUE	{ $$ = NS_ACTION_CONTINUE; }
+	;
+
+%%
+
+static void
+_nsaddsrctomap(elem)
+	const char *elem;
+{
+	int		i, lineno;
+	extern int	_nsyylineno;
+	extern char *	_nsyytext;
+
+	lineno = _nsyylineno - (*_nsyytext == '\n' ? 1 : 0);
+	if (curdbt.srclistsize > 0) {
+		if ((strcasecmp(elem, NSSRC_COMPAT) == 0) ||
+		    (strcasecmp(curdbt.srclist[0].name, NSSRC_COMPAT) == 0)) {
+#ifndef __EMX__
+			syslog(LOG_ERR,
+	    "NSSWITCH(nsparser): %s line %d: 'compat' used with other sources",
+			    _PATH_NS_CONF, lineno);
+#endif
+			return;
+		}
+	}
+	for (i = 0; i < curdbt.srclistsize; i++) {
+		if (strcasecmp(curdbt.srclist[i].name, elem) == 0) {
+#ifndef __EMX__
+			syslog(LOG_ERR,
+		       "NSSWITCH(nsparser): %s line %d: duplicate source '%s'",
+			    _PATH_NS_CONF, lineno, elem);
+#endif
+			return;
+		}
+	}
+	cursrc.name = elem;
+	_nsdbtaddsrc(&curdbt, &cursrc);
+}
Index: /trunk/libc/src/fbsdlibc/net/nss_backends.h
===================================================================
--- /trunk/libc/src/fbsdlibc/net/nss_backends.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/net/nss_backends.h	(revision 2448)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/libc/net/nss_backends.h,v 1.1 2003/04/17 14:14:22 nectar Exp $
+ */
+/*
+ * Eventually, the implementations of existing built-in NSS functions
+ * may be moved into NSS modules and live here.
+ */
+#if 0
+NSS_BACKEND(	files,	_files_nss_module_register	)
+NSS_BACKEND(	dns,	_dns_nss_module_register	)
+NSS_BACKEND(	nis,	_nis_nss_module_register	)
+NSS_BACKEND(	compat,	_compat_nss_module_register	)
+#endif
Index: /trunk/libc/src/fbsdlibc/nls/msgcat.c
===================================================================
--- /trunk/libc/src/fbsdlibc/nls/msgcat.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/nls/msgcat.c	(revision 2448)
@@ -0,0 +1,525 @@
+/***********************************************************
+Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that Alfalfa's name not be used in
+advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.
+
+ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+If you make any modifications, bugfixes or other changes to this software
+we'd appreciate it if you could send a copy to us so we can keep things
+up-to-date.  Many thanks.
+				Kee Hinckley
+				Alfalfa Software, Inc.
+				267 Allston St., #3
+				Cambridge, MA 02139  USA
+				nazgul@alfalfa.com
+
+******************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/nls/msgcat.c,v 1.48 2003/10/29 10:45:01 tjr Exp $");
+
+/*
+ * We need a better way of handling errors than printing text.  I need
+ * to add an error handling routine.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <locale.h>
+#include <nl_types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "msgcat.h"
+#ifndef __EMX__
+#include "../locale/setlocale.h"        /* for ENCODING_LEN */
+#else
+#define ENCODING_LEN    31              /* bird: wonder if this is allright. */
+#endif
+
+#ifndef __EMX__
+#define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:/usr/local/share/nls/%L/%N.cat:/usr/local/share/nls/%N/%L"
+#else /* bird: we use a different separator character. */
+#define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat;/usr/share/nls/%N/%L;/usr/local/share/nls/%L/%N.cat;/usr/local/share/nls/%N/%L"
+#endif
+
+#define	TRUE	1
+#define	FALSE	0
+
+#define	NLERR		((nl_catd) -1)
+#define NLRETERR(errc)  { errno = errc; return (NLERR); }
+
+#ifndef __EMX__
+static nl_catd  loadCat();
+static int      loadSet();
+static void     __nls_free_resources();
+#else
+static nl_catd  loadCat(__const char *);
+static int      loadSet(MCCatT*, MCSetT*);
+static void     __nls_free_resources(MCCatT*, int);
+#endif
+
+nl_catd
+catopen(name, type)
+	__const char    *name;
+	int             type;
+{
+	int             spcleft, saverr;
+	char            path[PATH_MAX];
+	char            *nlspath, *lang, *base, *cptr, *pathP, *tmpptr;
+	char            *cptr1, *plang, *pter, *pcode;
+	struct stat     sbuf;
+
+	if (name == NULL || *name == '\0')
+		NLRETERR(EINVAL);
+
+	/* is it absolute path ? if yes, load immediately */
+	if (strchr(name, '/') != NULL)
+		return (loadCat(name));
+
+	if (type == NL_CAT_LOCALE)
+		lang = setlocale(LC_MESSAGES, NULL);
+	else
+		lang = getenv("LANG");
+
+	if (lang == NULL || *lang == '\0' || strlen(lang) > ENCODING_LEN ||
+	    (lang[0] == '.' &&
+	     (lang[1] == '\0' || (lang[1] == '.' && lang[2] == '\0'))) ||
+	    strchr(lang, '/') != NULL)
+		lang = "C";
+
+	if ((plang = cptr1 = strdup(lang)) == NULL)
+		return (NLERR);
+	if ((cptr = strchr(cptr1, '@')) != NULL)
+		*cptr = '\0';
+	pter = pcode = "";
+	if ((cptr = strchr(cptr1, '_')) != NULL) {
+		*cptr++ = '\0';
+		pter = cptr1 = cptr;
+	}
+	if ((cptr = strchr(cptr1, '.')) != NULL) {
+		*cptr++ = '\0';
+		pcode = cptr;
+	}
+
+#ifndef __EMX__
+	if ((nlspath = getenv("NLSPATH")) == NULL || issetugid())
+#else
+	if ((nlspath = getenv("NLSPATH")) == NULL)
+#endif
+		nlspath = _DEFAULT_NLS_PATH;
+
+	if ((base = cptr = strdup(nlspath)) == NULL) {
+		saverr = errno;
+		free(plang);
+		errno = saverr;
+		return (NLERR);
+	}
+
+#ifndef __EMX__
+	while ((nlspath = strsep(&cptr, ":")) != NULL) {
+#else
+	while ((nlspath = strsep(&cptr, ";")) != NULL) {
+#endif
+		pathP = path;
+		if (*nlspath) {
+			for (; *nlspath; ++nlspath) {
+				if (*nlspath == '%') {
+					switch (*(nlspath + 1)) {
+					case 'l':
+						tmpptr = plang;
+						break;
+					case 't':
+						tmpptr = pter;
+						break;
+					case 'c':
+						tmpptr = pcode;
+						break;
+					case 'L':
+						tmpptr = lang;
+						break;
+					case 'N':
+						tmpptr = (char *)name;
+						break;
+					case '%':
+						++nlspath;
+						/* fallthrough */
+					default:
+						if (pathP - path >=
+						    sizeof(path) - 1)
+							goto too_long;
+						*(pathP++) = *nlspath;
+						continue;
+					}
+					++nlspath;
+			put_tmpptr:
+					spcleft = sizeof(path) -
+						  (pathP - path) - 1;
+					if (strlcpy(pathP, tmpptr, spcleft) >=
+					    spcleft) {
+				too_long:
+						free(plang);
+						free(base);
+						NLRETERR(ENAMETOOLONG);
+					}
+					pathP += strlen(tmpptr);
+				} else {
+					if (pathP - path >= sizeof(path) - 1)
+						goto too_long;
+					*(pathP++) = *nlspath;
+				}
+			}
+			*pathP = '\0';
+			if (stat(path, &sbuf) == 0) {
+				free(plang);
+				free(base);
+				return (loadCat(path));
+			}
+		} else {
+			tmpptr = (char *)name;
+			--nlspath;
+			goto put_tmpptr;
+		}
+	}
+	free(plang);
+	free(base);
+	NLRETERR(ENOENT);
+}
+
+/*
+ * We've got an odd situation here.  The odds are real good that the
+ * number we are looking for is almost the same as the index.  We could
+ * use the index, check the difference and do something intelligent, but
+ * I haven't quite figured out what's intelligent.
+ *
+ * Here's a start.
+ *	Take an id N.  If there are > N items in the list, then N cannot
+ *	be more than N items from the start, since otherwise there would
+ *	have to be duplicate items.  So we can safely set the top to N+1
+ *	(after taking into account that ids start at 1, and arrays at 0)
+ *
+ *	Let's say we are at position P, and we are looking for N, but have
+ *	V.  If N > V, then the furthest away that N could be is
+ *	P + (N-V).  So we can safely set hi to P+(N-V)+1.  For example:
+ *		We are looking for 10, but have 8
+ *		8	?	?	?	?
+ *			>=9	>=10	>=11
+ *
+ */
+
+#define LOOKUP(PARENT, CHILD, ID, NUM, SET) {                    \
+	lo = 0;                                                  \
+	if (ID - 1 < PARENT->NUM) {                              \
+		cur = ID - 1;                                    \
+		hi = ID;                                         \
+	} else {                                                 \
+		hi = PARENT->NUM;                                \
+		cur = (hi - lo) / 2;                             \
+	}                                                        \
+	while (TRUE) {                                           \
+		CHILD = PARENT->SET + cur;                       \
+		if (CHILD->ID == ID)                             \
+			break;                                   \
+		if (CHILD->ID < ID) {                            \
+			lo = cur + 1;                            \
+			if (hi > cur + (ID - CHILD->ID) + 1)     \
+				hi = cur + (ID - CHILD->ID) + 1; \
+			dir = 1;                                 \
+		} else {                                         \
+			hi = cur;                                \
+			dir = -1;                                \
+		}                                                \
+		if (lo >= hi)                                    \
+			return (NULL);                           \
+		if (hi - lo == 1)                                \
+			cur += dir;                              \
+		else                                             \
+			cur += ((hi - lo) / 2) * dir;            \
+	}                                                        \
+}
+
+static MCSetT *
+MCGetSet(cat, setId)
+	MCCatT  *cat;
+	int     setId;
+{
+	MCSetT  *set;
+	long    lo, hi, cur, dir;
+
+	if (cat == NULL || setId <= 0)
+		return (NULL);
+	LOOKUP(cat, set, setId, numSets, sets);
+	if (set->invalid && loadSet(cat, set) <= 0)
+		return (NULL);
+	return (set);
+}
+
+static MCMsgT *
+MCGetMsg(set, msgId)
+	MCSetT  *set;
+	int     msgId;
+{
+	MCMsgT  *msg;
+	long    lo, hi, cur, dir;
+
+	if (set == NULL || set->invalid || msgId <= 0)
+		return (NULL);
+	LOOKUP(set, msg, msgId, numMsgs, u.msgs);
+	return (msg);
+}
+
+char *
+catgets(catd, setId, msgId, dflt)
+	nl_catd         catd;
+	int             setId;
+	int             msgId;
+	__const char    *dflt;
+{
+	MCMsgT          *msg;
+	MCCatT          *cat = (MCCatT *)catd;
+	__const char    *cptr;
+
+	if (catd == NULL || catd == NLERR)
+		return ((char *)dflt);
+	msg = MCGetMsg(MCGetSet(cat, setId), msgId);
+	if (msg != NULL)
+		cptr = msg->msg.str;
+	else
+		cptr = dflt;
+	return ((char *)cptr);
+}
+
+int
+catclose(catd)
+	nl_catd catd;
+{
+	MCCatT  *cat = (MCCatT *)catd;
+
+	if (catd == NULL || catd == NLERR) {
+		errno = EBADF;
+		return (-1);
+	}
+#if 0
+	if (cat->loadType != MCLoadAll)
+#endif
+		(void)fclose(cat->fp);
+	__nls_free_resources(cat, cat->numSets);
+	free(cat);
+	return (0);
+}
+
+/*
+ * Internal routines
+ */
+
+/* Note that only malloc failures are allowed to return an error */
+static char     *_errowner = "Message Catalog System";
+
+#define CORRUPT() {                                            \
+	(void)fclose(cat->fp);                                 \
+	(void)fprintf(stderr, "%s: corrupt file.", _errowner); \
+	free(cat);                                             \
+	NLRETERR(EFTYPE);                                      \
+}
+
+#define NOSPACE() {                                              \
+	saverr = errno;                                          \
+	(void)fclose(cat->fp);                                   \
+	(void)fprintf(stderr, "%s: no more memory.", _errowner); \
+	free(cat);                                               \
+	errno = saverr;                                          \
+	return (NLERR);                                          \
+}
+
+static void
+__nls_free_resources(cat, i)
+	MCCatT  *cat;
+	int     i;
+{
+	MCSetT  *set;
+	int     j;
+
+	for (j = 0; j < i; j++) {
+		set = cat->sets + j;
+		if (!set->invalid) {
+			free(set->data.str);
+			free(set->u.msgs);
+		}
+	}
+	free(cat->sets);
+}
+
+static nl_catd
+loadCat(catpath)
+	__const char    *catpath;
+{
+	MCHeaderT       header;
+	MCCatT          *cat;
+	MCSetT          *set;
+	long            i;
+	off_t           nextSet;
+	int             saverr;
+
+	if ((cat = (MCCatT *)malloc(sizeof(MCCatT))) == NULL)
+		return (NLERR);
+	cat->loadType = MCLoadBySet;
+
+#ifndef __EMX__
+	if ((cat->fp = fopen(catpath, "r")) == NULL) {
+#else
+	if ((cat->fp = fopen(catpath, "rb")) == NULL) {
+#endif
+		saverr = errno;
+		free(cat);
+		errno = saverr;
+		return (NLERR);
+	}
+	(void)_fcntl(fileno(cat->fp), F_SETFD, FD_CLOEXEC);
+
+	if (fread(&header, sizeof(header), 1, cat->fp) != 1 ||
+	    strncmp(header.magic, MCMagic, MCMagicLen) != 0)
+		CORRUPT();
+
+	if (header.majorVer != MCMajorVer) {
+		(void)fclose(cat->fp);
+		free(cat);
+		(void)fprintf(stderr, "%s: %s is version %ld, we need %ld.\n",
+		    _errowner, catpath, header.majorVer, MCMajorVer);
+		NLRETERR(EFTYPE);
+	}
+	if (header.numSets <= 0) {
+		(void)fclose(cat->fp);
+		free(cat);
+		(void)fprintf(stderr, "%s: %s has %ld sets!\n",
+		    _errowner, catpath, header.numSets);
+		NLRETERR(EFTYPE);
+	}
+
+	cat->numSets = header.numSets;
+	if ((cat->sets = (MCSetT *)malloc(sizeof(MCSetT) * header.numSets)) ==
+	    NULL)
+		NOSPACE();
+
+	nextSet = header.firstSet;
+	for (i = 0; i < cat->numSets; ++i) {
+		if (fseeko(cat->fp, nextSet, SEEK_SET) == -1) {
+			__nls_free_resources(cat, i);
+			CORRUPT();
+		}
+
+		/* read in the set header */
+		set = cat->sets + i;
+		if (fread(set, sizeof(*set), 1, cat->fp) != 1) {
+			__nls_free_resources(cat, i);
+			CORRUPT();
+		}
+
+		/* if it's invalid, skip over it (and backup 'i') */
+		if (set->invalid) {
+			--i;
+			nextSet = set->nextSet;
+			continue;
+		}
+#if 0
+		if (cat->loadType == MCLoadAll) {
+			int     res;
+
+			if ((res = loadSet(cat, set)) <= 0) {
+				saverr = errno;
+				__nls_free_resources(cat, i);
+				errno = saverr;
+				if (res < 0)
+					NOSPACE();
+				CORRUPT();
+			}
+		} else
+#endif
+			set->invalid = TRUE;
+		nextSet = set->nextSet;
+	}
+#if 0
+	if (cat->loadType == MCLoadAll) {
+		(void)fclose(cat->fp);
+		cat->fp = NULL;
+	}
+#endif
+	return ((nl_catd) cat);
+}
+
+static int
+loadSet(cat, set)
+	MCCatT  *cat;
+	MCSetT  *set;
+{
+	MCMsgT  *msg;
+	int     i;
+	int     saverr;
+
+	/* Get the data */
+	if (fseeko(cat->fp, set->data.off, SEEK_SET) == -1)
+		return (0);
+	if ((set->data.str = malloc(set->dataLen)) == NULL)
+		return (-1);
+	if (fread(set->data.str, set->dataLen, 1, cat->fp) != 1) {
+		saverr = errno;
+		free(set->data.str);
+		errno = saverr;
+		return (0);
+	}
+
+	/* Get the messages */
+	if (fseeko(cat->fp, set->u.firstMsg, SEEK_SET) == -1) {
+		saverr = errno;
+		free(set->data.str);
+		errno = saverr;
+		return (0);
+	}
+	if ((set->u.msgs = (MCMsgT *)malloc(sizeof(MCMsgT) * set->numMsgs)) ==
+	    NULL) {
+		saverr = errno;
+		free(set->data.str);
+		errno = saverr;
+		return (-1);
+	}
+
+	for (i = 0; i < set->numMsgs; ++i) {
+		msg = set->u.msgs + i;
+		if (fread(msg, sizeof(*msg), 1, cat->fp) != 1) {
+			saverr = errno;
+			free(set->u.msgs);
+			free(set->data.str);
+			errno = saverr;
+			return (0);
+		}
+		if (msg->invalid) {
+			--i;
+			continue;
+		}
+		msg->msg.str = (char *)(set->data.str + msg->msg.off);
+	}
+	set->invalid = FALSE;
+	return (1);
+}
Index: /trunk/libc/src/fbsdlibc/nls/msgcat.h
===================================================================
--- /trunk/libc/src/fbsdlibc/nls/msgcat.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/nls/msgcat.h	(revision 2448)
@@ -0,0 +1,155 @@
+/* $FreeBSD: src/lib/libc/nls/msgcat.h,v 1.8 2000/09/03 21:05:10 ache Exp $ */
+
+#ifndef _MSGCAT_H_
+#define _MSGCAT_H_
+
+
+/***********************************************************
+Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that Alfalfa's name not be used in
+advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.
+
+ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+If you make any modifications, bugfixes or other changes to this software
+we'd appreciate it if you could send a copy to us so we can keep things
+up-to-date.  Many thanks.
+				Kee Hinckley
+				Alfalfa Software, Inc.
+				267 Allston St., #3
+				Cambridge, MA 02139  USA
+				nazgul@alfalfa.com
+
+******************************************************************/
+
+
+#include <sys/types.h>
+
+/*
+ * On disk data structures
+ */
+
+/* For or'd constants */
+#define MCMakeId(s,m)		(unsigned long) ( ((unsigned short)s << (sizeof(short)*8)) \
+						 | (unsigned short)m )
+#define MCSetId(id)		(unsigned int) ( id >> (sizeof(short) * 8) )
+#define MCMsgId(id)		(unsigned int) ( (id << (sizeof(short) * 8)) \
+						>> (sizeof(short) * 8) )
+#define MCMagicLen	8
+#define MCMagic		"*nazgul*"
+#define MCLastMsg	0
+#define MCLastSet	0
+
+#define MCMajorVer	1L
+#define MCMinorVer	0
+
+/*
+ * Critical note here.  Sets and Messages *MUST* be stored in ascending
+ * order.  There are stored that way (by specification) in the original
+ * data file, however in the process of merging in new stuff you might
+ * mix that up.  Don't!  The catget stuff does a binary search and will
+ * totally lose it if these aren't in order (not contiguous mind you, just
+ * in order.  If this turns out to be a major problem this could be enhanced
+ * by adding a 'sorted' flag to the db, and sorting msgs and sets at load
+ * time if things aren't sorted, but I'd like not to have to do that.
+ */
+
+/*
+ * I have tried here to define data structures which can be used
+ * while the catalog is on disk, and at runtime.
+ * This is rather dangerous of course, but I think it can be done without
+ * overly increasing the memory usage, and it makes loading and storing
+ * somewhat simpler and less prone to accidents.  I have also tried to
+ * define on disk data structures which can be updated in place, so that
+ * with a very large catalog (e.g. all system errors) you don't have to
+ * load everything in memory in order to add or update one set.  With
+ * this in mind there are "invalid" flags which allow items to be
+ * invalidated and thus not loaded at runtime.  Note however that although
+ * I pay attention to these when I load the DB, I do not currently use
+ * them in gencat (it just reads everything into memory), so there is
+ * no guarantee that this will all work.
+ */
+
+/* These should be publicly available */
+
+#define MCLoadBySet	0	/* Load entire sets as they are used */
+#define MCLoadAll	1	/* Load entire DB on catopen */
+
+/*
+ * MCOffsetT - Union to handle both disk and runtime pointers
+ */
+typedef union {
+    off_t	off;
+    char	*str;
+    void	*ptr;
+    struct _MCMsgT	*msg;
+    struct _MCSetT	*set;
+} MCOffsetT;
+
+/*
+ * MCMsgT - Message structure (disk and runtime)
+ */
+typedef struct _MCMsgT {
+    long	msgId;		/* Id of this message */
+    MCOffsetT	msg;		/* Relative offset on disk or pointer in memory */
+    long	invalid;	/* Valid on disk, loaded in memory */
+} MCMsgT;
+
+/*
+ * MCSetT - Set structure (disk and runtime)
+ */
+typedef struct _MCSetT {
+    long	setId;		/* Id of this set */
+    off_t	nextSet;	/* Offset of next set on disk */
+    union {
+	off_t	firstMsg;	/* Offset to first Msg (while on disk) */
+	MCMsgT	*msgs;		/* Pointer to array of msgs (in mem, loaded) */
+    } u;
+    MCOffsetT	data;		/* Offset to data, or pointer to data */
+    long	dataLen;	/* Length of data area on disk */
+    long	numMsgs;	/* Number of messages */
+    long	invalid;	/* Valid on disk, loaded in memory */
+} MCSetT;
+
+/*
+ * MCCatT - Runtime catalog pointer
+ */
+typedef struct {
+    long	loadType;	/* How to load the messages (see MSLoadType) */
+    FILE        *fp;            /* File descriptor of catalog (if load-on-demand) */
+    long	numSets;	/* Number of sets */
+    MCSetT	*sets;		/* Pointer to the sets */
+    off_t	firstSet;	/* Offset of first set on disk */
+} MCCatT;
+
+/*
+ * MCHeaderT - Disk file header
+ */
+typedef struct {
+    char	magic[MCMagicLen];	/* Magic cookie "*nazgul*" */
+    long	majorVer;		/* ++ on incompatible changes */
+    long	minorVer;		/* ++ on compatible changes */
+    long	flags;			/* Informational flags */
+    long	numSets;		/* Number of valid Sets */
+    off_t	firstSet;		/* Offset of first set on disk */
+} MCHeaderT;
+
+/* Some flags */
+#define MC68KByteOrder	0x01
+#define MCn86ByteOrder	0x02
+
+#endif /* !_MSGCAT_H_ */
Index: /trunk/libc/src/fbsdlibc/nls/nls.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/nls/nls.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/nls/nls.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/fbsdlibc/nls/*.c)
Index: /trunk/libc/src/fbsdlibc/stdio/mktemp.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdio/mktemp.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdio/mktemp.c	(revision 2448)
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1987, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mktemp.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/mktemp.c,v 1.28 2003/02/16 17:29:10 nectar Exp $");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+char *_mktemp(char *);
+
+static int _gettemp(char *, int *, int, int);
+
+static const unsigned char padchar[] =
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+int
+_STD(mkstemps)(path, slen)
+	char *path;
+	int slen;
+{
+	int fd;
+
+	return (_gettemp(path, &fd, 0, slen) ? fd : -1);
+}
+
+int
+_STD(mkstemp)(path)
+	char *path;
+{
+	int fd;
+
+	return (_gettemp(path, &fd, 0, 0) ? fd : -1);
+}
+
+/* mkstd.awk: NOUNDERSCORE(mkdtemp) */
+char *
+_STD(mkdtemp)(path)
+	char *path;
+{
+	return (_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
+}
+
+char *
+_mktemp(path)
+	char *path;
+{
+	return (_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL);
+}
+
+#ifndef __EMX__
+__warn_references(mktemp,
+    "warning: mktemp() possibly used unsafely; consider using mkstemp()");
+#endif
+
+char *
+_STD(mktemp)(path)
+	char *path;
+{
+	return (_mktemp(path));
+}
+
+static int
+_gettemp(path, doopen, domkdir, slen)
+	char *path;
+	int *doopen;
+	int domkdir;
+	int slen;
+{
+	char *start, *trv, *suffp;
+	char *pad;
+	struct stat sbuf;
+	int rval;
+	uint32_t rand;
+
+	if (doopen != NULL && domkdir) {
+		errno = EINVAL;
+		return (0);
+	}
+
+	for (trv = path; *trv != '\0'; ++trv)
+		;
+	trv -= slen;
+	suffp = trv;
+	--trv;
+	if (trv < path) {
+		errno = EINVAL;
+		return (0);
+	}
+
+	/* Fill space with random characters */
+	while (trv >= path && *trv == 'X') {
+		rand = arc4random() % (sizeof(padchar) - 1);
+		*trv-- = padchar[rand];
+	}
+	start = trv + 1;
+
+	/*
+	 * check the target directory.
+	 */
+	if (doopen != NULL || domkdir) {
+		for (; trv > path; --trv) {
+			if (*trv == '/') {
+				*trv = '\0';
+				rval = stat(path, &sbuf);
+				*trv = '/';
+				if (rval != 0)
+					return (0);
+				if (!S_ISDIR(sbuf.st_mode)) {
+					errno = ENOTDIR;
+					return (0);
+				}
+				break;
+			}
+		}
+	}
+
+	for (;;) {
+		if (doopen) {
+			if ((*doopen =
+			    _open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+				return (1);
+			if (errno != EEXIST)
+				return (0);
+		} else if (domkdir) {
+			if (mkdir(path, 0700) == 0)
+				return (1);
+			if (errno != EEXIST)
+				return (0);
+		} else if (lstat(path, &sbuf))
+			return (errno == ENOENT);
+
+		/* If we have a collision, cycle through the space of filenames */
+		for (trv = start;;) {
+			if (*trv == '\0' || trv == suffp)
+				return (0);
+			pad = strchr((const char *)padchar, *trv);
+			if (pad == NULL || *++pad == '\0')
+				*trv++ = padchar[0];
+			else {
+				*trv++ = *pad;
+				break;
+			}
+		}
+	}
+	/*NOTREACHED*/
+}
Index: /trunk/libc/src/fbsdlibc/stdio/setbuf.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdio/setbuf.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdio/setbuf.c	(revision 2448)
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include "namespace.h"
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setbuf.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/setbuf.c,v 1.4 2002/09/06 11:23:55 tjr Exp $");
+
+#include <stdio.h>
+/*#include "local.h"*/
+
+void
+_STD(setbuf)(FILE * __restrict fp, char * __restrict buf)
+{
+	(void) setvbuf(fp, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
Index: /trunk/libc/src/fbsdlibc/stdio/setbuffer.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdio/setbuffer.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdio/setbuffer.c	(revision 2448)
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include "namespace.h"
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setbuffer.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/setbuffer.c,v 1.7 2002/03/22 21:53:04 obrien Exp $");
+
+#include <stdio.h>
+
+void
+_STD(setbuffer)(fp, buf, size)
+	FILE *fp;
+	char *buf;
+	int size;
+{
+
+	(void)setvbuf(fp, buf, buf ? _IOFBF : _IONBF, (size_t)size);
+}
+
+/*
+ * set line buffering
+ */
+int
+_STD(setlinebuf)(fp)
+	FILE *fp;
+{
+
+	return (setvbuf(fp, (char *)NULL, _IOLBF, (size_t)0));
+}
Index: /trunk/libc/src/fbsdlibc/stdio/stdio.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/stdio/stdio.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdio/stdio.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/fbsdlibc/stdio/*.c)
Index: /trunk/libc/src/fbsdlibc/stdlib/getsubopt.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/getsubopt.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/getsubopt.c	(revision 2448)
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 1990, 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getsubopt.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/getsubopt.c,v 1.6 2004/02/23 03:30:02 ache Exp $");
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * The SVID interface to getsubopt provides no way of figuring out which
+ * part of the suboptions list wasn't matched.  This makes error messages
+ * tricky...  The extern variable suboptarg is a pointer to the token
+ * which didn't match.
+ */
+char *_STD(suboptarg);
+
+int
+_STD(getsubopt)(optionp, tokens, valuep)
+	char **optionp, **valuep;
+	char * const *tokens;
+{
+	int cnt;
+	char *p;
+
+	_STD(suboptarg) = *valuep = NULL;
+
+	if (!optionp || !*optionp)
+		return(-1);
+
+	/* skip leading white-space, commas */
+	for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
+
+	if (!*p) {
+		*optionp = p;
+		return(-1);
+	}
+
+	/* save the start of the token, and skip the rest of the token. */
+	for (_STD(suboptarg) = p;
+	    *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
+
+	if (*p) {
+		/*
+		 * If there's an equals sign, set the value pointer, and
+		 * skip over the value part of the token.  Terminate the
+		 * token.
+		 */
+		if (*p == '=') {
+			*p = '\0';
+			for (*valuep = ++p;
+			    *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
+			if (*p)
+				*p++ = '\0';
+		} else
+			*p++ = '\0';
+		/* Skip any whitespace or commas after this token. */
+		for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
+	}
+
+	/* set optionp for next round. */
+	*optionp = p;
+
+	for (cnt = 0; *tokens; ++tokens, ++cnt)
+		if (!strcmp(_STD(suboptarg), *tokens))
+			return(cnt);
+	return(-1);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/hcreate.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/hcreate.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/hcreate.c	(revision 2448)
@@ -0,0 +1,186 @@
+/* $NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $ */
+
+/*
+ * Copyright (c) 2001 Christopher G. Demetriou
+ * 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 for the
+ *          NetBSD Project.  See http://www.netbsd.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+/*
+ * hcreate() / hsearch() / hdestroy()
+ *
+ * SysV/XPG4 hash table functions.
+ *
+ * Implementation done based on NetBSD manual page and Solaris manual page,
+ * plus my own personal experience about how they're supposed to work.
+ *
+ * I tried to look at Knuth (as cited by the Solaris manual page), but
+ * nobody had a copy in the office, so...
+ */
+
+#include "libc-alias.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/hcreate.c,v 1.3 2002/06/27 13:18:27 deischen Exp $");
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <errno.h>
+#include <search.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit
+ * ptr machine) without adjusting MAX_BUCKETS_LG2 below.
+ */
+struct internal_entry {
+	SLIST_ENTRY(internal_entry) link;
+	ENTRY ent;
+};
+SLIST_HEAD(internal_head, internal_entry);
+
+#define	MIN_BUCKETS_LG2	4
+#define	MIN_BUCKETS	(1 << MIN_BUCKETS_LG2)
+
+/*
+ * max * sizeof internal_entry must fit into size_t.
+ * assumes internal_entry is <= 32 (2^5) bytes.
+ */
+#define	MAX_BUCKETS_LG2	(sizeof (size_t) * 8 - 1 - 5)
+#define	MAX_BUCKETS	((size_t)1 << MAX_BUCKETS_LG2)
+
+/* Default hash function, from db/hash/hash_func.c */
+extern u_int32_t (*__default_hash)(const void *, size_t);
+
+static struct internal_head *htable;
+static size_t htablesize;
+
+int
+_STD(hcreate)(size_t nel)
+{
+	size_t idx;
+	unsigned int p2;
+
+	/* Make sure this this isn't called when a table already exists. */
+	if (htable != NULL) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	/* If nel is too small, make it min sized. */
+	if (nel < MIN_BUCKETS)
+		nel = MIN_BUCKETS;
+
+	/* If it's too large, cap it. */
+	if (nel > MAX_BUCKETS)
+		nel = MAX_BUCKETS;
+
+	/* If it's is not a power of two in size, round up. */
+	if ((nel & (nel - 1)) != 0) {
+		for (p2 = 0; nel != 0; p2++)
+			nel >>= 1;
+		nel = 1 << p2;
+	}
+	
+	/* Allocate the table. */
+	htablesize = nel;
+	htable = malloc(htablesize * sizeof htable[0]);
+	if (htable == NULL) {
+		errno = ENOMEM;
+		return 0;
+	}
+
+	/* Initialize it. */
+	for (idx = 0; idx < htablesize; idx++)
+		SLIST_INIT(&htable[idx]);
+
+	return 1;
+}
+
+void
+_STD(hdestroy)(void)
+{
+	struct internal_entry *ie;
+	size_t idx;
+
+	if (htable == NULL)
+		return;
+
+	for (idx = 0; idx < htablesize; idx++) {
+		while (!SLIST_EMPTY(&htable[idx])) {
+			ie = SLIST_FIRST(&htable[idx]);
+			SLIST_REMOVE_HEAD(&htable[idx], link);
+			free(ie->ent.key);
+			free(ie);
+		}
+	}
+	free(htable);
+	htable = NULL;
+}
+
+ENTRY *
+_STD(hsearch)(ENTRY item, ACTION action)
+{
+	struct internal_head *head;
+	struct internal_entry *ie;
+	uint32_t hashval;
+	size_t len;
+
+	len = strlen(item.key);
+	hashval = (*__default_hash)(item.key, len);
+
+	head = &htable[hashval & (htablesize - 1)];
+	ie = SLIST_FIRST(head);
+	while (ie != NULL) {
+		if (strcmp(ie->ent.key, item.key) == 0)
+			break;
+		ie = SLIST_NEXT(ie, link);
+	}
+
+	if (ie != NULL)
+		return &ie->ent;
+	else if (action == FIND)
+		return NULL;
+
+	ie = malloc(sizeof *ie);
+	if (ie == NULL)
+		return NULL;
+	ie->ent.key = item.key;
+	ie->ent.data = item.data;
+
+	SLIST_INSERT_HEAD(head, ie, link);
+	return &ie->ent;
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/heapsort.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/heapsort.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/heapsort.c	(revision 2448)
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)heapsort.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include "libc-alias.h" /* bird: Get the right mapping of libc functions. */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/heapsort.c,v 1.4 2002/03/21 22:48:41 obrien Exp $");
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/*
+ * Swap two areas of size number of bytes.  Although qsort(3) permits random
+ * blocks of memory to be sorted, sorting pointers is almost certainly the
+ * common case (and, were it not, could easily be made so).  Regardless, it
+ * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
+ * arithmetic gets lost in the time required for comparison function calls.
+ */
+#define	SWAP(a, b, count, size, tmp) { \
+	count = size; \
+	do { \
+		tmp = *a; \
+		*a++ = *b; \
+		*b++ = tmp; \
+	} while (--count); \
+}
+
+/* Copy one block of size size to another. */
+#define COPY(a, b, count, size, tmp1, tmp2) { \
+	count = size; \
+	tmp1 = a; \
+	tmp2 = b; \
+	do { \
+		*tmp1++ = *tmp2++; \
+	} while (--count); \
+}
+
+/*
+ * Build the list into a heap, where a heap is defined such that for
+ * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
+ *
+ * There two cases.  If j == nmemb, select largest of Ki and Kj.  If
+ * j < nmemb, select largest of Ki, Kj and Kj+1.
+ */
+#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
+	for (par_i = initval; (child_i = par_i * 2) <= nmemb; \
+	    par_i = child_i) { \
+		child = base + child_i * size; \
+		if (child_i < nmemb && compar(child, child + size) < 0) { \
+			child += size; \
+			++child_i; \
+		} \
+		par = base + par_i * size; \
+		if (compar(child, par) <= 0) \
+			break; \
+		SWAP(par, child, count, size, tmp); \
+	} \
+}
+
+/*
+ * Select the top of the heap and 'heapify'.  Since by far the most expensive
+ * action is the call to the compar function, a considerable optimization
+ * in the average case can be achieved due to the fact that k, the displaced
+ * elememt, is ususally quite small, so it would be preferable to first
+ * heapify, always maintaining the invariant that the larger child is copied
+ * over its parent's record.
+ *
+ * Then, starting from the *bottom* of the heap, finding k's correct place,
+ * again maintianing the invariant.  As a result of the invariant no element
+ * is 'lost' when k is assigned its correct place in the heap.
+ *
+ * The time savings from this optimization are on the order of 15-20% for the
+ * average case. See Knuth, Vol. 3, page 158, problem 18.
+ *
+ * XXX Don't break the #define SELECT line, below.  Reiser cpp gets upset.
+ */
+#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \
+	for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \
+		child = base + child_i * size; \
+		if (child_i < nmemb && compar(child, child + size) < 0) { \
+			child += size; \
+			++child_i; \
+		} \
+		par = base + par_i * size; \
+		COPY(par, child, count, size, tmp1, tmp2); \
+	} \
+	for (;;) { \
+		child_i = par_i; \
+		par_i = child_i / 2; \
+		child = base + child_i * size; \
+		par = base + par_i * size; \
+		if (child_i == 1 || compar(k, par) < 0) { \
+			COPY(child, k, count, size, tmp1, tmp2); \
+			break; \
+		} \
+		COPY(child, par, count, size, tmp1, tmp2); \
+	} \
+}
+
+/*
+ * Heapsort -- Knuth, Vol. 3, page 145.  Runs in O (N lg N), both average
+ * and worst.  While heapsort is faster than the worst case of quicksort,
+ * the BSD quicksort does median selection so that the chance of finding
+ * a data set that will trigger the worst case is nonexistent.  Heapsort's
+ * only advantage over quicksort is that it requires little additional memory.
+ */
+int
+heapsort(vbase, nmemb, size, compar)
+	void *vbase;
+	size_t nmemb, size;
+	int (*compar)(const void *, const void *);
+{
+	int cnt, i, j, l;
+	char tmp, *tmp1, *tmp2;
+	char *base, *k, *p, *t;
+
+	if (nmemb <= 1)
+		return (0);
+
+	if (!size) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if ((k = malloc(size)) == NULL)
+		return (-1);
+
+	/*
+	 * Items are numbered from 1 to nmemb, so offset from size bytes
+	 * below the starting address.
+	 */
+	base = (char *)vbase - size;
+
+	for (l = nmemb / 2 + 1; --l;)
+		CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
+
+	/*
+	 * For each element of the heap, save the largest element into its
+	 * final slot, save the displaced element (k), then recreate the
+	 * heap.
+	 */
+	while (nmemb > 1) {
+		COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
+		COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
+		--nmemb;
+		SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
+	}
+	free(k);
+	return (0);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/imaxabs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/imaxabs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/imaxabs.c	(revision 2448)
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /*bird*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/imaxabs.c,v 1.1 2001/11/15 02:05:03 mike Exp $");
+
+#include <inttypes.h>
+
+intmax_t
+_STD(imaxabs)(intmax_t j)
+{
+	return (j < 0 ? -j : j);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/imaxdiv.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/imaxdiv.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/imaxdiv.c	(revision 2448)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /*bird*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/imaxdiv.c,v 1.1 2001/11/15 02:05:03 mike Exp $");
+
+#include <inttypes.h>
+
+/* See comments in div.c for implementation details. */
+imaxdiv_t
+_STD(imaxdiv)(intmax_t numer, intmax_t denom)
+{
+	imaxdiv_t retval;
+
+	retval.quot = numer / denom;
+	retval.rem = numer % denom;
+	if (numer >= 0 && retval.rem < 0) {
+		retval.quot++;
+		retval.rem -= denom;
+	}
+	return (retval);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/insque.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/insque.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/insque.c	(revision 2448)
@@ -0,0 +1,48 @@
+/*
+ * Initial implementation:
+ * Copyright (c) 2002 Robert Drehmel
+ * All rights reserved.
+ *
+ * As long as the above copyright statement and this notice remain
+ * unchanged, you can do what ever you want with this file.
+ */
+#include "libc-alias.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/insque.c,v 1.3 2003/01/04 07:34:41 tjr Exp $");
+
+#define	_SEARCH_PRIVATE
+#include <search.h>
+#ifdef DEBUG
+#include <stdio.h>
+#else
+#include <stdlib.h>	/* for NULL */
+#endif
+
+void
+_STD(insque)(void *element, void *pred)
+{
+	struct que_elem *prev, *next, *elem;
+
+	elem = (struct que_elem *)element;
+	prev = (struct que_elem *)pred;
+
+	if (prev == NULL) {
+		elem->prev = elem->next = NULL;
+		return;
+	}
+
+	next = prev->next;
+	if (next != NULL) {
+#ifdef DEBUG
+		if (next->prev != prev) {
+			fprintf(stderr, "insque: Inconsistency detected:"
+			    " next(%p)->prev(%p) != prev(%p)\n",
+			    next, next->prev, prev);
+		}
+#endif
+		next->prev = elem;
+	}
+	prev->next = elem;
+	elem->prev = prev;
+	elem->next = next;
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/llabs.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/llabs.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/llabs.c	(revision 2448)
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/llabs.c,v 1.1 2001/11/15 02:05:03 mike Exp $");
+
+#include <stdlib.h>
+
+long long
+_STD(llabs)(long long j)
+{
+	return (j < 0 ? -j : j);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/lldiv.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/lldiv.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/lldiv.c	(revision 2448)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/lldiv.c,v 1.1 2001/11/15 02:05:03 mike Exp $");
+
+#include <stdlib.h>
+
+/* See comments in div.c for implementation details. */
+lldiv_t
+_STD(lldiv)(long long numer, long long denom)
+{
+	lldiv_t retval;
+
+	retval.quot = numer / denom;
+	retval.rem = numer % denom;
+	if (numer >= 0 && retval.rem < 0) {
+		retval.quot++;
+		retval.rem -= denom;
+	}
+	return (retval);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/lsearch.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/lsearch.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/lsearch.c	(revision 2448)
@@ -0,0 +1,65 @@
+/*
+ * Initial implementation:
+ * Copyright (c) 2002 Robert Drehmel
+ * All rights reserved.
+ *
+ * As long as the above copyright statement and this notice remain
+ * unchanged, you can do what ever you want with this file.
+ */
+#include "libc-alias.h"
+#include <sys/types.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/lsearch.c,v 1.1 2002/10/16 14:29:22 robert Exp $");
+
+#define	_SEARCH_PRIVATE
+#include <search.h>
+#include <stdint.h>	/* for uint8_t */
+#include <stdlib.h>	/* for NULL */
+#include <string.h>	/* for memcpy() prototype */
+
+static void *lwork(const void *, const void *, size_t *, size_t,
+    int (*)(const void *, const void *), int);
+
+void *_STD(lsearch)(const void *key, void *base, size_t *nelp, size_t width,
+    int (*compar)(const void *, const void *))
+{
+
+	return (lwork(key, base, nelp, width, compar, 1));
+}
+
+void *_STD(lfind)(const void *key, const void *base, size_t *nelp, size_t width,
+    int (*compar)(const void *, const void *))
+{
+
+	return (lwork(key, base, nelp, width, compar, 0));
+}
+
+static void *
+lwork(const void *key, const void *base, size_t *nelp, size_t width,
+    int (*compar)(const void *, const void *), int addelem)
+{
+	uint8_t *ep, *endp;
+
+	/*
+	 * Cast to an integer value first to avoid the warning for removing
+	 * 'const' via a cast.
+	 */
+	ep = (uint8_t *)(uintptr_t)base;
+	for (endp = (uint8_t *)(ep + width * *nelp); ep < endp; ep += width) {
+		if (compar(key, ep) == 0)
+			return (ep);
+	}
+
+	/* lfind() shall return when the key was not found. */
+	if (!addelem)
+		return (NULL);
+
+	/*
+	 * lsearch() adds the key to the end of the table and increments
+	 * the number of elements.
+	 */
+	memcpy(endp, key, width);
+	++*nelp;
+
+	return (endp);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/merge.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/merge.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/merge.c	(revision 2448)
@@ -0,0 +1,353 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Peter McIlroy.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)merge.c	8.2 (Berkeley) 2/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include "libc-alias.h" /* bird: Get the right mapping of libc functions. */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/merge.c,v 1.6 2002/03/21 22:48:42 obrien Exp $");
+
+/*
+ * Hybrid exponential search/linear search merge sort with hybrid
+ * natural/pairwise first pass.  Requires about .3% more comparisons
+ * for random data than LSMS with pairwise first pass alone.
+ * It works for objects as small as two bytes.
+ */
+
+#define NATURAL
+#define THRESHOLD 16	/* Best choice for natural merge cut-off. */
+
+/* #define NATURAL to get hybrid natural merge.
+ * (The default is pairwise merging.)
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void setup(u_char *, u_char *, size_t, size_t, int (*)());
+static void insertionsort(u_char *, size_t, size_t, int (*)());
+
+#define ISIZE sizeof(int)
+#define PSIZE sizeof(u_char *)
+#define ICOPY_LIST(src, dst, last)				\
+	do							\
+	*(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE;	\
+	while(src < last)
+#define ICOPY_ELT(src, dst, i)					\
+	do							\
+	*(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE;	\
+	while (i -= ISIZE)
+
+#define CCOPY_LIST(src, dst, last)		\
+	do					\
+		*dst++ = *src++;		\
+	while (src < last)
+#define CCOPY_ELT(src, dst, i)			\
+	do					\
+		*dst++ = *src++;		\
+	while (i -= 1)
+
+/*
+ * Find the next possible pointer head.  (Trickery for forcing an array
+ * to do double duty as a linked list when objects do not align with word
+ * boundaries.
+ */
+/* Assumption: PSIZE is a power of 2. */
+#define EVAL(p) (u_char **)						\
+	((u_char *)0 +							\
+	    (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1)))
+
+/*
+ * Arguments are as for qsort.
+ */
+int
+mergesort(base, nmemb, size, cmp)
+	void *base;
+	size_t nmemb;
+	size_t size;
+	int (*cmp)(const void *, const void *);
+{
+	int i, sense;
+	int big, iflag;
+	u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
+	u_char *list2, *list1, *p2, *p, *last, **p1;
+
+	if (size < PSIZE / 2) {		/* Pointers must fit into 2 * size. */
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (nmemb == 0)
+		return (0);
+
+	/*
+	 * XXX
+	 * Stupid subtraction for the Cray.
+	 */
+	iflag = 0;
+	if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
+		iflag = 1;
+
+	if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
+		return (-1);
+
+	list1 = base;
+	setup(list1, list2, nmemb, size, cmp);
+	last = list2 + nmemb * size;
+	i = big = 0;
+	while (*EVAL(list2) != last) {
+	    l2 = list1;
+	    p1 = EVAL(list1);
+	    for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
+	    	p2 = *EVAL(p2);
+	    	f1 = l2;
+	    	f2 = l1 = list1 + (p2 - list2);
+	    	if (p2 != last)
+	    		p2 = *EVAL(p2);
+	    	l2 = list1 + (p2 - list2);
+	    	while (f1 < l1 && f2 < l2) {
+	    		if ((*cmp)(f1, f2) <= 0) {
+	    			q = f2;
+	    			b = f1, t = l1;
+	    			sense = -1;
+	    		} else {
+	    			q = f1;
+	    			b = f2, t = l2;
+	    			sense = 0;
+	    		}
+	    		if (!big) {	/* here i = 0 */
+				while ((b += size) < t && cmp(q, b) >sense)
+	    				if (++i == 6) {
+	    					big = 1;
+	    					goto EXPONENTIAL;
+	    				}
+	    		} else {
+EXPONENTIAL:	    		for (i = size; ; i <<= 1)
+	    				if ((p = (b + i)) >= t) {
+	    					if ((p = t - size) > b &&
+						    (*cmp)(q, p) <= sense)
+	    						t = p;
+	    					else
+	    						b = p;
+	    					break;
+	    				} else if ((*cmp)(q, p) <= sense) {
+	    					t = p;
+	    					if (i == size)
+	    						big = 0;
+	    					goto FASTCASE;
+	    				} else
+	    					b = p;
+				while (t > b+size) {
+	    				i = (((t - b) / size) >> 1) * size;
+	    				if ((*cmp)(q, p = b + i) <= sense)
+	    					t = p;
+	    				else
+	    					b = p;
+	    			}
+	    			goto COPY;
+FASTCASE:	    		while (i > size)
+	    				if ((*cmp)(q,
+	    					p = b + (i >>= 1)) <= sense)
+	    					t = p;
+	    				else
+	    					b = p;
+COPY:	    			b = t;
+	    		}
+	    		i = size;
+	    		if (q == f1) {
+	    			if (iflag) {
+	    				ICOPY_LIST(f2, tp2, b);
+	    				ICOPY_ELT(f1, tp2, i);
+	    			} else {
+	    				CCOPY_LIST(f2, tp2, b);
+	    				CCOPY_ELT(f1, tp2, i);
+	    			}
+	    		} else {
+	    			if (iflag) {
+	    				ICOPY_LIST(f1, tp2, b);
+	    				ICOPY_ELT(f2, tp2, i);
+	    			} else {
+	    				CCOPY_LIST(f1, tp2, b);
+	    				CCOPY_ELT(f2, tp2, i);
+	    			}
+	    		}
+	    	}
+	    	if (f2 < l2) {
+	    		if (iflag)
+	    			ICOPY_LIST(f2, tp2, l2);
+	    		else
+	    			CCOPY_LIST(f2, tp2, l2);
+	    	} else if (f1 < l1) {
+	    		if (iflag)
+	    			ICOPY_LIST(f1, tp2, l1);
+	    		else
+	    			CCOPY_LIST(f1, tp2, l1);
+	    	}
+	    	*p1 = l2;
+	    }
+	    tp2 = list1;	/* swap list1, list2 */
+	    list1 = list2;
+	    list2 = tp2;
+	    last = list2 + nmemb*size;
+	}
+	if (base == list2) {
+		memmove(list2, list1, nmemb*size);
+		list2 = list1;
+	}
+	free(list2);
+	return (0);
+}
+
+#define	swap(a, b) {					\
+		s = b;					\
+		i = size;				\
+		do {					\
+			tmp = *a; *a++ = *s; *s++ = tmp; \
+		} while (--i);				\
+		a -= size;				\
+	}
+#define reverse(bot, top) {				\
+	s = top;					\
+	do {						\
+		i = size;				\
+		do {					\
+			tmp = *bot; *bot++ = *s; *s++ = tmp; \
+		} while (--i);				\
+		s -= size2;				\
+	} while(bot < s);				\
+}
+
+/*
+ * Optional hybrid natural/pairwise first pass.  Eats up list1 in runs of
+ * increasing order, list2 in a corresponding linked list.  Checks for runs
+ * when THRESHOLD/2 pairs compare with same sense.  (Only used when NATURAL
+ * is defined.  Otherwise simple pairwise merging is used.)
+ */
+void
+setup(list1, list2, n, size, cmp)
+	size_t n, size;
+	int (*cmp)(const void *, const void *);
+	u_char *list1, *list2;
+{
+	int i, length, size2, tmp, sense;
+	u_char *f1, *f2, *s, *l2, *last, *p2;
+
+	size2 = size*2;
+	if (n <= 5) {
+		insertionsort(list1, n, size, cmp);
+		*EVAL(list2) = (u_char*) list2 + n*size;
+		return;
+	}
+	/*
+	 * Avoid running pointers out of bounds; limit n to evens
+	 * for simplicity.
+	 */
+	i = 4 + (n & 1);
+	insertionsort(list1 + (n - i) * size, i, size, cmp);
+	last = list1 + size * (n - i);
+	*EVAL(list2 + (last - list1)) = list2 + n * size;
+
+#ifdef NATURAL
+	p2 = list2;
+	f1 = list1;
+	sense = (cmp(f1, f1 + size) > 0);
+	for (; f1 < last; sense = !sense) {
+		length = 2;
+					/* Find pairs with same sense. */
+		for (f2 = f1 + size2; f2 < last; f2 += size2) {
+			if ((cmp(f2, f2+ size) > 0) != sense)
+				break;
+			length += 2;
+		}
+		if (length < THRESHOLD) {		/* Pairwise merge */
+			do {
+				p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
+				if (sense > 0)
+					swap (f1, f1 + size);
+			} while ((f1 += size2) < f2);
+		} else {				/* Natural merge */
+			l2 = f2;
+			for (f2 = f1 + size2; f2 < l2; f2 += size2) {
+				if ((cmp(f2-size, f2) > 0) != sense) {
+					p2 = *EVAL(p2) = f2 - list1 + list2;
+					if (sense > 0)
+						reverse(f1, f2-size);
+					f1 = f2;
+				}
+			}
+			if (sense > 0)
+				reverse (f1, f2-size);
+			f1 = f2;
+			if (f2 < last || cmp(f2 - size, f2) > 0)
+				p2 = *EVAL(p2) = f2 - list1 + list2;
+			else
+				p2 = *EVAL(p2) = list2 + n*size;
+		}
+	}
+#else		/* pairwise merge only. */
+	for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
+		p2 = *EVAL(p2) = p2 + size2;
+		if (cmp (f1, f1 + size) > 0)
+			swap(f1, f1 + size);
+	}
+#endif /* NATURAL */
+}
+
+/*
+ * This is to avoid out-of-bounds addresses in sorting the
+ * last 4 elements.
+ */
+static void
+insertionsort(a, n, size, cmp)
+	u_char *a;
+	size_t n, size;
+	int (*cmp)(const void *, const void *);
+{
+	u_char *ai, *s, *t, *u, tmp;
+	int i;
+
+	for (ai = a+size; --n >= 1; ai += size)
+		for (t = ai; t > a; t -= size) {
+			u = t - size;
+			if (cmp(u, t) <= 0)
+				break;
+			swap(u, t);
+		}
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/qsort.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/qsort.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/qsort.c	(revision 2448)
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 1992, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qsort.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include "libc-alias.h" /* bird: Get the right mapping of libc functions. */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.12 2002/09/10 02:04:49 wollman Exp $");
+
+#include <stdlib.h>
+
+#ifdef I_AM_QSORT_R
+typedef int		 cmp_t(void *, const void *, const void *);
+#else
+typedef int		 cmp_t(const void *, const void *);
+#endif
+static inline char	*med3(char *, char *, char *, cmp_t *, void *);
+static inline void	 swapfunc(char *, char *, int, int);
+
+#define min(a, b)	(a) < (b) ? a : b
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { 		\
+	long i = (n) / sizeof (TYPE); 			\
+	TYPE *pi = (TYPE *) (parmi); 		\
+	TYPE *pj = (TYPE *) (parmj); 		\
+	do { 						\
+		TYPE	t = *pi;		\
+		*pi++ = *pj;				\
+		*pj++ = t;				\
+        } while (--i > 0);				\
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+	es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static inline void
+swapfunc(a, b, n, swaptype)
+	char *a, *b;
+	int n, swaptype;
+{
+	if(swaptype <= 1)
+		swapcode(long, a, b, n)
+	else
+		swapcode(char, a, b, n)
+}
+
+#define swap(a, b)					\
+	if (swaptype == 0) {				\
+		long t = *(long *)(a);			\
+		*(long *)(a) = *(long *)(b);		\
+		*(long *)(b) = t;			\
+	} else						\
+		swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n) 	if ((n) > 0) swapfunc(a, b, n, swaptype)
+
+#ifdef I_AM_QSORT_R
+#define	CMP(t, x, y) (cmp((t), (x), (y)))
+#else
+#define	CMP(t, x, y) (cmp((x), (y)))
+#endif
+
+static inline char *
+med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
+#ifndef I_AM_QSORT_R
+__unused
+#endif
+)
+{
+	return CMP(thunk, a, b) < 0 ?
+	       (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
+              :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+}
+
+#ifdef I_AM_QSORT_R
+void
+_STD(qsort_r)(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
+#else
+#define thunk NULL
+void
+_STD(qsort)(void *a, size_t n, size_t es, cmp_t *cmp)
+#endif
+{
+	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+	int d, r, swaptype, swap_cnt;
+
+loop:	SWAPINIT(a, es);
+	swap_cnt = 0;
+	if (n < 7) {
+		for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+			for (pl = pm;
+			     pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+			     pl -= es)
+				swap(pl, pl - es);
+		return;
+	}
+	pm = (char *)a + (n / 2) * es;
+	if (n > 7) {
+		pl = a;
+		pn = (char *)a + (n - 1) * es;
+		if (n > 40) {
+			d = (n / 8) * es;
+			pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
+			pm = med3(pm - d, pm, pm + d, cmp, thunk);
+			pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
+		}
+		pm = med3(pl, pm, pn, cmp, thunk);
+	}
+	swap(a, pm);
+	pa = pb = (char *)a + es;
+
+	pc = pd = (char *)a + (n - 1) * es;
+	for (;;) {
+		while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
+			if (r == 0) {
+				swap_cnt = 1;
+				swap(pa, pb);
+				pa += es;
+			}
+			pb += es;
+		}
+		while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
+			if (r == 0) {
+				swap_cnt = 1;
+				swap(pc, pd);
+				pd -= es;
+			}
+			pc -= es;
+		}
+		if (pb > pc)
+			break;
+		swap(pb, pc);
+		swap_cnt = 1;
+		pb += es;
+		pc -= es;
+	}
+	if (swap_cnt == 0) {  /* Switch to insertion sort */
+		for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+			for (pl = pm;
+			     pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+			     pl -= es)
+				swap(pl, pl - es);
+		return;
+	}
+
+	pn = (char *)a + n * es;
+	r = min(pa - (char *)a, pb - pa);
+	vecswap(a, pb - r, r);
+	r = min(pd - pc, pn - pd - es);
+	vecswap(pb, pn - r, r);
+	if ((r = pb - pa) > es)
+#ifdef I_AM_QSORT_R
+		qsort_r(a, r / es, es, thunk, cmp);
+#else
+		qsort(a, r / es, es, cmp);
+#endif
+	if ((r = pd - pc) > es) {
+		/* Iterate rather than recurse to save stack space */
+		a = pn - r;
+		n = r / es;
+		goto loop;
+	}
+/*		qsort(pn - r, r / es, es, cmp);*/
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/qsort_r.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/qsort_r.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/qsort_r.c	(revision 2448)
@@ -0,0 +1,8 @@
+/*
+ * This file is in the public domain.  Originally written by Garrett
+ * A. Wollman.
+ *
+ * $FreeBSD: src/lib/libc/stdlib/qsort_r.c,v 1.1 2002/09/10 02:04:49 wollman Exp $
+ */
+#define I_AM_QSORT_R
+#include "qsort.c"
Index: /trunk/libc/src/fbsdlibc/stdlib/radixsort.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/radixsort.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/radixsort.c	(revision 2448)
@@ -0,0 +1,332 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Peter McIlroy and by Dan Bernstein at New York University,
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)radixsort.c	8.2 (Berkeley) 4/28/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/radixsort.c,v 1.7 2003/11/11 04:59:23 kientzle Exp $");
+
+/*
+ * Radixsort routines.
+ *
+ * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack.
+ * Use radixsort(a, n, trace, endchar) for this case.
+ *
+ * For stable sorting (using N extra pointers) use sradixsort(), which calls
+ * r_sort_b().
+ *
+ * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic,
+ * "Engineering Radix Sort".
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+
+typedef struct {
+	const u_char **sa;
+	int sn, si;
+} stack;
+
+static inline void simplesort
+(const u_char **, int, int, const u_char *, u_int);
+static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
+static void r_sort_b(const u_char **, const u_char **, int, int,
+    const u_char *, u_int);
+
+#define	THRESHOLD	20		/* Divert to simplesort(). */
+#define	SIZE		512		/* Default stack size. */
+
+#define SETUP {								\
+	if (tab == NULL) {						\
+		tr = tr0;						\
+		for (c = 0; c < endch; c++)				\
+			tr0[c] = c + 1;					\
+		tr0[c] = 0;						\
+		for (c++; c < 256; c++)					\
+			tr0[c] = c;					\
+		endch = 0;						\
+	} else {							\
+		endch = tab[endch];					\
+		tr = tab;						\
+		if (endch != 0 && endch != 255) {			\
+			errno = EINVAL;					\
+			return (-1);					\
+		}							\
+	}								\
+}
+
+int
+radixsort(a, n, tab, endch)
+	const u_char **a, *tab;
+	int n;
+	u_int endch;
+{
+	const u_char *tr;
+	int c;
+	u_char tr0[256];
+
+	SETUP;
+	r_sort_a(a, n, 0, tr, endch);
+	return (0);
+}
+
+int
+sradixsort(a, n, tab, endch)
+	const u_char **a, *tab;
+	int n;
+	u_int endch;
+{
+	const u_char *tr, **ta;
+	int c;
+	u_char tr0[256];
+
+	SETUP;
+	if (n < THRESHOLD)
+		simplesort(a, n, 0, tr, endch);
+	else {
+		if ((ta = malloc(n * sizeof(a))) == NULL)
+			return (-1);
+		r_sort_b(a, ta, n, 0, tr, endch);
+		free(ta);
+	}
+	return (0);
+}
+
+#define empty(s)	(s >= sp)
+#define pop(a, n, i)	a = (--sp)->sa, n = sp->sn, i = sp->si
+#define push(a, n, i)	sp->sa = a, sp->sn = n, (sp++)->si = i
+#define swap(a, b, t)	t = a, a = b, b = t
+
+/* Unstable, in-place sort. */
+static void
+r_sort_a(a, n, i, tr, endch)
+	const u_char **a;
+	int n, i;
+	const u_char *tr;
+	u_int endch;
+{
+	static int count[256], nc, bmin;
+	int c;
+	const u_char **ak, *r;
+	stack s[SIZE], *sp, *sp0, *sp1, temp;
+	int *cp, bigc;
+	const u_char **an, *t, **aj, **top[256];
+
+	/* Set up stack. */
+	sp = s;
+	push(a, n, i);
+	while (!empty(s)) {
+		pop(a, n, i);
+		if (n < THRESHOLD) {
+			simplesort(a, n, i, tr, endch);
+			continue;
+		}
+		an = a + n;
+
+		/* Make character histogram. */
+		if (nc == 0) {
+			bmin = 255;	/* First occupied bin, excluding eos. */
+			for (ak = a; ak < an;) {
+				c = tr[(*ak++)[i]];
+				if (++count[c] == 1 && c != endch) {
+					if (c < bmin)
+						bmin = c;
+					nc++;
+				}
+			}
+			if (sp + nc > s + SIZE) {	/* Get more stack. */
+				r_sort_a(a, n, i, tr, endch);
+				continue;
+			}
+		}
+
+		/*
+		 * Special case: if all strings have the same
+		 * character at position i, move on to the next
+		 * character.
+		 */
+		if (nc == 1 && count[bmin] == n) {
+			push(a, n, i+1);
+			nc = count[bmin] = 0;
+			continue;
+		}
+
+		/*
+		 * Set top[]; push incompletely sorted bins onto stack.
+		 * top[] = pointers to last out-of-place element in bins.
+		 * count[] = counts of elements in bins.
+		 * Before permuting: top[c-1] + count[c] = top[c];
+		 * during deal: top[c] counts down to top[c-1].
+		 */
+		sp0 = sp1 = sp;		/* Stack position of biggest bin. */
+		bigc = 2;		/* Size of biggest bin. */
+		if (endch == 0)		/* Special case: set top[eos]. */
+			top[0] = ak = a + count[0];
+		else {
+			ak = a;
+			top[255] = an;
+		}
+		for (cp = count + bmin; nc > 0; cp++) {
+			while (*cp == 0)	/* Find next non-empty pile. */
+				cp++;
+			if (*cp > 1) {
+				if (*cp > bigc) {
+					bigc = *cp;
+					sp1 = sp;
+				}
+				push(ak, *cp, i+1);
+			}
+			top[cp-count] = ak += *cp;
+			nc--;
+		}
+		swap(*sp0, *sp1, temp);	/* Play it safe -- biggest bin last. */
+
+		/*
+		 * Permute misplacements home.  Already home: everything
+		 * before aj, and in bin[c], items from top[c] on.
+		 * Inner loop:
+		 *	r = next element to put in place;
+		 *	ak = top[r[i]] = location to put the next element.
+		 *	aj = bottom of 1st disordered bin.
+		 * Outer loop:
+		 *	Once the 1st disordered bin is done, ie. aj >= ak,
+		 *	aj<-aj + count[c] connects the bins in a linked list;
+		 *	reset count[c].
+		 */
+		for (aj = a; aj < an;  *aj = r, aj += count[c], count[c] = 0)
+			for (r = *aj;  aj < (ak = --top[c = tr[r[i]]]);)
+				swap(*ak, r, t);
+	}
+}
+
+/* Stable sort, requiring additional memory. */
+static void
+r_sort_b(a, ta, n, i, tr, endch)
+	const u_char **a, **ta;
+	int n, i;
+	const u_char *tr;
+	u_int endch;
+{
+	static int count[256], nc, bmin;
+	int c;
+	const u_char **ak, **ai;
+	stack s[512], *sp, *sp0, *sp1, temp;
+	const u_char **top[256];
+	int *cp, bigc;
+
+	sp = s;
+	push(a, n, i);
+	while (!empty(s)) {
+		pop(a, n, i);
+		if (n < THRESHOLD) {
+			simplesort(a, n, i, tr, endch);
+			continue;
+		}
+
+		if (nc == 0) {
+			bmin = 255;
+			for (ak = a + n; --ak >= a;) {
+				c = tr[(*ak)[i]];
+				if (++count[c] == 1 && c != endch) {
+					if (c < bmin)
+						bmin = c;
+					nc++;
+				}
+			}
+			if (sp + nc > s + SIZE) {
+				r_sort_b(a, ta, n, i, tr, endch);
+				continue;
+			}
+		}
+
+		sp0 = sp1 = sp;
+		bigc = 2;
+		if (endch == 0) {
+			top[0] = ak = a + count[0];
+			count[0] = 0;
+		} else {
+			ak = a;
+			top[255] = a + n;
+			count[255] = 0;
+		}
+		for (cp = count + bmin; nc > 0; cp++) {
+			while (*cp == 0)
+				cp++;
+			if ((c = *cp) > 1) {
+				if (c > bigc) {
+					bigc = c;
+					sp1 = sp;
+				}
+				push(ak, c, i+1);
+			}
+			top[cp-count] = ak += c;
+			*cp = 0;			/* Reset count[]. */
+			nc--;
+		}
+		swap(*sp0, *sp1, temp);
+
+		for (ak = ta + n, ai = a+n; ak > ta;)	/* Copy to temp. */
+			*--ak = *--ai;
+		for (ak = ta+n; --ak >= ta;)		/* Deal to piles. */
+			*--top[tr[(*ak)[i]]] = *ak;
+	}
+}
+
+static inline void
+simplesort(a, n, b, tr, endch)	/* insertion sort */
+	const u_char **a;
+	int n, b;
+	const u_char *tr;
+	u_int endch;
+{
+	u_char ch;
+	const u_char  **ak, **ai, *s, *t;
+
+	for (ak = a+1; --n >= 1; ak++)
+		for (ai = ak; ai > a; ai--) {
+			for (s = ai[0] + b, t = ai[-1] + b;
+			    (ch = tr[*s]) != endch; s++, t++)
+				if (ch != tr[*t])
+					break;
+			if (ch >= tr[*t])
+				break;
+			swap(ai[0], ai[-1], s);
+		}
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/rand.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/rand.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/rand.c	(revision 2448)
@@ -0,0 +1,172 @@
+/*-
+ * Copyright (c) 1990, 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.
+ *
+ * Posix rand_r function added May 1999 by Wes Peters <wes@softweyr.com>.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rand.c	8.1 (Berkeley) 6/14/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/rand.c,v 1.15 2003/02/17 03:52:35 ache Exp $");
+
+#include "namespace.h"
+#include <sys/time.h>          /* for sranddev() */
+#include <sys/types.h>
+#include <fcntl.h>             /* for sranddev() */
+#include <stdlib.h>
+#include <unistd.h>            /* for sranddev() */
+#include "un-namespace.h"
+
+#ifdef TEST
+#include <stdio.h>
+#endif /* TEST */
+
+static int
+do_rand(unsigned long *ctx)
+{
+#ifdef  USE_WEAK_SEEDING
+/*
+ * Historic implementation compatibility.
+ * The random sequences do not vary much with the seed,
+ * even with overflowing.
+ */
+	return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
+#else   /* !USE_WEAK_SEEDING */
+/*
+ * Compute x = (7^5 * x) mod (2^31 - 1)
+ * wihout overflowing 31 bits:
+ *      (2^31 - 1) = 127773 * (7^5) + 2836
+ * From "Random number generators: good ones are hard to find",
+ * Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ * October 1988, p. 1195.
+ */
+	long hi, lo, x;
+
+	/* Can't be initialized with 0, so use another value. */
+	if (*ctx == 0)
+		*ctx = 123459876;
+	hi = *ctx / 127773;
+	lo = *ctx % 127773;
+	x = 16807 * lo - 2836 * hi;
+	if (x < 0)
+		x += 0x7fffffff;
+	return ((*ctx = x) % ((u_long)RAND_MAX + 1));
+#endif  /* !USE_WEAK_SEEDING */
+}
+
+
+int
+_STD(rand_r)(unsigned int *ctx)
+{
+	u_long val = (u_long) *ctx;
+	int r = do_rand(&val);
+
+	*ctx = (unsigned int) val;
+	return (r);
+}
+
+
+static u_long next = 1;
+
+int
+_STD(rand)()
+{
+	return (do_rand(&next));
+}
+
+void
+_STD(srand)(seed)
+u_int seed;
+{
+	next = seed;
+}
+
+
+/*
+ * sranddev:
+ *
+ * Many programs choose the seed value in a totally predictable manner.
+ * This often causes problems.  We seed the generator using the much more
+ * secure random(4) interface.
+ */
+void
+sranddev()
+{
+	int fd, done;
+
+	done = 0;
+	fd = _open("/dev/random", O_RDONLY, 0);
+	if (fd >= 0) {
+		if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next))
+			done = 1;
+		_close(fd);
+	}
+
+	if (!done) {
+		struct timeval tv;
+		unsigned long junk;
+
+		gettimeofday(&tv, NULL);
+		srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+	}
+}
+
+
+#ifdef TEST
+
+main()
+{
+    int i;
+    unsigned myseed;
+
+    printf("seeding rand with 0x19610910: \n");
+    srand(0x19610910);
+
+    printf("generating three pseudo-random numbers:\n");
+    for (i = 0; i < 3; i++)
+    {
+	printf("next random number = %d\n", rand());
+    }
+
+    printf("generating the same sequence with rand_r:\n");
+    myseed = 0x19610910;
+    for (i = 0; i < 3; i++)
+    {
+	printf("next random number = %d\n", rand_r(&myseed));
+    }
+
+    return 0;
+}
+
+#endif /* TEST */
+
Index: /trunk/libc/src/fbsdlibc/stdlib/random.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/random.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/random.c	(revision 2448)
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)random.c	8.2 (Berkeley) 5/19/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.24 2004/01/20 03:02:18 das Exp $");
+
+#include "namespace.h"
+#include <sys/time.h>          /* for srandomdev() */
+#include <fcntl.h>             /* for srandomdev() */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>            /* for srandomdev() */
+#include "un-namespace.h"
+
+/*
+ * random.c:
+ *
+ * An improved random number generation package.  In addition to the standard
+ * rand()/srand() like interface, this package also has a special state info
+ * interface.  The initstate() routine is called with a seed, an array of
+ * bytes, and a count of how many bytes are being passed in; this array is
+ * then initialized to contain information for random number generation with
+ * that much state information.  Good sizes for the amount of state
+ * information are 32, 64, 128, and 256 bytes.  The state can be switched by
+ * calling the setstate() routine with the same array as was initiallized
+ * with initstate().  By default, the package runs with 128 bytes of state
+ * information and generates far better random numbers than a linear
+ * congruential generator.  If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used.
+ *
+ * Internally, the state information is treated as an array of uint32_t's; the
+ * zeroeth element of the array is the type of R.N.G. being used (small
+ * integer); the remainder of the array is the state information for the
+ * R.N.G.  Thus, 32 bytes of state information will give 7 ints worth of
+ * state information, which will allow a degree seven polynomial.  (Note:
+ * the zeroeth word of state information also has some other information
+ * stored in it -- see setstate() for details).
+ *
+ * The random number generation technique is a linear feedback shift register
+ * approach, employing trinomials (since there are fewer terms to sum up that
+ * way).  In this approach, the least significant bit of all the numbers in
+ * the state table will act as a linear feedback shift register, and will
+ * have period 2^deg - 1 (where deg is the degree of the polynomial being
+ * used, assuming that the polynomial is irreducible and primitive).  The
+ * higher order bits will have longer periods, since their values are also
+ * influenced by pseudo-random carries out of the lower bits.  The total
+ * period of the generator is approximately deg*(2**deg - 1); thus doubling
+ * the amount of state information has a vast influence on the period of the
+ * generator.  Note: the deg*(2**deg - 1) is an approximation only good for
+ * large deg, when the period of the shift is the dominant factor.
+ * With deg equal to seven, the period is actually much longer than the
+ * 7*(2**7 - 1) predicted by this formula.
+ *
+ * Modified 28 December 1994 by Jacob S. Rosenberg.
+ * The following changes have been made:
+ * All references to the type u_int have been changed to unsigned long.
+ * All references to type int have been changed to type long.  Other
+ * cleanups have been made as well.  A warning for both initstate and
+ * setstate has been inserted to the effect that on Sparc platforms
+ * the 'arg_state' variable must be forced to begin on word boundaries.
+ * This can be easily done by casting a long integer array to char *.
+ * The overall logic has been left STRICTLY alone.  This software was
+ * tested on both a VAX and Sun SpacsStation with exactly the same
+ * results.  The new version and the original give IDENTICAL results.
+ * The new version is somewhat faster than the original.  As the
+ * documentation says:  "By default, the package runs with 128 bytes of
+ * state information and generates far better random numbers than a linear
+ * congruential generator.  If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used."  For a buffer of
+ * 128 bytes, this new version runs about 19 percent faster and for a 16
+ * byte buffer it is about 5 percent faster.
+ */
+
+/*
+ * For each of the currently supported random number generators, we have a
+ * break value on the amount of state information (you need at least this
+ * many bytes of state info to support this random number generator), a degree
+ * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ * the separation between the two lower order coefficients of the trinomial.
+ */
+#define	TYPE_0		0		/* linear congruential */
+#define	BREAK_0		8
+#define	DEG_0		0
+#define	SEP_0		0
+
+#define	TYPE_1		1		/* x**7 + x**3 + 1 */
+#define	BREAK_1		32
+#define	DEG_1		7
+#define	SEP_1		3
+
+#define	TYPE_2		2		/* x**15 + x + 1 */
+#define	BREAK_2		64
+#define	DEG_2		15
+#define	SEP_2		1
+
+#define	TYPE_3		3		/* x**31 + x**3 + 1 */
+#define	BREAK_3		128
+#define	DEG_3		31
+#define	SEP_3		3
+
+#define	TYPE_4		4		/* x**63 + x + 1 */
+#define	BREAK_4		256
+#define	DEG_4		63
+#define	SEP_4		1
+
+/*
+ * Array versions of the above information to make code run faster --
+ * relies on fact that TYPE_i == i.
+ */
+#define	MAX_TYPES	5		/* max number of types above */
+
+#ifdef  USE_WEAK_SEEDING
+#define NSHUFF 0
+#else   /* !USE_WEAK_SEEDING */
+#define NSHUFF 50       /* to drop some "seed -> 1st value" linearity */
+#endif  /* !USE_WEAK_SEEDING */
+
+static const int degrees[MAX_TYPES] =	{ DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static const int seps [MAX_TYPES] =	{ SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+/*
+ * Initially, everything is set up as if from:
+ *
+ *	initstate(1, randtbl, 128);
+ *
+ * Note that this initialization takes advantage of the fact that srandom()
+ * advances the front and rear pointers 10*rand_deg times, and hence the
+ * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ * element of the state information, which contains info about the current
+ * position of the rear pointer is just
+ *
+ *	MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
+ */
+
+static uint32_t randtbl[DEG_3 + 1] = {
+	TYPE_3,
+#ifdef  USE_WEAK_SEEDING
+/* Historic implementation compatibility */
+/* The random sequences do not vary much with the seed */
+	0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
+	0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
+	0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
+	0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
+	0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
+	0x27fb47b9,
+#else   /* !USE_WEAK_SEEDING */
+	0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
+	0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
+	0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
+	0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
+	0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
+	0xf3bec5da
+#endif  /* !USE_WEAK_SEEDING */
+};
+
+/*
+ * fptr and rptr are two pointers into the state info, a front and a rear
+ * pointer.  These two pointers are always rand_sep places aparts, as they
+ * cycle cyclically through the state information.  (Yes, this does mean we
+ * could get away with just one pointer, but the code for random() is more
+ * efficient this way).  The pointers are left positioned as they would be
+ * from the call
+ *
+ *	initstate(1, randtbl, 128);
+ *
+ * (The position of the rear pointer, rptr, is really 0 (as explained above
+ * in the initialization of randtbl) because the state table pointer is set
+ * to point to randtbl[1] (as explained below).
+ */
+static uint32_t *fptr = &randtbl[SEP_3 + 1];
+static uint32_t *rptr = &randtbl[1];
+
+/*
+ * The following things are the pointer to the state information table, the
+ * type of the current generator, the degree of the current polynomial being
+ * used, and the separation between the two pointers.  Note that for efficiency
+ * of random(), we remember the first location of the state information, not
+ * the zeroeth.  Hence it is valid to access state[-1], which is used to
+ * store the type of the R.N.G.  Also, we remember the last location, since
+ * this is more efficient than indexing every time to find the address of
+ * the last element to see if the front and rear pointers have wrapped.
+ */
+static uint32_t *state = &randtbl[1];
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
+
+static inline uint32_t good_rand(int32_t);
+
+static inline uint32_t good_rand (x)
+	int32_t x;
+{
+#ifdef  USE_WEAK_SEEDING
+/*
+ * Historic implementation compatibility.
+ * The random sequences do not vary much with the seed,
+ * even with overflowing.
+ */
+	return (1103515245 * x + 12345);
+#else   /* !USE_WEAK_SEEDING */
+/*
+ * Compute x = (7^5 * x) mod (2^31 - 1)
+ * wihout overflowing 31 bits:
+ *      (2^31 - 1) = 127773 * (7^5) + 2836
+ * From "Random number generators: good ones are hard to find",
+ * Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ * October 1988, p. 1195.
+ */
+	int32_t hi, lo;
+
+	/* Can't be initialized with 0, so use another value. */
+	if (x == 0)
+		x = 123459876;
+	hi = x / 127773;
+	lo = x % 127773;
+	x = 16807 * lo - 2836 * hi;
+	if (x < 0)
+		x += 0x7fffffff;
+	return (x);
+#endif  /* !USE_WEAK_SEEDING */
+}
+
+/*
+ * srandom:
+ *
+ * Initialize the random number generator based on the given seed.  If the
+ * type is the trivial no-state-information type, just remember the seed.
+ * Otherwise, initializes state[] based on the given "seed" via a linear
+ * congruential generator.  Then, the pointers are set to known locations
+ * that are exactly rand_sep places apart.  Lastly, it cycles the state
+ * information a given number of times to get rid of any initial dependencies
+ * introduced by the L.C.R.N.G.  Note that the initialization of randtbl[]
+ * for default usage relies on values produced by this routine.
+ */
+void
+_STD(srandom)(x)
+	unsigned long x;
+{
+	int i, lim;
+
+	state[0] = (uint32_t)x;
+	if (rand_type == TYPE_0)
+		lim = NSHUFF;
+	else {
+		for (i = 1; i < rand_deg; i++)
+			state[i] = good_rand(state[i - 1]);
+		fptr = &state[rand_sep];
+		rptr = &state[0];
+		lim = 10 * rand_deg;
+	}
+	for (i = 0; i < lim; i++)
+		(void)random();
+}
+
+/*
+ * srandomdev:
+ *
+ * Many programs choose the seed value in a totally predictable manner.
+ * This often causes problems.  We seed the generator using the much more
+ * secure random(4) interface.  Note that this particular seeding
+ * procedure can generate states which are impossible to reproduce by
+ * calling srandom() with any value, since the succeeding terms in the
+ * state buffer are no longer derived from the LC algorithm applied to
+ * a fixed seed.
+ */
+void
+srandomdev()
+{
+	int fd, done;
+	size_t len;
+
+	if (rand_type == TYPE_0)
+		len = sizeof state[0];
+	else
+		len = rand_deg * sizeof state[0];
+
+	done = 0;
+	fd = _open("/dev/random", O_RDONLY, 0);
+	if (fd >= 0) {
+		if (_read(fd, (void *) state, len) == (ssize_t) len)
+			done = 1;
+		_close(fd);
+	}
+
+	if (!done) {
+		struct timeval tv;
+		unsigned long junk;
+
+		gettimeofday(&tv, NULL);
+		srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+		return;
+	}
+
+	if (rand_type != TYPE_0) {
+		fptr = &state[rand_sep];
+		rptr = &state[0];
+	}
+}
+
+/*
+ * initstate:
+ *
+ * Initialize the state information in the given array of n bytes for future
+ * random number generation.  Based on the number of bytes we are given, and
+ * the break values for the different R.N.G.'s, we choose the best (largest)
+ * one we can and set things up for it.  srandom() is then called to
+ * initialize the state information.
+ *
+ * Note that on return from srandom(), we set state[-1] to be the type
+ * multiplexed with the current value of the rear pointer; this is so
+ * successive calls to initstate() won't lose this information and will be
+ * able to restart with setstate().
+ *
+ * Note: the first thing we do is save the current state, if any, just like
+ * setstate() so that it doesn't matter when initstate is called.
+ *
+ * Returns a pointer to the old state.
+ *
+ * Note: The Sparc platform requires that arg_state begin on an int
+ * word boundary; otherwise a bus error will occur. Even so, lint will
+ * complain about mis-alignment, but you should disregard these messages.
+ */
+char *
+_STD(initstate)(seed, arg_state, n)
+	unsigned long seed;		/* seed for R.N.G. */
+	char *arg_state;		/* pointer to state array */
+	long n;				/* # bytes of state info */
+{
+	char *ostate = (char *)(&state[-1]);
+	uint32_t *int_arg_state = (uint32_t *)arg_state;
+
+	if (rand_type == TYPE_0)
+		state[-1] = rand_type;
+	else
+		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+	if (n < BREAK_0) {
+		(void)fprintf(stderr,
+		    "random: not enough state (%ld bytes); ignored.\n", n);
+		return(0);
+	}
+	if (n < BREAK_1) {
+		rand_type = TYPE_0;
+		rand_deg = DEG_0;
+		rand_sep = SEP_0;
+	} else if (n < BREAK_2) {
+		rand_type = TYPE_1;
+		rand_deg = DEG_1;
+		rand_sep = SEP_1;
+	} else if (n < BREAK_3) {
+		rand_type = TYPE_2;
+		rand_deg = DEG_2;
+		rand_sep = SEP_2;
+	} else if (n < BREAK_4) {
+		rand_type = TYPE_3;
+		rand_deg = DEG_3;
+		rand_sep = SEP_3;
+	} else {
+		rand_type = TYPE_4;
+		rand_deg = DEG_4;
+		rand_sep = SEP_4;
+	}
+	state = int_arg_state + 1; /* first location */
+	end_ptr = &state[rand_deg];	/* must set end_ptr before srandom */
+	srandom(seed);
+	if (rand_type == TYPE_0)
+		int_arg_state[0] = rand_type;
+	else
+		int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
+	return(ostate);
+}
+
+/*
+ * setstate:
+ *
+ * Restore the state from the given state array.
+ *
+ * Note: it is important that we also remember the locations of the pointers
+ * in the current state information, and restore the locations of the pointers
+ * from the old state information.  This is done by multiplexing the pointer
+ * location into the zeroeth word of the state information.
+ *
+ * Note that due to the order in which things are done, it is OK to call
+ * setstate() with the same state as the current state.
+ *
+ * Returns a pointer to the old state information.
+ *
+ * Note: The Sparc platform requires that arg_state begin on an int
+ * word boundary; otherwise a bus error will occur. Even so, lint will
+ * complain about mis-alignment, but you should disregard these messages.
+ */
+char *
+_STD(setstate)(arg_state)
+	char *arg_state;		/* pointer to state array */
+{
+	uint32_t *new_state = (uint32_t *)arg_state;
+	uint32_t type = new_state[0] % MAX_TYPES;
+	uint32_t rear = new_state[0] / MAX_TYPES;
+	char *ostate = (char *)(&state[-1]);
+
+	if (rand_type == TYPE_0)
+		state[-1] = rand_type;
+	else
+		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+	switch(type) {
+	case TYPE_0:
+	case TYPE_1:
+	case TYPE_2:
+	case TYPE_3:
+	case TYPE_4:
+		rand_type = type;
+		rand_deg = degrees[type];
+		rand_sep = seps[type];
+		break;
+	default:
+		(void)fprintf(stderr,
+		    "random: state info corrupted; not changed.\n");
+	}
+	state = new_state + 1;
+	if (rand_type != TYPE_0) {
+		rptr = &state[rear];
+		fptr = &state[(rear + rand_sep) % rand_deg];
+	}
+	end_ptr = &state[rand_deg];		/* set end_ptr too */
+	return(ostate);
+}
+
+/*
+ * random:
+ *
+ * If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is
+ * the same in all the other cases due to all the global variables that have
+ * been set up.  The basic operation is to add the number at the rear pointer
+ * into the one at the front pointer.  Then both pointers are advanced to
+ * the next location cyclically in the table.  The value returned is the sum
+ * generated, reduced to 31 bits by throwing away the "least random" low bit.
+ *
+ * Note: the code takes advantage of the fact that both the front and
+ * rear pointers can't wrap on the same call by not testing the rear
+ * pointer if the front one has wrapped.
+ *
+ * Returns a 31-bit random number.
+ */
+long
+_STD(random)()
+{
+	uint32_t i;
+	uint32_t *f, *r;
+
+	if (rand_type == TYPE_0) {
+		i = state[0];
+		state[0] = i = (good_rand(i)) & 0x7fffffff;
+	} else {
+		/*
+		 * Use local variables rather than static variables for speed.
+		 */
+		f = fptr; r = rptr;
+		*f += *r;
+		i = (*f >> 1) & 0x7fffffff;	/* chucking least random bit */
+		if (++f >= end_ptr) {
+			f = state;
+			++r;
+		}
+		else if (++r >= end_ptr) {
+			r = state;
+		}
+
+		fptr = f; rptr = r;
+	}
+	return((long)i);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/reallocf.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/reallocf.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/reallocf.c	(revision 2448)
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 1998, M. Warner Losh <imp@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "libc-alias.h" /*bird*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/reallocf.c,v 1.4 2002/03/22 21:53:10 obrien Exp $");
+
+#include <stdlib.h>
+
+void *
+reallocf(void *ptr, size_t size)
+{
+	void *nptr;
+
+	nptr = realloc(ptr, size);
+	if (!nptr && ptr)
+		free(ptr);
+	return (nptr);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/remque.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/remque.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/remque.c	(revision 2448)
@@ -0,0 +1,31 @@
+/*
+ * Initial implementation:
+ * Copyright (c) 2002 Robert Drehmel
+ * All rights reserved.
+ *
+ * As long as the above copyright statement and this notice remain
+ * unchanged, you can do what ever you want with this file.
+ */
+#include "libc-alias.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/remque.c,v 1.3 2003/01/04 07:34:41 tjr Exp $");
+
+#define	_SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>	/* for NULL */
+
+void
+_STD(remque)(void *element)
+{
+	struct que_elem *prev, *next, *elem;
+
+	elem = (struct que_elem *)element;
+
+	prev = elem->prev;
+	next = elem->next;
+
+	if (prev != NULL)
+		prev->next = next;
+	if (next != NULL)
+		next->prev = prev;
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/stdlib.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/stdlib.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/stdlib.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/fbsdlibc/stdlib/*.c)
Index: /trunk/libc/src/fbsdlibc/stdlib/strtoimax.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/strtoimax.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/strtoimax.c	(revision 2448)
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 1992, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "from @(#)strtol.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include "namespace.h" /*bird*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.9 2003/01/01 18:48:43 schweikh Exp $");
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+/*
+ * Convert a string to an intmax_t integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+intmax_t
+_STD(strtoimax)(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+	const char *s;
+	uintmax_t acc;
+	char c;
+	uintmax_t cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	/*
+	 * Compute the cutoff value between legal numbers and illegal
+	 * numbers.  That is the largest legal value, divided by the
+	 * base.  An input number that is greater than this value, if
+	 * followed by a legal input character, is too big.  One that
+	 * is equal to this value may be valid or not; the limit
+	 * between valid and invalid numbers is then based on the last
+	 * digit.  For instance, if the range for intmax_t is
+	 * [-9223372036854775808..9223372036854775807] and the input base
+	 * is 10, cutoff will be set to 922337203685477580 and cutlim to
+	 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+	 * accumulated a value > 922337203685477580, or equal but the
+	 * next digit is > 7 (or 8), the number is too big, and we will
+	 * return a range error.
+	 *
+	 * Set 'any' if any `digits' consumed; make it negative to indicate
+	 * overflow.
+	 */
+	cutoff = neg ? (uintmax_t)-(INTMAX_MIN + INTMAX_MAX) + INTMAX_MAX
+	    : INTMAX_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? INTMAX_MIN : INTMAX_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/strtoumax.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/strtoumax.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/strtoumax.c	(revision 2448)
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 1992, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "from @(#)strtoul.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include "namespace.h" /*bird*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp $");
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+/*
+ * Convert a string to a uintmax_t integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+uintmax_t
+_STD(strtoumax)(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+	const char *s;
+	uintmax_t acc;
+	char c;
+	uintmax_t cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtoimax for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = UINTMAX_MAX / base;
+	cutlim = UINTMAX_MAX % base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = UINTMAX_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/tdelete.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/tdelete.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/tdelete.c	(revision 2448)
@@ -0,0 +1,72 @@
+/*	$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $	*/
+
+/*
+ * 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.
+ */
+
+#include "libc-alias.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/tdelete.c,v 1.6 2003/01/05 02:43:18 tjr Exp $");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+
+/*
+ * delete node with given key
+ *
+ * vkey:   key to be deleted
+ * vrootp: address of the root of the tree
+ * compar: function to carry out node comparisons
+ */
+void *
+_STD(tdelete)(const void * __restrict vkey, void ** __restrict vrootp,
+    int (*compar)(const void *, const void *))
+{
+	node_t **rootp = (node_t **)vrootp;
+	node_t *p, *q, *r;
+	int cmp;
+
+	if (rootp == NULL || (p = *rootp) == NULL)
+		return NULL;
+
+	while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
+		p = *rootp;
+		rootp = (cmp < 0) ?
+		    &(*rootp)->llink :		/* follow llink branch */
+		    &(*rootp)->rlink;		/* follow rlink branch */
+		if (*rootp == NULL)
+			return NULL;		/* key not found */
+	}
+	r = (*rootp)->rlink;			/* D1: */
+	if ((q = (*rootp)->llink) == NULL)	/* Left NULL? */
+		q = r;
+	else if (r != NULL) {			/* Right link is NULL? */
+		if (r->llink == NULL) {		/* D2: Find successor */
+			r->llink = q;
+			q = r;
+		} else {			/* D3: Find NULL link */
+			for (q = r->llink; q->llink != NULL; q = r->llink)
+				r = q;
+			r->llink = q->rlink;
+			q->llink = (*rootp)->llink;
+			q->rlink = (*rootp)->rlink;
+		}
+	}
+	free(*rootp);				/* D4: Free node */
+	*rootp = q;				/* link parent to new node */
+	return p;
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/tfind.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/tfind.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/tfind.c	(revision 2448)
@@ -0,0 +1,49 @@
+/*	$NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $	*/
+
+/*
+ * 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.
+ */
+
+#include "libc-alias.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/tfind.c,v 1.5 2003/01/05 02:43:18 tjr Exp $");
+
+#define _SEARCH_PRIVATE
+#include <stdlib.h>
+#include <search.h>
+
+/* find a node, or return 0 */
+void *
+_STD(tfind)(vkey, vrootp, compar)
+	const void *vkey;		/* key to be found */
+	void * const *vrootp;		/* address of the tree root */
+	int (*compar)(const void *, const void *);
+{
+	node_t **rootp = (node_t **)vrootp;
+
+	if (rootp == NULL)
+		return NULL;
+
+	while (*rootp != NULL) {		/* T1: */
+		int r;
+
+		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
+			return *rootp;		/* key found */
+		rootp = (r < 0) ?
+		    &(*rootp)->llink :		/* T3: follow left branch */
+		    &(*rootp)->rlink;		/* T4: follow right branch */
+	}
+	return NULL;
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/tsearch.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/tsearch.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/tsearch.c	(revision 2448)
@@ -0,0 +1,59 @@
+/*	$NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $	*/
+
+/*
+ * 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.
+ */
+
+#include "libc-alias.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/tsearch.c,v 1.4 2003/01/05 02:43:18 tjr Exp $");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+/* find or insert datum into search tree */
+void *
+_STD(tsearch)(vkey, vrootp, compar)
+	const void *vkey;		/* key to be located */
+	void **vrootp;			/* address of tree root */
+	int (*compar)(const void *, const void *);
+{
+	node_t *q;
+	node_t **rootp = (node_t **)vrootp;
+
+	if (rootp == NULL)
+		return NULL;
+
+	while (*rootp != NULL) {	/* Knuth's T1: */
+		int r;
+
+		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
+			return *rootp;		/* we found it! */
+
+		rootp = (r < 0) ?
+		    &(*rootp)->llink :		/* T3: follow left branch */
+		    &(*rootp)->rlink;		/* T4: follow right branch */
+	}
+
+	q = malloc(sizeof(node_t));		/* T5: key not found */
+	if (q != 0) {				/* make new node */
+		*rootp = q;			/* link new node to old */
+		/* LINTED const castaway ok */
+		q->key = (void *)vkey;		/* initialize new node */
+		q->llink = q->rlink = NULL;
+	}
+	return q;
+}
Index: /trunk/libc/src/fbsdlibc/stdlib/twalk.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdlib/twalk.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdlib/twalk.c	(revision 2448)
@@ -0,0 +1,59 @@
+/*	$NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $	*/
+
+/*
+ * 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.
+ */
+
+#include "libc-alias.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/twalk.c,v 1.5 2003/01/05 02:43:18 tjr Exp $");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+static void trecurse(const node_t *,
+    void (*action)(const void *, VISIT, int), int level);
+
+/* Walk the nodes of a tree */
+static void
+trecurse(root, action, level)
+	const node_t *root;	/* Root of the tree to be walked */
+	void (*action)(const void *, VISIT, int);
+	int level;
+{
+
+	if (root->llink == NULL && root->rlink == NULL)
+		(*action)(root, leaf, level);
+	else {
+		(*action)(root, preorder, level);
+		if (root->llink != NULL)
+			trecurse(root->llink, action, level + 1);
+		(*action)(root, postorder, level);
+		if (root->rlink != NULL)
+			trecurse(root->rlink, action, level + 1);
+		(*action)(root, endorder, level);
+	}
+}
+
+/* Walk the nodes of a tree */
+void
+_STD(twalk)(vroot, action)
+	const void *vroot;	/* Root of the tree to be walked */
+	void (*action)(const void *, VISIT, int);
+{
+	if (vroot != NULL && action != NULL)
+		trecurse(vroot, action, 0);
+}
Index: /trunk/libc/src/fbsdlibc/stdtime/difftime.c
===================================================================
--- /trunk/libc/src/fbsdlibc/stdtime/difftime.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdtime/difftime.c	(revision 2448)
@@ -0,0 +1,88 @@
+/*
+** This file is in the public domain, so clarified as of
+** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+#include <sys/cdefs.h>
+#ifndef lint
+#ifndef NOID
+static char	elsieid[] __unused = "@(#)difftime.c	7.9";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/difftime.c,v 1.8 2004/06/14 10:31:52 stefanf Exp $");
+
+/*LINTLIBRARY*/
+
+#include "namespace.h"
+#include "private.h"
+#include "un-namespace.h"
+
+/*
+** Algorithm courtesy Paul Eggert (eggert@twinsun.com).
+*/
+
+#ifdef HAVE_LONG_DOUBLE
+#define long_double	long double
+#endif /* defined HAVE_LONG_DOUBLE */
+#ifndef HAVE_LONG_DOUBLE
+#define long_double	double
+#error "we have long double, why isn't it defined?" /* bird */
+#endif /* !defined HAVE_LONG_DOUBLE */
+
+double
+_STD(difftime)(time1, time0)
+const time_t	time1;
+const time_t	time0;
+{
+	time_t	delta;
+	time_t	hibit;
+
+	{
+		time_t		tt;
+		double		d;
+		long_double	ld;
+
+		if (sizeof tt < sizeof d)
+			return (double) time1 - (double) time0;
+		if (sizeof tt < sizeof ld)
+			return (long_double) time1 - (long_double) time0;
+	}
+	if (time1 < time0)
+		return -difftime(time0, time1);
+	/*
+	** As much as possible, avoid loss of precision
+	** by computing the difference before converting to double.
+	*/
+	delta = time1 - time0;
+	if (delta >= 0)
+		return delta;
+	/*
+	** Repair delta overflow.
+	*/
+	hibit = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1);
+	/*
+	** The following expression rounds twice, which means
+	** the result may not be the closest to the true answer.
+	** For example, suppose time_t is 64-bit signed int,
+	** long_double is IEEE 754 double with default rounding,
+	** time1 = 9223372036854775807 and time0 = -1536.
+	** Then the true difference is 9223372036854777343,
+	** which rounds to 9223372036854777856
+	** with a total error of 513.
+	** But delta overflows to -9223372036854774273,
+	** which rounds to -9223372036854774784, and correcting
+	** this by subtracting 2 * (long_double) hibit
+	** (i.e. by adding 2**64 = 18446744073709551616)
+	** yields 9223372036854776832, which
+	** rounds to 9223372036854775808
+	** with a total error of 1535 instead.
+	** This problem occurs only with very large differences.
+	** It's too painful to fix this portably.
+	** We are not alone in this problem;
+	** some C compilers round twice when converting
+	** large unsigned types to small floating types,
+	** so if time_t is unsigned the "return delta" above
+	** has the same double-rounding problem with those compilers.
+	*/
+	return delta - 2 * (long_double) hibit;
+}
Index: /trunk/libc/src/fbsdlibc/stdtime/private.h
===================================================================
--- /trunk/libc/src/fbsdlibc/stdtime/private.h	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdtime/private.h	(revision 2448)
@@ -0,0 +1,260 @@
+#ifndef PRIVATE_H
+
+#define PRIVATE_H
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+**
+** $FreeBSD: src/lib/libc/stdtime/private.h,v 1.10 2004/06/14 10:31:52 stefanf Exp $
+*/
+
+/* Stuff moved from Makefile.inc to reduce clutter */
+#ifndef TM_GMTOFF
+#define TM_GMTOFF	tm_gmtoff
+#define TM_ZONE		tm_zone
+#define STD_INSPIRED	1
+#define PCTS		1
+#define HAVE_LONG_DOUBLE 1
+#define HAVE_STRERROR	1
+#define	HAVE_UNISTD_H	1
+#define	LOCALE_HOME	_PATH_LOCALE
+#define TZDIR		"/usr/share/zoneinfo"
+#endif /* ndef TM_GMTOFF */
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#ifndef lint
+#ifndef NOID
+/*
+static char	privatehid[] = "@(#)private.h	7.53";
+*/
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Defaults for preprocessor symbols.
+** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
+*/
+
+#ifndef HAVE_ADJTIME
+#define HAVE_ADJTIME		1
+#endif /* !defined HAVE_ADJTIME */
+
+#ifndef HAVE_GETTEXT
+#define HAVE_GETTEXT		0
+#endif /* !defined HAVE_GETTEXT */
+
+#ifndef HAVE_INCOMPATIBLE_CTIME_R
+#define HAVE_INCOMPATIBLE_CTIME_R	0
+#endif /* !defined INCOMPATIBLE_CTIME_R */
+
+#ifndef HAVE_SETTIMEOFDAY
+#define HAVE_SETTIMEOFDAY	3
+#endif /* !defined HAVE_SETTIMEOFDAY */
+
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR		1
+#endif /* !defined HAVE_STRERROR */
+
+#ifndef HAVE_SYMLINK
+#define HAVE_SYMLINK		1
+#endif /* !defined HAVE_SYMLINK */
+
+#ifndef HAVE_SYS_STAT_H
+#define HAVE_SYS_STAT_H		1
+#endif /* !defined HAVE_SYS_STAT_H */
+
+#ifndef HAVE_SYS_WAIT_H
+#define HAVE_SYS_WAIT_H		1
+#endif /* !defined HAVE_SYS_WAIT_H */
+
+#ifndef HAVE_UNISTD_H
+#define HAVE_UNISTD_H		1
+#endif /* !defined HAVE_UNISTD_H */
+
+#ifndef HAVE_UTMPX_H
+#define HAVE_UTMPX_H		0
+#endif /* !defined HAVE_UTMPX_H */
+
+#ifndef LOCALE_HOME
+#define LOCALE_HOME		"/usr/lib/locale"
+#endif /* !defined LOCALE_HOME */
+
+#if HAVE_INCOMPATIBLE_CTIME_R
+#define asctime_r _incompatible_asctime_r
+#define ctime_r _incompatible_ctime_r
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
+/*
+** Nested includes
+*/
+
+#include "sys/types.h"	/* for time_t */
+#include "stdio.h"
+#include "errno.h"
+#include "string.h"
+#include "limits.h"	/* for CHAR_BIT */
+#include "time.h"
+#include "stdlib.h"
+
+#if HAVE_GETTEXT - 0
+#include "libintl.h"
+#endif /* HAVE_GETTEXT - 0 */
+
+#if HAVE_SYS_WAIT_H - 0
+#include <sys/wait.h>	/* for WIFEXITED and WEXITSTATUS */
+#endif /* HAVE_SYS_WAIT_H - 0 */
+
+#ifndef WIFEXITED
+#define WIFEXITED(status)	(((status) & 0xff) == 0)
+#endif /* !defined WIFEXITED */
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(status)	(((status) >> 8) & 0xff)
+#endif /* !defined WEXITSTATUS */
+
+#if HAVE_UNISTD_H - 0
+#include "unistd.h"	/* for F_OK and R_OK */
+#endif /* HAVE_UNISTD_H - 0 */
+
+#if !(HAVE_UNISTD_H - 0)
+#ifndef F_OK
+#define F_OK	0
+#endif /* !defined F_OK */
+#ifndef R_OK
+#define R_OK	4
+#endif /* !defined R_OK */
+#endif /* !(HAVE_UNISTD_H - 0) */
+
+/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX.  */
+#define is_digit(c) ((unsigned)(c) - '0' <= 9)
+
+/*
+** SunOS 4.1.1 headers lack FILENAME_MAX.
+*/
+
+#ifndef FILENAME_MAX
+
+#ifndef MAXPATHLEN
+#ifdef unix
+#include "sys/param.h"
+#endif /* defined unix */
+#endif /* !defined MAXPATHLEN */
+
+#ifdef MAXPATHLEN
+#define FILENAME_MAX	MAXPATHLEN
+#endif /* defined MAXPATHLEN */
+#ifndef MAXPATHLEN
+#define FILENAME_MAX	1024		/* Pure guesswork */
+#endif /* !defined MAXPATHLEN */
+
+#endif /* !defined FILENAME_MAX */
+
+/*
+** Private function declarations.
+*/
+char *	icalloc(int nelem, int elsize);
+char *	icatalloc(char * old, const char * new);
+char *	icpyalloc(const char * string);
+char *	imalloc(int n);
+void *	irealloc(void * pointer, int size);
+void	icfree(char * pointer);
+void	ifree(char * pointer);
+char *	scheck(const char *string, const char *format);
+
+
+/*
+** Finally, some convenience items.
+*/
+
+#ifndef TRUE
+#define TRUE	1
+#endif /* !defined TRUE */
+
+#ifndef FALSE
+#define FALSE	0
+#endif /* !defined FALSE */
+
+#ifndef TYPE_BIT
+#define TYPE_BIT(type)	(sizeof (type) * CHAR_BIT)
+#endif /* !defined TYPE_BIT */
+
+#ifndef TYPE_SIGNED
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#endif /* !defined TYPE_SIGNED */
+
+#ifndef INT_STRLEN_MAXIMUM
+/*
+** 302 / 1000 is log10(2.0) rounded up.
+** Subtract one for the sign bit if the type is signed;
+** add one for integer division truncation;
+** add one more for a minus sign if the type is signed.
+*/
+#define INT_STRLEN_MAXIMUM(type) \
+    ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
+#endif /* !defined INT_STRLEN_MAXIMUM */
+
+/*
+** INITIALIZE(x)
+*/
+
+#ifndef GNUC_or_lint
+#ifdef lint
+#define GNUC_or_lint
+#endif /* defined lint */
+#ifndef lint
+#ifdef __GNUC__
+#define GNUC_or_lint
+#endif /* defined __GNUC__ */
+#endif /* !defined lint */
+#endif /* !defined GNUC_or_lint */
+
+#ifndef INITIALIZE
+#ifdef GNUC_or_lint
+#define INITIALIZE(x)	((x) = 0)
+#endif /* defined GNUC_or_lint */
+#ifndef GNUC_or_lint
+#define INITIALIZE(x)
+#endif /* !defined GNUC_or_lint */
+#endif /* !defined INITIALIZE */
+
+/*
+** For the benefit of GNU folk...
+** `_(MSGID)' uses the current locale's message library string for MSGID.
+** The default is to use gettext if available, and use MSGID otherwise.
+*/
+
+#ifndef _
+#if HAVE_GETTEXT - 0
+#define _(msgid) gettext(msgid)
+#else /* !(HAVE_GETTEXT - 0) */
+#define _(msgid) msgid
+#endif /* !(HAVE_GETTEXT - 0) */
+#endif /* !defined _ */
+
+#ifndef TZ_DOMAIN
+#define TZ_DOMAIN "tz"
+#endif /* !defined TZ_DOMAIN */
+
+#if HAVE_INCOMPATIBLE_CTIME_R
+#undef asctime_r
+#undef ctime_r
+char *asctime_r(struct tm const *, char *);
+char *ctime_r(time_t const *, char *);
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
+/*
+** UNIX was a registered trademark of The Open Group in 2003.
+*/
+
+#endif /* !defined PRIVATE_H */
Index: /trunk/libc/src/fbsdlibc/stdtime/stdtime.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/stdtime/stdtime.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/stdtime/stdtime.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/fbsdlibc/stdtime/*.c)
Index: /trunk/libc/src/fbsdlibc/string/stpcpy.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/stpcpy.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/stpcpy.c	(revision 2448)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1999
+ *	David E. O'Brien
+ * Copyright (c) 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. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcpy.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/stpcpy.c,v 1.1 2002/10/03 19:39:20 obrien Exp $");
+
+#include <string.h>
+
+char *
+stpcpy(char * to, const char * from)
+{
+
+	for (; (*to = *from); ++from, ++to);
+	return(to);
+}
Index: /trunk/libc/src/fbsdlibc/string/strcasestr.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strcasestr.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strcasestr.c	(revision 2448)
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strcasestr.c,v 1.3 2002/03/21 18:44:54 obrien Exp $");
+
+#include <ctype.h>
+#include <string.h>
+
+/*
+ * Find the first occurrence of find in s, ignore case.
+ */
+char *
+strcasestr(s, find)
+	const char *s, *find;
+{
+	char c, sc;
+	size_t len;
+
+	if ((c = *find++) != 0) {
+		c = tolower((unsigned char)c);
+		len = strlen(find);
+		do {
+			do {
+				if ((sc = *s++) == 0)
+					return (NULL);
+			} while ((char)tolower((unsigned char)sc) != c);
+		} while (strncasecmp(s, find, len) != 0);
+		s--;
+	}
+	return ((char *)s);
+}
Index: /trunk/libc/src/fbsdlibc/string/string.smak
===================================================================
--- /trunk/libc/src/fbsdlibc/string/string.smak	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/string.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/fbsdlibc/string/*.c)
Index: /trunk/libc/src/fbsdlibc/string/strlcat.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strlcat.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strlcat.c	(revision 2448)
@@ -0,0 +1,76 @@
+/*	$OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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 "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $");
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strlcat.c,v 1.9 2003/05/01 19:03:14 nectar Exp $");
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(dst, src, siz)
+	char *dst;
+	const char *src;
+	size_t siz;
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end */
+	while (n-- != 0 && *d != '\0')
+		d++;
+	dlen = d - dst;
+	n = siz - dlen;
+
+	if (n == 0)
+		return(dlen + strlen(s));
+	while (*s != '\0') {
+		if (n != 1) {
+			*d++ = *s;
+			n--;
+		}
+		s++;
+	}
+	*d = '\0';
+
+	return(dlen + (s - src));	/* count does not include NUL */
+}
Index: /trunk/libc/src/fbsdlibc/string/strlcpy.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strlcpy.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strlcpy.c	(revision 2448)
@@ -0,0 +1,70 @@
+/*	$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $");
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.7 2003/05/01 19:03:14 nectar Exp $");
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t strlcpy(dst, src, siz)
+	char *dst;
+	const char *src;
+	size_t siz;
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
Index: /trunk/libc/src/fbsdlibc/string/strmode.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strmode.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strmode.c	(revision 2448)
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (c) 1990, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strmode.c	8.3 (Berkeley) 8/15/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strmode.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+void
+strmode(mode, p)
+	mode_t mode;
+	char *p;
+{
+	 /* print type */
+	switch (mode & S_IFMT) {
+	case S_IFDIR:			/* directory */
+		*p++ = 'd';
+		break;
+	case S_IFCHR:			/* character special */
+		*p++ = 'c';
+		break;
+	case S_IFBLK:			/* block special */
+		*p++ = 'b';
+		break;
+	case S_IFREG:			/* regular */
+		*p++ = '-';
+		break;
+	case S_IFLNK:			/* symbolic link */
+		*p++ = 'l';
+		break;
+	case S_IFSOCK:			/* socket */
+		*p++ = 's';
+		break;
+#ifdef S_IFIFO
+	case S_IFIFO:			/* fifo */
+		*p++ = 'p';
+		break;
+#endif
+#ifdef S_IFWHT
+	case S_IFWHT:			/* whiteout */
+		*p++ = 'w';
+		break;
+#endif
+	default:			/* unknown */
+		*p++ = '?';
+		break;
+	}
+	/* usr */
+	if (mode & S_IRUSR)
+		*p++ = 'r';
+	else
+		*p++ = '-';
+	if (mode & S_IWUSR)
+		*p++ = 'w';
+	else
+		*p++ = '-';
+	switch (mode & (S_IXUSR | S_ISUID)) {
+	case 0:
+		*p++ = '-';
+		break;
+	case S_IXUSR:
+		*p++ = 'x';
+		break;
+	case S_ISUID:
+		*p++ = 'S';
+		break;
+	case S_IXUSR | S_ISUID:
+		*p++ = 's';
+		break;
+	}
+	/* group */
+	if (mode & S_IRGRP)
+		*p++ = 'r';
+	else
+		*p++ = '-';
+	if (mode & S_IWGRP)
+		*p++ = 'w';
+	else
+		*p++ = '-';
+	switch (mode & (S_IXGRP | S_ISGID)) {
+	case 0:
+		*p++ = '-';
+		break;
+	case S_IXGRP:
+		*p++ = 'x';
+		break;
+	case S_ISGID:
+		*p++ = 'S';
+		break;
+	case S_IXGRP | S_ISGID:
+		*p++ = 's';
+		break;
+	}
+	/* other */
+	if (mode & S_IROTH)
+		*p++ = 'r';
+	else
+		*p++ = '-';
+	if (mode & S_IWOTH)
+		*p++ = 'w';
+	else
+		*p++ = '-';
+	switch (mode & (S_IXOTH | S_ISVTX)) {
+	case 0:
+		*p++ = '-';
+		break;
+	case S_IXOTH:
+		*p++ = 'x';
+		break;
+	case S_ISVTX:
+		*p++ = 'T';
+		break;
+	case S_IXOTH | S_ISVTX:
+		*p++ = 't';
+		break;
+	}
+	*p++ = ' ';		/* will be a '+' if ACL's implemented */
+	*p = '\0';
+}
Index: /trunk/libc/src/fbsdlibc/string/strnstr.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strnstr.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strnstr.c	(revision 2448)
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strstr.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strnstr.c,v 1.2 2001/11/07 19:55:16 obrien Exp $");
+
+#include <string.h>
+
+/*
+ * Find the first occurrence of find in s, where the search is limited to the
+ * first slen characters of s.
+ */
+char *
+strnstr(s, find, slen)
+	const char *s;
+	const char *find;
+	size_t slen;
+{
+	char c, sc;
+	size_t len;
+
+	if ((c = *find++) != '\0') {
+		len = strlen(find);
+		do {
+			do {
+				if ((sc = *s++) == '\0' || slen-- < 1)
+					return (NULL);
+			} while (sc != c);
+			if (len > slen)
+				return (NULL);
+		} while (strncmp(s, find, len) != 0);
+		s--;
+	}
+	return ((char *)s);
+}
Index: /trunk/libc/src/fbsdlibc/string/strsep.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strsep.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strsep.c	(revision 2448)
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 1990, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strsep.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strsep.c,v 1.5 2002/03/21 18:44:54 obrien Exp $");
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(stringp, delim)
+	char **stringp;
+	const char *delim;
+{
+	char *s;
+	const char *spanp;
+	int c, sc;
+	char *tok;
+
+	if ((s = *stringp) == NULL)
+		return (NULL);
+	for (tok = s;;) {
+		c = *s++;
+		spanp = delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = 0;
+				*stringp = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
Index: /trunk/libc/src/fbsdlibc/string/strsignal.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strsignal.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strsignal.c	(revision 2448)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strerror.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strsignal.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+char *
+strsignal(num)
+	int num;
+{
+#define	UPREFIX	"Unknown signal: "
+	static char ebuf[40] = UPREFIX;		/* 64-bit number + slop */
+	unsigned int signum;
+	char *p, *t;
+	char tmp[40];
+
+	signum = num;				/* convert to unsigned */
+	if (signum < sys_nsig)
+		return ((char *)sys_siglist[signum]);
+
+	/* Do this by hand, so we don't link to stdio(3). */
+	t = tmp;
+	if (num < 0)
+		signum = -signum;
+	do {
+		*t++ = "0123456789"[signum % 10];
+	} while (signum /= 10);
+	if (num < 0)
+		*t++ = '-';
+	for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+		*p++ = *--t;
+		if (t <= tmp)
+			break;
+	}
+	*p = '\0';
+	return (ebuf);
+}
Index: /trunk/libc/src/fbsdlibc/string/strspn.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strspn.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strspn.c	(revision 2448)
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ * 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.
+ */
+
+#include "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strspn.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strspn.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+
+#include <string.h>
+
+/*
+ * Span the string s2 (skip characters that are in s2).
+ */
+size_t
+_STD(strspn)(s1, s2)
+	const char *s1;
+	const char *s2;
+{
+	const char *p = s1, *spanp;
+	char c, sc;
+
+	/*
+	 * Skip any characters in s2, excluding the terminating \0.
+	 */
+cont:
+	c = *p++;
+	for (spanp = s2; (sc = *spanp++) != 0;)
+		if (sc == c)
+			goto cont;
+	return (p - 1 - s1);
+}
Index: /trunk/libc/src/fbsdlibc/string/strtok.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/strtok.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/strtok.c	(revision 2448)
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 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
+ *    notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notices, 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 Softweyr LLC, 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 SOFTWEYR LLC, 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 SOFTWEYR LLC, 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 "namespace.h" /* bird */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtok.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strtok.c,v 1.9 2002/09/07 02:53:19 tjr Exp $");
+
+#include <stddef.h>
+#ifdef DEBUG_STRTOK
+#include <stdio.h>
+#endif
+#include <string.h>
+#ifdef __EMX__
+#include <InnoTekLIBC/thread.h>
+#endif
+
+
+/*NOTEMX: char	*__strtok_r(char *, const char *, char **); */
+
+/*NOTEMX: __ w e a k _ r e f e r e n c e(__strtok_r, strtok_r); */
+
+char *
+#ifdef __EMX__
+_STD(strtok_r)
+#else
+__strtok_r
+#endif
+(char *s, const char *delim, char **last)
+{
+	char *spanp, *tok;
+	int c, sc;
+
+	if (s == NULL && (s = *last) == NULL)
+		return (NULL);
+
+	/*
+	 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+	 */
+cont:
+	c = *s++;
+	for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+		if (c == sc)
+			goto cont;
+	}
+
+	if (c == 0) {		/* no non-delimiter characters */
+		*last = NULL;
+		return (NULL);
+	}
+	tok = s - 1;
+
+	/*
+	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+	 * Note that delim must have one NUL; we stop if we see that, too.
+	 */
+	for (;;) {
+		c = *s++;
+		spanp = (char *)delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = '\0';
+				*last = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
+
+char *
+#ifdef __EMX__
+_STD(strtok)
+#else
+strtok
+#endif
+(char *s, const char *delim)
+{
+#ifdef __EMX__
+	__LIBC_PTHREAD  pThrd = __libc_threadCurrent();
+	#define last pThrd->pszStrTokPos
+#else
+	static char *last;
+#endif
+	return (__strtok_r(s, delim, &last));
+
+}
+
+#ifdef DEBUG_STRTOK
+/*
+ * Test the tokenizer.
+ */
+int
+main(void)
+{
+	char blah[80], test[80];
+	char *brkb, *brkt, *phrase, *sep, *word;
+
+	sep = "\\/:;=-";
+	phrase = "foo";
+
+	printf("String tokenizer test:\n");
+	strcpy(test, "This;is.a:test:of=the/string\\tokenizer-function.");
+	for (word = strtok(test, sep); word; word = strtok(NULL, sep))
+		printf("Next word is \"%s\".\n", word);
+	strcpy(test, "This;is.a:test:of=the/string\\tokenizer-function.");
+
+	for (word = strtok_r(test, sep, &brkt); word;
+	    word = strtok_r(NULL, sep, &brkt)) {
+		strcpy(blah, "blah:blat:blab:blag");
+
+		for (phrase = strtok_r(blah, sep, &brkb); phrase;
+		    phrase = strtok_r(NULL, sep, &brkb))
+			printf("So far we're at %s:%s\n", word, phrase);
+	}
+
+	return (0);
+}
+
+#endif /* DEBUG_STRTOK */
Index: /trunk/libc/src/fbsdlibc/string/wcscat.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcscat.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcscat.c	(revision 2448)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcscat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscat.c,v 1.8 2002/09/26 09:28:55 tjr Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+_STD(wcscat)(s1, s2)
+	wchar_t * __restrict s1;
+	const wchar_t * __restrict s2;
+{
+	wchar_t *cp;
+
+	cp = s1;
+	while (*cp != L'\0')
+		cp++;
+	while ((*cp++ = *s2++) != L'\0')
+		;
+
+	return (s1);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcschr.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcschr.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcschr.c	(revision 2448)
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcschr.c,v 1.7 2002/10/23 10:47:47 tjr Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+_STD(wcschr)(const wchar_t *s, wchar_t c)
+{
+
+	while (*s != c && *s != L'\0')
+		s++;
+	if (*s == c)
+		return ((wchar_t *)s);
+	return (NULL);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcscmp.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcscmp.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcscmp.c	(revision 2448)
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcmp.c	8.1 (Berkeley) 6/4/93";
+#if 0
+__RCSID("$NetBSD: wcscmp.c,v 1.3 2001/01/05 12:13:12 itojun Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscmp.c,v 1.7 2002/10/23 11:08:40 tjr Exp $");
+
+#include <wchar.h>
+
+/*
+ * Compare strings.
+ */
+int
+_STD(wcscmp)(s1, s2)
+	const wchar_t *s1, *s2;
+{
+
+	while (*s1 == *s2++)
+		if (*s1++ == 0)
+			return (0);
+	/* XXX assumes wchar_t = int */
+	return (*(const unsigned int *)s1 - *(const unsigned int *)--s2);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcscoll.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcscoll.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcscoll.c	(revision 2448)
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscoll.c,v 1.3 2004/04/07 09:47:56 tjr Exp $");
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+/*#include "collate.h"*/
+
+static char *__mbsdup(const wchar_t *);
+
+/*
+ * Placeholder implementation of wcscoll(). Attempts to use the single-byte
+ * collation ordering where possible, and falls back on wcscmp() in locales
+ * with extended character sets.
+ */
+int
+_STD(wcscoll)(const wchar_t *ws1, const wchar_t *ws2)
+{
+	char *mbs1, *mbs2;
+	int diff, sverrno;
+
+	if (/*__collate_load_error || */MB_CUR_MAX > 1)
+		/*
+		 * Locale has no special collating order, could not be
+		 * loaded, or has an extended character set; do a fast binary
+		 * comparison.
+		 */
+		return (wcscmp(ws1, ws2));
+
+	if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) {
+		/*
+		 * Out of memory or illegal wide chars; fall back to wcscmp()
+		 * but leave errno indicating the error. Callers that don't
+		 * check for error will get a reasonable but often slightly
+		 * incorrect result.
+		 */
+		sverrno = errno;
+		free(mbs1);
+		errno = sverrno;
+		return (wcscmp(ws1, ws2));
+	}
+
+	diff = strcoll(mbs1, mbs2);
+	sverrno = errno;
+	free(mbs1);
+	free(mbs2);
+	errno = sverrno;
+
+	return (diff);
+}
+
+static char *
+__mbsdup(const wchar_t *ws)
+{
+	static const mbstate_t initial;
+	mbstate_t st;
+	const wchar_t *wcp;
+	size_t len;
+	char *mbs;
+
+	wcp = ws;
+	st = initial;
+	if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1)
+		return (NULL);
+	if ((mbs = malloc(len + 1)) == NULL)
+		return (NULL);
+	st = initial;
+	wcsrtombs(mbs, &ws, len + 1, &st);
+
+	return (mbs);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcscpy.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcscpy.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcscpy.c	(revision 2448)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcscpy.c,v 1.2 2000/12/21 04:51:09 itojun Exp
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscpy.c,v 1.8 2002/09/26 09:23:07 tjr Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+_STD(wcscpy)(s1, s2)
+	wchar_t * __restrict s1;
+	const wchar_t * __restrict s2;
+{
+	wchar_t *cp;
+
+	cp = s1;
+	while ((*cp++ = *s2++) != L'\0')
+		;
+
+	return (s1);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcscspn.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcscspn.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcscspn.c	(revision 2448)
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcscspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscspn.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscspn.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+
+#include <wchar.h>
+
+size_t
+_STD(wcscspn)(s, set)
+	const wchar_t *s;
+	const wchar_t *set;
+{
+	const wchar_t *p;
+	const wchar_t *q;
+
+	p = s;
+	while (*p) {
+		q = set;
+		while (*q) {
+			if (*p == *q)
+				goto done;
+			q++;
+		}
+		p++;
+	}
+
+done:
+	return (p - s);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcslcat.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcslcat.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcslcat.c	(revision 2448)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ *	from OpenBSD: strlcat.c,v 1.3 2000/11/24 11:10:02 itojun Exp
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcslcat.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+
+#include <sys/types.h>
+#include <wchar.h>
+
+/*
+ * Appends src to string dst of size siz (unlike wcsncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns wcslen(initial dst) + wcslen(src); if retval >= siz,
+ * truncation occurred.
+ */
+size_t
+_STD(wcslcat)(dst, src, siz)
+	wchar_t *dst;
+	const wchar_t *src;
+	size_t siz;
+{
+	wchar_t *d = dst;
+	const wchar_t *s = src;
+	size_t n = siz;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end */
+	while (*d != '\0' && n-- != 0)
+		d++;
+	dlen = d - dst;
+	n = siz - dlen;
+
+	if (n == 0)
+		return(dlen + wcslen(s));
+	while (*s != '\0') {
+		if (n != 1) {
+			*d++ = *s;
+			n--;
+		}
+		s++;
+	}
+	*d = '\0';
+
+	return(dlen + (s - src));	/* count does not include NUL */
+}
Index: /trunk/libc/src/fbsdlibc/string/wcslcpy.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcslcpy.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcslcpy.c	(revision 2448)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ *	from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcslcpy.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+
+#include <sys/types.h>
+#include <wchar.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns wcslen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+_STD(wcslcpy)(dst, src, siz)
+	wchar_t *dst;
+	const wchar_t *src;
+	size_t siz;
+{
+	wchar_t *d = dst;
+	const wchar_t *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
Index: /trunk/libc/src/fbsdlibc/string/wcsncat.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcsncat.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcsncat.c	(revision 2448)
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcsncat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsncat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsncat.c,v 1.7 2002/09/21 00:29:23 tjr Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+_STD(wcsncat)(s1, s2, n)
+	wchar_t * __restrict s1;
+	const wchar_t * __restrict s2;
+	size_t n;
+{
+	wchar_t *p;
+	wchar_t *q;
+	const wchar_t *r;
+
+	p = s1;
+	while (*p)
+		p++;
+	q = p;
+	r = s2;
+	while (*r && n) {
+		*q++ = *r++;
+		n--;
+	}
+	*q = '\0';
+	return s1;
+}
Index: /trunk/libc/src/fbsdlibc/string/wcsncmp.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcsncmp.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcsncmp.c	(revision 2448)
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ * 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.
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncmp.c	8.1 (Berkeley) 6/4/93";
+__RCSID("$NetBSD: wcsncmp.c,v 1.3 2001/01/05 12:13:13 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsncmp.c,v 1.7 2002/10/23 11:08:40 tjr Exp $");
+
+#include <wchar.h>
+
+int
+_STD(wcsncmp)(s1, s2, n)
+	const wchar_t *s1, *s2;
+	size_t n;
+{
+
+	if (n == 0)
+		return (0);
+	do {
+		if (*s1 != *s2++) {
+			/* XXX assumes wchar_t = int */
+			return (*(const unsigned int *)s1 -
+			    *(const unsigned int *)--s2);
+		}
+		if (*s1++ == 0)
+			break;
+	} while (--n != 0);
+	return (0);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcsncpy.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcsncpy.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcsncpy.c	(revision 2448)
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include "namespace.h"
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncpy.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsncpy.c,v 1.9 2002/10/24 02:48:45 tjr Exp $");
+
+#include <wchar.h>
+
+/*
+ * Copy src to dst, truncating or null-padding to always copy n bytes.
+ * Return dst.
+ */
+wchar_t *
+_STD(wcsncpy)(wchar_t * __restrict dst, const wchar_t * __restrict src, size_t n)
+{
+	if (n != 0) {
+		wchar_t *d = dst;
+		const wchar_t *s = src;
+
+		do {
+			if ((*d++ = *s++) == L'\0') {
+				/* NUL pad the remaining n-1 bytes */
+				while (--n != 0)
+					*d++ = L'\0';
+				break;
+			}
+		} while (--n != 0);
+	}
+	return (dst);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcspbrk.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcspbrk.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcspbrk.c	(revision 2448)
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcspbrk.c,v 1.2 2000/12/21 05:07:25 itojun Exp
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcspbrk.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcspbrk.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+_STD(wcspbrk)(s, set)
+	const wchar_t *s;
+	const wchar_t *set;
+{
+	const wchar_t *p;
+	const wchar_t *q;
+
+	p = s;
+	while (*p) {
+		q = set;
+		while (*q) {
+			if (*p == *q) {
+				/* LINTED interface specification */
+				return (wchar_t *)p;
+			}
+			q++;
+		}
+		p++;
+	}
+	return NULL;
+}
Index: /trunk/libc/src/fbsdlibc/string/wcsrchr.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcsrchr.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcsrchr.c	(revision 2448)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsrchr.c,v 1.7 2002/10/23 10:52:04 tjr Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+_STD(wcsrchr)(const wchar_t *s, wchar_t c)
+{
+	const wchar_t *last;
+
+	last = NULL;
+	for (;;) {
+		if (*s == c)
+			last = s;
+		if (*s == L'\0')
+			break;
+		s++;
+	}
+
+	return ((wchar_t *)last);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcsspn.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcsspn.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcsspn.c	(revision 2448)
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcsspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsspn.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsspn.c,v 1.7 2002/09/21 00:29:23 tjr Exp $");
+
+#include <wchar.h>
+
+size_t
+_STD(wcsspn)(s, set)
+	const wchar_t *s;
+	const wchar_t *set;
+{
+	const wchar_t *p;
+	const wchar_t *q;
+
+	p = s;
+	while (*p) {
+		q = set;
+		while (*q) {
+			if (*p == *q)
+				break;
+			q++;
+		}
+		if (!*q)
+			goto done;
+		p++;
+	}
+
+done:
+	return (p - s);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcsstr.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcsstr.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcsstr.c	(revision 2448)
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include "namespace.h"
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strstr.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsstr.c,v 1.8 2002/10/24 02:53:45 tjr Exp $");
+
+#include <wchar.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+wchar_t *
+_STD(wcsstr)(const wchar_t * __restrict s, const wchar_t * __restrict find)
+{
+	wchar_t c, sc;
+	size_t len;
+
+	if ((c = *find++) != 0) {
+		len = wcslen(find);
+		do {
+			do {
+				if ((sc = *s++) == L'\0')
+					return (NULL);
+			} while (sc != c);
+		} while (wcsncmp(s, find, len) != 0);
+		s--;
+	}
+	return ((wchar_t *)s);
+}
Index: /trunk/libc/src/fbsdlibc/string/wcstok.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcstok.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcstok.c	(revision 2448)
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 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
+ *    notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notices, 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 Softweyr LLC, 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 SOFTWEYR LLC, 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 SOFTWEYR LLC, 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcstok.c,v 1.2 2003/03/12 06:41:49 tjr Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+_STD(wcstok)(wchar_t * __restrict s, const wchar_t * __restrict delim,
+    wchar_t ** __restrict last)
+{
+	const wchar_t *spanp;
+	wchar_t *tok;
+	wchar_t c, sc;
+
+	if (s == NULL && (s = *last) == NULL)
+		return (NULL);
+
+	/*
+	 * Skip (span) leading delimiters (s += wcsspn(s, delim), sort of).
+	 */
+cont:
+	c = *s++;
+	for (spanp = delim; (sc = *spanp++) != L'\0';) {
+		if (c == sc)
+			goto cont;
+	}
+
+	if (c == L'\0') {	/* no non-delimiter characters */
+		*last = NULL;
+		return (NULL);
+	}
+	tok = s - 1;
+
+	/*
+	 * Scan token (scan for delimiters: s += wcscspn(s, delim), sort of).
+	 * Note that delim must have one NUL; we stop if we see that, too.
+	 */
+	for (;;) {
+		c = *s++;
+		spanp = delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == L'\0')
+					s = NULL;
+				else
+					s[-1] = L'\0';
+				*last = s;
+				return (tok);
+			}
+		} while (sc != L'\0');
+	}
+	/* NOTREACHED */
+}
Index: /trunk/libc/src/fbsdlibc/string/wcswidth.c
===================================================================
--- /trunk/libc/src/fbsdlibc/string/wcswidth.c	(revision 2448)
+++ /trunk/libc/src/fbsdlibc/string/wcswidth.c	(revision 2448)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * 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.
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcswidth.c,v 1.6 2002/08/20 02:06:28 ache Exp $");
+
+#include <wchar.h>
+
+int
+_STD(wcswidth)(const wchar_t *pwcs, size_t n)
+{
+	wchar_t wc;
+	int len, l;
+
+	len = 0;
+	while (n-- > 0 && (wc = *pwcs++) != L'\0') {
+		if ((l = wcwidth(wc)) < 0)
+			return (-1);
+		len += l;
+	}
+	return (len);
+}
+
Index: /trunk/libc/src/glibc/argp/argp-ba.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-ba.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-ba.c	(revision 2448)
@@ -0,0 +1,26 @@
+/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
+   Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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.  */
+
+/* If set by the user program, it should point to string that is the
+   bug-reporting address for the program.  It will be printed by argp_help if
+   the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help
+   messages), embedded in a sentence that says something like `Report bugs to
+   ADDR.'.  */
+const char *argp_program_bug_address = 0;
Index: /trunk/libc/src/glibc/argp/argp-eexst.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-eexst.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-eexst.c	(revision 2448)
@@ -0,0 +1,32 @@
+/* Default definition for ARGP_ERR_EXIT_STATUS
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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 <sysexits.h>
+
+#include "argp.h"
+
+/* The exit status that argp will use when exiting due to a parsing error.
+   If not defined or set by the user program, this defaults to EX_USAGE from
+   <sysexits.h>.  */
+error_t argp_err_exit_status = EX_USAGE;
Index: /trunk/libc/src/glibc/argp/argp-fmtstream.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-fmtstream.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-fmtstream.c	(revision 2448)
@@ -0,0 +1,445 @@
+/* Word-wrapping and line-truncating streams
+   Copyright (C) 1997,1998,1999,2001,2002,2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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.  */
+
+/* This package emulates glibc `line_wrap_stream' semantics for systems that
+   don't have that.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "argp-fmtstream.h"
+#include "argp-namefrob.h"
+
+#ifndef ARGP_FMTSTREAM_USE_LINEWRAP
+
+#ifndef isblank
+#define isblank(ch) ((ch)==' ' || (ch)=='\t')
+#endif
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+# include <libio/libioP.h>
+# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
+#endif
+
+#define INIT_BUF_SIZE 200
+#define PRINTF_SIZE_GUESS 150
+
+
+/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
+   written on it with LMARGIN spaces and limits them to RMARGIN columns
+   total.  If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
+   replacing the whitespace before them with a newline and WMARGIN spaces.
+   Otherwise, chars beyond RMARGIN are simply dropped until a newline.
+   Returns NULL if there was an error.  */
+argp_fmtstream_t
+__argp_make_fmtstream (FILE *stream,
+		       size_t lmargin, size_t rmargin, ssize_t wmargin)
+{
+  argp_fmtstream_t fs;
+
+  fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
+  if (fs != NULL)
+    {
+      fs->stream = stream;
+
+      fs->lmargin = lmargin;
+      fs->rmargin = rmargin;
+      fs->wmargin = wmargin;
+      fs->point_col = 0;
+      fs->point_offs = 0;
+
+      fs->buf = (char *) malloc (INIT_BUF_SIZE);
+      if (! fs->buf)
+	{
+	  free (fs);
+	  fs = 0;
+	}
+      else
+	{
+	  fs->p = fs->buf;
+	  fs->end = fs->buf + INIT_BUF_SIZE;
+	}
+    }
+
+  return fs;
+}
+#if 0
+/* Not exported.  */
+#ifdef weak_alias
+weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
+#endif
+#endif
+
+/* Flush FS to its stream, and free it (but don't close the stream).  */
+void
+__argp_fmtstream_free (argp_fmtstream_t fs)
+{
+  __argp_fmtstream_update (fs);
+  if (fs->p > fs->buf)
+    {
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (fs->stream, 0) > 0)
+	__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
+      else
+#endif
+	fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
+    }
+  free (fs->buf);
+  free (fs);
+}
+#if 0
+/* Not exported.  */
+#ifdef weak_alias
+weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
+#endif
+#endif
+
+
+/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the
+   end of its buffer.  This code is mostly from glibc stdio/linewrap.c.  */
+void
+__argp_fmtstream_update (argp_fmtstream_t fs)
+{
+  char *buf, *nl;
+  size_t len;
+
+  /* Scan the buffer for newlines.  */
+  buf = fs->buf + fs->point_offs;
+  while (buf < fs->p)
+    {
+      size_t r;
+
+      if (fs->point_col == 0 && fs->lmargin != 0)
+	{
+	  /* We are starting a new line.  Print spaces to the left margin.  */
+	  const size_t pad = fs->lmargin;
+	  if (fs->p + pad < fs->end)
+	    {
+	      /* We can fit in them in the buffer by moving the
+		 buffer text up and filling in the beginning.  */
+	      memmove (buf + pad, buf, fs->p - buf);
+	      fs->p += pad; /* Compensate for bigger buffer. */
+	      memset (buf, ' ', pad); /* Fill in the spaces.  */
+	      buf += pad; /* Don't bother searching them.  */
+	    }
+	  else
+	    {
+	      /* No buffer space for spaces.  Must flush.  */
+	      size_t i;
+	      for (i = 0; i < pad; i++)
+		{
+#ifdef USE_IN_LIBIO
+		  if (_IO_fwide (fs->stream, 0) > 0)
+		    putwc_unlocked (L' ', fs->stream);
+		  else
+#endif
+		    putc_unlocked (' ', fs->stream);
+		}
+	    }
+	  fs->point_col = pad;
+	}
+
+      len = fs->p - buf;
+      nl = memchr (buf, '\n', len);
+
+      if (fs->point_col < 0)
+	fs->point_col = 0;
+
+      if (!nl)
+	{
+	  /* The buffer ends in a partial line.  */
+
+	  if (fs->point_col + len < fs->rmargin)
+	    {
+	      /* The remaining buffer text is a partial line and fits
+		 within the maximum line width.  Advance point for the
+		 characters to be written and stop scanning.  */
+	      fs->point_col += len;
+	      break;
+	    }
+	  else
+	    /* Set the end-of-line pointer for the code below to
+	       the end of the buffer.  */
+	    nl = fs->p;
+	}
+      else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
+	{
+	  /* The buffer contains a full line that fits within the maximum
+	     line width.  Reset point and scan the next line.  */
+	  fs->point_col = 0;
+	  buf = nl + 1;
+	  continue;
+	}
+
+      /* This line is too long.  */
+      r = fs->rmargin - 1;
+
+      if (fs->wmargin < 0)
+	{
+	  /* Truncate the line by overwriting the excess with the
+	     newline and anything after it in the buffer.  */
+	  if (nl < fs->p)
+	    {
+	      memmove (buf + (r - fs->point_col), nl, fs->p - nl);
+	      fs->p -= buf + (r - fs->point_col) - nl;
+	      /* Reset point for the next line and start scanning it.  */
+	      fs->point_col = 0;
+	      buf += r + 1; /* Skip full line plus \n. */
+	    }
+	  else
+	    {
+	      /* The buffer ends with a partial line that is beyond the
+		 maximum line width.  Advance point for the characters
+		 written, and discard those past the max from the buffer.  */
+	      fs->point_col += len;
+	      fs->p -= fs->point_col - r;
+	      break;
+	    }
+	}
+      else
+	{
+	  /* Do word wrap.  Go to the column just past the maximum line
+	     width and scan back for the beginning of the word there.
+	     Then insert a line break.  */
+
+	  char *p, *nextline;
+	  int i;
+
+	  p = buf + (r + 1 - fs->point_col);
+	  while (p >= buf && !isblank (*p))
+	    --p;
+	  nextline = p + 1;	/* This will begin the next line.  */
+
+	  if (nextline > buf)
+	    {
+	      /* Swallow separating blanks.  */
+	      if (p >= buf)
+		do
+		  --p;
+		while (p >= buf && isblank (*p));
+	      nl = p + 1;	/* The newline will replace the first blank. */
+	    }
+	  else
+	    {
+	      /* A single word that is greater than the maximum line width.
+		 Oh well.  Put it on an overlong line by itself.  */
+	      p = buf + (r + 1 - fs->point_col);
+	      /* Find the end of the long word.  */
+	      do
+		++p;
+	      while (p < nl && !isblank (*p));
+	      if (p == nl)
+		{
+		  /* It already ends a line.  No fussing required.  */
+		  fs->point_col = 0;
+		  buf = nl + 1;
+		  continue;
+		}
+	      /* We will move the newline to replace the first blank.  */
+	      nl = p;
+	      /* Swallow separating blanks.  */
+	      do
+		++p;
+	      while (isblank (*p));
+	      /* The next line will start here.  */
+	      nextline = p;
+	    }
+
+	  /* Note: There are a bunch of tests below for
+	     NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall
+	     at the end of the buffer, and NEXTLINE is in fact empty (and so
+	     we need not be careful to maintain its contents).  */
+
+	  if ((nextline == buf + len + 1
+	       ? fs->end - nl < fs->wmargin + 1
+	       : nextline - (nl + 1) < fs->wmargin)
+	      && fs->p > nextline)
+	    {
+	      /* The margin needs more blanks than we removed.  */
+	      if (fs->end - fs->p > fs->wmargin + 1)
+		/* Make some space for them.  */
+		{
+		  size_t mv = fs->p - nextline;
+		  memmove (nl + 1 + fs->wmargin, nextline, mv);
+		  nextline = nl + 1 + fs->wmargin;
+		  len = nextline + mv - buf;
+		  *nl++ = '\n';
+		}
+	      else
+		/* Output the first line so we can use the space.  */
+		{
+#ifdef USE_IN_LIBIO
+		  if (_IO_fwide (fs->stream, 0) > 0)
+		    __fwprintf (fs->stream, L"%.*s\n",
+				(int) (nl - fs->buf), fs->buf);
+		  else
+#endif
+		    {
+		      if (nl > fs->buf)
+			fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
+		      putc_unlocked ('\n', fs->stream);
+		    }
+		  len += buf - fs->buf;
+		  nl = buf = fs->buf;
+		}
+	    }
+	  else
+	    /* We can fit the newline and blanks in before
+	       the next word.  */
+	    *nl++ = '\n';
+
+	  if (nextline - nl >= fs->wmargin
+	      || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin))
+	    /* Add blanks up to the wrap margin column.  */
+	    for (i = 0; i < fs->wmargin; ++i)
+	      *nl++ = ' ';
+	  else
+	    for (i = 0; i < fs->wmargin; ++i)
+#ifdef USE_IN_LIBIO
+	      if (_IO_fwide (fs->stream, 0) > 0)
+		putwc_unlocked (L' ', fs->stream);
+	      else
+#endif
+		putc_unlocked (' ', fs->stream);
+
+	  /* Copy the tail of the original buffer into the current buffer
+	     position.  */
+	  if (nl < nextline)
+	    memmove (nl, nextline, buf + len - nextline);
+	  len -= nextline - buf;
+
+	  /* Continue the scan on the remaining lines in the buffer.  */
+	  buf = nl;
+
+	  /* Restore bufp to include all the remaining text.  */
+	  fs->p = nl + len;
+
+	  /* Reset the counter of what has been output this line.  If wmargin
+	     is 0, we want to avoid the lmargin getting added, so we set
+	     point_col to a magic value of -1 in that case.  */
+	  fs->point_col = fs->wmargin ? fs->wmargin : -1;
+	}
+    }
+
+  /* Remember that we've scanned as far as the end of the buffer.  */
+  fs->point_offs = fs->p - fs->buf;
+}
+
+
+/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by
+   growing the buffer, or by flushing it.  True is returned iff we succeed. */
+int
+__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
+{
+  if ((size_t) (fs->end - fs->p) < amount)
+    {
+      ssize_t wrote;
+
+      /* Flush FS's buffer.  */
+      __argp_fmtstream_update (fs);
+
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (fs->stream, 0) > 0)
+	{
+	  __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
+	  wrote = fs->p - fs->buf;
+	}
+      else
+#endif
+	wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
+      if (wrote == fs->p - fs->buf)
+	{
+	  fs->p = fs->buf;
+	  fs->point_offs = 0;
+	}
+      else
+	{
+	  fs->p -= wrote;
+	  fs->point_offs -= wrote;
+	  memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
+	  return 0;
+	}
+
+      if ((size_t) (fs->end - fs->buf) < amount)
+	/* Gotta grow the buffer.  */
+	{
+	  size_t old_size = fs->end - fs->buf;
+	  size_t new_size = old_size + amount;
+	  char *new_buf;
+
+	  if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
+	    {
+	      __set_errno (ENOMEM);
+	      return 0;
+	    }
+
+	  fs->buf = new_buf;
+	  fs->end = new_buf + new_size;
+	  fs->p = fs->buf;
+	}
+    }
+
+  return 1;
+}
+
+
+ssize_t
+__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
+{
+  int out;
+  size_t avail;
+  size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */
+
+  do
+    {
+      va_list args;
+
+      if (! __argp_fmtstream_ensure (fs, size_guess))
+	return -1;
+
+      va_start (args, fmt);
+      avail = fs->end - fs->p;
+      out = __vsnprintf (fs->p, avail, fmt, args);
+      va_end (args);
+      if ((size_t) out >= avail)
+	size_guess = out + 1;
+    }
+  while ((size_t) out >= avail);
+
+  fs->p += out;
+
+  return out;
+}
+#if 0
+/* Not exported.  */
+#ifdef weak_alias
+weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
+#endif
+#endif
+
+#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */
Index: /trunk/libc/src/glibc/argp/argp-fmtstream.h
===================================================================
--- /trunk/libc/src/glibc/argp/argp-fmtstream.h	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-fmtstream.h	(revision 2448)
@@ -0,0 +1,321 @@
+/* Word-wrapping and line-truncating streams.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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.  */
+
+/* This package emulates glibc `line_wrap_stream' semantics for systems that
+   don't have that.  If the system does have it, it is just a wrapper for
+   that.  This header file is only used internally while compiling argp, and
+   shouldn't be installed.  */
+
+#ifndef _ARGP_FMTSTREAM_H
+#define _ARGP_FMTSTREAM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef __IN_INNOTEK_LIBC__
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+#  define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+   are accepted by gcc versions 2.6.4 (effectively 2.7) and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__
+#  define __format__ format
+#  define __printf__ printf
+# endif
+#endif
+
+#if    (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
+    || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
+/* line_wrap_stream is available, so use that.  */
+#define ARGP_FMTSTREAM_USE_LINEWRAP
+#endif
+#else /* __IN_INNOTEK_LIBC__ */
+# ifdef printf
+#  define __format__(a,b,c)
+# endif
+#endif /* __IN_INNOTEK_LIBC__ */
+
+#ifdef ARGP_FMTSTREAM_USE_LINEWRAP
+/* Just be a simple wrapper for line_wrap_stream; the semantics are
+   *slightly* different, as line_wrap_stream doesn't actually make a new
+   object, it just modifies the given stream (reversibly) to do
+   line-wrapping.  Since we control who uses this code, it doesn't matter.  */
+
+#include <linewrap.h>
+
+typedef FILE *argp_fmtstream_t;
+
+#define argp_make_fmtstream line_wrap_stream
+#define __argp_make_fmtstream line_wrap_stream
+#define argp_fmtstream_free line_unwrap_stream
+#define __argp_fmtstream_free line_unwrap_stream
+
+#define __argp_fmtstream_putc(fs,ch) putc(ch,fs)
+#define argp_fmtstream_putc(fs,ch) putc(ch,fs)
+#define __argp_fmtstream_puts(fs,str) fputs(str,fs)
+#define argp_fmtstream_puts(fs,str) fputs(str,fs)
+#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
+#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
+#define __argp_fmtstream_printf fprintf
+#define argp_fmtstream_printf fprintf
+
+#define __argp_fmtstream_lmargin line_wrap_lmargin
+#define argp_fmtstream_lmargin line_wrap_lmargin
+#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin
+#define argp_fmtstream_set_lmargin line_wrap_set_lmargin
+#define __argp_fmtstream_rmargin line_wrap_rmargin
+#define argp_fmtstream_rmargin line_wrap_rmargin
+#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin
+#define argp_fmtstream_set_rmargin line_wrap_set_rmargin
+#define __argp_fmtstream_wmargin line_wrap_wmargin
+#define argp_fmtstream_wmargin line_wrap_wmargin
+#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin
+#define argp_fmtstream_set_wmargin line_wrap_set_wmargin
+#define __argp_fmtstream_point line_wrap_point
+#define argp_fmtstream_point line_wrap_point
+
+#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
+/* Guess we have to define our own version.  */
+
+#ifndef __const
+#define __const const
+#endif
+
+
+struct argp_fmtstream
+{
+  FILE *stream;			/* The stream we're outputting to.  */
+
+  size_t lmargin, rmargin;	/* Left and right margins.  */
+  ssize_t wmargin;		/* Margin to wrap to, or -1 to truncate.  */
+
+  /* Point in buffer to which we've processed for wrapping, but not output.  */
+  size_t point_offs;
+  /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin.  */
+  ssize_t point_col;
+
+  char *buf;			/* Output buffer.  */
+  char *p;			/* Current end of text in BUF. */
+  char *end;			/* Absolute end of BUF.  */
+};
+
+typedef struct argp_fmtstream *argp_fmtstream_t;
+
+/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
+   written on it with LMARGIN spaces and limits them to RMARGIN columns
+   total.  If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
+   replacing the whitespace before them with a newline and WMARGIN spaces.
+   Otherwise, chars beyond RMARGIN are simply dropped until a newline.
+   Returns NULL if there was an error.  */
+extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream,
+					       size_t __lmargin,
+					       size_t __rmargin,
+					       ssize_t __wmargin);
+extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream,
+					     size_t __lmargin,
+					     size_t __rmargin,
+					     ssize_t __wmargin);
+
+/* Flush __FS to its stream, and free it (but don't close the stream).  */
+extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
+extern void argp_fmtstream_free (argp_fmtstream_t __fs);
+
+extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
+				       __const char *__fmt, ...)
+     __attribute__ ((__format__ (printf, 2, 3)));
+extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
+				      __const char *__fmt, ...)
+     __attribute__ ((__format__ (printf, 2, 3)));
+
+extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
+extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
+
+extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
+extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
+
+extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
+				      __const char *__str, size_t __len);
+extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
+				    __const char *__str, size_t __len);
+
+
+/* Access macros for various bits of state.  */
+#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
+#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin)
+#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin)
+#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
+#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
+#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
+
+/* Set __FS's left margin to LMARGIN and return the old value.  */
+extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
+					  size_t __lmargin);
+extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
+					    size_t __lmargin);
+
+/* Set __FS's right margin to __RMARGIN and return the old value.  */
+extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
+					  size_t __rmargin);
+extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
+					    size_t __rmargin);
+
+/* Set __FS's wrap margin to __WMARGIN and return the old value.  */
+extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
+					  size_t __wmargin);
+extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
+					    size_t __wmargin);
+
+/* Return the column number of the current output point in __FS.  */
+extern size_t argp_fmtstream_point (argp_fmtstream_t __fs);
+extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs);
+
+/* Internal routines.  */
+extern void _argp_fmtstream_update (argp_fmtstream_t __fs);
+extern void __argp_fmtstream_update (argp_fmtstream_t __fs);
+extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
+extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
+
+
+#ifdef __OPTIMIZE__
+/* Inline versions of above routines.  */
+
+#ifndef __IN_INNOTEK_LIBC__
+#if !_LIBC
+#define __argp_fmtstream_putc argp_fmtstream_putc
+#define __argp_fmtstream_puts argp_fmtstream_puts
+#define __argp_fmtstream_write argp_fmtstream_write
+#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
+#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
+#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
+#define __argp_fmtstream_point argp_fmtstream_point
+#define __argp_fmtstream_update _argp_fmtstream_update
+#define __argp_fmtstream_ensure _argp_fmtstream_ensure
+#endif
+#endif /* !__IN_INNOTEK_LIBC__ */
+
+#ifndef ARGP_FS_EI
+#define ARGP_FS_EI extern inline
+#endif
+
+ARGP_FS_EI size_t
+__argp_fmtstream_write (argp_fmtstream_t __fs,
+			__const char *__str, size_t __len)
+{
+  if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
+    {
+      memcpy (__fs->p, __str, __len);
+      __fs->p += __len;
+      return __len;
+    }
+  else
+    return 0;
+}
+
+ARGP_FS_EI int
+__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str)
+{
+  size_t __len = strlen (__str);
+  if (__len)
+    {
+      size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
+      return __wrote == __len ? 0 : -1;
+    }
+  else
+    return 0;
+}
+
+ARGP_FS_EI int
+__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch)
+{
+  if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
+    return *__fs->p++ = __ch;
+  else
+    return EOF;
+}
+
+/* Set __FS's left margin to __LMARGIN and return the old value.  */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->lmargin;
+  __fs->lmargin = __lmargin;
+  return __old;
+}
+
+/* Set __FS's right margin to __RMARGIN and return the old value.  */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->rmargin;
+  __fs->rmargin = __rmargin;
+  return __old;
+}
+
+/* Set FS's wrap margin to __WMARGIN and return the old value.  */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin)
+{
+  size_t __old;
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  __old = __fs->wmargin;
+  __fs->wmargin = __wmargin;
+  return __old;
+}
+
+/* Return the column number of the current output point in __FS.  */
+ARGP_FS_EI size_t
+__argp_fmtstream_point (argp_fmtstream_t __fs)
+{
+  if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+    __argp_fmtstream_update (__fs);
+  return __fs->point_col >= 0 ? __fs->point_col : 0;
+}
+
+#if (!defined _LIBC || !_LIBC) && !defined __IN_INNOTEK_LIBC__
+#undef __argp_fmtstream_putc
+#undef __argp_fmtstream_puts
+#undef __argp_fmtstream_write
+#undef __argp_fmtstream_set_lmargin
+#undef __argp_fmtstream_set_rmargin
+#undef __argp_fmtstream_set_wmargin
+#undef __argp_fmtstream_point
+#undef __argp_fmtstream_update
+#undef __argp_fmtstream_ensure
+#endif
+
+#endif /* __OPTIMIZE__ */
+
+#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
+
+#endif /* argp-fmtstream.h */
Index: /trunk/libc/src/glibc/argp/argp-fs-xinl.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-fs-xinl.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-fs-xinl.c	(revision 2448)
@@ -0,0 +1,44 @@
+/* Real definitions for extern inline functions in argp-fmtstream.h
+   Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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
+
+#define ARGP_FS_EI
+#undef __OPTIMIZE__
+#define __OPTIMIZE__ 1
+#include "argp-fmtstream.h"
+
+#if 0
+/* Not exported.  */
+/* Add weak aliases.  */
+#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias)
+
+weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc)
+weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts)
+weak_alias (__argp_fmtstream_write, argp_fmtstream_write)
+weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin)
+weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin)
+weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin)
+weak_alias (__argp_fmtstream_point, argp_fmtstream_point)
+
+#endif
+#endif
Index: /trunk/libc/src/glibc/argp/argp-help.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-help.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-help.c	(revision 2448)
@@ -0,0 +1,1953 @@
+/* Hierarchial argument parsing help output
+   Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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 _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+#pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.  */
+# if (defined HAVE_LIBINTL_H || defined _LIBC) && !defined __IN_INNOTEK_LIBC__
+#  include <libintl.h>
+#  ifdef _LIBC
+#   undef dgettext
+#   define dgettext(domain, msgid) \
+  INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
+#  endif
+# else
+#  define dgettext(domain, msgid) (msgid)
+# endif
+#endif
+
+#ifndef _LIBC
+# if HAVE_STRERROR_R
+#  if !HAVE_DECL_STRERROR_R
+char *strerror_r (int errnum, char *buf, size_t buflen);
+#  endif
+# else
+#  if !HAVE_DECL_STRERROR
+char *strerror (int errnum);
+#  endif
+# endif
+#endif
+
+#include "argp.h"
+#include "argp-fmtstream.h"
+#include "argp-namefrob.h"
+#ifdef __IN_INNOTEK_LIBC__
+#include <sys/stdint.h>
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+
+/* User-selectable (using an environment variable) formatting parameters.
+
+   These may be specified in an environment variable called `ARGP_HELP_FMT',
+   with a contents like:  VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2
+   Where VALn must be a positive integer.  The list of variables is in the
+   UPARAM_NAMES vector, below.  */
+
+/* Default parameters.  */
+#define DUP_ARGS      0		/* True if option argument can be duplicated. */
+#define DUP_ARGS_NOTE 1		/* True to print a note about duplicate args. */
+#define SHORT_OPT_COL 2		/* column in which short options start */
+#define LONG_OPT_COL  6		/* column in which long options start */
+#define DOC_OPT_COL   2		/* column in which doc options start */
+#define OPT_DOC_COL  29		/* column in which option text starts */
+#define HEADER_COL    1		/* column in which group headers are printed */
+#define USAGE_INDENT 12		/* indentation of wrapped usage lines */
+#define RMARGIN      79		/* right margin used for wrapping */
+
+/* User-selectable (using an environment variable) formatting parameters.
+   They must all be of type `int' for the parsing code to work.  */
+struct uparams
+{
+  /* If true, arguments for an option are shown with both short and long
+     options, even when a given option has both, e.g. `-x ARG, --longx=ARG'.
+     If false, then if an option has both, the argument is only shown with
+     the long one, e.g., `-x, --longx=ARG', and a message indicating that
+     this really means both is printed below the options.  */
+  int dup_args;
+
+  /* This is true if when DUP_ARGS is false, and some duplicate arguments have
+     been suppressed, an explanatory message should be printed.  */
+  int dup_args_note;
+
+  /* Various output columns.  */
+  int short_opt_col;
+  int long_opt_col;
+  int doc_opt_col;
+  int opt_doc_col;
+  int header_col;
+  int usage_indent;
+  int rmargin;
+
+  int valid;			/* True when the values in here are valid.  */
+};
+
+/* This is a global variable, as user options are only ever read once.  */
+static struct uparams uparams = {
+  DUP_ARGS, DUP_ARGS_NOTE,
+  SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
+  USAGE_INDENT, RMARGIN,
+  0
+};
+
+/* A particular uparam, and what the user name is.  */
+struct uparam_name
+{
+  const char *name;		/* User name.  */
+  int is_bool;			/* Whether it's `boolean'.  */
+  size_t uparams_offs;		/* Location of the (int) field in UPARAMS.  */
+};
+
+/* The name-field mappings we know about.  */
+static const struct uparam_name uparam_names[] =
+{
+  { "dup-args",       1, offsetof (struct uparams, dup_args) },
+  { "dup-args-note",  1, offsetof (struct uparams, dup_args_note) },
+  { "short-opt-col",  0, offsetof (struct uparams, short_opt_col) },
+  { "long-opt-col",   0, offsetof (struct uparams, long_opt_col) },
+  { "doc-opt-col",    0, offsetof (struct uparams, doc_opt_col) },
+  { "opt-doc-col",    0, offsetof (struct uparams, opt_doc_col) },
+  { "header-col",     0, offsetof (struct uparams, header_col) },
+  { "usage-indent",   0, offsetof (struct uparams, usage_indent) },
+  { "rmargin",        0, offsetof (struct uparams, rmargin) },
+  { 0 }
+};
+
+/* Read user options from the environment, and fill in UPARAMS appropiately.  */
+static void
+fill_in_uparams (const struct argp_state *state)
+{
+  const char *var = getenv ("ARGP_HELP_FMT");
+
+#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
+
+  if (var)
+    /* Parse var. */
+    while (*var)
+      {
+	SKIPWS (var);
+
+	if (isalpha (*var))
+	  {
+	    size_t var_len;
+	    const struct uparam_name *un;
+	    int unspec = 0, val = 0;
+	    const char *arg = var;
+
+	    while (isalnum (*arg) || *arg == '-' || *arg == '_')
+	      arg++;
+	    var_len = arg - var;
+
+	    SKIPWS (arg);
+
+	    if (*arg == '\0' || *arg == ',')
+	      unspec = 1;
+	    else if (*arg == '=')
+	      {
+		arg++;
+		SKIPWS (arg);
+	      }
+
+	    if (unspec)
+	      {
+		if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
+		  {
+		    val = 0;
+		    var += 3;
+		    var_len -= 3;
+		  }
+		else
+		  val = 1;
+	      }
+	    else if (isdigit (*arg))
+	      {
+		val = atoi (arg);
+		while (isdigit (*arg))
+		  arg++;
+		SKIPWS (arg);
+	      }
+
+	    for (un = uparam_names; un->name; un++)
+	      if (strlen (un->name) == var_len
+		  && strncmp (var, un->name, var_len) == 0)
+		{
+		  if (unspec && !un->is_bool)
+		    __argp_failure (state, 0, 0,
+				    dgettext (state->root_argp->argp_domain, "\
+%.*s: ARGP_HELP_FMT parameter requires a value"),
+				    (int) var_len, var);
+		  else
+		    *(int *)((char *)&uparams + un->uparams_offs) = val;
+		  break;
+		}
+	    if (! un->name)
+	      __argp_failure (state, 0, 0,
+			      dgettext (state->root_argp->argp_domain, "\
+%.*s: Unknown ARGP_HELP_FMT parameter"),
+			      (int) var_len, var);
+
+	    var = arg;
+	    if (*var == ',')
+	      var++;
+	  }
+	else if (*var)
+	  {
+	    __argp_failure (state, 0, 0,
+			    dgettext (state->root_argp->argp_domain,
+				      "Garbage in ARGP_HELP_FMT: %s"), var);
+	    break;
+	  }
+      }
+}
+
+
+/* Returns true if OPT hasn't been marked invisible.  Visibility only affects
+   whether OPT is displayed or used in sorting, not option shadowing.  */
+#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
+
+/* Returns true if OPT is an alias for an earlier option.  */
+#define oalias(opt) ((opt)->flags & OPTION_ALIAS)
+
+/* Returns true if OPT is an documentation-only entry.  */
+#define odoc(opt) ((opt)->flags & OPTION_DOC)
+
+/* Returns true if OPT is the end-of-list marker for a list of options.  */
+#define oend(opt) __option_is_end (opt)
+
+/* Returns true if OPT has a short option.  */
+#define oshort(opt) __option_is_short (opt)
+
+
+/*
+   The help format for a particular option is like:
+
+     -xARG, -yARG, --long1=ARG, --long2=ARG        Documentation...
+
+   Where ARG will be omitted if there's no argument, for this option, or
+   will be surrounded by "[" and "]" appropiately if the argument is
+   optional.  The documentation string is word-wrapped appropiately, and if
+   the list of options is long enough, it will be started on a separate line.
+   If there are no short options for a given option, the first long option is
+   indented slighly in a way that's supposed to make most long options appear
+   to be in a separate column.
+
+   For example, the following output (from ps):
+
+     -p PID, --pid=PID          List the process PID
+	 --pgrp=PGRP            List processes in the process group PGRP
+     -P, -x, --no-parent        Include processes without parents
+     -Q, --all-fields           Don't elide unusable fields (normally if there's
+				some reason ps can't print a field for any
+				process, it's removed from the output entirely)
+     -r, --reverse, --gratuitously-long-reverse-option
+				Reverse the order of any sort
+	 --session[=SID]        Add the processes from the session SID (which
+				defaults to the sid of the current process)
+
+    Here are some more options:
+     -f ZOT, --foonly=ZOT       Glork a foonly
+     -z, --zaza                 Snit a zar
+
+     -?, --help                 Give this help list
+	 --usage                Give a short usage message
+     -V, --version              Print program version
+
+   The struct argp_option array for the above could look like:
+
+   {
+     {"pid",       'p',      "PID",  0, "List the process PID"},
+     {"pgrp",      OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"},
+     {"no-parent", 'P',	      0,     0, "Include processes without parents"},
+     {0,           'x',       0,     OPTION_ALIAS},
+     {"all-fields",'Q',       0,     0, "Don't elide unusable fields (normally"
+                                        " if there's some reason ps can't"
+					" print a field for any process, it's"
+                                        " removed from the output entirely)" },
+     {"reverse",   'r',       0,     0, "Reverse the order of any sort"},
+     {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS},
+     {"session",   OPT_SESS,  "SID", OPTION_ARG_OPTIONAL,
+                                        "Add the processes from the session"
+					" SID (which defaults to the sid of"
+					" the current process)" },
+
+     {0,0,0,0, "Here are some more options:"},
+     {"foonly", 'f', "ZOT", 0, "Glork a foonly"},
+     {"zaza", 'z', 0, 0, "Snit a zar"},
+
+     {0}
+   }
+
+   Note that the last three options are automatically supplied by argp_parse,
+   unless you tell it not to with ARGP_NO_HELP.
+
+*/
+
+
+/* Returns true if CH occurs between BEG and END.  */
+static int
+find_char (char ch, char *beg, char *end)
+{
+  while (beg < end)
+    if (*beg == ch)
+      return 1;
+    else
+      beg++;
+  return 0;
+}
+
+
+struct hol_cluster;		/* fwd decl */
+
+struct hol_entry
+{
+  /* First option.  */
+  const struct argp_option *opt;
+  /* Number of options (including aliases).  */
+  unsigned num;
+
+  /* A pointers into the HOL's short_options field, to the first short option
+     letter for this entry.  The order of the characters following this point
+     corresponds to the order of options pointed to by OPT, and there are at
+     most NUM.  A short option recorded in a option following OPT is only
+     valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's
+     probably been shadowed by some other entry).  */
+  char *short_options;
+
+  /* Entries are sorted by their group first, in the order:
+       1, 2, ..., n, 0, -m, ..., -2, -1
+     and then alphabetically within each group.  The default is 0.  */
+  int group;
+
+  /* The cluster of options this entry belongs to, or 0 if none.  */
+  struct hol_cluster *cluster;
+
+  /* The argp from which this option came.  */
+  const struct argp *argp;
+};
+
+/* A cluster of entries to reflect the argp tree structure.  */
+struct hol_cluster
+{
+  /* A descriptive header printed before options in this cluster.  */
+  const char *header;
+
+  /* Used to order clusters within the same group with the same parent,
+     according to the order in which they occurred in the parent argp's child
+     list.  */
+  int index;
+
+  /* How to sort this cluster with respect to options and other clusters at the
+     same depth (clusters always follow options in the same group).  */
+  int group;
+
+  /* The cluster to which this cluster belongs, or 0 if it's at the base
+     level.  */
+  struct hol_cluster *parent;
+
+  /* The argp from which this cluster is (eventually) derived.  */
+  const struct argp *argp;
+
+  /* The distance this cluster is from the root.  */
+  int depth;
+
+  /* Clusters in a given hol are kept in a linked list, to make freeing them
+     possible.  */
+  struct hol_cluster *next;
+};
+
+/* A list of options for help.  */
+struct hol
+{
+  /* An array of hol_entry's.  */
+  struct hol_entry *entries;
+  /* The number of entries in this hol.  If this field is zero, the others
+     are undefined.  */
+  unsigned num_entries;
+
+  /* A string containing all short options in this HOL.  Each entry contains
+     pointers into this string, so the order can't be messed with blindly.  */
+  char *short_options;
+
+  /* Clusters of entries in this hol.  */
+  struct hol_cluster *clusters;
+};
+
+
+/* Create a struct hol from the options in ARGP.  CLUSTER is the
+   hol_cluster in which these entries occur, or 0, if at the root.  */
+static struct hol *
+make_hol (const struct argp *argp, struct hol_cluster *cluster)
+{
+  char *so;
+  const struct argp_option *o;
+  const struct argp_option *opts = argp->options;
+  struct hol_entry *entry;
+  unsigned num_short_options = 0;
+  struct hol *hol = malloc (sizeof (struct hol));
+
+  assert (hol);
+
+  hol->num_entries = 0;
+  hol->clusters = 0;
+
+  if (opts)
+    {
+      int cur_group = 0;
+
+      /* The first option must not be an alias.  */
+      assert (! oalias (opts));
+
+      /* Calculate the space needed.  */
+      for (o = opts; ! oend (o); o++)
+	{
+	  if (! oalias (o))
+	    hol->num_entries++;
+	  if (oshort (o))
+	    num_short_options++;	/* This is an upper bound.  */
+	}
+
+      hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
+      hol->short_options = malloc (num_short_options + 1);
+
+      assert (hol->entries && hol->short_options);
+#if SIZE_MAX <= UINT_MAX
+      assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry));
+#endif
+
+      /* Fill in the entries.  */
+      so = hol->short_options;
+      for (o = opts, entry = hol->entries; ! oend (o); entry++)
+	{
+	  entry->opt = o;
+	  entry->num = 0;
+	  entry->short_options = so;
+	  entry->group = cur_group =
+	    o->group
+	    ? o->group
+	    : ((!o->name && !o->key)
+	       ? cur_group + 1
+	       : cur_group);
+	  entry->cluster = cluster;
+	  entry->argp = argp;
+
+	  do
+	    {
+	      entry->num++;
+	      if (oshort (o) && ! find_char (o->key, hol->short_options, so))
+		/* O has a valid short option which hasn't already been used.*/
+		*so++ = o->key;
+	      o++;
+	    }
+	  while (! oend (o) && oalias (o));
+	}
+      *so = '\0';		/* null terminated so we can find the length */
+    }
+
+  return hol;
+}
+
+
+/* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the
+   associated argp child list entry), INDEX, and PARENT, and return a pointer
+   to it.  ARGP is the argp that this cluster results from.  */
+static struct hol_cluster *
+hol_add_cluster (struct hol *hol, int group, const char *header, int index,
+		 struct hol_cluster *parent, const struct argp *argp)
+{
+  struct hol_cluster *cl = malloc (sizeof (struct hol_cluster));
+  if (cl)
+    {
+      cl->group = group;
+      cl->header = header;
+
+      cl->index = index;
+      cl->parent = parent;
+      cl->argp = argp;
+      cl->depth = parent ? parent->depth + 1 : 0;
+
+      cl->next = hol->clusters;
+      hol->clusters = cl;
+    }
+  return cl;
+}
+
+
+/* Free HOL and any resources it uses.  */
+static void
+hol_free (struct hol *hol)
+{
+  struct hol_cluster *cl = hol->clusters;
+
+  while (cl)
+    {
+      struct hol_cluster *next = cl->next;
+      free (cl);
+      cl = next;
+    }
+
+  if (hol->num_entries > 0)
+    {
+      free (hol->entries);
+      free (hol->short_options);
+    }
+
+  free (hol);
+}
+
+
+static int
+hol_entry_short_iterate (const struct hol_entry *entry,
+			 int (*func)(const struct argp_option *opt,
+				     const struct argp_option *real,
+				     const char *domain, void *cookie),
+			 const char *domain, void *cookie)
+{
+  unsigned nopts;
+  int val = 0;
+  const struct argp_option *opt, *real = entry->opt;
+  char *so = entry->short_options;
+
+  for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
+    if (oshort (opt) && *so == opt->key)
+      {
+	if (!oalias (opt))
+	  real = opt;
+	if (ovisible (opt))
+	  val = (*func)(opt, real, domain, cookie);
+	so++;
+      }
+
+  return val;
+}
+
+static inline int
+__attribute__ ((always_inline))
+hol_entry_long_iterate (const struct hol_entry *entry,
+			int (*func)(const struct argp_option *opt,
+				    const struct argp_option *real,
+				    const char *domain, void *cookie),
+			const char *domain, void *cookie)
+{
+  unsigned nopts;
+  int val = 0;
+  const struct argp_option *opt, *real = entry->opt;
+
+  for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
+    if (opt->name)
+      {
+	if (!oalias (opt))
+	  real = opt;
+	if (ovisible (opt))
+	  val = (*func)(opt, real, domain, cookie);
+      }
+
+  return val;
+}
+
+
+/* Iterator that returns true for the first short option.  */
+static inline int
+until_short (const struct argp_option *opt, const struct argp_option *real,
+	     const char *domain, void *cookie)
+{
+  return oshort (opt) ? opt->key : 0;
+}
+
+/* Returns the first valid short option in ENTRY, or 0 if there is none.  */
+static char
+hol_entry_first_short (const struct hol_entry *entry)
+{
+  return hol_entry_short_iterate (entry, until_short,
+				  entry->argp->argp_domain, 0);
+}
+
+/* Returns the first valid long option in ENTRY, or 0 if there is none.  */
+static const char *
+hol_entry_first_long (const struct hol_entry *entry)
+{
+  const struct argp_option *opt;
+  unsigned num;
+  for (opt = entry->opt, num = entry->num; num > 0; opt++, num--)
+    if (opt->name && ovisible (opt))
+      return opt->name;
+  return 0;
+}
+
+/* Returns the entry in HOL with the long option name NAME, or 0 if there is
+   none.  */
+static struct hol_entry *
+hol_find_entry (struct hol *hol, const char *name)
+{
+  struct hol_entry *entry = hol->entries;
+  unsigned num_entries = hol->num_entries;
+
+  while (num_entries-- > 0)
+    {
+      const struct argp_option *opt = entry->opt;
+      unsigned num_opts = entry->num;
+
+      while (num_opts-- > 0)
+	if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0)
+	  return entry;
+	else
+	  opt++;
+
+      entry++;
+    }
+
+  return 0;
+}
+
+
+/* If an entry with the long option NAME occurs in HOL, set it's special
+   sort position to GROUP.  */
+static void
+hol_set_group (struct hol *hol, const char *name, int group)
+{
+  struct hol_entry *entry = hol_find_entry (hol, name);
+  if (entry)
+    entry->group = group;
+}
+
+
+/* Order by group:  0, 1, 2, ..., n, -m, ..., -2, -1.
+   EQ is what to return if GROUP1 and GROUP2 are the same.  */
+static int
+group_cmp (int group1, int group2, int eq)
+{
+  if (group1 == group2)
+    return eq;
+  else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
+    return group1 - group2;
+  else
+    return group2 - group1;
+}
+
+/* Compare clusters CL1 & CL2 by the order that they should appear in
+   output.  */
+static int
+hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
+{
+  /* If one cluster is deeper than the other, use its ancestor at the same
+     level, so that finding the common ancestor is straightforward.  */
+  while (cl1->depth < cl2->depth)
+    cl1 = cl1->parent;
+  while (cl2->depth < cl1->depth)
+    cl2 = cl2->parent;
+
+  /* Now reduce both clusters to their ancestors at the point where both have
+     a common parent; these can be directly compared.  */
+  while (cl1->parent != cl2->parent)
+    cl1 = cl1->parent, cl2 = cl2->parent;
+
+  return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index);
+}
+
+/* Return the ancestor of CL that's just below the root (i.e., has a parent
+   of 0).  */
+static struct hol_cluster *
+hol_cluster_base (struct hol_cluster *cl)
+{
+  while (cl->parent)
+    cl = cl->parent;
+  return cl;
+}
+
+/* Return true if CL1 is a child of CL2.  */
+static int
+hol_cluster_is_child (const struct hol_cluster *cl1,
+		      const struct hol_cluster *cl2)
+{
+  while (cl1 && cl1 != cl2)
+    cl1 = cl1->parent;
+  return cl1 == cl2;
+}
+
+
+/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail
+   that should be used for comparisons, and returns true iff it should be
+   treated as a non-option.  */
+static int
+canon_doc_option (const char **name)
+{
+  int non_opt;
+  /* Skip initial whitespace.  */
+  while (isspace (**name))
+    (*name)++;
+  /* Decide whether this looks like an option (leading `-') or not.  */
+  non_opt = (**name != '-');
+  /* Skip until part of name used for sorting.  */
+  while (**name && !isalnum (**name))
+    (*name)++;
+  return non_opt;
+}
+
+/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
+   listing.  */
+static int
+hol_entry_cmp (const struct hol_entry *entry1,
+	       const struct hol_entry *entry2)
+{
+  /* The group numbers by which the entries should be ordered; if either is
+     in a cluster, then this is just the group within the cluster.  */
+  int group1 = entry1->group, group2 = entry2->group;
+
+  if (entry1->cluster != entry2->cluster)
+    {
+      /* The entries are not within the same cluster, so we can't compare them
+	 directly, we have to use the appropiate clustering level too.  */
+      if (! entry1->cluster)
+	/* ENTRY1 is at the `base level', not in a cluster, so we have to
+	   compare it's group number with that of the base cluster in which
+	   ENTRY2 resides.  Note that if they're in the same group, the
+	   clustered option always comes laster.  */
+	return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1);
+      else if (! entry2->cluster)
+	/* Likewise, but ENTRY2's not in a cluster.  */
+	return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
+      else
+	/* Both entries are in clusters, we can just compare the clusters.  */
+	return hol_cluster_cmp (entry1->cluster, entry2->cluster);
+    }
+  else if (group1 == group2)
+    /* The entries are both in the same cluster and group, so compare them
+       alphabetically.  */
+    {
+      int short1 = hol_entry_first_short (entry1);
+      int short2 = hol_entry_first_short (entry2);
+      int doc1 = odoc (entry1->opt);
+      int doc2 = odoc (entry2->opt);
+      const char *long1 = hol_entry_first_long (entry1);
+      const char *long2 = hol_entry_first_long (entry2);
+
+      if (doc1)
+	doc1 = canon_doc_option (&long1);
+      if (doc2)
+	doc2 = canon_doc_option (&long2);
+
+      if (doc1 != doc2)
+	/* `documentation' options always follow normal options (or
+	   documentation options that *look* like normal options).  */
+	return doc1 - doc2;
+      else if (!short1 && !short2 && long1 && long2)
+	/* Only long options.  */
+	return __strcasecmp (long1, long2);
+      else
+	/* Compare short/short, long/short, short/long, using the first
+	   character of long options.  Entries without *any* valid
+	   options (such as options with OPTION_HIDDEN set) will be put
+	   first, but as they're not displayed, it doesn't matter where
+	   they are.  */
+	{
+	  char first1 = short1 ? short1 : long1 ? *long1 : 0;
+	  char first2 = short2 ? short2 : long2 ? *long2 : 0;
+#ifdef _tolower
+	  int lower_cmp = _tolower (first1) - _tolower (first2);
+#else
+	  int lower_cmp = tolower (first1) - tolower (first2);
+#endif
+	  /* Compare ignoring case, except when the options are both the
+	     same letter, in which case lower-case always comes first.  */
+	  return lower_cmp ? lower_cmp : first2 - first1;
+	}
+    }
+  else
+    /* Within the same cluster, but not the same group, so just compare
+       groups.  */
+    return group_cmp (group1, group2, 0);
+}
+
+/* Version of hol_entry_cmp with correct signature for qsort.  */
+static int
+hol_entry_qcmp (const void *entry1_v, const void *entry2_v)
+{
+  return hol_entry_cmp (entry1_v, entry2_v);
+}
+
+/* Sort HOL by group and alphabetically by option name (with short options
+   taking precedence over long).  Since the sorting is for display purposes
+   only, the shadowing of options isn't effected.  */
+static void
+hol_sort (struct hol *hol)
+{
+  if (hol->num_entries > 0)
+    qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
+	   hol_entry_qcmp);
+}
+
+
+/* Append MORE to HOL, destroying MORE in the process.  Options in HOL shadow
+   any in MORE with the same name.  */
+static void
+hol_append (struct hol *hol, struct hol *more)
+{
+  struct hol_cluster **cl_end = &hol->clusters;
+
+  /* Steal MORE's cluster list, and add it to the end of HOL's.  */
+  while (*cl_end)
+    cl_end = &(*cl_end)->next;
+  *cl_end = more->clusters;
+  more->clusters = 0;
+
+  /* Merge entries.  */
+  if (more->num_entries > 0)
+    {
+      if (hol->num_entries == 0)
+	{
+	  hol->num_entries = more->num_entries;
+	  hol->entries = more->entries;
+	  hol->short_options = more->short_options;
+	  more->num_entries = 0;	/* Mark MORE's fields as invalid.  */
+	}
+      else
+	/* Append the entries in MORE to those in HOL, taking care to only add
+	   non-shadowed SHORT_OPTIONS values.  */
+	{
+	  unsigned left;
+	  char *so, *more_so;
+	  struct hol_entry *e;
+	  unsigned num_entries = hol->num_entries + more->num_entries;
+	  struct hol_entry *entries =
+	    malloc (num_entries * sizeof (struct hol_entry));
+	  unsigned hol_so_len = strlen (hol->short_options);
+	  char *short_options =
+	    malloc (hol_so_len + strlen (more->short_options) + 1);
+
+	  assert (entries && short_options);
+#if SIZE_MAX <= UINT_MAX
+	  assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry));
+#endif
+
+	  __mempcpy (__mempcpy (entries, hol->entries,
+				hol->num_entries * sizeof (struct hol_entry)),
+		     more->entries,
+		     more->num_entries * sizeof (struct hol_entry));
+
+	  __mempcpy (short_options, hol->short_options, hol_so_len);
+
+	  /* Fix up the short options pointers from HOL.  */
+	  for (e = entries, left = hol->num_entries; left > 0; e++, left--)
+	    e->short_options += (short_options - hol->short_options);
+
+	  /* Now add the short options from MORE, fixing up its entries
+	     too.  */
+	  so = short_options + hol_so_len;
+	  more_so = more->short_options;
+	  for (left = more->num_entries; left > 0; e++, left--)
+	    {
+	      int opts_left;
+	      const struct argp_option *opt;
+
+	      e->short_options = so;
+
+	      for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--)
+		{
+		  int ch = *more_so;
+		  if (oshort (opt) && ch == opt->key)
+		    /* The next short option in MORE_SO, CH, is from OPT.  */
+		    {
+		      if (! find_char (ch, short_options,
+				       short_options + hol_so_len))
+			/* The short option CH isn't shadowed by HOL's options,
+			   so add it to the sum.  */
+			*so++ = ch;
+		      more_so++;
+		    }
+		}
+	    }
+
+	  *so = '\0';
+
+	  free (hol->entries);
+	  free (hol->short_options);
+
+	  hol->entries = entries;
+	  hol->num_entries = num_entries;
+	  hol->short_options = short_options;
+	}
+    }
+
+  hol_free (more);
+}
+
+
+/* Inserts enough spaces to make sure STREAM is at column COL.  */
+static void
+indent_to (argp_fmtstream_t stream, unsigned col)
+{
+  int needed = col - __argp_fmtstream_point (stream);
+  while (needed-- > 0)
+    __argp_fmtstream_putc (stream, ' ');
+}
+
+/* Output to STREAM either a space, or a newline if there isn't room for at
+   least ENSURE characters before the right margin.  */
+static void
+space (argp_fmtstream_t stream, size_t ensure)
+{
+  if (__argp_fmtstream_point (stream) + ensure
+      >= __argp_fmtstream_rmargin (stream))
+    __argp_fmtstream_putc (stream, '\n');
+  else
+    __argp_fmtstream_putc (stream, ' ');
+}
+
+/* If the option REAL has an argument, we print it in using the printf
+   format REQ_FMT or OPT_FMT depending on whether it's a required or
+   optional argument.  */
+static void
+arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt,
+     const char *domain, argp_fmtstream_t stream)
+{
+  if (real->arg)
+    {
+      if (real->flags & OPTION_ARG_OPTIONAL)
+	__argp_fmtstream_printf (stream, opt_fmt,
+				 dgettext (domain, real->arg));
+      else
+	__argp_fmtstream_printf (stream, req_fmt,
+				 dgettext (domain, real->arg));
+    }
+}
+
+
+/* Helper functions for hol_entry_help.  */
+
+/* State used during the execution of hol_help.  */
+struct hol_help_state
+{
+  /* PREV_ENTRY should contain the previous entry printed, or 0.  */
+  struct hol_entry *prev_entry;
+
+  /* If an entry is in a different group from the previous one, and SEP_GROUPS
+     is true, then a blank line will be printed before any output. */
+  int sep_groups;
+
+  /* True if a duplicate option argument was suppressed (only ever set if
+     UPARAMS.dup_args is false).  */
+  int suppressed_dup_arg;
+};
+
+/* Some state used while printing a help entry (used to communicate with
+   helper functions).  See the doc for hol_entry_help for more info, as most
+   of the fields are copied from its arguments.  */
+struct pentry_state
+{
+  const struct hol_entry *entry;
+  argp_fmtstream_t stream;
+  struct hol_help_state *hhstate;
+
+  /* True if nothing's been printed so far.  */
+  int first;
+
+  /* If non-zero, the state that was used to print this help.  */
+  const struct argp_state *state;
+};
+
+/* If a user doc filter should be applied to DOC, do so.  */
+static const char *
+filter_doc (const char *doc, int key, const struct argp *argp,
+	    const struct argp_state *state)
+{
+  if (argp->help_filter)
+    /* We must apply a user filter to this output.  */
+    {
+      void *input = __argp_input (argp, state);
+      return (*argp->help_filter) (key, doc, input);
+    }
+  else
+    /* No filter.  */
+    return doc;
+}
+
+/* Prints STR as a header line, with the margin lines set appropiately, and
+   notes the fact that groups should be separated with a blank line.  ARGP is
+   the argp that should dictate any user doc filtering to take place.  Note
+   that the previous wrap margin isn't restored, but the left margin is reset
+   to 0.  */
+static void
+print_header (const char *str, const struct argp *argp,
+	      struct pentry_state *pest)
+{
+  const char *tstr = dgettext (argp->argp_domain, str);
+  const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state);
+
+  if (fstr)
+    {
+      if (*fstr)
+	{
+	  if (pest->hhstate->prev_entry)
+	    /* Precede with a blank line.  */
+	    __argp_fmtstream_putc (pest->stream, '\n');
+	  indent_to (pest->stream, uparams.header_col);
+	  __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col);
+	  __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col);
+	  __argp_fmtstream_puts (pest->stream, fstr);
+	  __argp_fmtstream_set_lmargin (pest->stream, 0);
+	  __argp_fmtstream_putc (pest->stream, '\n');
+	}
+
+      pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */
+    }
+
+  if (fstr != tstr)
+    free ((char *) fstr);
+}
+
+/* Inserts a comma if this isn't the first item on the line, and then makes
+   sure we're at least to column COL.  If this *is* the first item on a line,
+   prints any pending whitespace/headers that should precede this line. Also
+   clears FIRST.  */
+static void
+comma (unsigned col, struct pentry_state *pest)
+{
+  if (pest->first)
+    {
+      const struct hol_entry *pe = pest->hhstate->prev_entry;
+      const struct hol_cluster *cl = pest->entry->cluster;
+
+      if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group)
+	__argp_fmtstream_putc (pest->stream, '\n');
+
+      if (cl && cl->header && *cl->header
+	  && (!pe
+	      || (pe->cluster != cl
+		  && !hol_cluster_is_child (pe->cluster, cl))))
+	/* If we're changing clusters, then this must be the start of the
+	   ENTRY's cluster unless that is an ancestor of the previous one
+	   (in which case we had just popped into a sub-cluster for a bit).
+	   If so, then print the cluster's header line.  */
+	{
+	  int old_wm = __argp_fmtstream_wmargin (pest->stream);
+	  print_header (cl->header, cl->argp, pest);
+	  __argp_fmtstream_set_wmargin (pest->stream, old_wm);
+	}
+
+      pest->first = 0;
+    }
+  else
+    __argp_fmtstream_puts (pest->stream, ", ");
+
+  indent_to (pest->stream, col);
+}
+
+
+/* Print help for ENTRY to STREAM.  */
+static void
+hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
+		argp_fmtstream_t stream, struct hol_help_state *hhstate)
+{
+  unsigned num;
+  const struct argp_option *real = entry->opt, *opt;
+  char *so = entry->short_options;
+  int have_long_opt = 0;	/* We have any long options.  */
+  /* Saved margins.  */
+  int old_lm = __argp_fmtstream_set_lmargin (stream, 0);
+  int old_wm = __argp_fmtstream_wmargin (stream);
+  /* PEST is a state block holding some of our variables that we'd like to
+     share with helper functions.  */
+  struct pentry_state pest = { entry, stream, hhstate, 1, state };
+
+  if (! odoc (real))
+    for (opt = real, num = entry->num; num > 0; opt++, num--)
+      if (opt->name && ovisible (opt))
+	{
+	  have_long_opt = 1;
+	  break;
+	}
+
+  /* First emit short options.  */
+  __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */
+  for (opt = real, num = entry->num; num > 0; opt++, num--)
+    if (oshort (opt) && opt->key == *so)
+      /* OPT has a valid (non shadowed) short option.  */
+      {
+	if (ovisible (opt))
+	  {
+	    comma (uparams.short_opt_col, &pest);
+	    __argp_fmtstream_putc (stream, '-');
+	    __argp_fmtstream_putc (stream, *so);
+	    if (!have_long_opt || uparams.dup_args)
+	      arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream);
+	    else if (real->arg)
+	      hhstate->suppressed_dup_arg = 1;
+	  }
+	so++;
+      }
+
+  /* Now, long options.  */
+  if (odoc (real))
+    /* A `documentation' option.  */
+    {
+      __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
+      for (opt = real, num = entry->num; num > 0; opt++, num--)
+	if (opt->name && ovisible (opt))
+	  {
+	    comma (uparams.doc_opt_col, &pest);
+	    /* Calling gettext here isn't quite right, since sorting will
+	       have been done on the original; but documentation options
+	       should be pretty rare anyway...  */
+	    __argp_fmtstream_puts (stream,
+				   dgettext (state->root_argp->argp_domain,
+					     opt->name));
+	  }
+    }
+  else
+    /* A real long option.  */
+    {
+      int first_long_opt = 1;
+
+      __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
+      for (opt = real, num = entry->num; num > 0; opt++, num--)
+	if (opt->name && ovisible (opt))
+	  {
+	    comma (uparams.long_opt_col, &pest);
+	    __argp_fmtstream_printf (stream, "--%s", opt->name);
+	    if (first_long_opt || uparams.dup_args)
+	      arg (real, "=%s", "[=%s]", state->root_argp->argp_domain,
+		   stream);
+	    else if (real->arg)
+	      hhstate->suppressed_dup_arg = 1;
+	  }
+    }
+
+  /* Next, documentation strings.  */
+  __argp_fmtstream_set_lmargin (stream, 0);
+
+  if (pest.first)
+    {
+      /* Didn't print any switches, what's up?  */
+      if (!oshort (real) && !real->name)
+	/* This is a group header, print it nicely.  */
+	print_header (real->doc, entry->argp, &pest);
+      else
+	/* Just a totally shadowed option or null header; print nothing.  */
+	goto cleanup;		/* Just return, after cleaning up.  */
+    }
+  else
+    {
+      const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain,
+					       real->doc) : 0;
+      const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
+      if (fstr && *fstr)
+	{
+	  unsigned int col = __argp_fmtstream_point (stream);
+
+	  __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col);
+	  __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col);
+
+	  if (col > (unsigned int) (uparams.opt_doc_col + 3))
+	    __argp_fmtstream_putc (stream, '\n');
+	  else if (col >= (unsigned int) uparams.opt_doc_col)
+	    __argp_fmtstream_puts (stream, "   ");
+	  else
+	    indent_to (stream, uparams.opt_doc_col);
+
+	  __argp_fmtstream_puts (stream, fstr);
+	}
+      if (fstr && fstr != tstr)
+	free ((char *) fstr);
+
+      /* Reset the left margin.  */
+      __argp_fmtstream_set_lmargin (stream, 0);
+      __argp_fmtstream_putc (stream, '\n');
+    }
+
+  hhstate->prev_entry = entry;
+
+cleanup:
+  __argp_fmtstream_set_lmargin (stream, old_lm);
+  __argp_fmtstream_set_wmargin (stream, old_wm);
+}
+
+
+/* Output a long help message about the options in HOL to STREAM.  */
+static void
+hol_help (struct hol *hol, const struct argp_state *state,
+	  argp_fmtstream_t stream)
+{
+  unsigned num;
+  struct hol_entry *entry;
+  struct hol_help_state hhstate = { 0, 0, 0 };
+
+  for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
+    hol_entry_help (entry, state, stream, &hhstate);
+
+  if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
+    {
+      const char *tstr = dgettext (state->root_argp->argp_domain, "\
+Mandatory or optional arguments to long options are also mandatory or \
+optional for any corresponding short options.");
+      const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE,
+				     state ? state->root_argp : 0, state);
+      if (fstr && *fstr)
+	{
+	  __argp_fmtstream_putc (stream, '\n');
+	  __argp_fmtstream_puts (stream, fstr);
+	  __argp_fmtstream_putc (stream, '\n');
+	}
+      if (fstr && fstr != tstr)
+	free ((char *) fstr);
+    }
+}
+
+
+/* Helper functions for hol_usage.  */
+
+/* If OPT is a short option without an arg, append its key to the string
+   pointer pointer to by COOKIE, and advance the pointer.  */
+static int
+add_argless_short_opt (const struct argp_option *opt,
+		       const struct argp_option *real,
+		       const char *domain, void *cookie)
+{
+  char **snao_end = cookie;
+  if (!(opt->arg || real->arg)
+      && !((opt->flags | real->flags) & OPTION_NO_USAGE))
+    *(*snao_end)++ = opt->key;
+  return 0;
+}
+
+/* If OPT is a short option with an arg, output a usage entry for it to the
+   stream pointed at by COOKIE.  */
+static int
+usage_argful_short_opt (const struct argp_option *opt,
+			const struct argp_option *real,
+			const char *domain, void *cookie)
+{
+  argp_fmtstream_t stream = cookie;
+  const char *arg = opt->arg;
+  int flags = opt->flags | real->flags;
+
+  if (! arg)
+    arg = real->arg;
+
+  if (arg && !(flags & OPTION_NO_USAGE))
+    {
+      arg = dgettext (domain, arg);
+
+      if (flags & OPTION_ARG_OPTIONAL)
+	__argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg);
+      else
+	{
+	  /* Manually do line wrapping so that it (probably) won't
+	     get wrapped at the embedded space.  */
+	  space (stream, 6 + strlen (arg));
+	  __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg);
+	}
+    }
+
+  return 0;
+}
+
+/* Output a usage entry for the long option opt to the stream pointed at by
+   COOKIE.  */
+static int
+usage_long_opt (const struct argp_option *opt,
+		const struct argp_option *real,
+		const char *domain, void *cookie)
+{
+  argp_fmtstream_t stream = cookie;
+  const char *arg = opt->arg;
+  int flags = opt->flags | real->flags;
+
+  if (! arg)
+    arg = real->arg;
+
+  if (! (flags & OPTION_NO_USAGE))
+    {
+      if (arg)
+	{
+	  arg = dgettext (domain, arg);
+	  if (flags & OPTION_ARG_OPTIONAL)
+	    __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg);
+	  else
+	    __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg);
+	}
+      else
+	__argp_fmtstream_printf (stream, " [--%s]", opt->name);
+    }
+
+  return 0;
+}
+
+
+/* Print a short usage description for the arguments in HOL to STREAM.  */
+static void
+hol_usage (struct hol *hol, argp_fmtstream_t stream)
+{
+  if (hol->num_entries > 0)
+    {
+      unsigned nentries;
+      struct hol_entry *entry;
+      char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
+      char *snao_end = short_no_arg_opts;
+
+      /* First we put a list of short options without arguments.  */
+      for (entry = hol->entries, nentries = hol->num_entries
+	   ; nentries > 0
+	   ; entry++, nentries--)
+	hol_entry_short_iterate (entry, add_argless_short_opt,
+				 entry->argp->argp_domain, &snao_end);
+      if (snao_end > short_no_arg_opts)
+	{
+	  *snao_end++ = 0;
+	  __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts);
+	}
+
+      /* Now a list of short options *with* arguments.  */
+      for (entry = hol->entries, nentries = hol->num_entries
+	   ; nentries > 0
+	   ; entry++, nentries--)
+	hol_entry_short_iterate (entry, usage_argful_short_opt,
+				 entry->argp->argp_domain, stream);
+
+      /* Finally, a list of long options (whew!).  */
+      for (entry = hol->entries, nentries = hol->num_entries
+	   ; nentries > 0
+	   ; entry++, nentries--)
+	hol_entry_long_iterate (entry, usage_long_opt,
+				entry->argp->argp_domain, stream);
+    }
+}
+
+
+/* Make a HOL containing all levels of options in ARGP.  CLUSTER is the
+   cluster in which ARGP's entries should be clustered, or 0.  */
+static struct hol *
+argp_hol (const struct argp *argp, struct hol_cluster *cluster)
+{
+  const struct argp_child *child = argp->children;
+  struct hol *hol = make_hol (argp, cluster);
+  if (child)
+    while (child->argp)
+      {
+	struct hol_cluster *child_cluster =
+	  ((child->group || child->header)
+	   /* Put CHILD->argp within its own cluster.  */
+	   ? hol_add_cluster (hol, child->group, child->header,
+			      child - argp->children, cluster, argp)
+	   /* Just merge it into the parent's cluster.  */
+	   : cluster);
+	hol_append (hol, argp_hol (child->argp, child_cluster)) ;
+	child++;
+      }
+  return hol;
+}
+
+
+/* Calculate how many different levels with alternative args strings exist in
+   ARGP.  */
+static size_t
+argp_args_levels (const struct argp *argp)
+{
+  size_t levels = 0;
+  const struct argp_child *child = argp->children;
+
+  if (argp->args_doc && strchr (argp->args_doc, '\n'))
+    levels++;
+
+  if (child)
+    while (child->argp)
+      levels += argp_args_levels ((child++)->argp);
+
+  return levels;
+}
+
+/* Print all the non-option args documented in ARGP to STREAM.  Any output is
+   preceded by a space.  LEVELS is a pointer to a byte vector the length
+   returned by argp_args_levels; it should be initialized to zero, and
+   updated by this routine for the next call if ADVANCE is true.  True is
+   returned as long as there are more patterns to output.  */
+static int
+argp_args_usage (const struct argp *argp, const struct argp_state *state,
+		 char **levels, int advance, argp_fmtstream_t stream)
+{
+  char *our_level = *levels;
+  int multiple = 0;
+  const struct argp_child *child = argp->children;
+  const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0;
+  const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
+
+  if (fdoc)
+    {
+      const char *cp = fdoc;
+      nl = __strchrnul (cp, '\n');
+      if (*nl != '\0')
+	/* This is a `multi-level' args doc; advance to the correct position
+	   as determined by our state in LEVELS, and update LEVELS.  */
+	{
+	  int i;
+	  multiple = 1;
+	  for (i = 0; i < *our_level; i++)
+	    cp = nl + 1, nl = __strchrnul (cp, '\n');
+	  (*levels)++;
+	}
+
+      /* Manually do line wrapping so that it (probably) won't get wrapped at
+	 any embedded spaces.  */
+      space (stream, 1 + nl - cp);
+
+      __argp_fmtstream_write (stream, cp, nl - cp);
+    }
+  if (fdoc && fdoc != tdoc)
+    free ((char *)fdoc);	/* Free user's modified doc string.  */
+
+  if (child)
+    while (child->argp)
+      advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream);
+
+  if (advance && multiple)
+    {
+      /* Need to increment our level.  */
+      if (*nl)
+	/* There's more we can do here.  */
+	{
+	  (*our_level)++;
+	  advance = 0;		/* Our parent shouldn't advance also. */
+	}
+      else if (*our_level > 0)
+	/* We had multiple levels, but used them up; reset to zero.  */
+	*our_level = 0;
+    }
+
+  return !advance;
+}
+
+
+/* Print the documentation for ARGP to STREAM; if POST is false, then
+   everything preceeding a `\v' character in the documentation strings (or
+   the whole string, for those with none) is printed, otherwise, everything
+   following the `\v' character (nothing for strings without).  Each separate
+   bit of documentation is separated a blank line, and if PRE_BLANK is true,
+   then the first is as well.  If FIRST_ONLY is true, only the first
+   occurrence is output.  Returns true if anything was output.  */
+static int
+argp_doc (const struct argp *argp, const struct argp_state *state,
+	  int post, int pre_blank, int first_only,
+	  argp_fmtstream_t stream)
+{
+  const char *text;
+  const char *inp_text;
+  void *input = 0;
+  int anything = 0;
+  size_t inp_text_limit = 0;
+  const char *doc = dgettext (argp->argp_domain, argp->doc);
+  const struct argp_child *child = argp->children;
+
+  if (doc)
+    {
+      char *vt = strchr (doc, '\v');
+      inp_text = post ? (vt ? vt + 1 : 0) : doc;
+      inp_text_limit = (!post && vt) ? (vt - doc) : 0;
+    }
+  else
+    inp_text = 0;
+
+  if (argp->help_filter)
+    /* We have to filter the doc strings.  */
+    {
+      if (inp_text_limit)
+	/* Copy INP_TEXT so that it's nul-terminated.  */
+	inp_text = __strndup (inp_text, inp_text_limit);
+      input = __argp_input (argp, state);
+      text =
+	(*argp->help_filter) (post
+			      ? ARGP_KEY_HELP_POST_DOC
+			      : ARGP_KEY_HELP_PRE_DOC,
+			      inp_text, input);
+    }
+  else
+    text = (const char *) inp_text;
+
+  if (text)
+    {
+      if (pre_blank)
+	__argp_fmtstream_putc (stream, '\n');
+
+      if (text == inp_text && inp_text_limit)
+	__argp_fmtstream_write (stream, inp_text, inp_text_limit);
+      else
+	__argp_fmtstream_puts (stream, text);
+
+      if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
+	__argp_fmtstream_putc (stream, '\n');
+
+      anything = 1;
+    }
+
+  if (text && text != inp_text)
+    free ((char *) text);	/* Free TEXT returned from the help filter.  */
+  if (inp_text && inp_text_limit && argp->help_filter)
+    free ((char *) inp_text);	/* We copied INP_TEXT, so free it now.  */
+
+  if (post && argp->help_filter)
+    /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text.  */
+    {
+      text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
+      if (text)
+	{
+	  if (anything || pre_blank)
+	    __argp_fmtstream_putc (stream, '\n');
+	  __argp_fmtstream_puts (stream, text);
+	  free ((char *) text);
+	  if (__argp_fmtstream_point (stream)
+	      > __argp_fmtstream_lmargin (stream))
+	    __argp_fmtstream_putc (stream, '\n');
+	  anything = 1;
+	}
+    }
+
+  if (child)
+    while (child->argp && !(first_only && anything))
+      anything |=
+	argp_doc ((child++)->argp, state,
+		  post, anything || pre_blank, first_only,
+		  stream);
+
+  return anything;
+}
+
+
+/* Output a usage message for ARGP to STREAM.  If called from
+   argp_state_help, STATE is the relevent parsing state.  FLAGS are from the
+   set ARGP_HELP_*.  NAME is what to use wherever a `program name' is
+   needed. */
+static void
+_help (const struct argp *argp, const struct argp_state *state, FILE *stream,
+       unsigned flags, char *name)
+{
+  int anything = 0;		/* Whether we've output anything.  */
+  struct hol *hol = 0;
+  argp_fmtstream_t fs;
+
+  if (! stream)
+    return;
+
+#if defined (__IN_INNOTEK_LIBC__) || _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+  __flockfile (stream);
+#endif
+
+  if (! uparams.valid)
+    fill_in_uparams (state);
+
+  fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
+  if (! fs)
+    {
+#if defined (__IN_INNOTEK_LIBC__) || _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+      __funlockfile (stream);
+#endif
+      return;
+    }
+
+  if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG))
+    {
+      hol = argp_hol (argp, 0);
+
+      /* If present, these options always come last.  */
+      hol_set_group (hol, "help", -1);
+      hol_set_group (hol, "version", -1);
+
+      hol_sort (hol);
+    }
+
+  if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE))
+    /* Print a short `Usage:' message.  */
+    {
+      int first_pattern = 1, more_patterns;
+      size_t num_pattern_levels = argp_args_levels (argp);
+      char *pattern_levels = alloca (num_pattern_levels);
+
+      memset (pattern_levels, 0, num_pattern_levels);
+
+      do
+	{
+	  int old_lm;
+	  int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent);
+	  char *levels = pattern_levels;
+
+	  if (first_pattern)
+	    __argp_fmtstream_printf (fs, "%s %s",
+				     dgettext (argp->argp_domain, "Usage:"),
+				     name);
+	  else
+	    __argp_fmtstream_printf (fs, "%s %s",
+				     dgettext (argp->argp_domain, "  or: "),
+				     name);
+
+	  /* We set the lmargin as well as the wmargin, because hol_usage
+	     manually wraps options with newline to avoid annoying breaks.  */
+	  old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent);
+
+	  if (flags & ARGP_HELP_SHORT_USAGE)
+	    /* Just show where the options go.  */
+	    {
+	      if (hol->num_entries > 0)
+		__argp_fmtstream_puts (fs, dgettext (argp->argp_domain,
+						     " [OPTION...]"));
+	    }
+	  else
+	    /* Actually print the options.  */
+	    {
+	      hol_usage (hol, fs);
+	      flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once.  */
+	    }
+
+	  more_patterns = argp_args_usage (argp, state, &levels, 1, fs);
+
+	  __argp_fmtstream_set_wmargin (fs, old_wm);
+	  __argp_fmtstream_set_lmargin (fs, old_lm);
+
+	  __argp_fmtstream_putc (fs, '\n');
+	  anything = 1;
+
+	  first_pattern = 0;
+	}
+      while (more_patterns);
+    }
+
+  if (flags & ARGP_HELP_PRE_DOC)
+    anything |= argp_doc (argp, state, 0, 0, 1, fs);
+
+  if (flags & ARGP_HELP_SEE)
+    {
+      __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\
+Try `%s --help' or `%s --usage' for more information.\n"),
+			       name, name);
+      anything = 1;
+    }
+
+  if (flags & ARGP_HELP_LONG)
+    /* Print a long, detailed help message.  */
+    {
+      /* Print info about all the options.  */
+      if (hol->num_entries > 0)
+	{
+	  if (anything)
+	    __argp_fmtstream_putc (fs, '\n');
+	  hol_help (hol, state, fs);
+	  anything = 1;
+	}
+    }
+
+  if (flags & ARGP_HELP_POST_DOC)
+    /* Print any documentation strings at the end.  */
+    anything |= argp_doc (argp, state, 1, anything, 0, fs);
+
+  if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address)
+    {
+      if (anything)
+	__argp_fmtstream_putc (fs, '\n');
+      __argp_fmtstream_printf (fs, dgettext (argp->argp_domain,
+					     "Report bugs to %s.\n"),
+ 			       argp_program_bug_address);
+      anything = 1;
+    }
+
+#if  defined (__IN_INNOTEK_LIBC__) || _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+  __funlockfile (stream);
+#endif
+
+  if (hol)
+    hol_free (hol);
+
+  __argp_fmtstream_free (fs);
+}
+
+
+/* Output a usage message for ARGP to STREAM.  FLAGS are from the set
+   ARGP_HELP_*.  NAME is what to use wherever a `program name' is needed. */
+void __argp_help (const struct argp *argp, FILE *stream,
+		  unsigned flags, char *name)
+{
+  _help (argp, 0, stream, flags, name);
+}
+#ifdef weak_alias
+weak_alias (__argp_help, argp_help)
+#endif
+
+#ifndef __IN_INNOTEK_LIBC__
+#ifndef _LIBC
+char *__argp_basename (char *name)
+{
+  char *short_name = strrchr (name, '/');
+  return short_name ? short_name + 1 : name;
+}
+
+char *
+__argp_short_program_name (void)
+{
+# if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+  return program_invocation_short_name;
+# elif HAVE_DECL_PROGRAM_INVOCATION_NAME
+  return __argp_basename (program_invocation_name);
+# else
+  /* FIXME: What now? Miles suggests that it is better to use NULL,
+     but currently the value is passed on directly to fputs_unlocked,
+     so that requires more changes. */
+# if __GNUC__
+#  warning No reasonable value to return
+# endif /* __GNUC__ */
+  return "";
+# endif
+}
+#endif
+#else /* __IN_INNOTEK_LIBC__ */
+char *
+__argp_short_program_name (void)
+{
+    return (char *)getprogname();
+}
+#endif /* __IN_INNOTEK_LIBC__ */
+
+
+/* Output, if appropriate, a usage message for STATE to STREAM.  FLAGS are
+   from the set ARGP_HELP_*.  */
+void
+__argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
+{
+  if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream)
+    {
+      if (state && (state->flags & ARGP_LONG_ONLY))
+	flags |= ARGP_HELP_LONG_ONLY;
+
+      _help (state ? state->root_argp : 0, state, stream, flags,
+	     state ? state->name : __argp_short_program_name ());
+
+      if (!state || ! (state->flags & ARGP_NO_EXIT))
+	{
+	  if (flags & ARGP_HELP_EXIT_ERR)
+	    exit (argp_err_exit_status);
+	  if (flags & ARGP_HELP_EXIT_OK)
+	    exit (0);
+	}
+  }
+}
+#ifdef weak_alias
+weak_alias (__argp_state_help, argp_state_help)
+#endif
+
+
+/* If appropriate, print the printf string FMT and following args, preceded
+   by the program name and `:', to stderr, and followed by a `Try ... --help'
+   message, then exit (1).  */
+void
+__argp_error (const struct argp_state *state, const char *fmt, ...)
+{
+  if (!state || !(state->flags & ARGP_NO_ERRS))
+    {
+      FILE *stream = state ? state->err_stream : stderr;
+
+      if (stream)
+	{
+	  va_list ap;
+
+#if  defined (__IN_INNOTEK_LIBC__) || _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+	  __flockfile (stream);
+#endif
+
+	  va_start (ap, fmt);
+
+#ifdef USE_IN_LIBIO
+	  if (_IO_fwide (stream, 0) > 0)
+	    {
+	      char *buf;
+
+	      if (__asprintf (&buf, fmt, ap) < 0)
+		buf = NULL;
+
+	      __fwprintf (stream, L"%s: %s\n",
+			  state ? state->name : __argp_short_program_name (),
+			  buf);
+
+	      free (buf);
+	    }
+	  else
+#endif
+	    {
+	      fputs_unlocked (state
+			      ? state->name : __argp_short_program_name (),
+			      stream);
+	      putc_unlocked (':', stream);
+	      putc_unlocked (' ', stream);
+
+	      vfprintf (stream, fmt, ap);
+
+	      putc_unlocked ('\n', stream);
+	    }
+
+	  __argp_state_help (state, stream, ARGP_HELP_STD_ERR);
+
+	  va_end (ap);
+
+#if  defined (__IN_INNOTEK_LIBC__) || _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+	  __funlockfile (stream);
+#endif
+	}
+    }
+}
+#ifdef weak_alias
+weak_alias (__argp_error, argp_error)
+#endif
+
+
+/* Similar to the standard gnu error-reporting function error(), but will
+   respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
+   to STATE->err_stream.  This is useful for argument parsing code that is
+   shared between program startup (when exiting is desired) and runtime
+   option parsing (when typically an error code is returned instead).  The
+   difference between this function and argp_error is that the latter is for
+   *parsing errors*, and the former is for other problems that occur during
+   parsing but don't reflect a (syntactic) problem with the input.  */
+void
+__argp_failure (const struct argp_state *state, int status, int errnum,
+		const char *fmt, ...)
+{
+  if (!state || !(state->flags & ARGP_NO_ERRS))
+    {
+      FILE *stream = state ? state->err_stream : stderr;
+
+      if (stream)
+	{
+#if  defined (__IN_INNOTEK_LIBC__) || _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+	  __flockfile (stream);
+#endif
+
+#ifdef USE_IN_LIBIO
+	  if (_IO_fwide (stream, 0) > 0)
+	    __fwprintf (stream, L"%s",
+			state ? state->name : __argp_short_program_name ());
+	  else
+#endif
+	    fputs_unlocked (state
+			    ? state->name : __argp_short_program_name (),
+			    stream);
+
+	  if (fmt)
+	    {
+	      va_list ap;
+
+	      va_start (ap, fmt);
+#ifdef USE_IN_LIBIO
+	      if (_IO_fwide (stream, 0) > 0)
+		{
+		  char *buf;
+
+		  if (__asprintf (&buf, fmt, ap) < 0)
+		    buf = NULL;
+
+		  __fwprintf (stream, L": %s", buf);
+
+		  free (buf);
+		}
+	      else
+#endif
+		{
+		  putc_unlocked (':', stream);
+		  putc_unlocked (' ', stream);
+
+		  vfprintf (stream, fmt, ap);
+		}
+
+	      va_end (ap);
+	    }
+
+	  if (errnum)
+	    {
+	      char buf[200];
+
+#ifdef USE_IN_LIBIO
+	      if (_IO_fwide (stream, 0) > 0)
+		__fwprintf (stream, L": %s",
+			    __strerror_r (errnum, buf, sizeof (buf)));
+	      else
+#endif
+		{
+		  putc_unlocked (':', stream);
+		  putc_unlocked (' ', stream);
+#if defined (__IN_INNOTEK_LIBC__)
+                  buf [sizeof (buf) - 1] = buf [0] = '\0';
+                  strerror_r (errnum, buf, sizeof (buf));
+		  fputs (buf, stream);
+#else /* !__IN_INNOTEK_LIBC__ */
+#if defined _LIBC || defined HAVE_STRERROR_R
+		  fputs (__strerror_r (errnum, buf, sizeof (buf)), stream);
+#else
+		  fputs (strerror (errnum), stream);
+#endif
+#endif /* !__IN_INNOTEK_LIBC__ */
+		}
+	    }
+
+#ifdef USE_IN_LIBIO
+	  if (_IO_fwide (stream, 0) > 0)
+	    putwc_unlocked (L'\n', stream);
+	  else
+#endif
+	    putc_unlocked ('\n', stream);
+
+#if  defined (__IN_INNOTEK_LIBC__) || _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+	  __funlockfile (stream);
+#endif
+
+	  if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
+	    exit (status);
+	}
+    }
+}
+#ifdef weak_alias
+weak_alias (__argp_failure, argp_failure)
+#endif
Index: /trunk/libc/src/glibc/argp/argp-namefrob.h
===================================================================
--- /trunk/libc/src/glibc/argp/argp-namefrob.h	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-namefrob.h	(revision 2448)
@@ -0,0 +1,158 @@
+/* Name frobnication for compiling argp outside of glibc
+   Copyright (C) 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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.  */
+
+#if (!defined _LIBC || !_LIBC) && !defined __IN_INNOTEK_LIBC__
+#error "__IN_INNOTEK_LIBC__ isn't defined!"
+/* This code is written for inclusion in gnu-libc, and uses names in the
+   namespace reserved for libc.  If we're not compiling in libc, define those
+   names to be the normal ones instead.  */
+
+/* argp-parse functions */
+#undef __argp_parse
+#define __argp_parse argp_parse
+#undef __option_is_end
+#define __option_is_end _option_is_end
+#undef __option_is_short
+#define __option_is_short _option_is_short
+#undef __argp_input
+#define __argp_input _argp_input
+
+/* argp-help functions */
+#undef __argp_help
+#define __argp_help argp_help
+#undef __argp_error
+#define __argp_error argp_error
+#undef __argp_failure
+#define __argp_failure argp_failure
+#undef __argp_state_help
+#define __argp_state_help argp_state_help
+#undef __argp_usage
+#define __argp_usage argp_usage
+
+/* argp-fmtstream functions */
+#undef __argp_make_fmtstream
+#define __argp_make_fmtstream argp_make_fmtstream
+#undef __argp_fmtstream_free
+#define __argp_fmtstream_free argp_fmtstream_free
+#undef __argp_fmtstream_putc
+#define __argp_fmtstream_putc argp_fmtstream_putc
+#undef __argp_fmtstream_puts
+#define __argp_fmtstream_puts argp_fmtstream_puts
+#undef __argp_fmtstream_write
+#define __argp_fmtstream_write argp_fmtstream_write
+#undef __argp_fmtstream_printf
+#define __argp_fmtstream_printf argp_fmtstream_printf
+#undef __argp_fmtstream_set_lmargin
+#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
+#undef __argp_fmtstream_set_rmargin
+#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
+#undef __argp_fmtstream_set_wmargin
+#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
+#undef __argp_fmtstream_point
+#define __argp_fmtstream_point argp_fmtstream_point
+#undef __argp_fmtstream_update
+#define __argp_fmtstream_update _argp_fmtstream_update
+#undef __argp_fmtstream_ensure
+#define __argp_fmtstream_ensure _argp_fmtstream_ensure
+#undef __argp_fmtstream_lmargin
+#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
+#undef __argp_fmtstream_rmargin
+#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
+#undef __argp_fmtstream_wmargin
+#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
+
+#include "mempcpy.h"
+#include "strcase.h"
+#include "strchrnul.h"
+#include "strndup.h"
+
+/* normal libc functions we call */
+#undef __flockfile
+#define __flockfile flockfile
+#undef __funlockfile
+#define __funlockfile funlockfile
+#undef __mempcpy
+#define __mempcpy mempcpy
+#undef __sleep
+#define __sleep sleep
+#undef __strcasecmp
+#define __strcasecmp strcasecmp
+#undef __strchrnul
+#define __strchrnul strchrnul
+#undef __strerror_r
+#define __strerror_r strerror_r
+#undef __strndup
+#define __strndup strndup
+#undef __vsnprintf
+#define __vsnprintf vsnprintf
+
+#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
+# define clearerr_unlocked(x) clearerr (x)
+#endif
+#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
+# define feof_unlocked(x) feof (x)
+# endif
+#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
+# define ferror_unlocked(x) ferror (x)
+# endif
+#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
+# define fflush_unlocked(x) fflush (x)
+# endif
+#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
+# define fgets_unlocked(x,y,z) fgets (x,y,z)
+# endif
+#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED
+# define fputc_unlocked(x,y) fputc (x,y)
+# endif
+#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
+# define fputs_unlocked(x,y) fputs (x,y)
+# endif
+#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
+# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
+# endif
+#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
+# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
+# endif
+#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED
+# define getc_unlocked(x) getc (x)
+# endif
+#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED
+#  define getchar_unlocked() getchar ()
+# endif
+#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED
+# define putc_unlocked(x,y) putc (x,y)
+# endif
+#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED
+# define putchar_unlocked(x) putchar (x)
+# endif
+
+extern char *__argp_basename (char *name);
+
+#endif /* !_LIBC */
+
+#ifndef __set_errno
+#define __set_errno(e) (errno = (e))
+#endif
+
+#if defined _LIBC || (defined(HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME) && HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
+# define __argp_short_program_name()	(program_invocation_short_name)
+#else
+extern char *__argp_short_program_name (void);
+#endif
Index: /trunk/libc/src/glibc/argp/argp-parse.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-parse.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-parse.c	(revision 2448)
@@ -0,0 +1,971 @@
+/* Hierarchial argument parsing, layered over getopt
+   Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+#pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <getopt.h>
+#ifndef __IN_INNOTEK_LIBC__
+#include <getopt_int.h>
+#else
+#include "../posix/getopt_int.h"
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+   When compiling libc, the _ macro is predefined.  */
+# if defined HAVE_LIBINTL_H || defined _LIBC
+#  include <libintl.h>
+#  ifdef _LIBC
+#   undef dgettext
+#   define dgettext(domain, msgid) \
+  INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
+#  endif
+# else
+#  define dgettext(domain, msgid) (msgid)
+#  define gettext(msgid) (msgid)
+# endif
+#endif
+#ifndef N_
+# define N_(msgid) (msgid)
+#endif
+
+#include "argp.h"
+#include "argp-namefrob.h"
+
+/* Getopt return values.  */
+#define KEY_END (-1)		/* The end of the options.  */
+#define KEY_ARG 1		/* A non-option argument.  */
+#define KEY_ERR '?'		/* An error parsing the options.  */
+
+/* The meta-argument used to prevent any further arguments being interpreted
+   as options.  */
+#define QUOTE "--"
+
+/* The number of bits we steal in a long-option value for our own use.  */
+#define GROUP_BITS CHAR_BIT
+
+/* The number of bits available for the user value.  */
+#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
+#define USER_MASK ((1 << USER_BITS) - 1)
+
+/* EZ alias for ARGP_ERR_UNKNOWN.  */
+#define EBADKEY ARGP_ERR_UNKNOWN
+
+
+/* Default options.  */
+
+/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
+   for one second intervals, decrementing _ARGP_HANG until it's zero.  Thus
+   you can force the program to continue by attaching a debugger and setting
+   it to 0 yourself.  */
+static volatile int _argp_hang;
+
+#define OPT_PROGNAME	-2
+#define OPT_USAGE	-3
+#define OPT_HANG	-4
+
+static const struct argp_option argp_default_options[] =
+{
+  {"help",	  '?',    	0, 0,  N_("Give this help list"), -1},
+  {"usage",	  OPT_USAGE,	0, 0,  N_("Give a short usage message")},
+  {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name")},
+  {"HANG",	  OPT_HANG,    "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
+     N_("Hang for SECS seconds (default 3600)")},
+  {0, 0}
+};
+
+static error_t
+argp_default_parser (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case '?':
+      __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
+      break;
+    case OPT_USAGE:
+      __argp_state_help (state, state->out_stream,
+		       ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
+      break;
+
+    case OPT_PROGNAME:		/* Set the program name.  */
+#ifndef __IN_INNOTEK_LIBC__
+#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME
+      program_invocation_name = arg;
+#endif
+#endif
+      /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka
+	 __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined
+	 to be that, so we have to be a bit careful here.]  */
+
+      /* Update what we use for messages.  */
+      state->name = strrchr (arg, '/');
+      if (state->name)
+	state->name++;
+      else
+	state->name = arg;
+
+#ifndef __IN_INNOTEK_LIBC__
+#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+      program_invocation_short_name = state->name;
+#endif
+#endif
+
+      if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
+	  == ARGP_PARSE_ARGV0)
+	/* Update what getopt uses too.  */
+	state->argv[0] = arg;
+
+      break;
+
+    case OPT_HANG:
+      _argp_hang = atoi (arg ? arg : "3600");
+      while (_argp_hang-- > 0)
+	__sleep (1);
+      break;
+
+    default:
+      return EBADKEY;
+    }
+  return 0;
+}
+
+static const struct argp argp_default_argp =
+  {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"};
+
+
+
+static const struct argp_option argp_version_options[] =
+{
+  {"version",	  'V',    	0, 0,  N_("Print program version"), -1},
+  {0, 0}
+};
+
+static error_t
+argp_version_parser (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'V':
+      if (argp_program_version_hook)
+	(*argp_program_version_hook) (state->out_stream, state);
+      else if (argp_program_version)
+	fprintf (state->out_stream, "%s\n", argp_program_version);
+      else
+	__argp_error (state, dgettext (state->root_argp->argp_domain,
+				       "(PROGRAM ERROR) No version known!?"));
+      if (! (state->flags & ARGP_NO_EXIT))
+	exit (0);
+      break;
+    default:
+      return EBADKEY;
+    }
+  return 0;
+}
+
+static const struct argp argp_version_argp =
+  {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"};
+
+
+/* Returns the offset into the getopt long options array LONG_OPTIONS of a
+   long option with called NAME, or -1 if none is found.  Passing NULL as
+   NAME will return the number of options.  */
+static int
+find_long_option (struct option *long_options, const char *name)
+{
+  struct option *l = long_options;
+  while (l->name != NULL)
+    if (name != NULL && strcmp (l->name, name) == 0)
+      return l - long_options;
+    else
+      l++;
+  if (name == NULL)
+    return l - long_options;
+  else
+    return -1;
+}
+
+
+
+/* The state of a `group' during parsing.  Each group corresponds to a
+   particular argp structure from the tree of such descending from the top
+   level argp passed to argp_parse.  */
+struct group
+{
+  /* This group's parsing function.  */
+  argp_parser_t parser;
+
+  /* Which argp this group is from.  */
+  const struct argp *argp;
+
+  /* Points to the point in SHORT_OPTS corresponding to the end of the short
+     options for this group.  We use it to determine from which group a
+     particular short options is from.  */
+  char *short_end;
+
+  /* The number of non-option args sucessfully handled by this parser.  */
+  unsigned args_processed;
+
+  /* This group's parser's parent's group.  */
+  struct group *parent;
+  unsigned parent_index;	/* And the our position in the parent.   */
+
+  /* These fields are swapped into and out of the state structure when
+     calling this group's parser.  */
+  void *input, **child_inputs;
+  void *hook;
+};
+
+/* Call GROUP's parser with KEY and ARG, swapping any group-specific info
+   from STATE before calling, and back into state afterwards.  If GROUP has
+   no parser, EBADKEY is returned.  */
+static error_t
+group_parse (struct group *group, struct argp_state *state, int key, char *arg)
+{
+  if (group->parser)
+    {
+      error_t err;
+      state->hook = group->hook;
+      state->input = group->input;
+      state->child_inputs = group->child_inputs;
+      state->arg_num = group->args_processed;
+      err = (*group->parser)(key, arg, state);
+      group->hook = state->hook;
+      return err;
+    }
+  else
+    return EBADKEY;
+}
+
+
+struct parser
+{
+  const struct argp *argp;
+
+  /* SHORT_OPTS is the getopt short options string for the union of all the
+     groups of options.  */
+  char *short_opts;
+  /* LONG_OPTS is the array of getop long option structures for the union of
+     all the groups of options.  */
+  struct option *long_opts;
+  /* OPT_DATA is the getopt data used for the re-entrant getopt.  */
+  struct _getopt_data opt_data;
+
+  /* States of the various parsing groups.  */
+  struct group *groups;
+  /* The end of the GROUPS array.  */
+  struct group *egroup;
+  /* An vector containing storage for the CHILD_INPUTS field in all groups.  */
+  void **child_inputs;
+
+  /* True if we think using getopt is still useful; if false, then
+     remaining arguments are just passed verbatim with ARGP_KEY_ARG.  This is
+     cleared whenever getopt returns KEY_END, but may be set again if the user
+     moves the next argument pointer backwards.  */
+  int try_getopt;
+
+  /* State block supplied to parsing routines.  */
+  struct argp_state state;
+
+  /* Memory used by this parser.  */
+  void *storage;
+};
+
+
+/* The next usable entries in the various parser tables being filled in by
+   convert_options.  */
+struct parser_convert_state
+{
+  struct parser *parser;
+  char *short_end;
+  struct option *long_end;
+  void **child_inputs_end;
+};
+
+/* Converts all options in ARGP (which is put in GROUP) and ancestors
+   into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and
+   CVT->LONG_END are the points at which new options are added.  Returns the
+   next unused group entry.  CVT holds state used during the conversion.  */
+static struct group *
+convert_options (const struct argp *argp,
+		 struct group *parent, unsigned parent_index,
+		 struct group *group, struct parser_convert_state *cvt)
+{
+  /* REAL is the most recent non-alias value of OPT.  */
+  const struct argp_option *real = argp->options;
+  const struct argp_child *children = argp->children;
+
+  if (real || argp->parser)
+    {
+      const struct argp_option *opt;
+
+      if (real)
+	for (opt = real; !__option_is_end (opt); opt++)
+	  {
+	    if (! (opt->flags & OPTION_ALIAS))
+	      /* OPT isn't an alias, so we can use values from it.  */
+	      real = opt;
+
+	    if (! (real->flags & OPTION_DOC))
+	      /* A real option (not just documentation).  */
+	      {
+		if (__option_is_short (opt))
+		  /* OPT can be used as a short option.  */
+		  {
+		    *cvt->short_end++ = opt->key;
+		    if (real->arg)
+		      {
+			*cvt->short_end++ = ':';
+			if (real->flags & OPTION_ARG_OPTIONAL)
+			  *cvt->short_end++ = ':';
+		      }
+		    *cvt->short_end = '\0'; /* keep 0 terminated */
+		  }
+
+		if (opt->name
+		    && find_long_option (cvt->parser->long_opts, opt->name) < 0)
+		  /* OPT can be used as a long option.  */
+		  {
+		    cvt->long_end->name = opt->name;
+		    cvt->long_end->has_arg =
+		      (real->arg
+		       ? (real->flags & OPTION_ARG_OPTIONAL
+			  ? optional_argument
+			  : required_argument)
+		       : no_argument);
+		    cvt->long_end->flag = 0;
+		    /* we add a disambiguating code to all the user's
+		       values (which is removed before we actually call
+		       the function to parse the value); this means that
+		       the user loses use of the high 8 bits in all his
+		       values (the sign of the lower bits is preserved
+		       however)...  */
+		    cvt->long_end->val =
+		      ((opt->key | real->key) & USER_MASK)
+		      + (((group - cvt->parser->groups) + 1) << USER_BITS);
+
+		    /* Keep the LONG_OPTS list terminated.  */
+		    (++cvt->long_end)->name = NULL;
+		  }
+	      }
+	    }
+
+      group->parser = argp->parser;
+      group->argp = argp;
+      group->short_end = cvt->short_end;
+      group->args_processed = 0;
+      group->parent = parent;
+      group->parent_index = parent_index;
+      group->input = 0;
+      group->hook = 0;
+      group->child_inputs = 0;
+
+      if (children)
+	/* Assign GROUP's CHILD_INPUTS field some space from
+           CVT->child_inputs_end.*/
+	{
+	  unsigned num_children = 0;
+	  while (children[num_children].argp)
+	    num_children++;
+	  group->child_inputs = cvt->child_inputs_end;
+	  cvt->child_inputs_end += num_children;
+	}
+
+      parent = group++;
+    }
+  else
+    parent = 0;
+
+  if (children)
+    {
+      unsigned index = 0;
+      while (children->argp)
+	group =
+	  convert_options (children++->argp, parent, index++, group, cvt);
+    }
+
+  return group;
+}
+
+/* Find the merged set of getopt options, with keys appropiately prefixed. */
+static void
+parser_convert (struct parser *parser, const struct argp *argp, int flags)
+{
+  struct parser_convert_state cvt;
+
+  cvt.parser = parser;
+  cvt.short_end = parser->short_opts;
+  cvt.long_end = parser->long_opts;
+  cvt.child_inputs_end = parser->child_inputs;
+
+  if (flags & ARGP_IN_ORDER)
+    *cvt.short_end++ = '-';
+  else if (flags & ARGP_NO_ARGS)
+    *cvt.short_end++ = '+';
+  *cvt.short_end = '\0';
+
+  cvt.long_end->name = NULL;
+
+  parser->argp = argp;
+
+  if (argp)
+    parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt);
+  else
+    parser->egroup = parser->groups; /* No parsers at all! */
+}
+
+
+/* Lengths of various parser fields which we will allocated.  */
+struct parser_sizes
+{
+  size_t short_len;		/* Getopt short options string.  */
+  size_t long_len;		/* Getopt long options vector.  */
+  size_t num_groups;		/* Group structures we allocate.  */
+  size_t num_child_inputs;	/* Child input slots.  */
+};
+
+/* For ARGP, increments the NUM_GROUPS field in SZS by the total number of
+ argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by
+ the maximum lengths of the resulting merged getopt short options string and
+ long-options array, respectively.  */
+static void
+calc_sizes (const struct argp *argp,  struct parser_sizes *szs)
+{
+  const struct argp_child *child = argp->children;
+  const struct argp_option *opt = argp->options;
+
+  if (opt || argp->parser)
+    {
+      szs->num_groups++;
+      if (opt)
+	{
+	  int num_opts = 0;
+	  while (!__option_is_end (opt++))
+	    num_opts++;
+	  szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */
+	  szs->long_len += num_opts;
+	}
+    }
+
+  if (child)
+    while (child->argp)
+      {
+	calc_sizes ((child++)->argp, szs);
+	szs->num_child_inputs++;
+      }
+}
+
+/* Initializes PARSER to parse ARGP in a manner described by FLAGS.  */
+static error_t
+parser_init (struct parser *parser, const struct argp *argp,
+	     int argc, char **argv, int flags, void *input)
+{
+  error_t err = 0;
+  struct group *group;
+  struct parser_sizes szs;
+  struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
+
+  szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
+  szs.long_len = 0;
+  szs.num_groups = 0;
+  szs.num_child_inputs = 0;
+
+  if (argp)
+    calc_sizes (argp, &szs);
+
+  /* Lengths of the various bits of storage used by PARSER.  */
+#define GLEN (szs.num_groups + 1) * sizeof (struct group)
+#define CLEN (szs.num_child_inputs * sizeof (void *))
+#define LLEN ((szs.long_len + 1) * sizeof (struct option))
+#define SLEN (szs.short_len + 1)
+
+  parser->storage = malloc (GLEN + CLEN + LLEN + SLEN);
+  if (! parser->storage)
+    return ENOMEM;
+
+  parser->groups = parser->storage;
+  parser->child_inputs = (void **)((char *)parser->storage + GLEN);
+  parser->long_opts = (struct option *)((char *)parser->storage + GLEN + CLEN);
+  parser->short_opts = (char *)parser->storage + GLEN + CLEN + LLEN;
+  parser->opt_data = opt_data;
+
+  memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
+  parser_convert (parser, argp, flags);
+
+  memset (&parser->state, 0, sizeof (struct argp_state));
+  parser->state.root_argp = parser->argp;
+  parser->state.argc = argc;
+  parser->state.argv = argv;
+  parser->state.flags = flags;
+  parser->state.err_stream = stderr;
+  parser->state.out_stream = stdout;
+  parser->state.next = 0;	/* Tell getopt to initialize.  */
+  parser->state.pstate = parser;
+
+  parser->try_getopt = 1;
+
+  /* Call each parser for the first time, giving it a chance to propagate
+     values to child parsers.  */
+  if (parser->groups < parser->egroup)
+    parser->groups->input = input;
+  for (group = parser->groups;
+       group < parser->egroup && (!err || err == EBADKEY);
+       group++)
+    {
+      if (group->parent)
+	/* If a child parser, get the initial input value from the parent. */
+	group->input = group->parent->child_inputs[group->parent_index];
+
+      if (!group->parser
+	  && group->argp->children && group->argp->children->argp)
+	/* For the special case where no parsing function is supplied for an
+	   argp, propagate its input to its first child, if any (this just
+	   makes very simple wrapper argps more convenient).  */
+	group->child_inputs[0] = group->input;
+
+      err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0);
+    }
+  if (err == EBADKEY)
+    err = 0;			/* Some parser didn't understand.  */
+
+  if (err)
+    return err;
+
+  if (parser->state.flags & ARGP_NO_ERRS)
+    {
+      parser->opt_data.opterr = 0;
+      if (parser->state.flags & ARGP_PARSE_ARGV0)
+	/* getopt always skips ARGV[0], so we have to fake it out.  As long
+	   as OPTERR is 0, then it shouldn't actually try to access it.  */
+	parser->state.argv--, parser->state.argc++;
+    }
+  else
+    parser->opt_data.opterr = 1;	/* Print error messages.  */
+
+  if (parser->state.argv == argv && argv[0])
+    /* There's an argv[0]; use it for messages.  */
+    {
+      char *short_name = strrchr (argv[0], '/');
+      parser->state.name = short_name ? short_name + 1 : argv[0];
+    }
+  else
+    parser->state.name = __argp_short_program_name ();
+
+  return 0;
+}
+
+
+/* Free any storage consumed by PARSER (but not PARSER itself).  */
+static error_t
+parser_finalize (struct parser *parser,
+		 error_t err, int arg_ebadkey, int *end_index)
+{
+  struct group *group;
+
+  if (err == EBADKEY && arg_ebadkey)
+    /* Suppress errors generated by unparsed arguments.  */
+    err = 0;
+
+  if (! err)
+    {
+      if (parser->state.next == parser->state.argc)
+	/* We successfully parsed all arguments!  Call all the parsers again,
+	   just a few more times... */
+	{
+	  for (group = parser->groups;
+	       group < parser->egroup && (!err || err==EBADKEY);
+	       group++)
+	    if (group->args_processed == 0)
+	      err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0);
+	  for (group = parser->egroup - 1;
+	       group >= parser->groups && (!err || err==EBADKEY);
+	       group--)
+	    err = group_parse (group, &parser->state, ARGP_KEY_END, 0);
+
+	  if (err == EBADKEY)
+	    err = 0;		/* Some parser didn't understand.  */
+
+	  /* Tell the user that all arguments are parsed.  */
+	  if (end_index)
+	    *end_index = parser->state.next;
+	}
+      else if (end_index)
+	/* Return any remaining arguments to the user.  */
+	*end_index = parser->state.next;
+      else
+	/* No way to return the remaining arguments, they must be bogus. */
+	{
+	  if (!(parser->state.flags & ARGP_NO_ERRS)
+	      && parser->state.err_stream)
+	    fprintf (parser->state.err_stream,
+		     dgettext (parser->argp->argp_domain,
+			       "%s: Too many arguments\n"),
+		     parser->state.name);
+	  err = EBADKEY;
+	}
+    }
+
+  /* Okay, we're all done, with either an error or success; call the parsers
+     to indicate which one.  */
+
+  if (err)
+    {
+      /* Maybe print an error message.  */
+      if (err == EBADKEY)
+	/* An appropriate message describing what the error was should have
+	   been printed earlier.  */
+	__argp_state_help (&parser->state, parser->state.err_stream,
+			   ARGP_HELP_STD_ERR);
+
+      /* Since we didn't exit, give each parser an error indication.  */
+      for (group = parser->groups; group < parser->egroup; group++)
+	group_parse (group, &parser->state, ARGP_KEY_ERROR, 0);
+    }
+  else
+    /* Notify parsers of success, and propagate back values from parsers.  */
+    {
+      /* We pass over the groups in reverse order so that child groups are
+	 given a chance to do there processing before passing back a value to
+	 the parent.  */
+      for (group = parser->egroup - 1
+	   ; group >= parser->groups && (!err || err == EBADKEY)
+	   ; group--)
+	err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0);
+      if (err == EBADKEY)
+	err = 0;		/* Some parser didn't understand.  */
+    }
+
+  /* Call parsers once more, to do any final cleanup.  Errors are ignored.  */
+  for (group = parser->egroup - 1; group >= parser->groups; group--)
+    group_parse (group, &parser->state, ARGP_KEY_FINI, 0);
+
+  if (err == EBADKEY)
+    err = EINVAL;
+
+  free (parser->storage);
+
+  return err;
+}
+
+
+/* Call the user parsers to parse the non-option argument VAL, at the current
+   position, returning any error.  The state NEXT pointer is assumed to have
+   been adjusted (by getopt) to point after this argument; this function will
+   adjust it correctly to reflect however many args actually end up being
+   consumed.  */
+static error_t
+parser_parse_arg (struct parser *parser, char *val)
+{
+  /* Save the starting value of NEXT, first adjusting it so that the arg
+     we're parsing is again the front of the arg vector.  */
+  int index = --parser->state.next;
+  error_t err = EBADKEY;
+  struct group *group;
+  int key = 0;			/* Which of ARGP_KEY_ARG[S] we used.  */
+
+  /* Try to parse the argument in each parser.  */
+  for (group = parser->groups
+       ; group < parser->egroup && err == EBADKEY
+       ; group++)
+    {
+      parser->state.next++;	/* For ARGP_KEY_ARG, consume the arg.  */
+      key = ARGP_KEY_ARG;
+      err = group_parse (group, &parser->state, key, val);
+
+      if (err == EBADKEY)
+	/* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */
+	{
+	  parser->state.next--;	/* For ARGP_KEY_ARGS, put back the arg.  */
+	  key = ARGP_KEY_ARGS;
+	  err = group_parse (group, &parser->state, key, 0);
+	}
+    }
+
+  if (! err)
+    {
+      if (key == ARGP_KEY_ARGS)
+	/* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't
+	   changed by the user, *all* arguments should be considered
+	   consumed.  */
+	parser->state.next = parser->state.argc;
+
+      if (parser->state.next > index)
+	/* Remember that we successfully processed a non-option
+	   argument -- but only if the user hasn't gotten tricky and set
+	   the clock back.  */
+	(--group)->args_processed += (parser->state.next - index);
+      else
+	/* The user wants to reparse some args, give getopt another try.  */
+	parser->try_getopt = 1;
+    }
+
+  return err;
+}
+
+
+/* Call the user parsers to parse the option OPT, with argument VAL, at the
+   current position, returning any error.  */
+static error_t
+parser_parse_opt (struct parser *parser, int opt, char *val)
+{
+  /* The group key encoded in the high bits; 0 for short opts or
+     group_number + 1 for long opts.  */
+  int group_key = opt >> USER_BITS;
+  error_t err = EBADKEY;
+
+  if (group_key == 0)
+    /* A short option.  By comparing OPT's position in SHORT_OPTS to the
+       various starting positions in each group's SHORT_END field, we can
+       determine which group OPT came from.  */
+    {
+      struct group *group;
+      char *short_index = strchr (parser->short_opts, opt);
+
+      if (short_index)
+	for (group = parser->groups; group < parser->egroup; group++)
+	  if (group->short_end > short_index)
+	    {
+	      err = group_parse (group, &parser->state, opt,
+				 parser->opt_data.optarg);
+	      break;
+	    }
+    }
+  else
+    /* A long option.  We use shifts instead of masking for extracting
+       the user value in order to preserve the sign.  */
+    err =
+      group_parse (&parser->groups[group_key - 1], &parser->state,
+		   (opt << GROUP_BITS) >> GROUP_BITS,
+		   parser->opt_data.optarg);
+
+  if (err == EBADKEY)
+    /* At least currently, an option not recognized is an error in the
+       parser, because we pre-compute which parser is supposed to deal
+       with each option.  */
+    {
+      static const char bad_key_err[] =
+	N_("(PROGRAM ERROR) Option should have been recognized!?");
+      if (group_key == 0)
+	__argp_error (&parser->state, "-%c: %s", opt,
+		      dgettext (parser->argp->argp_domain, bad_key_err));
+      else
+	{
+	  struct option *long_opt = parser->long_opts;
+	  while (long_opt->val != opt && long_opt->name)
+	    long_opt++;
+	  __argp_error (&parser->state, "--%s: %s",
+			long_opt->name ? long_opt->name : "???",
+			dgettext (parser->argp->argp_domain, bad_key_err));
+	}
+    }
+
+  return err;
+}
+
+
+/* Parse the next argument in PARSER (as indicated by PARSER->state.next).
+   Any error from the parsers is returned, and *ARGP_EBADKEY indicates
+   whether a value of EBADKEY is due to an unrecognized argument (which is
+   generally not fatal).  */
+static error_t
+parser_parse_next (struct parser *parser, int *arg_ebadkey)
+{
+  int opt;
+  error_t err = 0;
+
+  if (parser->state.quoted && parser->state.next < parser->state.quoted)
+    /* The next argument pointer has been moved to before the quoted
+       region, so pretend we never saw the quoting `--', and give getopt
+       another chance.  If the user hasn't removed it, getopt will just
+       process it again.  */
+    parser->state.quoted = 0;
+
+  if (parser->try_getopt && !parser->state.quoted)
+    /* Give getopt a chance to parse this.  */
+    {
+      /* Put it back in OPTIND for getopt.  */
+      parser->opt_data.optind = parser->state.next;
+      /* Distinguish KEY_ERR from a real option.  */
+      parser->opt_data.optopt = KEY_END;
+      if (parser->state.flags & ARGP_LONG_ONLY)
+	opt = _getopt_long_only_r (parser->state.argc, parser->state.argv,
+				   parser->short_opts, parser->long_opts, 0,
+				   &parser->opt_data);
+      else
+	opt = _getopt_long_r (parser->state.argc, parser->state.argv,
+			      parser->short_opts, parser->long_opts, 0,
+			      &parser->opt_data);
+      /* And see what getopt did.  */
+      parser->state.next = parser->opt_data.optind;
+
+      if (opt == KEY_END)
+	/* Getopt says there are no more options, so stop using
+	   getopt; we'll continue if necessary on our own.  */
+	{
+	  parser->try_getopt = 0;
+	  if (parser->state.next > 1
+	      && strcmp (parser->state.argv[parser->state.next - 1], QUOTE)
+	           == 0)
+	    /* Not only is this the end of the options, but it's a
+	       `quoted' region, which may have args that *look* like
+	       options, so we definitely shouldn't try to use getopt past
+	       here, whatever happens.  */
+	    parser->state.quoted = parser->state.next;
+	}
+      else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END)
+	/* KEY_ERR can have the same value as a valid user short
+	   option, but in the case of a real error, getopt sets OPTOPT
+	   to the offending character, which can never be KEY_END.  */
+	{
+	  *arg_ebadkey = 0;
+	  return EBADKEY;
+	}
+    }
+  else
+    opt = KEY_END;
+
+  if (opt == KEY_END)
+    {
+      /* We're past what getopt considers the options.  */
+      if (parser->state.next >= parser->state.argc
+	  || (parser->state.flags & ARGP_NO_ARGS))
+	/* Indicate that we're done.  */
+	{
+	  *arg_ebadkey = 1;
+	  return EBADKEY;
+	}
+      else
+	/* A non-option arg; simulate what getopt might have done.  */
+	{
+	  opt = KEY_ARG;
+	  parser->opt_data.optarg = parser->state.argv[parser->state.next++];
+	}
+    }
+
+  if (opt == KEY_ARG)
+    /* A non-option argument; try each parser in turn.  */
+    err = parser_parse_arg (parser, parser->opt_data.optarg);
+  else
+    err = parser_parse_opt (parser, opt, parser->opt_data.optarg);
+
+  if (err == EBADKEY)
+    *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
+
+  return err;
+}
+
+
+/* Parse the options strings in ARGC & ARGV according to the argp in ARGP.
+   FLAGS is one of the ARGP_ flags above.  If END_INDEX is non-NULL, the
+   index in ARGV of the first unparsed option is returned in it.  If an
+   unknown option is present, EINVAL is returned; if some parser routine
+   returned a non-zero value, it is returned; otherwise 0 is returned.  */
+error_t
+__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
+	      int *end_index, void *input)
+{
+  error_t err;
+  struct parser parser;
+
+  /* If true, then err == EBADKEY is a result of a non-option argument failing
+     to be parsed (which in some cases isn't actually an error).  */
+  int arg_ebadkey = 0;
+
+  if (! (flags & ARGP_NO_HELP))
+    /* Add our own options.  */
+    {
+      struct argp_child *child = alloca (4 * sizeof (struct argp_child));
+      struct argp *top_argp = alloca (sizeof (struct argp));
+
+      /* TOP_ARGP has no options, it just serves to group the user & default
+	 argps.  */
+      memset (top_argp, 0, sizeof (*top_argp));
+      top_argp->children = child;
+
+      memset (child, 0, 4 * sizeof (struct argp_child));
+
+      if (argp)
+	(child++)->argp = argp;
+      (child++)->argp = &argp_default_argp;
+      if (argp_program_version || argp_program_version_hook)
+	(child++)->argp = &argp_version_argp;
+      child->argp = 0;
+
+      argp = top_argp;
+    }
+
+  /* Construct a parser for these arguments.  */
+  err = parser_init (&parser, argp, argc, argv, flags, input);
+
+  if (! err)
+    /* Parse! */
+    {
+      while (! err)
+	err = parser_parse_next (&parser, &arg_ebadkey);
+      err = parser_finalize (&parser, err, arg_ebadkey, end_index);
+    }
+
+  return err;
+}
+#ifdef weak_alias
+weak_alias (__argp_parse, argp_parse)
+#endif
+
+
+/* Return the input field for ARGP in the parser corresponding to STATE; used
+   by the help routines.  */
+void *
+__argp_input (const struct argp *argp, const struct argp_state *state)
+{
+  if (state)
+    {
+      struct group *group;
+      struct parser *parser = state->pstate;
+
+      for (group = parser->groups; group < parser->egroup; group++)
+	if (group->argp == argp)
+	  return group->input;
+    }
+
+  return 0;
+}
+#ifdef weak_alias
+weak_alias (__argp_input, _argp_input)
+#endif
Index: /trunk/libc/src/glibc/argp/argp-pv.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-pv.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-pv.c	(revision 2448)
@@ -0,0 +1,25 @@
+/* Default definition for ARGP_PROGRAM_VERSION.
+   Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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.  */
+
+/* If set by the user program to a non-zero value, then a default option
+   --version is added (unless the ARGP_NO_HELP flag is used), which will
+   print this this string followed by a newline and exit (unless the
+   ARGP_NO_EXIT flag is used).  Overridden by ARGP_PROGRAM_VERSION_HOOK.  */
+const char *argp_program_version = 0;
Index: /trunk/libc/src/glibc/argp/argp-pvh.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-pvh.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-pvh.c	(revision 2448)
@@ -0,0 +1,32 @@
+/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
+   Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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 "argp.h"
+
+/* If set by the user program to a non-zero value, then a default option
+   --version is added (unless the ARGP_NO_HELP flag is used), which calls
+   this function with a stream to print the version to and a pointer to the
+   current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
+   used).  This variable takes precedent over ARGP_PROGRAM_VERSION.  */
+void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL;
Index: /trunk/libc/src/glibc/argp/argp-xinl.c
===================================================================
--- /trunk/libc/src/glibc/argp/argp-xinl.c	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp-xinl.c	(revision 2448)
@@ -0,0 +1,46 @@
+/* Real definitions for extern inline functions in argp.h
+   Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+   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
+
+#if defined _LIBC || defined HAVE_FEATURES_H
+# include <features.h>
+#endif
+
+#ifndef __USE_EXTERN_INLINES
+# define __USE_EXTERN_INLINES	1
+#endif
+#define ARGP_EI
+#undef __OPTIMIZE__
+#define __OPTIMIZE__ 1
+#include "argp.h"
+
+/* Add weak aliases.  */
+#ifndef __IN_INNOTEK_LIBC__
+#if _LIBC - 0 && defined (weak_alias)
+
+weak_alias (__argp_usage, argp_usage)
+weak_alias (__option_is_short, _option_is_short)
+weak_alias (__option_is_end, _option_is_end)
+
+#endif
+#endif
Index: /trunk/libc/src/glibc/argp/argp.smak
===================================================================
--- /trunk/libc/src/glibc/argp/argp.smak	(revision 2448)
+++ /trunk/libc/src/glibc/argp/argp.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/glibc/argp/*.c)
Index: /trunk/libc/src/glibc/crypt/Banner
===================================================================
--- /trunk/libc/src/glibc/crypt/Banner	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/Banner	(revision 2448)
@@ -0,0 +1,1 @@
+crypt add-on version 2.1 by Michael Glad and others
Index: /trunk/libc/src/glibc/crypt/README.ufc-crypt
===================================================================
--- /trunk/libc/src/glibc/crypt/README.ufc-crypt	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/README.ufc-crypt	(revision 2448)
@@ -0,0 +1,135 @@
+The following is the README for UFC-crypt, with those portions deleted
+that are known to be incorrect for the implementation used with the
+GNU C library.
+
+
+	UFC-crypt: ultra fast 'crypt' implementation
+	============================================
+
+	@(#)README	2.27 11 Sep 1996
+
+Design goals/non goals:
+----------------------
+
+- Crypt implementation plugin compatible with crypt(3)/fcrypt.
+
+- High performance when used for password cracking.
+
+- Portable to most 32/64 bit machines.
+
+- Startup time/mixed salt performance not critical.
+
+Features of the implementation:
+------------------------------
+
+- On most machines, UFC-crypt runs 30-60 times faster than crypt(3) when
+  invoked repeated times with the same salt and varying passwords.
+
+- With mostly constant salts, performance is about two to three times
+  that of the default fcrypt implementation shipped with Alec
+  Muffets 'Crack' password cracker. For instructions on how to
+  plug UFC-crypt into 'Crack', see below.
+
+- With alternating salts, performance is only about twice
+  that of crypt(3).
+
+- Requires 165 kb for tables.
+
+Author & licensing etc
+----------------------
+
+UFC-crypt is created by Michael Glad, email: glad@daimi.aau.dk, and has
+been donated to the Free Software Foundation, Inc. It is covered by the
+GNU library license version 2, see the file 'COPYING.LIB'.
+
+NOTES FOR USERS OUTSIDE THE US:
+------------------------------
+
+The US government limits the export of DES based software/hardware.
+This software is written in Aarhus, Denmark. It can therefore be retrieved
+from ftp sites outside the US without breaking US law. Please do not
+ftp it from american sites.
+
+Benchmark table:
+---------------
+
+The table shows how many operations per second UFC-crypt can
+do on various machines.
+
+|--------------|-------------------------------------------|
+|Machine       |  SUN*  SUN*   HP*     DecStation   HP     |
+|              | 3/50   ELC  9000/425e    3100    9000/720 |
+|--------------|-------------------------------------------|
+| Crypt(3)/sec |  4.6    30     15         25        57    |
+| Ufc/sec      |  220   990    780       1015      3500    |
+|--------------|-------------------------------------------|
+| Speedup      |   48    30     52         40        60    |
+|--------------|-------------------------------------------|
+
+*) Compiled using special assembly language support module.
+
+It seems as if performance is limited by CPU bus and data cache capacity.
+This also makes the benchmarks debatable compared to a real test with
+UFC-crypt wired into Crack. However, the table gives an outline of
+what can be expected.
+
+Optimizations:
+-------------
+
+Here are the optimizations used relative to an ordinary implementation
+such as the one said to be used in crypt(3).
+
+Major optimizations
+*******************
+
+- Keep data packed as bits in integer variables -- allows for
+  fast permutations & parallel xor's in CPU hardware.
+
+- Let adjacent final & initial permutations collapse.
+
+- Keep working data in 'E expanded' format all the time.
+
+- Implement DES 'f' function mostly by table lookup
+
+- Calculate the above function on 12 bit basis rather than 6
+  as would be the most natural.
+
+- Implement setup routines so that performance is limited by the DES
+  inner loops only.
+
+- Instead of doing salting in the DES inner loops, modify the above tables
+  each time a new salt is seen. According to the BSD crypt code this is
+  ugly :-)
+
+Minor (dirty) optimizations
+***************************
+
+- combine iterations of DES inner loop so that DES only loops
+  8 times. This saves a lot of variable swapping.
+
+- Implement key access by a walking pointer rather than coding
+  as array indexing.
+
+- As described, the table based f function uses a 3 dimensional array:
+
+	sb ['number of 12 bit segment']['12 bit index']['48 bit half index']
+
+  Code the routine with 4 (one dimensional) vectors.
+
+- Design the internal data format & uglify the DES loops so that
+  the compiler does not need to do bit shifts when indexing vectors.
+
+Revision history
+****************
+
+UFC patchlevel 0: base version; released to alt.sources on Sep 24 1991
+UFC patchlevel 1: patch released to alt.sources on Sep 27 1991.
+		  No longer rebuilds sb tables when seeing a new salt.
+UFC-crypt pl0:	  Essentially UFC pl 1. Released to comp.sources.misc
+		  on Oct 22 1991.
+UFC-crypt pl1:    Released to comp.sources.misc in march 1992
+		  * setkey/encrypt routines added
+		  * added validation/benchmarking programs
+		  * reworked keyschedule setup code
+		  * memory demands reduced
+		  * 64 bit support added
Index: /trunk/libc/src/glibc/crypt/cert.c
===================================================================
--- /trunk/libc/src/glibc/crypt/cert.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/cert.c	(revision 2448)
@@ -0,0 +1,113 @@
+
+/*
+ * This crypt(3) validation program shipped with UFC-crypt
+ * is derived from one distributed with Phil Karns PD DES package.
+ *
+ * @(#)cert.c	1.8 11 Aug 1996
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "crypt.h"
+
+int totfails = 0;
+
+#if __STDC__ - 0
+int main (int argc, char *argv[]);
+void get8 (char *cp);
+void put8 (char *cp);
+void good_bye (void) __attribute__ ((noreturn));
+#else
+void get8(), put8();
+#endif
+
+void good_bye ()
+{
+  if(totfails == 0) {
+    printf("Passed DES validation suite\n");
+    exit(0);
+  } else {
+    printf("%d failures during DES validation suite!!!\n", totfails);
+    exit(1);
+  }
+}
+
+int
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+	char key[64],plain[64],cipher[64],answer[64];
+	int i;
+	int test;
+	int fail;
+
+	for(test=0;!feof(stdin);test++){
+
+		get8(key);
+		printf(" K: "); put8(key);
+		setkey(key);
+
+		get8(plain);
+		printf(" P: "); put8(plain);
+
+		get8(answer);
+		printf(" C: "); put8(answer);
+
+		for(i=0;i<64;i++)
+			cipher[i] = plain[i];
+		encrypt(cipher, 0);
+
+		for(i=0;i<64;i++)
+			if(cipher[i] != answer[i])
+				break;
+		fail = 0;
+		if(i != 64){
+			printf(" Encrypt FAIL");
+			fail++; totfails++;
+		}
+
+		encrypt(cipher, 1);
+
+		for(i=0;i<64;i++)
+			if(cipher[i] != plain[i])
+				break;
+		if(i != 64){
+			printf(" Decrypt FAIL");
+			fail++; totfails++;
+		}
+
+		if(fail == 0)
+			printf(" OK");
+		printf("\n");
+	}
+	good_bye();
+}
+void
+get8(cp)
+char *cp;
+{
+	int i,j,t;
+
+	for(i=0;i<8;i++){
+		scanf("%2x",&t);
+		if(feof(stdin))
+		  good_bye();
+		for(j=0; j<8 ; j++) {
+		  *cp++ = (t & (0x01 << (7-j))) != 0;
+		}
+	}
+}
+void
+put8(cp)
+char *cp;
+{
+	int i,j,t;
+
+	for(i=0;i<8;i++){
+	  t = 0;
+	  for(j = 0; j<8; j++)
+	    t = (t<<1) | *cp++;
+	  printf("%02x", t);
+	}
+}
Index: /trunk/libc/src/glibc/crypt/cert.input
===================================================================
--- /trunk/libc/src/glibc/crypt/cert.input	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/cert.input	(revision 2448)
@@ -0,0 +1,171 @@
+0101010101010101 95f8a5e5dd31d900 8000000000000000
+0101010101010101 dd7f121ca5015619 4000000000000000
+0101010101010101 2e8653104f3834ea 2000000000000000
+0101010101010101 4bd388ff6cd81d4f 1000000000000000
+0101010101010101 20b9e767b2fb1456 0800000000000000
+0101010101010101 55579380d77138ef 0400000000000000
+0101010101010101 6cc5defaaf04512f 0200000000000000
+0101010101010101 0d9f279ba5d87260 0100000000000000
+0101010101010101 d9031b0271bd5a0a 0080000000000000
+0101010101010101 424250b37c3dd951 0040000000000000
+0101010101010101 b8061b7ecd9a21e5 0020000000000000
+0101010101010101 f15d0f286b65bd28 0010000000000000
+0101010101010101 add0cc8d6e5deba1 0008000000000000
+0101010101010101 e6d5f82752ad63d1 0004000000000000
+0101010101010101 ecbfe3bd3f591a5e 0002000000000000
+0101010101010101 f356834379d165cd 0001000000000000
+0101010101010101 2b9f982f20037fa9 0000800000000000
+0101010101010101 889de068a16f0be6 0000400000000000
+0101010101010101 e19e275d846a1298 0000200000000000
+0101010101010101 329a8ed523d71aec 0000100000000000
+0101010101010101 e7fce22557d23c97 0000080000000000
+0101010101010101 12a9f5817ff2d65d 0000040000000000
+0101010101010101 a484c3ad38dc9c19 0000020000000000
+0101010101010101 fbe00a8a1ef8ad72 0000010000000000
+0101010101010101 750d079407521363 0000008000000000
+0101010101010101 64feed9c724c2faf 0000004000000000
+0101010101010101 f02b263b328e2b60 0000002000000000
+0101010101010101 9d64555a9a10b852 0000001000000000
+0101010101010101 d106ff0bed5255d7 0000000800000000
+0101010101010101 e1652c6b138c64a5 0000000400000000
+0101010101010101 e428581186ec8f46 0000000200000000
+0101010101010101 aeb5f5ede22d1a36 0000000100000000
+0101010101010101 e943d7568aec0c5c 0000000080000000
+0101010101010101 df98c8276f54b04b 0000000040000000
+0101010101010101 b160e4680f6c696f 0000000020000000
+0101010101010101 fa0752b07d9c4ab8 0000000010000000
+0101010101010101 ca3a2b036dbc8502 0000000008000000
+0101010101010101 5e0905517bb59bcf 0000000004000000
+0101010101010101 814eeb3b91d90726 0000000002000000
+0101010101010101 4d49db1532919c9f 0000000001000000
+0101010101010101 25eb5fc3f8cf0621 0000000000800000
+0101010101010101 ab6a20c0620d1c6f 0000000000400000
+0101010101010101 79e90dbc98f92cca 0000000000200000
+0101010101010101 866ecedd8072bb0e 0000000000100000
+0101010101010101 8b54536f2f3e64a8 0000000000080000
+0101010101010101 ea51d3975595b86b 0000000000040000
+0101010101010101 caffc6ac4542de31 0000000000020000
+0101010101010101 8dd45a2ddf90796c 0000000000010000
+0101010101010101 1029d55e880ec2d0 0000000000008000
+0101010101010101 5d86cb23639dbea9 0000000000004000
+0101010101010101 1d1ca853ae7c0c5f 0000000000002000
+0101010101010101 ce332329248f3228 0000000000001000
+0101010101010101 8405d1abe24fb942 0000000000000800
+0101010101010101 e643d78090ca4207 0000000000000400
+0101010101010101 48221b9937748a23 0000000000000200
+0101010101010101 dd7c0bbd61fafd54 0000000000000100
+0101010101010101 2fbc291a570db5c4 0000000000000080
+0101010101010101 e07c30d7e4e26e12 0000000000000040
+0101010101010101 0953e2258e8e90a1 0000000000000020
+0101010101010101 5b711bc4ceebf2ee 0000000000000010
+0101010101010101 cc083f1e6d9e85f6 0000000000000008
+0101010101010101 d2fd8867d50d2dfe 0000000000000004
+0101010101010101 06e7ea22ce92708f 0000000000000002
+0101010101010101 166b40b44aba4bd6 0000000000000001
+8001010101010101 0000000000000000 95a8d72813daa94d
+4001010101010101 0000000000000000 0eec1487dd8c26d5
+2001010101010101 0000000000000000 7ad16ffb79c45926
+1001010101010101 0000000000000000 d3746294ca6a6cf3
+0801010101010101 0000000000000000 809f5f873c1fd761
+0401010101010101 0000000000000000 c02faffec989d1fc
+0201010101010101 0000000000000000 4615aa1d33e72f10
+0180010101010101 0000000000000000 2055123350c00858
+0140010101010101 0000000000000000 df3b99d6577397c8
+0120010101010101 0000000000000000 31fe17369b5288c9
+0110010101010101 0000000000000000 dfdd3cc64dae1642
+0108010101010101 0000000000000000 178c83ce2b399d94
+0104010101010101 0000000000000000 50f636324a9b7f80
+0102010101010101 0000000000000000 a8468ee3bc18f06d
+0101800101010101 0000000000000000 a2dc9e92fd3cde92
+0101400101010101 0000000000000000 cac09f797d031287
+0101200101010101 0000000000000000 90ba680b22aeb525
+0101100101010101 0000000000000000 ce7a24f350e280b6
+0101080101010101 0000000000000000 882bff0aa01a0b87
+0101040101010101 0000000000000000 25610288924511c2
+0101020101010101 0000000000000000 c71516c29c75d170
+0101018001010101 0000000000000000 5199c29a52c9f059
+0101014001010101 0000000000000000 c22f0a294a71f29f
+0101012001010101 0000000000000000 ee371483714c02ea
+0101011001010101 0000000000000000 a81fbd448f9e522f
+0101010801010101 0000000000000000 4f644c92e192dfed
+0101010401010101 0000000000000000 1afa9a66a6df92ae
+0101010201010101 0000000000000000 b3c1cc715cb879d8
+0101010180010101 0000000000000000 19d032e64ab0bd8b
+0101010140010101 0000000000000000 3cfaa7a7dc8720dc
+0101010120010101 0000000000000000 b7265f7f447ac6f3
+0101010110010101 0000000000000000 9db73b3c0d163f54
+0101010108010101 0000000000000000 8181b65babf4a975
+0101010104010101 0000000000000000 93c9b64042eaa240
+0101010102010101 0000000000000000 5570530829705592
+0101010101800101 0000000000000000 8638809e878787a0
+0101010101400101 0000000000000000 41b9a79af79ac208
+0101010101200101 0000000000000000 7a9be42f2009a892
+0101010101100101 0000000000000000 29038d56ba6d2745
+0101010101080101 0000000000000000 5495c6abf1e5df51
+0101010101040101 0000000000000000 ae13dbd561488933
+0101010101020101 0000000000000000 024d1ffa8904e389
+0101010101018001 0000000000000000 d1399712f99bf02e
+0101010101014001 0000000000000000 14c1d7c1cffec79e
+0101010101012001 0000000000000000 1de5279dae3bed6f
+0101010101011001 0000000000000000 e941a33f85501303
+0101010101010801 0000000000000000 da99dbbc9a03f379
+0101010101010401 0000000000000000 b7fc92f91d8e92e9
+0101010101010201 0000000000000000 ae8e5caa3ca04e85
+0101010101010180 0000000000000000 9cc62df43b6eed74
+0101010101010140 0000000000000000 d863dbb5c59a91a0
+0101010101010120 0000000000000000 a1ab2190545b91d7
+0101010101010110 0000000000000000 0875041e64c570f7
+0101010101010108 0000000000000000 5a594528bebef1cc
+0101010101010104 0000000000000000 fcdb3291de21f0c0
+0101010101010102 0000000000000000 869efd7f9f265a09
+1046913489980131 0000000000000000 88d55e54f54c97b4
+1007103489988020 0000000000000000 0c0cc00c83ea48fd
+10071034c8980120 0000000000000000 83bc8ef3a6570183
+1046103489988020 0000000000000000 df725dcad94ea2e9
+1086911519190101 0000000000000000 e652b53b550be8b0
+1086911519580101 0000000000000000 af527120c485cbb0
+5107b01519580101 0000000000000000 0f04ce393db926d5
+1007b01519190101 0000000000000000 c9f00ffc74079067
+3107915498080101 0000000000000000 7cfd82a593252b4e
+3107919498080101 0000000000000000 cb49a2f9e91363e3
+10079115b9080140 0000000000000000 00b588be70d23f56
+3107911598080140 0000000000000000 406a9a6ab43399ae
+1007d01589980101 0000000000000000 6cb773611dca9ada
+9107911589980101 0000000000000000 67fd21c17dbb5d70
+9107d01589190101 0000000000000000 9592cb4110430787
+1007d01598980120 0000000000000000 a6b7ff68a318ddd3
+1007940498190101 0000000000000000 4d102196c914ca16
+0107910491190401 0000000000000000 2dfa9f4573594965
+0107910491190101 0000000000000000 b46604816c0e0774
+0107940491190401 0000000000000000 6e7e6221a4f34e87
+19079210981a0101 0000000000000000 aa85e74643233199
+1007911998190801 0000000000000000 2e5a19db4d1962d6
+10079119981a0801 0000000000000000 23a866a809d30894
+1007921098190101 0000000000000000 d812d961f017d320
+100791159819010b 0000000000000000 055605816e58608f
+1004801598190101 0000000000000000 abd88e8b1b7716f1
+1004801598190102 0000000000000000 537ac95be69da1e1
+1004801598190108 0000000000000000 aed0f6ae3c25cdd8
+1002911598100104 0000000000000000 b3e35a5ee53e7b8d
+1002911598190104 0000000000000000 61c79c71921a2ef8
+1002911598100201 0000000000000000 e2f5728f0995013c
+1002911698100101 0000000000000000 1aeac39a61f0a464
+7ca110454a1a6e57 01a1d6d039776742 690f5b0d9a26939b
+0131d9619dc1376e 5cd54ca83def57da 7a389d10354bd271
+07a1133e4a0b2686 0248d43806f67172 868ebb51cab4599a
+3849674c2602319e 51454b582ddf440a 7178876e01f19b2a
+04b915ba43feb5b6 42fd443059577fa2 af37fb421f8c4095
+0113b970fd34f2ce 059b5e0851cf143a 86a560f10ec6d85b
+0170f175468fb5e6 0756d8e0774761d2 0cd3da020021dc09
+43297fad38e373fe 762514b829bf486a ea676b2cb7db2b7a
+07a7137045da2a16 3bdd119049372802 dfd64a815caf1a0f
+04689104c2fd3b2f 26955f6835af609a 5c513c9c4886c088
+37d06bb516cb7546 164d5e404f275232 0a2aeeae3ff4ab77
+1f08260d1ac2465e 6b056e18759f5cca ef1bf03e5dfa575a
+584023641aba6176 004bd6ef09176062 88bf0db6d70dee56
+025816164629b007 480d39006ee762f2 a1f9915541020b56
+49793ebc79b3258f 437540c8698f3cfa 6fbf1cafcffd0556
+4fb05e1515ab73a7 072d43a077075292 2f22e49bab7ca1ac
+49e95d6d4ca229bf 02fe55778117f12a 5a6b612cc26cce4a
+018310dc409b26d6 1d9d5c5018f728c2 5f4c038ed12b2e41
+1c587f1c13924fef 305532286d6f295a 63fac0d034d9f793
Index: /trunk/libc/src/glibc/crypt/crypt-entry.c
===================================================================
--- /trunk/libc/src/glibc/crypt/crypt-entry.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/crypt-entry.c	(revision 2448)
@@ -0,0 +1,150 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc.
+ *
+ * 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.
+ *
+ * crypt entry points
+ *
+ * @(#)crypt-entry.c	1.2 12/20/96
+ *
+ */
+
+#include "libc-alias-glibc.h"
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+#include <string.h>
+
+#ifndef STATIC
+#define STATIC static
+#endif
+
+#ifndef DOS
+#include "ufc-crypt.h"
+#else
+/*
+ * Thanks to greg%wind@plains.NoDak.edu (Greg W. Wettstein)
+ * for DOS patches
+ */
+#include "ufc.h"
+#endif
+#include "crypt.h"
+#include "crypt-private.h"
+
+/* Prototypes for local functions.  */
+#if __STDC__ - 0
+#if !defined __GNU_LIBRARY__ && !defined __INNOTEK_LIBC__
+void _ufc_clearmem (char *start, int cnt);
+#else
+#define _ufc_clearmem(start, cnt)   memset(start, 0, cnt)
+#endif
+extern char *__md5_crypt_r (const char *key, const char *salt, char *buffer,
+			    int buflen);
+extern char *__md5_crypt (const char *key, const char *salt);
+#endif
+
+/* Define our magic string to mark salt for MD5 encryption
+   replacement.  This is meant to be the same as for other MD5 based
+   encryption implementations.  */
+static const char md5_salt_prefix[] = "$1$";
+
+/* For use by the old, non-reentrant routines (crypt/encrypt/setkey)  */
+extern struct crypt_data _ufc_foobar;
+
+/*
+ * UNIX crypt function
+ */
+
+char *
+__crypt_r (key, salt, data)
+     const char *key;
+     const char *salt;
+     struct crypt_data * __restrict data;
+{
+  ufc_long res[4];
+  char ktab[9];
+  ufc_long xx = 25; /* to cope with GCC long long compiler bugs */
+
+#if defined _LIBC || defined __INNOTEK_LIBC__
+  /* Try to find out whether we have to use MD5 encryption replacement.  */
+  if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
+    return __md5_crypt_r (key, salt, (char *) data,
+			  sizeof (struct crypt_data));
+#endif
+
+  /*
+   * Hack DES tables according to salt
+   */
+  _ufc_setup_salt_r (salt, data);
+
+  /*
+   * Setup key schedule
+   */
+  _ufc_clearmem (ktab, (int) sizeof (ktab));
+  (void) strncpy (ktab, key, 8);
+  _ufc_mk_keytab_r (ktab, data);
+
+  /*
+   * Go for the 25 DES encryptions
+   */
+  _ufc_clearmem ((char*) res, (int) sizeof (res));
+  _ufc_doit_r (xx,  data, &res[0]);
+
+  /*
+   * Do final permutations
+   */
+  _ufc_dofinalperm_r (res, data);
+
+  /*
+   * And convert back to 6 bit ASCII
+   */
+  _ufc_output_conversion_r (res[0], res[1], salt, data);
+  return data->crypt_3_buf;
+}
+weak_alias (__crypt_r, crypt_r)
+
+char *
+_STD(crypt) (key, salt)
+     const char *key;
+     const char *salt;
+{
+#if defined _LIBC || defined __INNOTEK_LIBC__
+  /* Try to find out whether we have to use MD5 encryption replacement.  */
+  if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
+    return __md5_crypt (key, salt);
+#endif
+
+  return __crypt_r (key, salt, &_ufc_foobar);
+}
+
+
+/*
+ * To make fcrypt users happy.
+ * They don't need to call init_des.
+ */
+#if defined _LIBC || defined __INNOTEK_LIBC__
+weak_alias (crypt, fcrypt)
+#else
+char *
+__fcrypt (key, salt)
+     const char *key;
+     const char *salt;
+{
+  return crypt (key, salt);
+}
+#endif
Index: /trunk/libc/src/glibc/crypt/crypt-private.h
===================================================================
--- /trunk/libc/src/glibc/crypt/crypt-private.h	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/crypt-private.h	(revision 2448)
@@ -0,0 +1,60 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * Copyright (C) 1991, 92, 93, 96, 97, 98 Free Software Foundation, Inc.
+ *
+ * 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.
+ *
+ * @(#)crypt-private.h	1.4 12/20/96
+ */
+
+/* Prototypes for local functions in libcrypt.a.  */
+
+#ifndef CRYPT_PRIVATE_H
+#define CRYPT_PRIVATE_H	1
+
+#include <features.h>
+
+/* crypt.c */
+extern void _ufc_doit_r (ufc_long itr, struct crypt_data * __restrict __data,
+			 ufc_long *res);
+
+
+/* crypt_util.c */
+extern void __init_des_r (struct crypt_data * __restrict __data);
+extern void __init_des (void);
+
+extern void _ufc_setup_salt_r (__const char *s, 
+			       struct crypt_data * __restrict __data);
+extern void _ufc_mk_keytab_r (__const char *key, 
+			      struct crypt_data * __restrict __data);
+extern void _ufc_dofinalperm_r (ufc_long *res, 
+				struct crypt_data * __restrict __data);
+extern void _ufc_output_conversion_r (ufc_long v1, ufc_long v2,
+				      __const char *salt,
+				      struct crypt_data * __restrict __data);
+
+extern void __setkey_r (__const char *__key,
+			     struct crypt_data * __restrict __data);
+extern void __encrypt_r (char * __restrict __block, int __edflag,
+			      struct crypt_data * __restrict __data);
+
+/* crypt-entry.c */
+extern char *__crypt_r (__const char *__key, __const char *__salt,
+			     struct crypt_data * __restrict __data);
+extern char *fcrypt (__const char *key, __const char *salt);
+
+#endif  /* crypt-private.h */
Index: /trunk/libc/src/glibc/crypt/crypt.c
===================================================================
--- /trunk/libc/src/glibc/crypt/crypt.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/crypt.c	(revision 2448)
@@ -0,0 +1,121 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * 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 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.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this 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.
+ *
+ * @(#)crypt.c	2.25 12/20/96
+ *
+ * Semiportable C version
+ *
+ */
+
+#include "libc-alias-glibc.h"
+#include "ufc-crypt.h"
+#include "crypt.h"
+#include "crypt-private.h"
+
+#ifdef _UFC_32_
+
+/*
+ * 32 bit version
+ */
+
+#define SBA(sb, v) (*(long32*)((char*)(sb)+(v)))
+
+void
+_ufc_doit_r(itr, __data, res)
+     ufc_long itr, *res;
+     struct crypt_data * __restrict __data;
+{
+  int i;
+  long32 s, *k;
+  long32 *sb01 = (long32*)__data->sb0;
+  long32 *sb23 = (long32*)__data->sb2;
+  long32 l1, l2, r1, r2;
+
+  l1 = (long32)res[0]; l2 = (long32)res[1];
+  r1 = (long32)res[2]; r2 = (long32)res[3];
+
+  while(itr--) {
+    k = (long32*)__data->keysched;
+    for(i=8; i--; ) {
+      s = *k++ ^ r1;
+      l1 ^= SBA(sb01, s & 0xffff); l2 ^= SBA(sb01, (s & 0xffff)+4);
+      l1 ^= SBA(sb01, s >>= 16  ); l2 ^= SBA(sb01, (s         )+4);
+      s = *k++ ^ r2;
+      l1 ^= SBA(sb23, s & 0xffff); l2 ^= SBA(sb23, (s & 0xffff)+4);
+      l1 ^= SBA(sb23, s >>= 16  ); l2 ^= SBA(sb23, (s         )+4);
+
+      s = *k++ ^ l1;
+      r1 ^= SBA(sb01, s & 0xffff); r2 ^= SBA(sb01, (s & 0xffff)+4);
+      r1 ^= SBA(sb01, s >>= 16  ); r2 ^= SBA(sb01, (s         )+4);
+      s = *k++ ^ l2;
+      r1 ^= SBA(sb23, s & 0xffff); r2 ^= SBA(sb23, (s & 0xffff)+4);
+      r1 ^= SBA(sb23, s >>= 16  ); r2 ^= SBA(sb23, (s         )+4);
+    }
+    s=l1; l1=r1; r1=s; s=l2; l2=r2; r2=s;
+  }
+  res[0] = l1; res[1] = l2; res[2] = r1; res[3] = r2;
+}
+
+#endif
+
+#ifdef _UFC_64_
+
+/*
+ * 64 bit version
+ */
+
+#define SBA(sb, v) (*(long64*)((char*)(sb)+(v)))
+
+void
+_ufc_doit_r(itr, __data, res)
+     ufc_long itr, *res;
+     struct crypt_data * __restrict __data;
+{
+  int i;
+  long64 l, r, s, *k;
+  register long64 *sb01 = (long64*)__data->sb0;
+  register long64 *sb23 = (long64*)__data->sb2;
+
+  l = (((long64)res[0]) << 32) | ((long64)res[1]);
+  r = (((long64)res[2]) << 32) | ((long64)res[3]);
+
+  while(itr--) {
+    k = (long64*)__data->keysched;
+    for(i=8; i--; ) {
+      s = *k++ ^ r;
+      l ^= SBA(sb23, (s       ) & 0xffff);
+      l ^= SBA(sb23, (s >>= 16) & 0xffff);
+      l ^= SBA(sb01, (s >>= 16) & 0xffff);
+      l ^= SBA(sb01, (s >>= 16)         );
+
+      s = *k++ ^ l;
+      r ^= SBA(sb23, (s       ) & 0xffff);
+      r ^= SBA(sb23, (s >>= 16) & 0xffff);
+      r ^= SBA(sb01, (s >>= 16) & 0xffff);
+      r ^= SBA(sb01, (s >>= 16)         );
+    }
+    s=l; l=r; r=s;
+  }
+
+  res[0] = l >> 32; res[1] = l & 0xffffffff;
+  res[2] = r >> 32; res[3] = r & 0xffffffff;
+}
+
+#endif
Index: /trunk/libc/src/glibc/crypt/crypt.smak
===================================================================
--- /trunk/libc/src/glibc/crypt/crypt.smak	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/crypt.smak	(revision 2448)
@@ -0,0 +1,17 @@
+libc.TSRC += $(addprefix src/glibc/crypt/,crypt-entry.c md5-crypt.c md5.c crypt.c crypt_util.c)
+
+include comend.smak
+.MODULE	:= libcrypt
+.MDESC	:= Stub crypt library (the actual code is in libc)
+
+.TARGET	:= libcrypt.a
+.TKIND	:= aout
+.TSRC	:= # stub
+.INSDIR	= lib/
+.TKEEP	:= 1
+include mklib.smak
+include mkomflib.smak
+
+# Forget temporary variables
+include comend.smak
+
Index: /trunk/libc/src/glibc/crypt/crypt_util.c
===================================================================
--- /trunk/libc/src/glibc/crypt/crypt_util.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/crypt_util.c	(revision 2448)
@@ -0,0 +1,932 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * Copyright (C) 1991, 92, 93, 96, 97, 98, 2000 Free Software Foundation, Inc.
+ *
+ * This 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.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this 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.
+ *
+ * @(#)crypt_util.c	2.56 12/20/96
+ *
+ * Support routines
+ *
+ */
+
+#include "libc-alias-glibc.h"
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+#include <string.h>
+
+#ifndef STATIC
+#define STATIC static
+#endif
+
+#ifndef DOS
+#include "ufc-crypt.h"
+#else
+/*
+ * Thanks to greg%wind@plains.NoDak.edu (Greg W. Wettstein)
+ * for DOS patches
+ */
+#include "pl.h"
+#include "ufc.h"
+#endif
+#include "crypt.h"
+#include "crypt-private.h"
+
+/* Prototypes for local functions.  */
+#if __STDC__ - 0
+#if !defined(__GNU_LIBRARY__) && !defined(__INNOTEK_LIBC__)
+void _ufc_clearmem (char *start, int cnt);
+void _ufc_copymem (char *from, char *to, int cnt);
+#endif
+#ifdef _UFC_32_
+STATIC void shuffle_sb (long32 *k, ufc_long saltbits);
+#else
+STATIC void shuffle_sb (long64 *k, ufc_long saltbits);
+#endif
+#endif
+
+
+/*
+ * Permutation done once on the 56 bit
+ *  key derived from the original 8 byte ASCII key.
+ */
+static const int pc1[56] = {
+  57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
+  10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
+  63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
+  14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
+};
+
+/*
+ * How much to rotate each 28 bit half of the pc1 permutated
+ *  56 bit key before using pc2 to give the i' key
+ */
+static const int rots[16] = {
+  1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+/*
+ * Permutation giving the key
+ * of the i' DES round
+ */
+static const int pc2[48] = {
+  14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
+  23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
+  41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
+  44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
+};
+
+/*
+ * The E expansion table which selects
+ * bits from the 32 bit intermediate result.
+ */
+static const int esel[48] = {
+  32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,
+   8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
+  16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
+  24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1
+};
+
+/*
+ * Permutation done on the
+ * result of sbox lookups
+ */
+static const int perm32[32] = {
+  16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
+  2,   8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
+};
+
+/*
+ * The sboxes
+ */
+static const int sbox[8][4][16]= {
+        { { 14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7 },
+          {  0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8 },
+          {  4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0 },
+          { 15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13 }
+        },
+
+        { { 15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10 },
+          {  3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5 },
+          {  0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15 },
+          { 13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9 }
+        },
+
+        { { 10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8 },
+          { 13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1 },
+          { 13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7 },
+          {  1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12 }
+        },
+
+        { {  7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15 },
+          { 13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9 },
+          { 10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4 },
+          {  3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14 }
+        },
+
+        { {  2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9 },
+          { 14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6 },
+          {  4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14 },
+          { 11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3 }
+        },
+
+        { { 12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11 },
+          { 10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8 },
+          {  9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6 },
+          {  4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13 }
+        },
+
+        { {  4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1 },
+          { 13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6 },
+          {  1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2 },
+          {  6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12 }
+        },
+
+        { { 13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7 },
+          {  1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2 },
+          {  7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8 },
+          {  2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11 }
+        }
+};
+
+/*
+ * This is the initial
+ * permutation matrix
+ */
+static const int initial_perm[64] = {
+  58, 50, 42, 34, 26, 18, 10,  2, 60, 52, 44, 36, 28, 20, 12, 4,
+  62, 54, 46, 38, 30, 22, 14,  6, 64, 56, 48, 40, 32, 24, 16, 8,
+  57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11, 3,
+  61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15, 7
+};
+
+/*
+ * This is the final
+ * permutation matrix
+ */
+static const int final_perm[64] = {
+  40,  8, 48, 16, 56, 24, 64, 32, 39,  7, 47, 15, 55, 23, 63, 31,
+  38,  6, 46, 14, 54, 22, 62, 30, 37,  5, 45, 13, 53, 21, 61, 29,
+  36,  4, 44, 12, 52, 20, 60, 28, 35,  3, 43, 11, 51, 19, 59, 27,
+  34,  2, 42, 10, 50, 18, 58, 26, 33,  1, 41,  9, 49, 17, 57, 25
+};
+
+#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.')
+#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
+
+static const ufc_long BITMASK[24] = {
+  0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000,
+  0x01000000, 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000,
+  0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200,
+  0x00000100, 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008
+};
+
+static const unsigned char bytemask[8]  = {
+  0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
+};
+
+static const ufc_long longmask[32] = {
+  0x80000000, 0x40000000, 0x20000000, 0x10000000,
+  0x08000000, 0x04000000, 0x02000000, 0x01000000,
+  0x00800000, 0x00400000, 0x00200000, 0x00100000,
+  0x00080000, 0x00040000, 0x00020000, 0x00010000,
+  0x00008000, 0x00004000, 0x00002000, 0x00001000,
+  0x00000800, 0x00000400, 0x00000200, 0x00000100,
+  0x00000080, 0x00000040, 0x00000020, 0x00000010,
+  0x00000008, 0x00000004, 0x00000002, 0x00000001
+};
+
+/*
+ * do_pc1: permform pc1 permutation in the key schedule generation.
+ *
+ * The first   index is the byte number in the 8 byte ASCII key
+ *  -  second    -      -    the two 28 bits halfs of the result
+ *  -  third     -   selects the 7 bits actually used of each byte
+ *
+ * The result is kept with 28 bit per 32 bit with the 4 most significant
+ * bits zero.
+ */
+static ufc_long do_pc1[8][2][128];
+
+/*
+ * do_pc2: permform pc2 permutation in the key schedule generation.
+ *
+ * The first   index is the septet number in the two 28 bit intermediate values
+ *  -  second    -    -  -  septet values
+ *
+ * Knowledge of the structure of the pc2 permutation is used.
+ *
+ * The result is kept with 28 bit per 32 bit with the 4 most significant
+ * bits zero.
+ */
+static ufc_long do_pc2[8][128];
+
+/*
+ * eperm32tab: do 32 bit permutation and E selection
+ *
+ * The first index is the byte number in the 32 bit value to be permuted
+ *  -  second  -   is the value of this byte
+ *  -  third   -   selects the two 32 bit values
+ *
+ * The table is used and generated internally in init_des to speed it up
+ */
+static ufc_long eperm32tab[4][256][2];
+
+/*
+ * efp: undo an extra e selection and do final
+ *      permutation giving the DES result.
+ *
+ *      Invoked 6 bit a time on two 48 bit values
+ *      giving two 32 bit longs.
+ */
+static ufc_long efp[16][64][2];
+
+/*
+ * For use by the old, non-reentrant routines
+ * (crypt/encrypt/setkey)
+ */
+struct crypt_data _ufc_foobar = {{0}};
+
+#ifdef __GNU_LIBRARY__
+#include <bits/libc-lock.h>
+
+__libc_lock_define_initialized (static, _ufc_tables_lock)
+#endif
+#ifdef __INNOTEK_LIBC__
+#include <sys/smutex.h>
+#endif
+
+
+
+#if defined(DEBUG) && !defined(__INNOTEK_LIBC__)
+
+void
+_ufc_prbits(a, n)
+     ufc_long *a;
+     int n;
+{
+  ufc_long i, j, t, tmp;
+  n /= 8;
+  for(i = 0; i < n; i++) {
+    tmp=0;
+    for(j = 0; j < 8; j++) {
+      t=8*i+j;
+      tmp|=(a[t/24] & BITMASK[t % 24])?bytemask[j]:0;
+    }
+    (void)printf("%02x ",tmp);
+  }
+  printf(" ");
+}
+
+static void
+_ufc_set_bits(v, b)
+     ufc_long v;
+     ufc_long *b;
+{
+  ufc_long i;
+  *b = 0;
+  for(i = 0; i < 24; i++) {
+    if(v & longmask[8 + i])
+      *b |= BITMASK[i];
+  }
+}
+
+#endif
+
+#if !defined(__GNU_LIBRARY__) && !defined(__INNOTEK_LIBC__)
+/*
+ * Silly rewrites of 'bzero'/'memset'. I do so
+ * because some machines don't have
+ * bzero and some don't have memset.
+ */
+
+void
+_ufc_clearmem(start, cnt)
+     char *start;
+     int cnt;
+{
+  while(cnt--)
+    *start++ = '\0';
+}
+
+void
+_ufc_copymem(from, to, cnt)
+     char *from, *to;
+     int cnt;
+{
+  while(cnt--)
+    *to++ = *from++;
+}
+#else
+#define _ufc_clearmem(start, cnt)   memset(start, 0, cnt)
+#define _ufc_copymem(from, to, cnt) memcpy(to, from, cnt)
+#endif
+
+/* lookup a 6 bit value in sbox */
+
+#define s_lookup(i,s) sbox[(i)][(((s)>>4) & 0x2)|((s) & 0x1)][((s)>>1) & 0xf];
+
+/*
+ * Initialize unit - may be invoked directly
+ * by fcrypt users.
+ */
+
+void
+__init_des_r(__data)
+     struct crypt_data * __restrict __data;
+{
+  int comes_from_bit;
+  int bit, sg;
+  ufc_long j;
+  ufc_long mask1, mask2;
+  int e_inverse[64];
+  static volatile int small_tables_initialized = 0;
+
+#ifdef _UFC_32_
+  long32 *sb[4];
+  sb[0] = (long32*)__data->sb0; sb[1] = (long32*)__data->sb1;
+  sb[2] = (long32*)__data->sb2; sb[3] = (long32*)__data->sb3;
+#endif
+#ifdef _UFC_64_
+  long64 *sb[4];
+  sb[0] = (long64*)__data->sb0; sb[1] = (long64*)__data->sb1;
+  sb[2] = (long64*)__data->sb2; sb[3] = (long64*)__data->sb3;
+#endif
+
+  if(small_tables_initialized == 0) {
+#ifdef __GNU_LIBRARY__
+    __libc_lock_lock (_ufc_tables_lock);
+    if(small_tables_initialized)
+      goto small_tables_done;
+#endif
+#ifdef __INNOTEK_LIBC__
+    static _smutex smtx;
+    _smutex_request(&smtx);
+    if(small_tables_initialized)
+      goto small_tables_done;
+#endif
+
+
+
+    /*
+     * Create the do_pc1 table used
+     * to affect pc1 permutation
+     * when generating keys
+     */
+    _ufc_clearmem((char*)do_pc1, (int)sizeof(do_pc1));
+    for(bit = 0; bit < 56; bit++) {
+      comes_from_bit  = pc1[bit] - 1;
+      mask1 = bytemask[comes_from_bit % 8 + 1];
+      mask2 = longmask[bit % 28 + 4];
+      for(j = 0; j < 128; j++) {
+	if(j & mask1)
+	  do_pc1[comes_from_bit / 8][bit / 28][j] |= mask2;
+      }
+    }
+
+    /*
+     * Create the do_pc2 table used
+     * to affect pc2 permutation when
+     * generating keys
+     */
+    _ufc_clearmem((char*)do_pc2, (int)sizeof(do_pc2));
+    for(bit = 0; bit < 48; bit++) {
+      comes_from_bit  = pc2[bit] - 1;
+      mask1 = bytemask[comes_from_bit % 7 + 1];
+      mask2 = BITMASK[bit % 24];
+      for(j = 0; j < 128; j++) {
+	if(j & mask1)
+	  do_pc2[comes_from_bit / 7][j] |= mask2;
+      }
+    }
+
+    /*
+     * Now generate the table used to do combined
+     * 32 bit permutation and e expansion
+     *
+     * We use it because we have to permute 16384 32 bit
+     * longs into 48 bit in order to initialize sb.
+     *
+     * Looping 48 rounds per permutation becomes
+     * just too slow...
+     *
+     */
+
+    _ufc_clearmem((char*)eperm32tab, (int)sizeof(eperm32tab));
+    for(bit = 0; bit < 48; bit++) {
+      ufc_long mask1,comes_from;
+      comes_from = perm32[esel[bit]-1]-1;
+      mask1      = bytemask[comes_from % 8];
+      for(j = 256; j--;) {
+	if(j & mask1)
+	  eperm32tab[comes_from / 8][j][bit / 24] |= BITMASK[bit % 24];
+      }
+    }
+
+    /*
+     * Create an inverse matrix for esel telling
+     * where to plug out bits if undoing it
+     */
+    for(bit=48; bit--;) {
+      e_inverse[esel[bit] - 1     ] = bit;
+      e_inverse[esel[bit] - 1 + 32] = bit + 48;
+    }
+
+    /*
+     * create efp: the matrix used to
+     * undo the E expansion and effect final permutation
+     */
+    _ufc_clearmem((char*)efp, (int)sizeof efp);
+    for(bit = 0; bit < 64; bit++) {
+      int o_bit, o_long;
+      ufc_long word_value, mask1, mask2;
+      int comes_from_f_bit, comes_from_e_bit;
+      int comes_from_word, bit_within_word;
+
+      /* See where bit i belongs in the two 32 bit long's */
+      o_long = bit / 32; /* 0..1  */
+      o_bit  = bit % 32; /* 0..31 */
+
+      /*
+       * And find a bit in the e permutated value setting this bit.
+       *
+       * Note: the e selection may have selected the same bit several
+       * times. By the initialization of e_inverse, we only look
+       * for one specific instance.
+       */
+      comes_from_f_bit = final_perm[bit] - 1;         /* 0..63 */
+      comes_from_e_bit = e_inverse[comes_from_f_bit]; /* 0..95 */
+      comes_from_word  = comes_from_e_bit / 6;        /* 0..15 */
+      bit_within_word  = comes_from_e_bit % 6;        /* 0..5  */
+
+      mask1 = longmask[bit_within_word + 26];
+      mask2 = longmask[o_bit];
+
+      for(word_value = 64; word_value--;) {
+	if(word_value & mask1)
+	  efp[comes_from_word][word_value][o_long] |= mask2;
+      }
+    }
+    small_tables_initialized = 1;
+#ifdef __GNU_LIBRARY__
+small_tables_done:
+    __libc_lock_unlock(_ufc_tables_lock);
+#endif
+#ifdef __INNOTEK_LIBC__
+small_tables_done:
+    _smutex_release(&smtx);
+#endif
+  }
+
+  /*
+   * Create the sb tables:
+   *
+   * For each 12 bit segment of an 48 bit intermediate
+   * result, the sb table precomputes the two 4 bit
+   * values of the sbox lookups done with the two 6
+   * bit halves, shifts them to their proper place,
+   * sends them through perm32 and finally E expands
+   * them so that they are ready for the next
+   * DES round.
+   *
+   */
+
+  _ufc_clearmem((char*)__data->sb0, (int)sizeof(__data->sb0));
+  _ufc_clearmem((char*)__data->sb1, (int)sizeof(__data->sb1));
+  _ufc_clearmem((char*)__data->sb2, (int)sizeof(__data->sb2));
+  _ufc_clearmem((char*)__data->sb3, (int)sizeof(__data->sb3));
+
+  for(sg = 0; sg < 4; sg++) {
+    int j1, j2;
+    int s1, s2;
+
+    for(j1 = 0; j1 < 64; j1++) {
+      s1 = s_lookup(2 * sg, j1);
+      for(j2 = 0; j2 < 64; j2++) {
+	ufc_long to_permute, inx;
+
+	s2         = s_lookup(2 * sg + 1, j2);
+	to_permute = (((ufc_long)s1 << 4)  |
+		      (ufc_long)s2) << (24 - 8 * (ufc_long)sg);
+
+#ifdef _UFC_32_
+	inx = ((j1 << 6)  | j2) << 1;
+	sb[sg][inx  ]  = eperm32tab[0][(to_permute >> 24) & 0xff][0];
+	sb[sg][inx+1]  = eperm32tab[0][(to_permute >> 24) & 0xff][1];
+	sb[sg][inx  ] |= eperm32tab[1][(to_permute >> 16) & 0xff][0];
+	sb[sg][inx+1] |= eperm32tab[1][(to_permute >> 16) & 0xff][1];
+	sb[sg][inx  ] |= eperm32tab[2][(to_permute >>  8) & 0xff][0];
+	sb[sg][inx+1] |= eperm32tab[2][(to_permute >>  8) & 0xff][1];
+	sb[sg][inx  ] |= eperm32tab[3][(to_permute)       & 0xff][0];
+	sb[sg][inx+1] |= eperm32tab[3][(to_permute)       & 0xff][1];
+#endif
+#ifdef _UFC_64_
+	inx = ((j1 << 6)  | j2);
+	sb[sg][inx]  =
+	  ((long64)eperm32tab[0][(to_permute >> 24) & 0xff][0] << 32) |
+	   (long64)eperm32tab[0][(to_permute >> 24) & 0xff][1];
+	sb[sg][inx] |=
+	  ((long64)eperm32tab[1][(to_permute >> 16) & 0xff][0] << 32) |
+	   (long64)eperm32tab[1][(to_permute >> 16) & 0xff][1];
+	sb[sg][inx] |=
+	  ((long64)eperm32tab[2][(to_permute >>  8) & 0xff][0] << 32) |
+	   (long64)eperm32tab[2][(to_permute >>  8) & 0xff][1];
+	sb[sg][inx] |=
+	  ((long64)eperm32tab[3][(to_permute)       & 0xff][0] << 32) |
+	   (long64)eperm32tab[3][(to_permute)       & 0xff][1];
+#endif
+      }
+    }
+  }
+
+  __data->current_saltbits = 0;
+  __data->current_salt[0] = 0;
+  __data->current_salt[1] = 0;
+  __data->initialized++;
+}
+
+void
+__init_des()
+{
+  __init_des_r(&_ufc_foobar);
+}
+
+/*
+ * Process the elements of the sb table permuting the
+ * bits swapped in the expansion by the current salt.
+ */
+
+#ifdef _UFC_32_
+STATIC void
+shuffle_sb(k, saltbits)
+     long32 *k;
+     ufc_long saltbits;
+{
+  ufc_long j;
+  long32 x;
+  for(j=4096; j--;) {
+    x = (k[0] ^ k[1]) & (long32)saltbits;
+    *k++ ^= x;
+    *k++ ^= x;
+  }
+}
+#endif
+
+#ifdef _UFC_64_
+STATIC void
+shuffle_sb(k, saltbits)
+     long64 *k;
+     ufc_long saltbits;
+{
+  ufc_long j;
+  long64 x;
+  for(j=4096; j--;) {
+    x = ((*k >> 32) ^ *k) & (long64)saltbits;
+    *k++ ^= (x << 32) | x;
+  }
+}
+#endif
+
+/*
+ * Setup the unit for a new salt
+ * Hopefully we'll not see a new salt in each crypt call.
+ */
+
+void
+_ufc_setup_salt_r(s, __data)
+     __const char *s;
+     struct crypt_data * __restrict __data;
+{
+  ufc_long i, j, saltbits;
+
+  if(__data->initialized == 0)
+    __init_des_r(__data);
+
+  if(s[0] == __data->current_salt[0] && s[1] == __data->current_salt[1])
+    return;
+  __data->current_salt[0] = s[0]; __data->current_salt[1] = s[1];
+
+  /*
+   * This is the only crypt change to DES:
+   * entries are swapped in the expansion table
+   * according to the bits set in the salt.
+   */
+  saltbits = 0;
+  for(i = 0; i < 2; i++) {
+    long c=ascii_to_bin(s[i]);
+    for(j = 0; j < 6; j++) {
+      if((c >> j) & 0x1)
+	saltbits |= BITMASK[6 * i + j];
+    }
+  }
+
+  /*
+   * Permute the sb table values
+   * to reflect the changed e
+   * selection table
+   */
+#ifdef _UFC_32_
+#define LONGG long32*
+#endif
+#ifdef _UFC_64_
+#define LONGG long64*
+#endif
+
+  shuffle_sb((LONGG)__data->sb0, __data->current_saltbits ^ saltbits);
+  shuffle_sb((LONGG)__data->sb1, __data->current_saltbits ^ saltbits);
+  shuffle_sb((LONGG)__data->sb2, __data->current_saltbits ^ saltbits);
+  shuffle_sb((LONGG)__data->sb3, __data->current_saltbits ^ saltbits);
+
+  __data->current_saltbits = saltbits;
+}
+
+void
+_ufc_mk_keytab_r(key, __data)
+     const char *key;
+     struct crypt_data * __restrict __data;
+{
+  ufc_long v1, v2, *k1;
+  int i;
+#ifdef _UFC_32_
+  long32 v, *k2;
+  k2 = (long32*)__data->keysched;
+#endif
+#ifdef _UFC_64_
+  long64 v, *k2;
+  k2 = (long64*)__data->keysched;
+#endif
+
+  v1 = v2 = 0; k1 = &do_pc1[0][0][0];
+  for(i = 8; i--;) {
+    v1 |= k1[*key   & 0x7f]; k1 += 128;
+    v2 |= k1[*key++ & 0x7f]; k1 += 128;
+  }
+
+  for(i = 0; i < 16; i++) {
+    k1 = &do_pc2[0][0];
+
+    v1 = (v1 << rots[i]) | (v1 >> (28 - rots[i]));
+    v  = k1[(v1 >> 21) & 0x7f]; k1 += 128;
+    v |= k1[(v1 >> 14) & 0x7f]; k1 += 128;
+    v |= k1[(v1 >>  7) & 0x7f]; k1 += 128;
+    v |= k1[(v1      ) & 0x7f]; k1 += 128;
+
+#ifdef _UFC_32_
+    *k2++ = (v | 0x00008000);
+    v = 0;
+#endif
+#ifdef _UFC_64_
+    v = (v << 32);
+#endif
+
+    v2 = (v2 << rots[i]) | (v2 >> (28 - rots[i]));
+    v |= k1[(v2 >> 21) & 0x7f]; k1 += 128;
+    v |= k1[(v2 >> 14) & 0x7f]; k1 += 128;
+    v |= k1[(v2 >>  7) & 0x7f]; k1 += 128;
+    v |= k1[(v2      ) & 0x7f];
+
+#ifdef _UFC_32_
+    *k2++ = (v | 0x00008000);
+#endif
+#ifdef _UFC_64_
+    *k2++ = v | 0x0000800000008000l;
+#endif
+  }
+
+  __data->direction = 0;
+}
+
+/*
+ * Undo an extra E selection and do final permutations
+ */
+
+void
+_ufc_dofinalperm_r(res, __data)
+     ufc_long *res;
+     struct crypt_data * __restrict __data;
+{
+  ufc_long v1, v2, x;
+  ufc_long l1,l2,r1,r2;
+
+  l1 = res[0]; l2 = res[1];
+  r1 = res[2]; r2 = res[3];
+
+  x = (l1 ^ l2) & __data->current_saltbits; l1 ^= x; l2 ^= x;
+  x = (r1 ^ r2) & __data->current_saltbits; r1 ^= x; r2 ^= x;
+
+  v1=v2=0; l1 >>= 3; l2 >>= 3; r1 >>= 3; r2 >>= 3;
+
+  v1 |= efp[15][ r2         & 0x3f][0]; v2 |= efp[15][ r2 & 0x3f][1];
+  v1 |= efp[14][(r2 >>= 6)  & 0x3f][0]; v2 |= efp[14][ r2 & 0x3f][1];
+  v1 |= efp[13][(r2 >>= 10) & 0x3f][0]; v2 |= efp[13][ r2 & 0x3f][1];
+  v1 |= efp[12][(r2 >>= 6)  & 0x3f][0]; v2 |= efp[12][ r2 & 0x3f][1];
+
+  v1 |= efp[11][ r1         & 0x3f][0]; v2 |= efp[11][ r1 & 0x3f][1];
+  v1 |= efp[10][(r1 >>= 6)  & 0x3f][0]; v2 |= efp[10][ r1 & 0x3f][1];
+  v1 |= efp[ 9][(r1 >>= 10) & 0x3f][0]; v2 |= efp[ 9][ r1 & 0x3f][1];
+  v1 |= efp[ 8][(r1 >>= 6)  & 0x3f][0]; v2 |= efp[ 8][ r1 & 0x3f][1];
+
+  v1 |= efp[ 7][ l2         & 0x3f][0]; v2 |= efp[ 7][ l2 & 0x3f][1];
+  v1 |= efp[ 6][(l2 >>= 6)  & 0x3f][0]; v2 |= efp[ 6][ l2 & 0x3f][1];
+  v1 |= efp[ 5][(l2 >>= 10) & 0x3f][0]; v2 |= efp[ 5][ l2 & 0x3f][1];
+  v1 |= efp[ 4][(l2 >>= 6)  & 0x3f][0]; v2 |= efp[ 4][ l2 & 0x3f][1];
+
+  v1 |= efp[ 3][ l1         & 0x3f][0]; v2 |= efp[ 3][ l1 & 0x3f][1];
+  v1 |= efp[ 2][(l1 >>= 6)  & 0x3f][0]; v2 |= efp[ 2][ l1 & 0x3f][1];
+  v1 |= efp[ 1][(l1 >>= 10) & 0x3f][0]; v2 |= efp[ 1][ l1 & 0x3f][1];
+  v1 |= efp[ 0][(l1 >>= 6)  & 0x3f][0]; v2 |= efp[ 0][ l1 & 0x3f][1];
+
+  res[0] = v1; res[1] = v2;
+}
+
+/*
+ * crypt only: convert from 64 bit to 11 bit ASCII
+ * prefixing with the salt
+ */
+
+void
+_ufc_output_conversion_r(v1, v2, salt, __data)
+     ufc_long v1, v2;
+     __const char *salt;
+     struct crypt_data * __restrict __data;
+{
+  int i, s, shf;
+
+  __data->crypt_3_buf[0] = salt[0];
+  __data->crypt_3_buf[1] = salt[1] ? salt[1] : salt[0];
+
+  for(i = 0; i < 5; i++) {
+    shf = (26 - 6 * i); /* to cope with MSC compiler bug */
+    __data->crypt_3_buf[i + 2] = bin_to_ascii((v1 >> shf) & 0x3f);
+  }
+
+  s  = (v2 & 0xf) << 2;
+  v2 = (v2 >> 2) | ((v1 & 0x3) << 30);
+
+  for(i = 5; i < 10; i++) {
+    shf = (56 - 6 * i);
+    __data->crypt_3_buf[i + 2] = bin_to_ascii((v2 >> shf) & 0x3f);
+  }
+
+  __data->crypt_3_buf[12] = bin_to_ascii(s);
+  __data->crypt_3_buf[13] = 0;
+}
+
+
+/*
+ * UNIX encrypt function. Takes a bitvector
+ * represented by one byte per bit and
+ * encrypt/decrypt according to edflag
+ */
+
+void
+__encrypt_r(__block, __edflag, __data)
+     char *__block;
+     int __edflag;
+     struct crypt_data * __restrict __data;
+{
+  ufc_long l1, l2, r1, r2, res[4];
+  int i;
+#ifdef _UFC_32_
+  long32 *kt;
+  kt = (long32*)__data->keysched;
+#endif
+#ifdef _UFC_64_
+  long64 *kt;
+  kt = (long64*)__data->keysched;
+#endif
+
+  /*
+   * Undo any salt changes to E expansion
+   */
+  _ufc_setup_salt_r("..", __data);
+
+  /*
+   * Reverse key table if
+   * changing operation (encrypt/decrypt)
+   */
+  if((__edflag == 0) != (__data->direction == 0)) {
+    for(i = 0; i < 8; i++) {
+#ifdef _UFC_32_
+      long32 x;
+      x = kt[2 * (15-i)];
+      kt[2 * (15-i)] = kt[2 * i];
+      kt[2 * i] = x;
+
+      x = kt[2 * (15-i) + 1];
+      kt[2 * (15-i) + 1] = kt[2 * i + 1];
+      kt[2 * i + 1] = x;
+#endif
+#ifdef _UFC_64_
+      long64 x;
+      x = kt[15-i];
+      kt[15-i] = kt[i];
+      kt[i] = x;
+#endif
+      }
+    __data->direction = __edflag;
+  }
+
+  /*
+   * Do initial permutation + E expansion
+   */
+  i = 0;
+  for(l1 = 0; i < 24; i++) {
+    if(__block[initial_perm[esel[i]-1]-1])
+      l1 |= BITMASK[i];
+  }
+  for(l2 = 0; i < 48; i++) {
+    if(__block[initial_perm[esel[i]-1]-1])
+      l2 |= BITMASK[i-24];
+  }
+
+  i = 0;
+  for(r1 = 0; i < 24; i++) {
+    if(__block[initial_perm[esel[i]-1+32]-1])
+      r1 |= BITMASK[i];
+  }
+  for(r2 = 0; i < 48; i++) {
+    if(__block[initial_perm[esel[i]-1+32]-1])
+      r2 |= BITMASK[i-24];
+  }
+
+  /*
+   * Do DES inner loops + final conversion
+   */
+  res[0] = l1; res[1] = l2;
+  res[2] = r1; res[3] = r2;
+  _ufc_doit_r((ufc_long)1, __data, &res[0]);
+
+  /*
+   * Do final permutations
+   */
+  _ufc_dofinalperm_r(res, __data);
+
+  /*
+   * And convert to bit array
+   */
+  l1 = res[0]; r1 = res[1];
+  for(i = 0; i < 32; i++) {
+    *__block++ = (l1 & longmask[i]) != 0;
+  }
+  for(i = 0; i < 32; i++) {
+    *__block++ = (r1 & longmask[i]) != 0;
+  }
+}
+weak_alias (__encrypt_r, encrypt_r)
+
+void
+_STD(encrypt)(__block, __edflag)
+     char *__block;
+     int __edflag;
+{
+  __encrypt_r(__block, __edflag, &_ufc_foobar);
+}
+
+
+/*
+ * UNIX setkey function. Take a 64 bit DES
+ * key and setup the machinery.
+ */
+
+void
+__setkey_r(__key, __data)
+     __const char *__key;
+     struct crypt_data * __restrict __data;
+{
+  int i,j;
+  unsigned char c;
+  unsigned char ktab[8];
+
+  _ufc_setup_salt_r("..", __data); /* be sure we're initialized */
+
+  for(i = 0; i < 8; i++) {
+    for(j = 0, c = 0; j < 8; j++)
+      c = c << 1 | *__key++;
+    ktab[i] = c >> 1;
+  }
+  _ufc_mk_keytab_r((char *) ktab, __data);
+}
+weak_alias (__setkey_r, setkey_r)
+
+void
+_STD(setkey)(__key)
+     __const char *__key;
+{
+  __setkey_r(__key, &_ufc_foobar);
+}
Index: /trunk/libc/src/glibc/crypt/md5-crypt.c
===================================================================
--- /trunk/libc/src/glibc/crypt/md5-crypt.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/md5-crypt.c	(revision 2448)
@@ -0,0 +1,273 @@
+/* One way encryption based on MD5 sum.
+   Compatible with the behavior of MD5 crypt introduced in FreeBSD 2.0.
+   Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 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.  */
+
+#include "libc-alias-glibc.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include "md5.h"
+
+
+/* Define our magic string to mark salt for MD5 "encryption"
+   replacement.  This is meant to be the same as for other MD5 based
+   encryption implementations.  */
+static const char md5_salt_prefix[] = "$1$";
+
+/* Table with characters for base64 transformation.  */
+static const char b64t[64] =
+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+
+/* Prototypes for local functions.  */
+extern char *__md5_crypt_r (const char *key, const char *salt,
+			    char *buffer, int buflen);
+extern char *__md5_crypt (const char *key, const char *salt);
+
+
+/* This entry point is equivalent to the `crypt' function in Unix
+   libcs.  */
+char *
+__md5_crypt_r (key, salt, buffer, buflen)
+     const char *key;
+     const char *salt;
+     char *buffer;
+     int buflen;
+{
+  unsigned char alt_result[16]
+    __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
+  struct md5_ctx ctx;
+  struct md5_ctx alt_ctx;
+  size_t salt_len;
+  size_t key_len;
+  size_t cnt;
+  char *cp;
+  char *copied_key = NULL;
+  char *copied_salt = NULL;
+
+  /* Find beginning of salt string.  The prefix should normally always
+     be present.  Just in case it is not.  */
+  if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
+    /* Skip salt prefix.  */
+    salt += sizeof (md5_salt_prefix) - 1;
+
+  salt_len = MIN (strcspn (salt, "$"), 8);
+  key_len = strlen (key);
+
+  if ((key - (char *) 0) % __alignof__ (md5_uint32) != 0)
+    {
+      char *tmp = (char *) alloca (key_len + __alignof__ (md5_uint32));
+      key = copied_key =
+	memcpy (tmp + __alignof__ (md5_uint32)
+		- (tmp - (char *) 0) % __alignof__ (md5_uint32),
+		key, key_len);
+      assert ((key - (char *) 0) % __alignof__ (md5_uint32) == 0);
+    }
+
+  if ((salt - (char *) 0) % __alignof__ (md5_uint32) != 0)
+    {
+      char *tmp = (char *) alloca (salt_len + __alignof__ (md5_uint32));
+      salt = copied_salt =
+	memcpy (tmp + __alignof__ (md5_uint32)
+		- (tmp - (char *) 0) % __alignof__ (md5_uint32),
+		salt, salt_len);
+      assert ((salt - (char *) 0) % __alignof__ (md5_uint32) == 0);
+    }
+
+  /* Prepare for the real work.  */
+  __md5_init_ctx (&ctx);
+
+  /* Add the key string.  */
+  __md5_process_bytes (key, key_len, &ctx);
+
+  /* Because the SALT argument need not always have the salt prefix we
+     add it separately.  */
+  __md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, &ctx);
+
+  /* The last part is the salt string.  This must be at most 8
+     characters and it ends at the first `$' character (for
+     compatibility which existing solutions).  */
+  __md5_process_bytes (salt, salt_len, &ctx);
+
+
+  /* Compute alternate MD5 sum with input KEY, SALT, and KEY.  The
+     final result will be added to the first context.  */
+  __md5_init_ctx (&alt_ctx);
+
+  /* Add key.  */
+  __md5_process_bytes (key, key_len, &alt_ctx);
+
+  /* Add salt.  */
+  __md5_process_bytes (salt, salt_len, &alt_ctx);
+
+  /* Add key again.  */
+  __md5_process_bytes (key, key_len, &alt_ctx);
+
+  /* Now get result of this (16 bytes) and add it to the other
+     context.  */
+  __md5_finish_ctx (&alt_ctx, alt_result);
+
+  /* Add for any character in the key one byte of the alternate sum.  */
+  for (cnt = key_len; cnt > 16; cnt -= 16)
+    __md5_process_bytes (alt_result, 16, &ctx);
+  __md5_process_bytes (alt_result, cnt, &ctx);
+
+  /* For the following code we need a NUL byte.  */
+  *alt_result = '\0';
+
+  /* The original implementation now does something weird: for every 1
+     bit in the key the first 0 is added to the buffer, for every 0
+     bit the first character of the key.  This does not seem to be
+     what was intended but we have to follow this to be compatible.  */
+  for (cnt = key_len; cnt > 0; cnt >>= 1)
+    __md5_process_bytes ((cnt & 1) != 0 ? (const char *) alt_result : key, 1,
+			 &ctx);
+
+  /* Create intermediate result.  */
+  __md5_finish_ctx (&ctx, alt_result);
+
+  /* Now comes another weirdness.  In fear of password crackers here
+     comes a quite long loop which just processes the output of the
+     previous round again.  We cannot ignore this here.  */
+  for (cnt = 0; cnt < 1000; ++cnt)
+    {
+      /* New context.  */
+      __md5_init_ctx (&ctx);
+
+      /* Add key or last result.  */
+      if ((cnt & 1) != 0)
+	__md5_process_bytes (key, key_len, &ctx);
+      else
+	__md5_process_bytes (alt_result, 16, &ctx);
+
+      /* Add salt for numbers not divisible by 3.  */
+      if (cnt % 3 != 0)
+	__md5_process_bytes (salt, salt_len, &ctx);
+
+      /* Add key for numbers not divisible by 7.  */
+      if (cnt % 7 != 0)
+	__md5_process_bytes (key, key_len, &ctx);
+
+      /* Add key or last result.  */
+      if ((cnt & 1) != 0)
+	__md5_process_bytes (alt_result, 16, &ctx);
+      else
+	__md5_process_bytes (key, key_len, &ctx);
+
+      /* Create intermediate result.  */
+      __md5_finish_ctx (&ctx, alt_result);
+    }
+
+  /* Now we can construct the result string.  It consists of three
+     parts.  */
+  cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen));
+  buflen -= sizeof (md5_salt_prefix) - 1;
+
+  cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
+  buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
+
+  if (buflen > 0)
+    {
+      *cp++ = '$';
+      --buflen;
+    }
+
+#define b64_from_24bit(B2, B1, B0, N)					      \
+  do {									      \
+    unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);			      \
+    int n = (N);							      \
+    while (n-- > 0 && buflen > 0)					      \
+      {									      \
+	*cp++ = b64t[w & 0x3f];						      \
+	--buflen;							      \
+	w >>= 6;							      \
+      }									      \
+  } while (0)
+
+
+  b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4);
+  b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4);
+  b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4);
+  b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4);
+  b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4);
+  b64_from_24bit (0, 0, alt_result[11], 2);
+  if (buflen <= 0)
+    {
+      errno = ERANGE;
+      buffer = NULL;
+    }
+  else
+    *cp = '\0';		/* Terminate the string.  */
+
+  /* Clear the buffer for the intermediate result so that people
+     attaching to processes or reading core dumps cannot get any
+     information.  We do it in this way to clear correct_words[]
+     inside the MD5 implementation as well.  */
+  __md5_init_ctx (&ctx);
+  __md5_finish_ctx (&ctx, alt_result);
+  memset (&ctx, '\0', sizeof (ctx));
+  memset (&alt_ctx, '\0', sizeof (alt_ctx));
+  if (copied_key != NULL)
+    memset (copied_key, '\0', key_len);
+  if (copied_salt != NULL)
+    memset (copied_salt, '\0', salt_len);
+
+  return buffer;
+}
+
+#ifndef _LIBC
+# define libc_freeres_ptr(decl) decl
+#endif
+libc_freeres_ptr (static char *buffer);
+
+char *
+__md5_crypt (const char *key, const char *salt)
+{
+  /* We don't want to have an arbitrary limit in the size of the
+     password.  We can compute the size of the result in advance and
+     so we can prepare the buffer we pass to `md5_crypt_r'.  */
+  static int buflen;
+  int needed = 3 + strlen (salt) + 1 + 26 + 1;
+
+  if (buflen < needed)
+    {
+      char *new_buffer = (char *) realloc (buffer, needed);
+      if (new_buffer == NULL)
+	return NULL;
+
+      buffer = new_buffer;
+      buflen = needed;
+    }
+
+  return __md5_crypt_r (key, salt, buffer, buflen);
+}
+
+#if !defined _LIBC && !defined __INNOTEK_LIBC__
+static void
+__attribute__ ((__destructor__))
+free_mem (void)
+{
+  free (buffer);
+}
+#endif
Index: /trunk/libc/src/glibc/crypt/md5.c
===================================================================
--- /trunk/libc/src/glibc/crypt/md5.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/md5.c	(revision 2448)
@@ -0,0 +1,459 @@
+/* Functions to compute MD5 message digest of files or memory blocks.
+   according to the definition of MD5 in RFC 1321 from April 1992.
+   Copyright (C) 1995,1996,1997,1999,2000,2001,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 Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
+
+#include "libc-alias-glibc.h"
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS || defined _LIBC || defined __INNOTEK_LIBC__
+# include <stdlib.h>
+# include <string.h>
+#else
+# ifndef HAVE_MEMCPY
+#  define memcpy(d, s, n) (bcopy ((s), (d), (n)), (d))
+# endif
+#endif
+
+#include "md5.h"
+
+#if defined _LIBC || defined __INNOTEK_LIBC__
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+# endif
+/* We need to keep the namespace clean so define the MD5 function
+   protected using leading __ .  */
+# define md5_init_ctx __md5_init_ctx
+# define md5_process_block __md5_process_block
+# define md5_process_bytes __md5_process_bytes
+# define md5_finish_ctx __md5_finish_ctx
+# define md5_read_ctx __md5_read_ctx
+# define md5_stream __md5_stream
+# define md5_buffer __md5_buffer
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n)							\
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+void
+md5_init_ctx (ctx)
+     struct md5_ctx *ctx;
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_read_ctx (ctx, resbuf)
+     const struct md5_ctx *ctx;
+     void *resbuf;
+{
+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_finish_ctx (ctx, resbuf)
+     struct md5_ctx *ctx;
+     void *resbuf;
+{
+  /* Take yet unprocessed bytes into account.  */
+  md5_uint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+							(ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return md5_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md5_stream (stream, resblock)
+     FILE *stream;
+     void *resblock;
+{
+  /* Important: BLOCKSIZE must be a multiple of 64.  */
+#define BLOCKSIZE 4096
+  struct md5_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+	 computation function processes the whole buffer so that with the
+	 next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      do
+	{
+	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+	  sum += n;
+	}
+      while (sum < BLOCKSIZE && n != 0);
+      if (n == 0 && ferror (stream))
+        return 1;
+
+      /* If end of file is reached, end the loop.  */
+      if (n == 0)
+	break;
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+			BLOCKSIZE % 64 == 0
+       */
+      md5_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+  /* Add the last bytes if necessary.  */
+  if (sum > 0)
+    md5_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md5_finish_ctx (&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *
+md5_buffer (buffer, len, resblock)
+     const char *buffer;
+     size_t len;
+     void *resblock;
+{
+  struct md5_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md5_process_bytes (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return md5_finish_ctx (&ctx, resblock);
+}
+
+
+void
+md5_process_bytes (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct md5_ctx *ctx;
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (ctx->buflen > 64)
+	{
+	  md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+	  ctx->buflen &= 63;
+	  /* The regions in the following copy operation cannot overlap.  */
+	  memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+		  ctx->buflen);
+	}
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len >= 64)
+    {
+#if defined _STRING_ARCH_unaligned && !_STRING_ARCH_unaligned
+/* To check alignment gcc has an appropriate operator.  Other
+   compilers don't.  */
+# if __GNUC__ >= 2
+#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
+# else
+#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
+# endif
+      if (UNALIGNED_P (buffer))
+	while (len > 64)
+	  {
+	    md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+	    buffer = (const char *) buffer + 64;
+	    len -= 64;
+	  }
+      else
+#endif
+	{
+	  md5_process_block (buffer, len & ~63, ctx);
+	  buffer = (const char *) buffer + (len & ~63);
+	  len &= 63;
+	}
+    }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      size_t left_over = ctx->buflen;
+
+      memcpy (&ctx->buffer[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 64)
+	{
+	  md5_process_block (ctx->buffer, 64, ctx);
+	  left_over -= 64;
+	  memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+	}
+      ctx->buflen = left_over;
+    }
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+
+void
+md5_process_block (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct md5_ctx *ctx;
+{
+  md5_uint32 correct_words[16];
+  const md5_uint32 *words = buffer;
+  size_t nwords = len / sizeof (md5_uint32);
+  const md5_uint32 *endp = words + nwords;
+  md5_uint32 A = ctx->A;
+  md5_uint32 B = ctx->B;
+  md5_uint32 C = ctx->C;
+  md5_uint32 D = ctx->D;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp)
+    {
+      md5_uint32 *cwp = correct_words;
+      md5_uint32 A_save = A;
+      md5_uint32 B_save = B;
+      md5_uint32 C_save = C;
+      md5_uint32 D_save = D;
+
+      /* First round: using the given function, the context and a constant
+	 the next context is computed.  Because the algorithms processing
+	 unit is a 32-bit word and it is determined to work on words in
+	 little endian byte order we perhaps have to change the byte order
+	 before the computation.  To reduce the work for the next steps
+	 we store the swapped words in the array CORRECT_WORDS.  */
+
+#define OP(a, b, c, d, s, T)						\
+      do								\
+        {								\
+	  a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;		\
+	  ++words;							\
+	  CYCLIC (a, s);						\
+	  a += b;							\
+        }								\
+      while (0)
+
+      /* It is unfortunate that C does not provide an operator for
+	 cyclic rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+      /* Before we start, one word to the strange constants.
+	 They are defined in RFC 1321 as
+
+	 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+       */
+
+      /* Round 1.  */
+      OP (A, B, C, D,  7, 0xd76aa478);
+      OP (D, A, B, C, 12, 0xe8c7b756);
+      OP (C, D, A, B, 17, 0x242070db);
+      OP (B, C, D, A, 22, 0xc1bdceee);
+      OP (A, B, C, D,  7, 0xf57c0faf);
+      OP (D, A, B, C, 12, 0x4787c62a);
+      OP (C, D, A, B, 17, 0xa8304613);
+      OP (B, C, D, A, 22, 0xfd469501);
+      OP (A, B, C, D,  7, 0x698098d8);
+      OP (D, A, B, C, 12, 0x8b44f7af);
+      OP (C, D, A, B, 17, 0xffff5bb1);
+      OP (B, C, D, A, 22, 0x895cd7be);
+      OP (A, B, C, D,  7, 0x6b901122);
+      OP (D, A, B, C, 12, 0xfd987193);
+      OP (C, D, A, B, 17, 0xa679438e);
+      OP (B, C, D, A, 22, 0x49b40821);
+
+      /* For the second to fourth round we have the possibly swapped words
+	 in CORRECT_WORDS.  Redefine the macro to take an additional first
+	 argument specifying the function to use.  */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)					\
+      do 								\
+	{								\
+	  a += f (b, c, d) + correct_words[k] + T;			\
+	  CYCLIC (a, s);						\
+	  a += b;							\
+	}								\
+      while (0)
+
+      /* Round 2.  */
+      OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+      OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+      OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+      OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+      OP (FG, D, A, B, C, 10,  9, 0x02441453);
+      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+      OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+      OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+      OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+      /* Round 3.  */
+      OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+      OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+      OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+      OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+      OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+      /* Round 4.  */
+      OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+      OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+      OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+      OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+      OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+      OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+      OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+      OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+      OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+      OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+      OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+      /* Add the starting values of the context.  */
+      A += A_save;
+      B += B_save;
+      C += C_save;
+      D += D_save;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
+}
Index: /trunk/libc/src/glibc/crypt/md5.h
===================================================================
--- /trunk/libc/src/glibc/crypt/md5.h	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/md5.h	(revision 2448)
@@ -0,0 +1,144 @@
+/* Declaration of functions and data types used for MD5 sum computing
+   library functions.
+   Copyright (C) 1995-1997,1999,2000,2001,2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   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 _MD5_H
+#define _MD5_H 1
+
+#include <stdio.h>
+
+#if defined HAVE_LIMITS_H || (defined _LIBC && _LIBC) || defined(__INNOTEK_LIBC__)
+# include <limits.h>
+#endif
+
+/* The following contortions are an attempt to use the C preprocessor
+   to determine an unsigned integral type that is 32 bits wide.  An
+   alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+   doing that would require that the configure script compile and *run*
+   the resulting executable.  Locally running cross-compiled executables
+   is usually not possible.  */
+
+#if defined _LIBC || defined __INNOTEK_LIBC__
+# include <stdint.h>
+typedef uint32_t md5_uint32;
+typedef uintptr_t md5_uintptr;
+#else
+# if defined __STDC__ && __STDC__
+#  define UINT_MAX_32_BITS 4294967295U
+# else
+#  define UINT_MAX_32_BITS 0xFFFFFFFF
+# endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+   This should be valid for all systems GNU cares about because
+   that doesn't include 16-bit systems, and only modern systems
+   (that certainly have <limits.h>) have 64+-bit integral types.  */
+
+# ifndef UINT_MAX
+#  define UINT_MAX UINT_MAX_32_BITS
+# endif
+
+# if UINT_MAX == UINT_MAX_32_BITS
+   typedef unsigned int md5_uint32;
+# else
+#  if USHRT_MAX == UINT_MAX_32_BITS
+    typedef unsigned short md5_uint32;
+#  else
+#   if ULONG_MAX == UINT_MAX_32_BITS
+     typedef unsigned long md5_uint32;
+#   else
+     /* The following line is intended to evoke an error.
+        Using #error is not portable enough.  */
+     "Cannot determine unsigned 32-bit data type."
+#   endif
+#  endif
+# endif
+/* We have to make a guess about the integer type equivalent in size
+   to pointers which should always be correct.  */
+typedef unsigned long int md5_uintptr;
+#endif
+
+/* Structure to save state of computation between the single steps.  */
+struct md5_ctx
+{
+  md5_uint32 A;
+  md5_uint32 B;
+  md5_uint32 C;
+  md5_uint32 D;
+
+  md5_uint32 total[2];
+  md5_uint32 buflen;
+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW;
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void __md5_process_block (const void *buffer, size_t len,
+				 struct md5_ctx *ctx) __THROW;
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void __md5_process_bytes (const void *buffer, size_t len,
+				 struct md5_ctx *ctx) __THROW;
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 16 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
+
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
+
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int __md5_stream (FILE *stream, void *resblock) __THROW;
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+extern void *__md5_buffer (const char *buffer, size_t len,
+			   void *resblock) __THROW;
+
+#endif /* md5.h */
Index: /trunk/libc/src/glibc/crypt/md5c-test.c
===================================================================
--- /trunk/libc/src/glibc/crypt/md5c-test.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/md5c-test.c	(revision 2448)
@@ -0,0 +1,15 @@
+#include <crypt.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+  const char salt[] = "$1$saltstring";
+  char *cp;
+  int result = 0;
+
+  cp = crypt ("Hello world!", salt);
+  result |= strcmp ("$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1", cp);
+
+  return result;
+}
Index: /trunk/libc/src/glibc/crypt/md5test.c
===================================================================
--- /trunk/libc/src/glibc/crypt/md5test.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/md5test.c	(revision 2448)
@@ -0,0 +1,53 @@
+#include <string.h>
+#include "md5.h"
+
+static const struct
+{
+  const char *input;
+  const char result[16];
+} tests[] =
+  {
+    { "",
+      "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e" },
+    { "a",
+      "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8\x31\xc3\x99\xe2\x69\x77\x26\x61" },
+    { "abc",
+      "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f\x72" },
+    { "message digest",
+      "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0" },
+    { "abcdefghijklmnopqrstuvwxyz",
+      "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1\x3b" },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+      "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f" },
+    { "123456789012345678901234567890123456789012345678901234567890"
+      "12345678901234567890",
+      "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6\x7a" }
+  };
+
+
+int
+main (int argc, char *argv[])
+{
+  struct md5_ctx ctx;
+  char sum[16];
+  int result = 0;
+  int cnt;
+
+  for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
+    {
+      int i;
+
+      __md5_init_ctx (&ctx);
+      __md5_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx);
+      __md5_finish_ctx (&ctx, sum);
+      result |= memcmp (tests[cnt].result, sum, 16);
+
+      __md5_init_ctx (&ctx);
+      for (i = 0; tests[cnt].input[i] != '\0'; ++i)
+	__md5_process_bytes (&tests[cnt].input[i], 1, &ctx);
+      __md5_finish_ctx (&ctx, sum);
+      result |= memcmp (tests[cnt].result, sum, 16);
+    }
+
+  return result;
+}
Index: /trunk/libc/src/glibc/crypt/speeds.c
===================================================================
--- /trunk/libc/src/glibc/crypt/speeds.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/speeds.c	(revision 2448)
@@ -0,0 +1,153 @@
+/*
+ * This fcrypt/crypt speed testing program
+ * is derived from one floating around in
+ * the net. It's distributed along with
+ * UFC-crypt but is not covered by any
+ * licence.
+ *
+ * @(#)speeds.c	1.11 20 Aug 1996
+ */
+
+#include <signal.h>
+#include <stdio.h>
+
+#ifndef SIGVTALRM
+/* 
+ * patch from chip@chinacat.unicom.com (Chip Rosenthal):
+ * you may enable it if your system does not include
+ * a setitimer() function. You'll have to ensure the
+ * existence a environment variable: HZ giving how many
+ * ticks goes per second.
+ * If not existing in your default environment 50, 60 
+ * or even 100 may be the right value. Perhaps you should
+ * then use 'time ./ufc 10000' instead of guessing.
+ */
+#define NO_ITIMER
+#endif
+
+#ifdef NO_ITIMER
+#include <sys/types.h>
+#include <sys/times.h>
+#else
+#include <sys/time.h>
+#endif
+
+static int cnt;
+#ifdef NO_ITIMER
+char *hz;
+struct tms tstart, tfinish;
+#endif
+#define ITIME	10		/* Number of seconds to run test. */
+
+char *crypt(), *fcrypt();
+
+void
+Stop ()
+{
+    double elapsed;
+#ifdef NO_ITIMER
+    (void) times(&tfinish);
+    elapsed = ((tfinish.tms_utime + tfinish.tms_stime) -
+	(tstart.tms_utime + tstart.tms_stime)) / atoi(hz);
+    printf("elapsed time = %d sec,  CPU time = %f sec\n", ITIME, elapsed);
+#else
+    elapsed = ITIME;
+#endif
+    printf ("Did %f %s()s per second.\n", ((float) cnt) / elapsed,
+#if defined(FCRYPT)
+	    "fcrypt"
+#else
+	    "crypt"
+#endif
+    );
+    exit (0);
+}
+
+/*
+ * Silly rewrite of 'bzero'. I do so
+ * because some machines don't have
+ * bzero and some don't have memset.
+ */
+
+static void clearmem(start, cnt)
+  char *start;
+  int cnt;
+  { while(cnt--)
+      *start++ = '\0';
+  }
+
+main ()
+{
+   char *s;
+#ifdef NO_ITIMER
+    extern char *getenv();
+#else
+    struct itimerval itv;
+#endif
+
+#ifdef NO_ITIMER
+    if ((hz = getenv("HZ")) == NULL) {
+	fprintf(stderr, "HZ environment parameter undefined\n");
+	exit(1);
+    }
+#endif
+
+#ifdef FCRYPT
+    printf("\n");
+    printf("Warning: this version of the speed program may run slower when\n");
+    printf("benchmarking UFC-crypt than previous versions. This is because it\n");
+    printf("stresses the CPU hardware cache in order to get benchmark figures\n");
+    printf("that corresponds closer to the performance that can be expected in\n");
+    printf("a password cracker.\n\n");
+#endif
+
+    printf ("Running %s for %d seconds of virtual time ...\n",
+#ifdef FCRYPT
+    "UFC-crypt",
+#else
+    "crypt(libc)",
+#endif
+	    ITIME);
+
+#ifdef FCRYPT
+    init_des ();
+#endif
+
+#ifdef NO_ITIMER
+    signal(SIGALRM, Stop);
+    switch (fork()) {
+    case -1:
+	perror("fork failed");
+	exit(1);
+    case 0:
+	sleep(10);
+	kill(getppid(), SIGALRM);
+	exit(0);
+    default:
+	(void) times(&tstart);
+    }
+#else
+    clearmem ((char*)&itv, (int)sizeof (itv));
+    signal (SIGVTALRM, Stop);
+    itv.it_value.tv_sec = ITIME;
+    itv.it_value.tv_usec = 0;
+    setitimer (ITIMER_VIRTUAL, &itv, NULL);
+#endif
+
+
+    s = "fredred";
+    for (cnt = 0;; cnt++)
+    {
+#ifdef FCRYPT
+	s = fcrypt (s, "eek");
+#else
+	s = crypt (s, "eek");
+#endif
+    }
+}
+
+
+
+
+
+
Index: /trunk/libc/src/glibc/crypt/ufc-crypt.h
===================================================================
--- /trunk/libc/src/glibc/crypt/ufc-crypt.h	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/ufc-crypt.h	(revision 2448)
@@ -0,0 +1,29 @@
+/* Types for UFC-crypt.
+   Copyright (C) 1998 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 <stdint.h>
+
+typedef uint_fast32_t ufc_long;
+typedef uint64_t long64;
+typedef uint32_t long32;
+#if UINT_FAST32_MAX == UINT_FAST64_MAX
+# define _UFC_64_
+#else
+# define _UFC_32_
+#endif
Index: /trunk/libc/src/glibc/crypt/ufc.c
===================================================================
--- /trunk/libc/src/glibc/crypt/ufc.c	(revision 2448)
+++ /trunk/libc/src/glibc/crypt/ufc.c	(revision 2448)
@@ -0,0 +1,56 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * 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 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.
+ *
+ * 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
+ * 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; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * @(#)ufc.c	2.7 9/10/96
+ *
+ * Stub main program for debugging
+ * and benchmarking.
+ *
+ */
+
+#include <stdio.h>
+
+char *crypt();
+
+main(argc, argv)
+  int argc;
+  char **argv;
+  { char *s;
+    unsigned long i,iterations;
+
+    if(argc != 2) {
+      fprintf(stderr, "usage: ufc iterations\n");
+      exit(1);
+    }
+    argv++;
+    iterations = atoi(*argv);
+    printf("ufc: running %d iterations\n", iterations);
+
+    for(i=0; i<iterations; i++)
+      s=crypt("foob","ar");
+    if(strcmp(s, "arlEKn0OzVJn.") == 0)
+      printf("OK\n");
+    else {
+      printf("wrong result: %s!!\n", s);
+      exit(1);
+    }
+    exit(0);
+  }
+
Index: /trunk/libc/src/glibc/include/config.h
===================================================================
--- /trunk/libc/src/glibc/include/config.h	(revision 2448)
+++ /trunk/libc/src/glibc/include/config.h	(revision 2448)
@@ -0,0 +1,126 @@
+/* $Id$ */
+/** @file
+ *
+ * config.h file for GLIBC porting.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of Innotek LIBC.
+ *
+ * Innotek LIBC 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Innotek LIBC 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 Innotek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __config_h_
+#define __config_h_
+
+
+#define HAVE_VPRINTF 1
+#define STDC_HEADERS 1
+#define HAVE_DECL_STRERROR_R 1
+#define HAVE_STRERROR_R 1
+#define HAVE_STRERROR 1
+#define HAVE_DECL_STRERROR 1
+#define HAVE_STRDUP 1
+#define HAVE_MEMPCPY 1
+#define HAVE_ALLOCA 1
+#define HAVE_ALLOCA_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_GETUID 1
+#define HAVE_GETGID 1
+#define HAVE_GETEUID 1
+#define HAVE_GETEGID 1
+#define HAVE_ICONV 1
+#define HAVE_STPCPY 1
+#define HAVE_UNISTD_H 1
+#define HAVE_BUILTIN_EXPECT 1
+#define HAVE_ARGZ_H 1
+#define HAVE___ARGZ_COUNT 1
+#define HAVE___ARGZ_STRINGIFY 1
+#define HAVE___ARGZ_NEXT 1
+#define HAVE_STDINT_H_WITH_UINTMAX 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRTOUL 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_GETCWD 1
+#define HAVE_TSEARCH 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_LANGINFO_CODESET 1
+#define HAVE_SETLOCALE 1
+#define HAVE_LOCALE_H 1
+#define HAVE_LC_MESSAGES 1
+#define HAVE_LOCALE_NULL 1
+#define HAVE_WCHAR_H 1
+#define HAVE_WCTYPE_H 1
+#define HAVE_ISBLANK 1
+#define HAVE_WCRTOMB 1
+#define HAVE_MBRTOWC 1
+#define HAVE_WCSCOLL 0
+#define HAVE_DECL_GETC_UNLOCKED 1
+
+#define STRERROR_R_CHAR_P 0
+#define DISALLOW_MMAP 1
+
+/* shut up stupid yy */
+#define YYSTACK_USE_ALLOCA 1
+#define YYMAXDEPTH 10000
+#define YYDEBUG 0
+#define YYLSP_NEEDED 0
+
+#define LOCALEDIR           "/@unixroot/usr/locale"
+#define LIBDIR              "/@unixroot/usr/lib"
+#define LOCALE_ALIAS_PATH   LOCALEDIR
+
+#define ICONV_CONST const
+
+#if 0
+# define INTUSE(name)                   __libc_internal_##name
+# define INTDEF(name)                   strong_alias (name, __libc_internal_##name)
+# define INTVARDEF(name)                _INTVARDEF (name, __libc_internal_##name)
+# if defined HAVE_VISIBILITY_ATTRIBUTE
+#  define _INTVARDEF(name, aliasname)   extern __typeof (name) aliasname __attribute__ ((alias (#name), visibility ("hidden")));
+# else
+#  define _INTVARDEF(name, aliasname)   extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+# endif
+# define INTDEF2(name, newname)         strong_alias (name, __libc_internal_##newname)
+# define INTVARDEF2(name, newname)      _INTVARDEF (name,  __libc_internal_##newname)
+#else
+# define INTUSE(name)                   name
+# define INTDEF(name)
+# define INTVARDEF(name)
+# define INTDEF2(name, newname)
+# define INTVARDEF2(name, newname)
+#endif
+
+#undef HAVE_ASM_SET_DIRECTIVE
+#define ASM_GLOBAL_DIRECTIVE        .globl
+#undef ASM_TYPE_DIRECTIVE_PREFIX
+#undef HAVE_GNU_LD
+#undef HAVE_ELF
+#undef HAVE_ASM_WEAK_DIRECTIVE
+#undef HAVE_ASM_WEAKEXT_DIRECTIVE
+
+#define DO_VERSIONING 0
+#ifndef __BOUNDED_POINTERS__
+#define __BOUNDED_POINTERS__ 0
+#endif
+
+#ifndef __ASSEMBLER__
+#include "libc-alias-glibc.h"
+#endif
+#endif
Index: /trunk/libc/src/glibc/include/libc-alias-glibc.h
===================================================================
--- /trunk/libc/src/glibc/include/libc-alias-glibc.h	(revision 2448)
+++ /trunk/libc/src/glibc/include/libc-alias-glibc.h	(revision 2448)
@@ -0,0 +1,574 @@
+/* $Id$ */
+/** @file
+ *
+ * Innotek LIBC aliasing for GLIBC.
+ *
+ * Routes the __<stdname> to it's appropriate Innotek LIBC implementation.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of Innotek LIBC.
+ *
+ * Innotek LIBC 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Innotek LIBC 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 Innotek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __libc_alias_glibc_h__
+#define __libc_alias_glibc_h__
+
+#include "libc-alias.h"
+
+/* a little hack */
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+#undef _BSD_SOURCE
+#define _BSD_SOURCE
+#undef _SVID_SOURCE
+#define _SVID_SOURCE
+#undef _POSIX_SOURCE
+#undef _POSIX_C_SOURCE
+#include <sys/cdefs.h>
+
+#ifndef _LIBC_SYMBOLS_H /* hackityhack */
+# undef weak_alias
+# ifdef __WANT_WEAK__
+#  define weak_alias(name, aliasname) \
+    extern __typeof(name) aliasname  __attribute__((weak, alias(#name)));
+# else
+#  define weak_alias(name, aliasname)
+# endif
+#undef INTDEF
+#define INTDEF(name)
+#define libc_hidden_def(name)
+#endif
+
+#define __stpcpy(d, s) stpcpy(d, s)
+
+/* Generated from libc-std.h using:
+ *  sed -e "/^#define.*_STD(/!d" -e "s/#define \([a-zA-Z0-9_]*\) /#define __\1 /"
+ */
+#define __mrand48 _STD(mrand48)
+#define __memmove _STD(memmove)
+#define __floorf _STD(floorf)
+#define __getppid _STD(getppid)
+#define __execv _STD(execv)
+#define __ioctl _STD(ioctl)
+#define __tcsendbreak _STD(tcsendbreak)
+#define __seed48 _STD(seed48)
+#define __fmodf _STD(fmodf)
+#define __rand _STD(rand)
+#define __strdup _STD(strdup)
+#define __rindex _STD(rindex)
+#define __strnset _STD(strnset)
+#define __read _STD(read)
+#define __putenv _STD(putenv)
+#define __fgetpos _STD(fgetpos)
+#define __bsearch _STD(bsearch)
+#define __floorl _STD(floorl)
+#define __localtime _STD(localtime)
+#define __pause _STD(pause)
+#define __execle _STD(execle)
+#define __getpagesize _STD(getpagesize)
+#define __rewind _STD(rewind)
+#define __strtoll _STD(strtoll)
+#define __pipe _STD(pipe)
+#define __insque _STD(insque)
+#define __sigsuspend _STD(sigsuspend)
+#define __fmodl _STD(fmodl)
+#define __setvbuf _STD(setvbuf)
+#define __powf _STD(powf)
+#define __setgid _STD(setgid)
+#define __posix_memalign _STD(posix_memalign)
+#define __tzname _STD(tzname)
+#define __spawnlpe _STD(spawnlpe)
+#define __sys_nerr _STD(sys_nerr)
+#define __hypotf _STD(hypotf)
+#define __getpass _STD(getpass)
+#define __localtime_r _STD(localtime_r)
+#define __getpwuid _STD(getpwuid)
+#define __printf _STD(printf)
+#define __fgetc _STD(fgetc)
+#define __memicmp _STD(memicmp)
+#define __spawnl _STD(spawnl)
+#define __sinhf _STD(sinhf)
+#define __ceil _STD(ceil)
+#define __spawnle _STD(spawnle)
+#define __lcong48 _STD(lcong48)
+#define __powl _STD(powl)
+#define __cfgetospeed _STD(cfgetospeed)
+#define __getenv _STD(getenv)
+#define __qsort _STD(qsort)
+#define __sigdelset _STD(sigdelset)
+#define __setmode _STD(setmode)
+#define __malloc _STD(malloc)
+#define __hypotl _STD(hypotl)
+#define __execlp _STD(execlp)
+#define __fscanf _STD(fscanf)
+#define __floor _STD(floor)
+#define __nextafter _STD(nextafter)
+#define __strupr _STD(strupr)
+#define __scanf _STD(scanf)
+#define __sinhl _STD(sinhl)
+#define __cfsetispeed _STD(cfsetispeed)
+#define __exit _STD(exit)
+#define __setuid _STD(setuid)
+#define __realpath _STD(realpath)
+#define __logf _STD(logf)
+#define __tcgetattr _STD(tcgetattr)
+#define __strcoll _STD(strcoll)
+#define __tmpfile _STD(tmpfile)
+#define __timezone _STD(timezone)
+#define __sbrk _STD(sbrk)
+#define __strcspn _STD(strcspn)
+#define __pathconf _STD(pathconf)
+#define __bzero _STD(bzero)
+#define __log _STD(log)
+#define __spawnv _STD(spawnv)
+#define __sysconf _STD(sysconf)
+#define __ftruncate _STD(ftruncate)
+#define __gcvt _STD(gcvt)
+#define __sigsetjmp _STD(sigsetjmp)
+#define __pow _STD(pow)
+#define __cfsetspeed _STD(cfsetspeed)
+#define __sleep _STD(sleep)
+#define __spawnlp _STD(spawnlp)
+#define __sprintf _STD(sprintf)
+#define __cbrtl _STD(cbrtl)
+#define __writev _STD(writev)
+#define __ffs _STD(ffs)
+#define __strftime _STD(strftime)
+#define __strtoimax _STD(strtoimax)
+#define __tanhf _STD(tanhf)
+#define __logl _STD(logl)
+#define __opendir _STD(opendir)
+#define __fprintf _STD(fprintf)
+#define __erand48 _STD(erand48)
+#define __acos _STD(acos)
+#define __gmtime _STD(gmtime)
+#define __srand _STD(srand)
+#define __fgets _STD(fgets)
+#define __mbtowc _STD(mbtowc)
+#define __asctime _STD(asctime)
+#define __utimes _STD(utimes)
+#define __isatty _STD(isatty)
+#define __getopt _STD(getopt)
+#define __strcpy _STD(strcpy)
+#define __ftell _STD(ftell)
+#define __memcpy _STD(memcpy)
+#define __ctime _STD(ctime)
+#define __stat _STD(stat)
+#define __tdelete _STD(tdelete)
+#define __sqrtf _STD(sqrtf)
+#define __tanhl _STD(tanhl)
+#define __cbrt _STD(cbrt)
+#define __closedir _STD(closedir)
+#define __hdestroy _STD(hdestroy)
+#define __bcopy _STD(bcopy)
+#define __strerror_r _STD(strerror_r)
+#define __expand _STD(expand)
+#define __readdir_r _STD(readdir_r)
+#define __strcat _STD(strcat)
+#define __rintf _STD(rintf)
+#define __fabs _STD(fabs)
+#define __settimeofday _STD(settimeofday)
+#define __clock _STD(clock)
+#define __spawnvpe _STD(spawnvpe)
+#define __getgroups _STD(getgroups)
+#define __getcwd _STD(getcwd)
+#define __fgetchar _STD(fgetchar)
+#define __modff _STD(modff)
+#define __cos _STD(cos)
+#define __atan2 _STD(atan2)
+#define __sopen _STD(sopen)
+#define __strtod _STD(strtod)
+#define __sqrtl _STD(sqrtl)
+#define __calloc _STD(calloc)
+#define __mblen _STD(mblen)
+#define __fseeko _STD(fseeko)
+#define __imaxdiv _STD(imaxdiv)
+#define __ldexp _STD(ldexp)
+#define __strtof _STD(strtof)
+#define __setbuf _STD(setbuf)
+#define __execve _STD(execve)
+#define __setlocale _STD(setlocale)
+#define __glob _STD(glob)
+#define __strlen _STD(strlen)
+#define __rintl _STD(rintl)
+#define __getpwent _STD(getpwent)
+#define __modfl _STD(modfl)
+#define __stricmp _STD(stricmp)
+#define __ulimit _STD(ulimit)
+#define __strtok _STD(strtok)
+#define __sscanf _STD(sscanf)
+#define __tsearch _STD(tsearch)
+#define __modf _STD(modf)
+#define __strnicmp _STD(strnicmp)
+#define __strncpy _STD(strncpy)
+#define __getwd _STD(getwd)
+#define __creat _STD(creat)
+#define __rewinddir _STD(rewinddir)
+#define __strtol _STD(strtol)
+#define __abort _STD(abort)
+#define __copysignf _STD(copysignf)
+#define __waitpid _STD(waitpid)
+#define __div _STD(div)
+#define __cuserid _STD(cuserid)
+#define __siglongjmp _STD(siglongjmp)
+#define __spawnve _STD(spawnve)
+#define __longjmp _STD(longjmp)
+#define __getegid _STD(getegid)
+#define __setbuffer _STD(setbuffer)
+#define __strptime _STD(strptime)
+#define __ctime_r _STD(ctime_r)
+#define __strncat _STD(strncat)
+#define __getpwnam _STD(getpwnam)
+#define __fnmatch _STD(fnmatch)
+#define __ftello _STD(ftello)
+#define __log10 _STD(log10)
+#define __copysignl _STD(copysignl)
+#define __execvp _STD(execvp)
+#define __setenv _STD(setenv)
+#define __fdopen _STD(fdopen)
+#define __sigemptyset _STD(sigemptyset)
+#define __uname _STD(uname)
+#define __lrand48 _STD(lrand48)
+#define __nrand48 _STD(nrand48)
+#define __times _STD(times)
+#define __tcgetpgrp _STD(tcgetpgrp)
+#define __utime _STD(utime)
+#define __fputc _STD(fputc)
+#define __ltoa _STD(ltoa)
+#define __exp _STD(exp)
+#define __coshf _STD(coshf)
+#define __setpwent _STD(setpwent)
+#define __fsetpos _STD(fsetpos)
+#define __lseek _STD(lseek)
+#define __chsize _STD(chsize)
+#define __ttyname _STD(ttyname)
+#define __cfgetispeed _STD(cfgetispeed)
+#define __spawnvp _STD(spawnvp)
+#define __gmtime_r _STD(gmtime_r)
+#define __getgrgid _STD(getgrgid)
+#define __geteuid _STD(geteuid)
+#define __fflush _STD(fflush)
+#define __memccpy _STD(memccpy)
+#define __index _STD(index)
+#define __coshl _STD(coshl)
+#define __mkdir _STD(mkdir)
+#define __free _STD(free)
+#define __flushall _STD(flushall)
+#define __qsort_r _STD(qsort_r)
+#define __strerror _STD(strerror)
+#define __system _STD(system)
+#define __difftime _STD(difftime)
+#define __copysign _STD(copysign)
+#define __getlogin _STD(getlogin)
+#define __putchar _STD(putchar)
+#define __snprintf _STD(snprintf)
+#define __hcreate _STD(hcreate)
+#define __strrchr _STD(strrchr)
+#define __cosf _STD(cosf)
+#define __atan _STD(atan)
+#define __asin _STD(asin)
+#define __labs _STD(labs)
+#define __localeconv _STD(localeconv)
+#define __tempnam _STD(tempnam)
+#define __jrand48 _STD(jrand48)
+#define __sqrt _STD(sqrt)
+#define __realloc _STD(realloc)
+#define __lockf _STD(lockf)
+#define __cosh _STD(cosh)
+#define __setpgid _STD(setpgid)
+#define __fcntl _STD(fcntl)
+#define __dirname _STD(dirname)
+#define __vfscanf _STD(vfscanf)
+#define __gets _STD(gets)
+#define __sinf _STD(sinf)
+#define __log10f _STD(log10f)
+#define __tell _STD(tell)
+#define __fputs _STD(fputs)
+#define __strcmp _STD(strcmp)
+#define __sinh _STD(sinh)
+#define __memcmp _STD(memcmp)
+#define __cosl _STD(cosl)
+#define __ftime _STD(ftime)
+#define __raise _STD(raise)
+#define __brk _STD(brk)
+#define __ulltoa _STD(ulltoa)
+#define __getw _STD(getw)
+#define __chdrive _STD(chdrive)
+#define __sys_errlist _STD(sys_errlist)
+#define __strtoumax _STD(strtoumax)
+#define __vsnprintf _STD(vsnprintf)
+#define __lfind _STD(lfind)
+#define __tan _STD(tan)
+#define __sinl _STD(sinl)
+#define __sin _STD(sin)
+#define __atofl _STD(atofl)
+#define __chdir _STD(chdir)
+#define __pclose _STD(pclose)
+#define __clearerr _STD(clearerr)
+#define __tfind _STD(tfind)
+#define __log10l _STD(log10l)
+#define __ftw _STD(ftw)
+#define __fpathconf _STD(fpathconf)
+#define __fopen _STD(fopen)
+#define __nextafterf _STD(nextafterf)
+#define __asctime_r _STD(asctime_r)
+#define __sigaction _STD(sigaction)
+#define __kill _STD(kill)
+#define __mkstemp _STD(mkstemp)
+#define __eof _STD(eof)
+#define __ceilf _STD(ceilf)
+#define __tcflush _STD(tcflush)
+#define __getpid _STD(getpid)
+#define __fseek _STD(fseek)
+#define __readv _STD(readv)
+#define __srand48 _STD(srand48)
+#define __execlpe _STD(execlpe)
+#define __vprintf _STD(vprintf)
+#define __filelength _STD(filelength)
+#define __fwrite _STD(fwrite)
+#define __tzset _STD(tzset)
+#define __sigaddset _STD(sigaddset)
+#define __getgid _STD(getgid)
+#define __atexit _STD(atexit)
+#define __chmod _STD(chmod)
+#define __dup _STD(dup)
+#define __write _STD(write)
+#define __select _STD(select)
+#define __fmod _STD(fmod)
+#define __fabsf _STD(fabsf)
+#define __acosf _STD(acosf)
+#define __signal _STD(signal)
+#define __sigismember _STD(sigismember)
+#define __nextafterl _STD(nextafterl)
+#define __mktime _STD(mktime)
+#define __strspn _STD(strspn)
+#define __close _STD(close)
+#define __ceill _STD(ceill)
+#define __readdir _STD(readdir)
+#define __asinf _STD(asinf)
+#define __lsearch _STD(lsearch)
+#define __tanf _STD(tanf)
+#define __atanf _STD(atanf)
+#define __strxfrm _STD(strxfrm)
+#define __strncmp _STD(strncmp)
+#define __fread _STD(fread)
+#define __tcsetattr _STD(tcsetattr)
+#define __tanh _STD(tanh)
+#define __fabsl _STD(fabsl)
+#define __acosl _STD(acosl)
+#define __strrev _STD(strrev)
+#define __setsid _STD(setsid)
+#define __perror _STD(perror)
+#define __strtoull _STD(strtoull)
+#define __fileno _STD(fileno)
+#define __lstat _STD(lstat)
+#define __atan2f _STD(atan2f)
+#define __fsync _STD(fsync)
+#define __vscanf _STD(vscanf)
+#define __truncate _STD(truncate)
+#define __twalk _STD(twalk)
+#define __expf _STD(expf)
+#define __asinl _STD(asinl)
+#define __gettimeofday _STD(gettimeofday)
+#define __umask _STD(umask)
+#define __getuid _STD(getuid)
+#define __tanl _STD(tanl)
+#define __atanl _STD(atanl)
+#define __strpbrk _STD(strpbrk)
+#define __fork _STD(fork)
+#define __flock _STD(flock)
+#define __swab _STD(swab)
+#define __ungetc _STD(ungetc)
+#define __sigprocmask _STD(sigprocmask)
+#define __dup2 _STD(dup2)
+#define __vsscanf _STD(vsscanf)
+#define __drand48 _STD(drand48)
+#define __trunc _STD(trunc)
+#define __atan2l _STD(atan2l)
+#define __tcflow _STD(tcflow)
+#define __wcstombs _STD(wcstombs)
+#define __atoll _STD(atoll)
+#define __remque _STD(remque)
+#define __expl _STD(expl)
+#define __seekdir _STD(seekdir)
+#define __fclose _STD(fclose)
+#define __strtoul _STD(strtoul)
+#define __cfsetospeed _STD(cfsetospeed)
+#define __sigfillset _STD(sigfillset)
+#define __lltoa _STD(lltoa)
+#define __tmpnam _STD(tmpnam)
+#define __hsearch _STD(hsearch)
+#define __getpw _STD(getpw)
+#define __strstr _STD(strstr)
+#define __popen _STD(popen)
+#define __truncf _STD(truncf)
+#define __rmdir _STD(rmdir)
+#define __getchar _STD(getchar)
+#define __ldexpf _STD(ldexpf)
+#define __daylight _STD(daylight)
+#define __basename _STD(basename)
+#define __execvpe _STD(execvpe)
+#define __tcsetpgrp _STD(tcsetpgrp)
+#define __strlwr _STD(strlwr)
+#define __getpgrp _STD(getpgrp)
+#define __wait _STD(wait)
+#define __atof _STD(atof)
+#define __truncl _STD(truncl)
+#define __remove _STD(remove)
+#define __getgrnam _STD(getgrnam)
+#define __mbstowcs _STD(mbstowcs)
+#define __mktemp _STD(mktemp)
+#define __ldexpl _STD(ldexpl)
+#define __endpwent _STD(endpwent)
+#define __ferror _STD(ferror)
+#define __access _STD(access)
+#define __atoi _STD(atoi)
+#define __frexpf _STD(frexpf)
+#define __vsprintf _STD(vsprintf)
+#define __rint _STD(rint)
+#define __unlink _STD(unlink)
+#define __fstat _STD(fstat)
+#define __bcmp _STD(bcmp)
+#define __atol _STD(atol)
+#define __unsetenv _STD(unsetenv)
+#define __puts _STD(puts)
+#define __vfprintf _STD(vfprintf)
+#define __ldiv _STD(ldiv)
+#define __strset _STD(strset)
+#define __execl _STD(execl)
+#define __feof _STD(feof)
+#define __wctomb _STD(wctomb)
+#define __imaxabs _STD(imaxabs)
+#define __memset _STD(memset)
+#define __frexp _STD(frexp)
+#define __time _STD(time)
+#define __setjmp _STD(setjmp)
+#define __rename _STD(rename)
+#define __frexpl _STD(frexpl)
+#define __tcdrain _STD(tcdrain)
+#define __putw _STD(putw)
+#define __strchr _STD(strchr)
+#define __open _STD(open)
+#define __memchr _STD(memchr)
+#define __ultoa _STD(ultoa)
+#define __telldir _STD(telldir)
+#define __fputchar _STD(fputchar)
+#define __globfree _STD(globfree)
+#define __hypot _STD(hypot)
+#define __sigpending _STD(sigpending)
+#define __strtold _STD(strtold)
+#define __freopen _STD(freopen)
+#define __abs _STD(abs)
+#define __environ _STD(environ)
+#define __strcasecmp _STD(stricmp)
+#define __strncasecmp _STD(strnicmp)
+#define __flockfile _STD(flockfile)
+#define __ftrylockfile _STD(ftrylockfile)
+#define __funlockfile _STD(funlockfile)
+
+/* complex */
+#define __cabs       _STD(cabs)
+#define __cabsf      _STD(cabsf)
+#define __cimag      _STD(cimag)
+#define __cimagf     _STD(cimagf)
+#define __cimagl     _STD(cimagl)
+#define __conj       _STD(conj)
+#define __conjf      _STD(conjf)
+#define __conjl      _STD(conjl)
+#define __creal      _STD(creal)
+#define __crealf     _STD(crealf)
+#define __creall     _STD(creall)
+#define __cabsl _STD(cabsl)
+#define __cacos _STD(cacos)
+#define __cacosf _STD(cacosf)
+#define __cacosh _STD(cacosh)
+#define __cacoshf _STD(cacoshf)
+#define __cacoshl _STD(cacoshl)
+#define __cacosl _STD(cacosl)
+#define __carg _STD(carg)
+#define __cargf _STD(cargf)
+#define __cargl _STD(cargl)
+#define __casin _STD(casin)
+#define __casinf _STD(casinf)
+#define __casinh _STD(casinh)
+#define __casinhf _STD(casinhf)
+#define __casinhl _STD(casinhl)
+#define __casinl _STD(casinl)
+#define __catan _STD(catan)
+#define __catanf _STD(catanf)
+#define __catanh _STD(catanh)
+#define __catanhf _STD(catanhf)
+#define __catanhl _STD(catanhl)
+#define __catanl _STD(catanl)
+#define __ccos _STD(ccos)
+#define __ccosf _STD(ccosf)
+#define __ccosh _STD(ccosh)
+#define __ccoshf _STD(ccoshf)
+#define __ccoshl _STD(ccoshl)
+#define __ccosl _STD(ccosl)
+#define __cexp _STD(cexp)
+#define __cexpf _STD(cexpf)
+#define __cexpl _STD(cexpl)
+#define __clog _STD(clog)
+#define __clogf _STD(clogf)
+#define __clogl _STD(clogl)
+#define __cpow _STD(cpow)
+#define __cpowf _STD(cpowf)
+#define __cpowl _STD(cpowl)
+#define __cproj _STD(cproj)
+#define __cprojf _STD(cprojf)
+#define __cprojl _STD(cprojl)
+#define __csin _STD(csin)
+#define __csinf _STD(csinf)
+#define __csinh _STD(csinh)
+#define __csinhf _STD(csinhf)
+#define __csinhl _STD(csinhl)
+#define __csinl _STD(csinl)
+#define __csqrt _STD(csqrt)
+#define __csqrtf _STD(csqrtf)
+#define __csqrtl _STD(csqrtl)
+#define __ctan _STD(ctan)
+#define __ctanf _STD(ctanf)
+#define __ctanh _STD(ctanh)
+#define __ctanhf _STD(ctanhf)
+#define __ctanhl _STD(ctanhl)
+#define __ctanl _STD(ctanl)
+
+/* more math */
+#define __isinf isinf
+#define __isnan isnan
+#define __isnanf isnanf
+#define __nanf nanf
+#define __nanl nanl
+#define __sincosf   _STD(sincosf)
+#define __sincosl   _STD(sincosl)
+#define __sincos    _STD(sincos)
+#define __log1pl    _STD(log1pl)
+#define __expm1l    _STD(expm1l)
+#define __scalbnl   _STD(scalbnl)
+#define __gammal    _STD(gammal)
+#define __gammal_r  _STD(gammal_r)
+#define __lgammal   _STD(lgammal)
+#define __lgammal_r _STD(lgammal_r)
+#define __gamma     _STD(gamma)
+#define __gamma_r   _STD(gamma_r)
+#define __lgamma    _STD(lgamma)
+#define __lgamma_r  _STD(lgamma_r)
+
+#define mempcpy     __mempcpy
+#endif
Index: /trunk/libc/src/glibc/include/libc-symbols.h
===================================================================
--- /trunk/libc/src/glibc/include/libc-symbols.h	(revision 2448)
+++ /trunk/libc/src/glibc/include/libc-symbols.h	(revision 2448)
@@ -0,0 +1,845 @@
+/* Support macros for making weak and strong aliases for symbols,
+   and for using symbol sets and linker warnings with GNU ld.
+   Copyright (C) 1995-1998,2000-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.  */
+
+#ifndef _LIBC_SYMBOLS_H
+#define _LIBC_SYMBOLS_H	1
+
+/* This file's macros are included implicitly in the compilation of every
+   file in the C library by -imacros.
+
+   We include config.h which is generated by configure.
+   It should define for us the following symbols:
+
+   * HAVE_ASM_SET_DIRECTIVE if we have `.set B, A' instead of `A = B'.
+   * ASM_GLOBAL_DIRECTIVE with `.globl' or `.global'.
+   * ASM_TYPE_DIRECTIVE_PREFIX with `@' or `#' or whatever for .type,
+     or leave it undefined if there is no .type directive.
+   * HAVE_GNU_LD if using GNU ld, with support for weak symbols in a.out,
+   and for symbol set and warning messages extensions in a.out and ELF.
+   * HAVE_ELF if using ELF, which supports weak symbols using `.weak'.
+   * HAVE_ASM_WEAK_DIRECTIVE if we have weak symbols using `.weak'.
+   * HAVE_ASM_WEAKEXT_DIRECTIVE if we have weak symbols using `.weakext'.
+
+   */
+
+/* This is defined for the compilation of all C library code.  features.h
+   tests this to avoid inclusion of stubs.h while compiling the library,
+   before stubs.h has been generated.  Some library code that is shared
+   with other packages also tests this symbol to see if it is being
+   compiled as part of the C library.  We must define this before including
+   config.h, because it makes some definitions conditional on whether libc
+   itself is being compiled, or just some generator program.  */
+#define _LIBC	1
+
+/* Enable declarations of GNU extensions, since we are compiling them.  */
+#define _GNU_SOURCE	1
+/* And we also need the data for the reentrant functions.  */
+#define _REENTRANT	1
+
+#include <config.h>
+
+/* The symbols in all the user (non-_) macros are C symbols.
+   HAVE_GNU_LD without HAVE_ELF implies a.out.  */
+
+#if defined HAVE_ASM_WEAK_DIRECTIVE || defined HAVE_ASM_WEAKEXT_DIRECTIVE
+# define HAVE_WEAK_SYMBOLS
+#endif
+
+#ifndef __SYMBOL_PREFIX
+# ifdef NO_UNDERSCORES
+#  define __SYMBOL_PREFIX
+# else
+#  define __SYMBOL_PREFIX "_"
+# endif
+#endif
+
+#ifndef C_SYMBOL_NAME
+# ifdef NO_UNDERSCORES
+#  define C_SYMBOL_NAME(name) name
+# else
+#  define C_SYMBOL_NAME(name) _##name
+# endif
+#endif
+
+#ifndef ASM_LINE_SEP
+# define ASM_LINE_SEP ;
+#endif
+
+#ifdef HAVE_ASM_GLOBAL_DOT_NAME
+# ifndef C_SYMBOL_DOT_NAME
+#  if defined __GNUC__ && defined __GNUC_MINOR__ \
+      && (__GNUC__ << 16) + __GNUC_MINOR__ >= (3 << 16) + 1
+#   define C_SYMBOL_DOT_NAME(name) .name
+#  else
+#   define C_SYMBOL_DOT_NAME(name) .##name
+#  endif
+# endif
+#endif
+
+#ifdef __IN_INNOTEK_LIBC__
+
+/* InnoTek LIBC uses an awk script for generating aliases. */
+# define weak_alias(original, alias)
+# define weak_extern(original, alias)
+
+#else /* !__IN_INNOTEK_LIBC__ */
+
+#ifndef __ASSEMBLER__
+/* GCC understands weak symbols and aliases; use its interface where
+   possible, instead of embedded assembly language.  */
+
+/* Define ALIASNAME as a strong alias for NAME.  */
+# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+# define _strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+
+/* This comes between the return type and function name in
+   a function definition to make that definition weak.  */
+# define weak_function __attribute__ ((weak))
+# define weak_const_function __attribute__ ((weak, __const__))
+
+# ifdef HAVE_WEAK_SYMBOLS
+
+/* Define ALIASNAME as a weak alias for NAME.
+   If weak aliases are not available, this defines a strong alias.  */
+#  define weak_alias(name, aliasname) _weak_alias (name, aliasname)
+#  define _weak_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
+
+/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined).  */
+#  define weak_extern(symbol) _weak_extern (weak symbol)
+#  define _weak_extern(expr) _Pragma (#expr)
+
+# else
+
+#  define weak_alias(name, aliasname) strong_alias(name, aliasname)
+#  define weak_extern(symbol) /* Nothing. */
+
+# endif
+
+#else /* __ASSEMBLER__ */
+
+# ifdef HAVE_ASM_SET_DIRECTIVE
+#  ifdef HAVE_ASM_GLOBAL_DOT_NAME
+#   define strong_alias(original, alias)				\
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP		\
+  .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original) ASM_LINE_SEP	\
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP		\
+  .set C_SYMBOL_DOT_NAME (alias),C_SYMBOL_DOT_NAME (original)
+#   define strong_data_alias(original, alias)				\
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP		\
+  .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original)
+#  else
+#   define strong_alias(original, alias)				\
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP		\
+  .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original)
+#   define strong_data_alias(original, alias) strong_alias(original, alias)
+#  endif
+# else
+#  ifdef HAVE_ASM_GLOBAL_DOT_NAME
+#   define strong_alias(original, alias)				\
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP		\
+  C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP		\
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP		\
+  C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original)
+#   define strong_data_alias(original, alias)				\
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP		\
+  C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original)
+#  else
+#   define strong_alias(original, alias)				\
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP		\
+  C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original)
+#   define strong_data_alias(original, alias) strong_alias(original, alias)
+#  endif
+# endif
+
+# ifdef HAVE_WEAK_SYMBOLS
+#  ifdef HAVE_ASM_WEAKEXT_DIRECTIVE
+#   ifdef HAVE_ASM_GLOBAL_DOT_NAME
+#    define weak_alias(original, alias)					\
+  .weakext C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original) ASM_LINE_SEP \
+  .weakext C_SYMBOL_DOT_NAME (alias), C_SYMBOL_DOT_NAME (original)
+#   else
+#    define weak_alias(original, alias)					\
+  .weakext C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original)
+#   endif
+#   define weak_extern(symbol)						\
+  .weakext C_SYMBOL_NAME (symbol)
+
+#  else /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */
+
+#   ifdef HAVE_ASM_GLOBAL_DOT_NAME
+#    define weak_alias(original, alias)					\
+  .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP				\
+  C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP		\
+  .weak C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP				\
+  C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original)
+#   else
+#    define weak_alias(original, alias)					\
+  .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP				\
+  C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original)
+#   endif
+
+#   define weak_extern(symbol)						\
+  .weak C_SYMBOL_NAME (symbol)
+
+#  endif /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */
+
+# else /* ! HAVE_WEAK_SYMBOLS */
+
+#  define weak_alias(original, alias) strong_alias(original, alias)
+#  define weak_extern(symbol) /* Nothing */
+# endif /* ! HAVE_WEAK_SYMBOLS */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* !__IN_INNOTEK_LIBC__ */
+
+/* On some platforms we can make internal function calls (i.e., calls of
+   functions not exported) a bit faster by using a different calling
+   convention.  */
+#ifndef internal_function
+# define internal_function	/* empty */
+#endif
+
+/* Prepare for the case that `__builtin_expect' is not available.  */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+/* Determine the return address.  */
+#define RETURN_ADDRESS(nr) \
+  __builtin_extract_return_addr (__builtin_return_address (nr))
+
+/* When a reference to SYMBOL is encountered, the linker will emit a
+   warning message MSG.  */
+#ifdef HAVE_GNU_LD
+# ifdef HAVE_ELF
+
+/* We want the .gnu.warning.SYMBOL section to be unallocated.  */
+#  ifdef HAVE_ASM_PREVIOUS_DIRECTIVE
+#   define __make_section_unallocated(section_string)	\
+  asm (".section " section_string "\n\t.previous");
+#  elif defined HAVE_ASM_POPSECTION_DIRECTIVE
+#   define __make_section_unallocated(section_string)	\
+  asm (".pushsection " section_string "\n\t.popsection");
+#  else
+#   define __make_section_unallocated(section_string)
+#  endif
+
+/* Tacking on "\n\t#" to the section name makes gcc put it's bogus
+   section attributes on what looks like a comment to the assembler.  */
+#  ifdef HAVE_SECTION_QUOTES
+#   define __sec_comment "\"\n\t#\""
+#  else
+#   define __sec_comment "\n\t#"
+#  endif
+#  define link_warning(symbol, msg) \
+  __make_section_unallocated (".gnu.warning." #symbol) \
+  static const char __evoke_link_warning_##symbol[]	\
+    __attribute__ ((used, section (".gnu.warning." #symbol __sec_comment))) \
+    = msg;
+#  define libc_freeres_ptr(decl) \
+  __make_section_unallocated ("__libc_freeres_ptrs, \"aw\", %nobits") \
+  decl __attribute__ ((section ("__libc_freeres_ptrs" __sec_comment)))
+#  define __libc_freeres_fn_section \
+  __attribute__ ((section ("__libc_freeres_fn")))
+# else /* Not ELF: a.out */
+#  ifdef HAVE_XCOFF
+/* XCOFF does not support .stabs.
+   The native aix linker will remove the .stab and .stabstr sections
+   The gnu linker will have a fatal error if there is a relocation for
+   symbol in the .stab section.  Silently disable this macro.  */
+#   define link_warning(symbol, msg)
+#  else
+#   define link_warning(symbol, msg)		\
+     asm (".stabs \"" msg "\",30,0,0,0\n\t"	\
+          ".stabs \"" __SYMBOL_PREFIX #symbol "\",1,0,0,0\n");
+#  endif /* XCOFF */
+#  define libc_freeres_ptr(decl) decl
+#  define __libc_freeres_fn_section
+# endif
+#else
+/* We will never be heard; they will all die horribly.  */
+# define link_warning(symbol, msg)
+# define libc_freeres_ptr(decl) decl
+# define __libc_freeres_fn_section
+#endif
+#define libc_freeres_fn(name)	\
+  static void name (void) __attribute_used__ __libc_freeres_fn_section;	\
+  text_set_element (__libc_subfreeres, name);				\
+  static void name (void)
+
+/* A canned warning for sysdeps/stub functions.  */
+#define	stub_warning(name) \
+  __make_section_unallocated (".gnu.glibc-stub." #name) \
+  link_warning (name, \
+		"warning: " #name " is not implemented and will always fail")
+
+/* Warning for linking functions calling dlopen into static binaries.  */
+#ifdef SHARED
+#define static_link_warning(name)
+#else
+#define static_link_warning(name) static_link_warning1(name)
+#define static_link_warning1(name) \
+  link_warning(name, "Using '" #name "' in statically linked applications \
+requires at runtime the shared libraries from the glibc version used \
+for linking")
+#endif
+
+/* Declare SYMBOL to be TYPE (`function' or `object') and of SIZE bytes,
+   when the assembler supports such declarations (such as in ELF).
+   This is only necessary when defining something in assembly, or playing
+   funny alias games where the size should be other than what the compiler
+   thinks it is.  */
+#define declare_symbol(symbol, type, size) \
+  declare_symbol_1 (symbol, type, size)
+#ifdef ASM_TYPE_DIRECTIVE_PREFIX
+# ifdef __ASSEMBLER__
+#  define declare_symbol_1(symbol, type, size) \
+    .type C_SYMBOL_NAME (symbol), \
+	  declare_symbol_1_paste (ASM_TYPE_DIRECTIVE_PREFIX, type), size
+#  define declare_symbol_1_paste(a, b)	declare_symbol_1_paste_1 (a,b)
+#  define declare_symbol_1_paste_1(a,b)	a##b
+# else /* Not __ASSEMBLER__.  */
+#  define declare_symbol_1(symbol, type, size) \
+    asm (".type " __SYMBOL_PREFIX #symbol ", " \
+	 declare_symbol_1_stringify (ASM_TYPE_DIRECTIVE_PREFIX) #type \
+	 "\n\t.size " __SYMBOL_PREFIX #symbol ", " #size);
+#  define declare_symbol_1_stringify(x) declare_symbol_1_stringify_1 (x)
+#  define declare_symbol_1_stringify_1(x) #x
+# endif /* __ASSEMBLER__ */
+#else
+# define declare_symbol_1(symbol, type, size) /* Nothing.  */
+#endif
+
+
+/*
+
+
+*/
+
+#ifdef HAVE_GNU_LD
+
+/* Symbol set support macros.  */
+
+# ifdef HAVE_ELF
+
+/* Make SYMBOL, which is in the text segment, an element of SET.  */
+#  define text_set_element(set, symbol)	_elf_set_element(set, symbol)
+/* Make SYMBOL, which is in the data segment, an element of SET.  */
+#  define data_set_element(set, symbol)	_elf_set_element(set, symbol)
+/* Make SYMBOL, which is in the bss segment, an element of SET.  */
+#  define bss_set_element(set, symbol)	_elf_set_element(set, symbol)
+
+/* These are all done the same way in ELF.
+   There is a new section created for each set.  */
+#  ifdef SHARED
+/* When building a shared library, make the set section writable,
+   because it will need to be relocated at run time anyway.  */
+#   define _elf_set_element(set, symbol) \
+  static const void *__elf_set_##set##_element_##symbol##__ \
+    __attribute__ ((used, section (#set))) = &(symbol)
+#  else
+#   define _elf_set_element(set, symbol) \
+  static const void *const __elf_set_##set##_element_##symbol##__ \
+    __attribute__ ((used, section (#set))) = &(symbol)
+#  endif
+
+/* Define SET as a symbol set.  This may be required (it is in a.out) to
+   be able to use the set's contents.  */
+#  define symbol_set_define(set)	symbol_set_declare(set)
+
+/* Declare SET for use in this module, if defined in another module.
+   In a shared library, this is always local to that shared object.
+   For static linking, the set might be wholly absent and so we use
+   weak references.  */
+#  define symbol_set_declare(set) \
+  extern char const __start_##set[] __symbol_set_attribute; \
+  extern char const __stop_##set[] __symbol_set_attribute;
+#  ifdef SHARED
+#   define __symbol_set_attribute attribute_hidden
+#  else
+#   define __symbol_set_attribute __attribute__ ((weak))
+#  endif
+
+/* Return a pointer (void *const *) to the first element of SET.  */
+#  define symbol_set_first_element(set)	((void *const *) (&__start_##set))
+
+/* Return true iff PTR (a void *const *) has been incremented
+   past the last element in SET.  */
+#  define symbol_set_end_p(set, ptr) ((ptr) >= (void *const *) &__stop_##set)
+
+# else	/* Not ELF: a.out.  */
+
+#  ifdef HAVE_XCOFF
+/* XCOFF does not support .stabs.
+   The native aix linker will remove the .stab and .stabstr sections
+   The gnu linker will have a fatal error if there is a relocation for
+   symbol in the .stab section.  Silently disable these macros.  */
+#   define text_set_element(set, symbol)
+#   define data_set_element(set, symbol)
+#   define bss_set_element(set, symbol)
+#  else
+#   define text_set_element(set, symbol)	\
+    asm (".stabs \"" __SYMBOL_PREFIX #set "\",23,0,0," __SYMBOL_PREFIX #symbol)
+#   define data_set_element(set, symbol)	\
+    asm (".stabs \"" __SYMBOL_PREFIX #set "\",25,0,0," __SYMBOL_PREFIX #symbol)
+#   define bss_set_element(set, symbol)	?error Must use initialized data.
+#  endif /* XCOFF */
+#  define symbol_set_define(set)	void *const (set)[1];
+#  define symbol_set_declare(set)	extern void *const (set)[1];
+
+#  define symbol_set_first_element(set)	&(set)[1]
+#  define symbol_set_end_p(set, ptr)	(*(ptr) == 0)
+
+# endif	/* ELF.  */
+#else
+/* We cannot do anything in generial.  */
+# define text_set_element(set, symbol) asm ("")
+# define data_set_element(set, symbol) asm ("")
+# define bss_set_element(set, symbol) asm ("")
+# define symbol_set_define(set)		void *const (set)[1];
+# define symbol_set_declare(set)	extern void *const (set)[1];
+
+# define symbol_set_first_element(set)	&(set)[1]
+# define symbol_set_end_p(set, ptr)	(*(ptr) == 0)
+#endif	/* Have GNU ld.  */
+
+#if DO_VERSIONING
+# define symbol_version(real, name, version) \
+     _symbol_version(real, name, version)
+# define default_symbol_version(real, name, version) \
+     _default_symbol_version(real, name, version)
+# ifdef __ASSEMBLER__
+#  ifdef HAVE_ASM_GLOBAL_DOT_NAME
+#   define _symbol_version(real, name, version) \
+     .symver real, name##@##version ASM_LINE_SEP			\
+     .symver C_SYMBOL_DOT_NAME(real), C_SYMBOL_DOT_NAME(name##@##version)
+#   define _default_symbol_version(real, name, version) \
+     .symver real, name##@##@##version ASM_LINE_SEP			\
+     .symver C_SYMBOL_DOT_NAME(real), C_SYMBOL_DOT_NAME(name##@##@##version)
+#  else
+#   define _symbol_version(real, name, version) \
+     .symver real, name##@##version
+#   define _default_symbol_version(real, name, version) \
+     .symver real, name##@##@##version
+#  endif
+# else
+#  ifdef HAVE_ASM_GLOBAL_DOT_NAME
+#   define _symbol_version(real, name, version) \
+     __asm__ (".symver " #real "," #name "@" #version "\n\t"	\
+	      ".symver ." #real ",." #name "@" #version)
+#   define _default_symbol_version(real, name, version) \
+     __asm__ (".symver " #real "," #name "@@" #version "\n\t"	\
+	      ".symver ." #real ",." #name "@@" #version)
+#  else
+#   define _symbol_version(real, name, version) \
+     __asm__ (".symver " #real "," #name "@" #version)
+#   define _default_symbol_version(real, name, version) \
+     __asm__ (".symver " #real "," #name "@@" #version)
+#  endif
+# endif
+#else
+# define symbol_version(real, name, version)
+# define default_symbol_version(real, name, version) \
+  strong_alias(real, name)
+#endif
+
+#if defined HAVE_VISIBILITY_ATTRIBUTE \
+    && (defined SHARED || defined LIBC_NONSHARED)
+# define attribute_hidden __attribute__ ((visibility ("hidden")))
+#else
+# define attribute_hidden
+#endif
+
+#ifdef HAVE_TLS_MODEL_ATTRIBUTE
+# define attribute_tls_model_ie __attribute__ ((tls_model ("initial-exec")))
+#else
+# define attribute_tls_model_ie
+#endif
+
+#ifdef HAVE_Z_RELRO
+# define attribute_relro __attribute__ ((section (".data.rel.ro")))
+#else
+# define attribute_relro
+#endif
+
+/* Handling on non-exported internal names.  We have to do this only
+   for shared code.  */
+#ifdef SHARED
+# define INTUSE(name) name##_internal
+# define INTDEF(name) strong_alias (name, name##_internal)
+# define INTVARDEF(name) \
+  _INTVARDEF (name, name##_internal)
+# if defined HAVE_VISIBILITY_ATTRIBUTE
+#  define _INTVARDEF(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name), \
+						   visibility ("hidden")));
+# else
+#  define _INTVARDEF(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+# endif
+# define INTDEF2(name, newname) strong_alias (name, newname##_internal)
+# define INTVARDEF2(name, newname) _INTVARDEF (name, newname##_internal)
+#else
+# define INTUSE(name) name
+# define INTDEF(name)
+# define INTVARDEF(name)
+# define INTDEF2(name, newname)
+# define INTVARDEF2(name, newname)
+#endif
+
+/* The following macros are used for PLT bypassing within libc.so
+   (and if needed other libraries similarly).
+   First of all, you need to have the function prototyped somewhere,
+   say in foo/foo.h:
+
+   int foo (int __bar);
+
+   If calls to foo within libc.so should always go to foo defined in libc.so,
+   then in include/foo.h you add:
+
+   libc_hidden_proto (foo)
+
+   line and after the foo function definition:
+
+   int foo (int __bar)
+   {
+     return __bar;
+   }
+   libc_hidden_def (foo)
+
+   or
+
+   int foo (int __bar)
+   {
+     return __bar;
+   }
+   libc_hidden_weak (foo)
+
+   Simularly for global data. If references to foo within libc.so should
+   always go to foo defined in libc.so, then in include/foo.h you add:
+
+   libc_hidden_proto (foo)
+
+   line and after foo's definition:
+
+   int foo = INITIAL_FOO_VALUE;
+   libc_hidden_data_def (foo)
+
+   or
+
+   int foo = INITIAL_FOO_VALUE;
+   libc_hidden_data_weak (foo)
+
+   If foo is normally just an alias (strong or weak) of some other function,
+   you should use the normal strong_alias first, then add libc_hidden_def
+   or libc_hidden_weak:
+
+   int baz (int __bar)
+   {
+     return __bar;
+   }
+   strong_alias (baz, foo)
+   libc_hidden_weak (foo)
+
+   If the function should be internal to multiple objects, say ld.so and
+   libc.so, the best way is to use:
+
+   #if !defined NOT_IN_libc || defined IS_IN_rtld
+   hidden_proto (foo)
+   #endif
+
+   in include/foo.h and the normal macros at all function definitions
+   depending on what DSO they belong to.
+
+   If versioned_symbol macro is used to define foo,
+   libc_hidden_ver macro should be used, as in:
+
+   int __real_foo (int __bar)
+   {
+     return __bar;
+   }
+   versioned_symbol (libc, __real_foo, foo, GLIBC_2_1);
+   libc_hidden_ver (__real_foo, foo)  */
+
+#if defined SHARED && defined DO_VERSIONING \
+    && !defined HAVE_BROKEN_ALIAS_ATTRIBUTE && !defined NO_HIDDEN
+# ifndef __ASSEMBLER__
+#  if !defined HAVE_VISIBILITY_ATTRIBUTE \
+      || defined HAVE_BROKEN_VISIBILITY_ATTRIBUTE
+#   define __hidden_proto_hiddenattr(attrs...)
+#  else
+#   define __hidden_proto_hiddenattr(attrs...) \
+  __attribute__ ((visibility ("hidden"), ##attrs))
+#  endif
+#  define hidden_proto(name, attrs...) \
+  __hidden_proto (name, __GI_##name, ##attrs)
+#  define __hidden_proto(name, internal, attrs...) \
+  extern __typeof (name) name __asm__ (__hidden_asmname (#internal)) \
+  __hidden_proto_hiddenattr (attrs);
+#  define __hidden_asmname(name) \
+  __hidden_asmname1 (__USER_LABEL_PREFIX__, name)
+#  define __hidden_asmname1(prefix, name) __hidden_asmname2(prefix, name)
+#  define __hidden_asmname2(prefix, name) #prefix name
+#  define __hidden_ver1(local, internal, name) \
+  extern __typeof (name) __EI_##name __asm__(__hidden_asmname (#internal)); \
+  extern __typeof (name) __EI_##name \
+	__attribute__((alias (__hidden_asmname (#local))))
+#  define hidden_ver(local, name)	__hidden_ver1(local, __GI_##name, name);
+#  define hidden_data_ver(local, name)	hidden_ver(local, name)
+#  define hidden_def(name)		__hidden_ver1(__GI_##name, name, name);
+#  define hidden_data_def(name)		hidden_def(name)
+#  define hidden_weak(name) \
+	__hidden_ver1(__GI_##name, name, name) __attribute__((weak));
+#  define hidden_data_weak(name)	hidden_weak(name)
+# else
+/* For assembly, we need to do the opposite of what we do in C:
+   in assembly gcc __REDIRECT stuff is not in place, so functions
+   are defined by its normal name and we need to create the
+   __GI_* alias to it, in C __REDIRECT causes the function definition
+   to use __GI_* name and we need to add alias to the real name.
+   There is no reason to use hidden_weak over hidden_def in assembly,
+   but we provide it for consistency with the C usage.
+   hidden_proto doesn't make sense for assembly but the equivalent
+   is to call via the HIDDEN_JUMPTARGET macro instead of JUMPTARGET.  */
+#  define hidden_def(name)	strong_alias (name, __GI_##name)
+#  define hidden_weak(name)	hidden_def (name)
+#  define hidden_ver(local, name) strong_alias (local, __GI_##name)
+#  define hidden_data_def(name)	strong_data_alias (name, __GI_##name)
+#  define hidden_data_weak(name)	hidden_data_def (name)
+#  define hidden_data_ver(local, name) strong_data_alias (local, __GI_##name)
+#  ifdef HAVE_ASM_GLOBAL_DOT_NAME
+#   define HIDDEN_JUMPTARGET(name) .__GI_##name
+#  else
+#   define HIDDEN_JUMPTARGET(name) __GI_##name
+#  endif
+# endif
+#else
+# ifndef __ASSEMBLER__
+#  define hidden_proto(name, attrs...)
+# else
+#  define HIDDEN_JUMPTARGET(name) JUMPTARGET(name)
+# endif /* Not  __ASSEMBLER__ */
+# define hidden_weak(name)
+# define hidden_def(name)
+# define hidden_ver(local, name)
+# define hidden_data_weak(name)
+# define hidden_data_def(name)
+# define hidden_data_ver(local, name)
+#endif
+
+#if !defined NOT_IN_libc
+# define libc_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define libc_hidden_def(name) hidden_def (name)
+# define libc_hidden_weak(name) hidden_weak (name)
+# define libc_hidden_ver(local, name) hidden_ver (local, name)
+# define libc_hidden_data_def(name) hidden_data_def (name)
+# define libc_hidden_data_weak(name) hidden_data_weak (name)
+# define libc_hidden_data_ver(local, name) hidden_data_ver (local, name)
+#else
+# define libc_hidden_proto(name, attrs...)
+# define libc_hidden_def(name)
+# define libc_hidden_weak(name)
+# define libc_hidden_ver(local, name)
+# define libc_hidden_data_def(name)
+# define libc_hidden_data_weak(name)
+# define libc_hidden_data_ver(local, name)
+#endif
+
+#if defined NOT_IN_libc && defined IS_IN_rtld
+# define rtld_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define rtld_hidden_def(name) hidden_def (name)
+# define rtld_hidden_weak(name) hidden_weak (name)
+# define rtld_hidden_ver(local, name) hidden_ver (local, name)
+# define rtld_hidden_data_def(name) hidden_data_def (name)
+# define rtld_hidden_data_weak(name) hidden_data_weak (name)
+# define rtld_hidden_data_ver(local, name) hidden_data_ver (local, name)
+#else
+# define rtld_hidden_proto(name, attrs...)
+# define rtld_hidden_def(name)
+# define rtld_hidden_weak(name)
+# define rtld_hidden_ver(local, name)
+# define rtld_hidden_data_def(name)
+# define rtld_hidden_data_weak(name)
+# define rtld_hidden_data_ver(local, name)
+#endif
+
+#if defined NOT_IN_libc && defined IS_IN_libm
+# define libm_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define libm_hidden_def(name) hidden_def (name)
+# define libm_hidden_weak(name) hidden_weak (name)
+# define libm_hidden_ver(local, name) hidden_ver (local, name)
+# define libm_hidden_data_def(name) hidden_data_def (name)
+# define libm_hidden_data_weak(name) hidden_data_weak (name)
+# define libm_hidden_data_ver(local, name) hidden_data_ver (local, name)
+#else
+# define libm_hidden_proto(name, attrs...)
+# define libm_hidden_def(name)
+# define libm_hidden_weak(name)
+# define libm_hidden_ver(local, name)
+# define libm_hidden_data_def(name)
+# define libm_hidden_data_weak(name)
+# define libm_hidden_data_ver(local, name)
+#endif
+
+#if defined NOT_IN_libc && defined IS_IN_libresolv
+# define libresolv_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define libresolv_hidden_def(name) hidden_def (name)
+# define libresolv_hidden_weak(name) hidden_weak (name)
+# define libresolv_hidden_ver(local, name) hidden_ver (local, name)
+# define libresolv_hidden_data_def(name) hidden_data_def (name)
+# define libresolv_hidden_data_weak(name) hidden_data_weak (name)
+# define libresolv_hidden_data_ver(local, name) hidden_data_ver (local, name)
+#else
+# define libresolv_hidden_proto(name, attrs...)
+# define libresolv_hidden_def(name)
+# define libresolv_hidden_weak(name)
+# define libresolv_hidden_ver(local, name)
+# define libresolv_hidden_data_def(name)
+# define libresolv_hidden_data_weak(name)
+# define libresolv_hidden_data_ver(local, name)
+#endif
+
+#if defined NOT_IN_libc && defined IS_IN_libdl
+# define libdl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define libdl_hidden_def(name) hidden_def (name)
+# define libdl_hidden_weak(name) hidden_weak (name)
+# define libdl_hidden_ver(local, name) hidden_ver (local, name)
+# define libdl_hidden_data_def(name) hidden_data_def (name)
+# define libdl_hidden_data_weak(name) hidden_data_weak (name)
+# define libdl_hidden_data_ver(local, name) hidden_data_ver (local, name)
+#else
+# define libdl_hidden_proto(name, attrs...)
+# define libdl_hidden_def(name)
+# define libdl_hidden_weak(name)
+# define libdl_hidden_ver(local, name)
+# define libdl_hidden_data_def(name)
+# define libdl_hidden_data_weak(name)
+# define libdl_hidden_data_ver(local, name)
+#endif
+
+#if defined NOT_IN_libc && defined IS_IN_libnss_files
+# define libnss_files_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define libnss_files_hidden_def(name) hidden_def (name)
+# define libnss_files_hidden_weak(name) hidden_weak (name)
+# define libnss_files_hidden_ver(local, name) hidden_ver (local, name)
+# define libnss_files_hidden_data_def(name) hidden_data_def (name)
+# define libnss_files_hidden_data_weak(name) hidden_data_weak (name)
+# define libnss_files_hidden_data_ver(local, name) hidden_data_ver(local, name)
+#else
+# define libnss_files_hidden_proto(name, attrs...)
+# define libnss_files_hidden_def(name)
+# define libnss_files_hidden_weak(name)
+# define libnss_files_hidden_ver(local, name)
+# define libnss_files_hidden_data_def(name)
+# define libnss_files_hidden_data_weak(name)
+# define libnss_files_hidden_data_ver(local, name)
+#endif
+
+#if defined NOT_IN_libc && defined IS_IN_libnsl
+# define libnsl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define libnsl_hidden_def(name) hidden_def (name)
+# define libnsl_hidden_weak(name) hidden_weak (name)
+# define libnsl_hidden_ver(local, name) hidden_ver (local, name)
+# define libnsl_hidden_data_def(name) hidden_data_def (name)
+# define libnsl_hidden_data_weak(name) hidden_data_weak (name)
+# define libnsl_hidden_data_ver(local, name) hidden_data_ver (local, name)
+#else
+# define libnsl_hidden_proto(name, attrs...)
+# define libnsl_hidden_def(name)
+# define libnsl_hidden_weak(name)
+# define libnsl_hidden_ver(local, name)
+# define libnsl_hidden_data_def(name)
+# define libnsl_hidden_data_weak(name)
+# define libnsl_hidden_data_ver(local, name)
+#endif
+
+#if defined NOT_IN_libc && defined IS_IN_libnss_nisplus
+# define libnss_nisplus_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define libnss_nisplus_hidden_def(name) hidden_def (name)
+# define libnss_nisplus_hidden_weak(name) hidden_weak (name)
+# define libnss_nisplus_hidden_ver(local, name) hidden_ver (local, name)
+# define libnss_nisplus_hidden_data_def(name) hidden_data_def (name)
+# define libnss_nisplus_hidden_data_weak(name) hidden_data_weak (name)
+# define libnss_nisplus_hidden_data_ver(local, name) hidden_data_ver (local, name)
+#else
+# define libnss_nisplus_hidden_proto(name, attrs...)
+# define libnss_nisplus_hidden_def(name)
+# define libnss_nisplus_hidden_weak(name)
+# define libnss_nisplus_hidden_ver(local, name)
+# define libnss_nisplus_hidden_data_def(name)
+# define libnss_nisplus_hidden_data_weak(name)
+# define libnss_nisplus_hidden_data_ver(local, name)
+#endif
+
+#ifdef HAVE_BUILTIN_REDIRECTION
+# define libc_hidden_builtin_proto(name, attrs...) libc_hidden_proto (name, ##attrs)
+# define libc_hidden_builtin_def(name) libc_hidden_def (name)
+# define libc_hidden_builtin_weak(name) libc_hidden_weak (name)
+# define libc_hidden_builtin_ver(local, name) libc_hidden_ver (local, name)
+# ifdef __ASSEMBLER__
+#  define HIDDEN_BUILTIN_JUMPTARGET(name) HIDDEN_JUMPTARGET(name)
+# endif
+#else
+# define libc_hidden_builtin_proto(name, attrs...)
+# define libc_hidden_builtin_def(name)
+# define libc_hidden_builtin_weak(name)
+# define libc_hidden_builtin_ver(local, name)
+# ifdef __ASSEMBLER__
+#  define HIDDEN_BUILTIN_JUMPTARGET(name) JUMPTARGET(name)
+# endif
+#endif
+
+#if defined NOT_IN_libc && defined IS_IN_libutil
+# define libutil_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
+# define libutil_hidden_def(name) hidden_def (name)
+# define libutil_hidden_weak(name) hidden_weak (name)
+# define libutil_hidden_ver(local, name) hidden_ver (local, name)
+# define libutil_hidden_data_def(name) hidden_data_def (name)
+# define libutil_hidden_data_weak(name) hidden_data_weak (name)
+# define libutil_hidden_data_ver(local, name) hidden_data_ver (local, name)
+#else
+# define libutil_hidden_proto(name, attrs...)
+# define libutil_hidden_def(name)
+# define libutil_hidden_weak(name)
+# define libutil_hidden_ver(local, name)
+# define libutil_hidden_data_def(name)
+# define libutil_hidden_data_weak(name)
+# define libutil_hidden_data_ver(local, name)
+#endif
+
+/* Get some dirty hacks.  */
+#include <symbol-hacks.h>
+
+/* Move compatibility symbols out of the way by placing them all in a
+   special section.  */
+#ifndef __ASSEMBLER__
+# define attribute_compat_text_section \
+    __attribute__ ((section (".text.compat")))
+# define attribute_compat_data_section \
+    __attribute__ ((section (".data.compat")))
+#else
+# define compat_text_section .section ".text.compat", "ax";
+# define compat_data_section .section ".data.compat", "aw";
+#endif
+
+#endif /* libc-symbols.h */
Index: /trunk/libc/src/glibc/intl/bindtextdom.c
===================================================================
--- /trunk/libc/src/glibc/intl/bindtextdom.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/bindtextdom.c	(revision 2448)
@@ -0,0 +1,373 @@
+/* Implementation of the bindtextdomain(3) function
+   Copyright (C) 1995-1998, 2000, 2001, 2002, 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.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "gettextP.h"
+
+#ifdef _LIBC
+/* We have to handle multi-threaded applications.  */
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_rwlock_define(CLASS, NAME)
+# define __libc_rwlock_wrlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#endif
+
+/* The internal variables in the standalone libintl.a must have different
+   names than the internal variables in GNU libc, otherwise programs
+   using libintl.a cannot be linked statically.  */
+#if !defined(_LIBC) && !defined(IN_INNOTEK_LIBC)
+# define _nl_default_dirname libintl_nl_default_dirname
+# define _nl_domain_bindings libintl_nl_domain_bindings
+#endif
+
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Contains the default location of the message catalogs.  */
+extern const char _nl_default_dirname[];
+#ifdef _LIBC
+libc_hidden_proto (_nl_default_dirname)
+#endif
+
+/* List with bindings of specific domains.  */
+extern struct binding *_nl_domain_bindings;
+
+/* Lock variable to protect the global data in the gettext implementation.  */
+__libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
+
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define BINDTEXTDOMAIN __bindtextdomain
+# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
+# ifndef strdup
+#  define strdup(str) __strdup (str)
+# endif
+#else
+# define BINDTEXTDOMAIN libintl_bindtextdomain
+# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
+#endif
+
+/* Prototypes for local functions.  */
+static void set_binding_values PARAMS ((const char *domainname,
+					const char **dirnamep,
+					const char **codesetp));
+
+/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
+   to be used for the DOMAINNAME message catalog.
+   If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
+   modified, only the current value is returned.
+   If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
+   modified nor returned.  */
+static void
+set_binding_values (domainname, dirnamep, codesetp)
+     const char *domainname;
+     const char **dirnamep;
+     const char **codesetp;
+{
+  struct binding *binding;
+  int modified;
+
+  /* Some sanity checks.  */
+  if (domainname == NULL || domainname[0] == '\0')
+    {
+      if (dirnamep)
+	*dirnamep = NULL;
+      if (codesetp)
+	*codesetp = NULL;
+      return;
+    }
+
+  __libc_rwlock_wrlock (_nl_state_lock);
+
+  modified = 0;
+
+  for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
+    {
+      int compare = strcmp (domainname, binding->domainname);
+      if (compare == 0)
+	/* We found it!  */
+	break;
+      if (compare < 0)
+	{
+	  /* It is not in the list.  */
+	  binding = NULL;
+	  break;
+	}
+    }
+
+  if (binding != NULL)
+    {
+      if (dirnamep)
+	{
+	  const char *dirname = *dirnamep;
+
+	  if (dirname == NULL)
+	    /* The current binding has be to returned.  */
+	    *dirnamep = binding->dirname;
+	  else
+	    {
+	      /* The domain is already bound.  If the new value and the old
+		 one are equal we simply do nothing.  Otherwise replace the
+		 old binding.  */
+	      char *result = binding->dirname;
+	      if (strcmp (dirname, result) != 0)
+		{
+		  if (strcmp (dirname, _nl_default_dirname) == 0)
+		    result = (char *) _nl_default_dirname;
+		  else
+		    {
+#if defined _LIBC || defined HAVE_STRDUP
+		      result = strdup (dirname);
+#else
+		      size_t len = strlen (dirname) + 1;
+		      result = (char *) malloc (len);
+		      if (__builtin_expect (result != NULL, 1))
+			memcpy (result, dirname, len);
+#endif
+		    }
+
+		  if (__builtin_expect (result != NULL, 1))
+		    {
+		      if (binding->dirname != _nl_default_dirname)
+			free (binding->dirname);
+
+		      binding->dirname = result;
+		      modified = 1;
+		    }
+		}
+	      *dirnamep = result;
+	    }
+	}
+
+      if (codesetp)
+	{
+	  const char *codeset = *codesetp;
+
+	  if (codeset == NULL)
+	    /* The current binding has be to returned.  */
+	    *codesetp = binding->codeset;
+	  else
+	    {
+	      /* The domain is already bound.  If the new value and the old
+		 one are equal we simply do nothing.  Otherwise replace the
+		 old binding.  */
+	      char *result = binding->codeset;
+	      if (result == NULL || strcmp (codeset, result) != 0)
+		{
+#if defined _LIBC || defined HAVE_STRDUP
+		  result = strdup (codeset);
+#else
+		  size_t len = strlen (codeset) + 1;
+		  result = (char *) malloc (len);
+		  if (__builtin_expect (result != NULL, 1))
+		    memcpy (result, codeset, len);
+#endif
+
+		  if (__builtin_expect (result != NULL, 1))
+		    {
+		      if (binding->codeset != NULL)
+			free (binding->codeset);
+
+		      binding->codeset = result;
+		      ++binding->codeset_cntr;
+		      modified = 1;
+		    }
+		}
+	      *codesetp = result;
+	    }
+	}
+    }
+  else if ((dirnamep == NULL || *dirnamep == NULL)
+	   && (codesetp == NULL || *codesetp == NULL))
+    {
+      /* Simply return the default values.  */
+      if (dirnamep)
+	*dirnamep = _nl_default_dirname;
+      if (codesetp)
+	*codesetp = NULL;
+    }
+  else
+    {
+      /* We have to create a new binding.  */
+      size_t len = strlen (domainname) + 1;
+      struct binding *new_binding =
+	(struct binding *) malloc (offsetof (struct binding, domainname) + len);
+
+      if (__builtin_expect (new_binding == NULL, 0))
+	goto failed;
+
+      memcpy (new_binding->domainname, domainname, len);
+
+      if (dirnamep)
+	{
+	  const char *dirname = *dirnamep;
+
+	  if (dirname == NULL)
+	    /* The default value.  */
+	    dirname = _nl_default_dirname;
+	  else
+	    {
+	      if (strcmp (dirname, _nl_default_dirname) == 0)
+		dirname = _nl_default_dirname;
+	      else
+		{
+		  char *result;
+#if defined _LIBC || defined HAVE_STRDUP
+		  result = strdup (dirname);
+		  if (__builtin_expect (result == NULL, 0))
+		    goto failed_dirname;
+#else
+		  size_t len = strlen (dirname) + 1;
+		  result = (char *) malloc (len);
+		  if (__builtin_expect (result == NULL, 0))
+		    goto failed_dirname;
+		  memcpy (result, dirname, len);
+#endif
+		  dirname = result;
+		}
+	    }
+	  *dirnamep = dirname;
+	  new_binding->dirname = (char *) dirname;
+	}
+      else
+	/* The default value.  */
+	new_binding->dirname = (char *) _nl_default_dirname;
+
+      new_binding->codeset_cntr = 0;
+
+      if (codesetp)
+	{
+	  const char *codeset = *codesetp;
+
+	  if (codeset != NULL)
+	    {
+	      char *result;
+
+#if defined _LIBC || defined HAVE_STRDUP
+	      result = strdup (codeset);
+	      if (__builtin_expect (result == NULL, 0))
+		goto failed_codeset;
+#else
+	      size_t len = strlen (codeset) + 1;
+	      result = (char *) malloc (len);
+	      if (__builtin_expect (result == NULL, 0))
+		goto failed_codeset;
+	      memcpy (result, codeset, len);
+#endif
+	      codeset = result;
+	      ++new_binding->codeset_cntr;
+	    }
+	  *codesetp = codeset;
+	  new_binding->codeset = (char *) codeset;
+	}
+      else
+	new_binding->codeset = NULL;
+
+      /* Now enqueue it.  */
+      if (_nl_domain_bindings == NULL
+	  || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
+	{
+	  new_binding->next = _nl_domain_bindings;
+	  _nl_domain_bindings = new_binding;
+	}
+      else
+	{
+	  binding = _nl_domain_bindings;
+	  while (binding->next != NULL
+		 && strcmp (domainname, binding->next->domainname) > 0)
+	    binding = binding->next;
+
+	  new_binding->next = binding->next;
+	  binding->next = new_binding;
+	}
+
+      modified = 1;
+
+      /* Here we deal with memory allocation failures.  */
+      if (0)
+	{
+	failed_codeset:
+	  if (new_binding->dirname != _nl_default_dirname)
+	    free (new_binding->dirname);
+	failed_dirname:
+	  free (new_binding);
+	failed:
+	  if (dirnamep)
+	    *dirnamep = NULL;
+	  if (codesetp)
+	    *codesetp = NULL;
+	}
+    }
+
+  /* If we modified any binding, we flush the caches.  */
+  if (modified)
+    ++_nl_msg_cat_cntr;
+
+  __libc_rwlock_unlock (_nl_state_lock);
+}
+
+/* Specify that the DOMAINNAME message catalog will be found
+   in DIRNAME rather than in the system locale data base.  */
+char *
+BINDTEXTDOMAIN (domainname, dirname)
+     const char *domainname;
+     const char *dirname;
+{
+  set_binding_values (domainname, &dirname, NULL);
+  return (char *) dirname;
+}
+
+/* Specify the character encoding in which the messages from the
+   DOMAINNAME message catalog will be returned.  */
+char *
+BIND_TEXTDOMAIN_CODESET (domainname, codeset)
+     const char *domainname;
+     const char *codeset;
+{
+  set_binding_values (domainname, NULL, &codeset);
+  return (char *) codeset;
+}
+
+#ifdef _LIBC
+/* Aliases for function names in GNU C Library.  */
+weak_alias (__bindtextdomain, bindtextdomain);
+weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
+#endif
Index: /trunk/libc/src/glibc/intl/dcgettext.c
===================================================================
--- /trunk/libc/src/glibc/intl/dcgettext.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/dcgettext.c	(revision 2448)
@@ -0,0 +1,60 @@
+/* Implementation of the dcgettext(3) function.
+   Copyright (C) 1995-1999, 2000, 2001, 2002 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
+
+#include "gettextP.h"
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define DCGETTEXT __dcgettext
+# define DCIGETTEXT __dcigettext
+#else
+# define DCGETTEXT libintl_dcgettext
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+   locale.  */
+char *
+DCGETTEXT (domainname, msgid, category)
+     const char *domainname;
+     const char *msgid;
+     int category;
+{
+  return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+INTDEF(__dcgettext)
+weak_alias (__dcgettext, dcgettext);
+#endif
Index: /trunk/libc/src/glibc/intl/dcigettext.c
===================================================================
--- /trunk/libc/src/glibc/intl/dcigettext.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/dcigettext.c	(revision 2448)
@@ -0,0 +1,1209 @@
+/* Implementation of the internal dcigettext function.
+   Copyright (C) 1995-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., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include <locale.h>
+
+#if defined HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+
+#include "gettextP.h"
+#include "plural-exp.h"
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "hash-string.h"
+
+/* Thread safetyness.  */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_lock_define_initialized(CLASS, NAME)
+# define __libc_lock_lock(NAME)
+# define __libc_lock_unlock(NAME)
+# define __libc_rwlock_define_initialized(CLASS, NAME)
+# define __libc_rwlock_rdlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+# define __libc_rwlock_wrlock(NAME)
+#endif
+
+/* Alignment of types.  */
+#if defined __GNUC__ && __GNUC__ >= 2
+# define alignof(TYPE) __alignof__ (TYPE)
+#else
+# define alignof(TYPE) \
+    ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
+#endif
+
+/* The internal variables in the standalone libintl.a must have different
+   names than the internal variables in GNU libc, otherwise programs
+   using libintl.a cannot be linked statically.  */
+#if !defined(_LIBC) && !defined(IN_INNOTEK_LIBC)
+# define _nl_default_default_domain libintl_nl_default_default_domain
+# define _nl_current_default_domain libintl_nl_current_default_domain
+# define _nl_default_dirname libintl_nl_default_dirname
+# define _nl_domain_bindings libintl_nl_domain_bindings
+#endif
+
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions.  This is required by the standard
+   because some ANSI C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# define getcwd __getcwd
+# ifndef stpcpy
+#  define stpcpy __stpcpy
+# endif
+# define tfind __tfind
+#else
+# if !defined HAVE_GETCWD
+char *getwd ();
+#  define getcwd(buf, max) getwd (buf)
+# else
+char *getcwd ();
+# endif
+# ifndef HAVE_STPCPY
+static char *stpcpy PARAMS ((char *dest, const char *src));
+# endif
+# ifndef HAVE_MEMPCPY
+static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
+# endif
+#endif
+
+/* Amount to increase buffer size by in each try.  */
+#define PATH_INCR 32
+
+/* The following is from pathmax.h.  */
+/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
+   PATH_MAX but might cause redefinition warnings when sys/param.h is
+   later included (as on MORE/BSD 4.3).  */
+#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
+# include <limits.h>
+#endif
+
+#ifndef _POSIX_PATH_MAX
+# define _POSIX_PATH_MAX 255
+#endif
+
+#if !defined PATH_MAX && defined _PC_PATH_MAX
+# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
+#endif
+
+/* Don't include sys/param.h if it already has been.  */
+#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
+# include <sys/param.h>
+#endif
+
+#if !defined PATH_MAX && defined MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+/* Pathname support.
+   ISSLASH(C)           tests whether C is a directory separator character.
+   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
+                        it may be concatenated to a directory pathname.
+   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+     && (P)[1] == ':')
+# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
+# define IS_PATH_WITH_DIR(P) \
+    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+#else
+  /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+#endif
+
+/* This is the type used for the search tree where known translations
+   are stored.  */
+struct known_translation_t
+{
+  /* Domain in which to search.  */
+  char *domainname;
+
+  /* The category.  */
+  int category;
+
+  /* State of the catalog counter at the point the string was found.  */
+  int counter;
+
+  /* Catalog where the string was found.  */
+  struct loaded_l10nfile *domain;
+
+  /* And finally the translation.  */
+  const char *translation;
+  size_t translation_length;
+
+  /* Pointer to the string in question.  */
+  char msgid[ZERO];
+};
+
+/* Root of the search tree with known translations.  We can use this
+   only if the system provides the `tsearch' function family.  */
+#if defined HAVE_TSEARCH || defined _LIBC
+# include <search.h>
+
+static void *root;
+
+# ifdef _LIBC
+#  define tsearch __tsearch
+# endif
+
+/* Function to compare two entries in the table of known translations.  */
+static int transcmp PARAMS ((const void *p1, const void *p2));
+static int
+transcmp (p1, p2)
+     const void *p1;
+     const void *p2;
+{
+  const struct known_translation_t *s1;
+  const struct known_translation_t *s2;
+  int result;
+
+  s1 = (const struct known_translation_t *) p1;
+  s2 = (const struct known_translation_t *) p2;
+
+  result = strcmp (s1->msgid, s2->msgid);
+  if (result == 0)
+    {
+      result = strcmp (s1->domainname, s2->domainname);
+      if (result == 0)
+	/* We compare the category last (though this is the cheapest
+	   operation) since it is hopefully always the same (namely
+	   LC_MESSAGES).  */
+	result = s1->category - s2->category;
+    }
+
+  return result;
+}
+#endif
+
+/* Name of the default domain used for gettext(3) prior any call to
+   textdomain(3).  The default value for this is "messages".  */
+const char _nl_default_default_domain[] attribute_hidden = "messages";
+
+/* Value used as the default domain for gettext(3).  */
+const char *_nl_current_default_domain attribute_hidden
+     = _nl_default_default_domain;
+
+/* Contains the default location of the message catalogs.  */
+
+#ifdef _LIBC
+extern const char _nl_default_dirname[];
+libc_hidden_proto (_nl_default_dirname)
+#endif
+const char _nl_default_dirname[] = LOCALEDIR;
+#ifdef _LIBC
+libc_hidden_data_def (_nl_default_dirname)
+#endif
+
+/* List with bindings of specific domains created by bindtextdomain()
+   calls.  */
+struct binding *_nl_domain_bindings;
+
+/* Prototypes for local functions.  */
+static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
+				    unsigned long int n,
+				    const char *translation,
+				    size_t translation_len))
+     internal_function;
+static const char *guess_category_value PARAMS ((int category,
+						 const char *categoryname))
+     internal_function;
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# define category_to_name(category)	_nl_category_names[category]
+#else
+static const char *category_to_name PARAMS ((int category)) internal_function;
+#endif
+
+
+/* For those loosing systems which don't have `alloca' we have to add
+   some additional code emulating it.  */
+#ifdef HAVE_ALLOCA
+/* Nothing has to be done.  */
+# define freea(p) /* nothing */
+# define ADD_BLOCK(list, address) /* nothing */
+# define FREE_BLOCKS(list) /* nothing */
+#else
+struct block_list
+{
+  void *address;
+  struct block_list *next;
+};
+# define ADD_BLOCK(list, addr)						      \
+  do {									      \
+    struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
+    /* If we cannot get a free block we cannot add the new element to	      \
+       the list.  */							      \
+    if (newp != NULL) {							      \
+      newp->address = (addr);						      \
+      newp->next = (list);						      \
+      (list) = newp;							      \
+    }									      \
+  } while (0)
+# define FREE_BLOCKS(list)						      \
+  do {									      \
+    while (list != NULL) {						      \
+      struct block_list *old = list;					      \
+      list = list->next;						      \
+      free (old->address);						      \
+      free (old);							      \
+    }									      \
+  } while (0)
+# undef alloca
+# define alloca(size) (malloc (size))
+# define freea(p) free (p)
+#endif	/* have alloca */
+
+
+#ifdef _LIBC
+/* List of blocks allocated for translations.  */
+typedef struct transmem_list
+{
+  struct transmem_list *next;
+  char data[ZERO];
+} transmem_block_t;
+static struct transmem_list *transmem_list;
+#else
+typedef unsigned char transmem_block_t;
+#endif
+
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define DCIGETTEXT __dcigettext
+#else
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Lock variable to protect the global data in the gettext implementation.  */
+#ifdef _LIBC
+__libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
+#endif
+
+/* Checking whether the binaries runs SUID must be done and glibc provides
+   easier methods therefore we make a difference here.  */
+#ifdef _LIBC
+# define ENABLE_SECURE __libc_enable_secure
+# define DETERMINE_SECURE
+#else
+# ifndef HAVE_GETUID
+#  define getuid() 0
+# endif
+# ifndef HAVE_GETGID
+#  define getgid() 0
+# endif
+# ifndef HAVE_GETEUID
+#  define geteuid() getuid()
+# endif
+# ifndef HAVE_GETEGID
+#  define getegid() getgid()
+# endif
+static int enable_secure;
+# define ENABLE_SECURE (enable_secure == 1)
+# define DETERMINE_SECURE \
+  if (enable_secure == 0)						      \
+    {									      \
+      if (getuid () != geteuid () || getgid () != getegid ())		      \
+	enable_secure = 1;						      \
+      else								      \
+	enable_secure = -1;						      \
+    }
+#endif
+
+/* Get the function to evaluate the plural expression.  */
+#include "plural-eval.c"
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+   CATEGORY locale and, if PLURAL is nonzero, search over string
+   depending on the plural form determined by N.  */
+char *
+DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     int plural;
+     unsigned long int n;
+     int category;
+{
+#ifndef HAVE_ALLOCA
+  struct block_list *block_list = NULL;
+#endif
+  struct loaded_l10nfile *domain;
+  struct binding *binding;
+  const char *categoryname;
+  const char *categoryvalue;
+  char *dirname, *xdomainname;
+  char *single_locale;
+  char *retval;
+  size_t retlen;
+  int saved_errno;
+#if defined HAVE_TSEARCH || defined _LIBC
+  struct known_translation_t *search;
+  struct known_translation_t **foundp = NULL;
+  size_t msgid_len;
+#endif
+  size_t domainname_len;
+
+  /* If no real MSGID is given return NULL.  */
+  if (msgid1 == NULL)
+    return NULL;
+
+#ifdef _LIBC
+  if (category < 0 || category >= __LC_LAST || category == LC_ALL)
+    /* Bogus.  */
+    return (plural == 0
+	    ? (char *) msgid1
+	    /* Use the Germanic plural rule.  */
+	    : n == 1 ? (char *) msgid1 : (char *) msgid2);
+#endif
+
+  __libc_rwlock_rdlock (_nl_state_lock);
+
+  /* If DOMAINNAME is NULL, we are interested in the default domain.  If
+     CATEGORY is not LC_MESSAGES this might not make much sense but the
+     definition left this undefined.  */
+  if (domainname == NULL)
+    domainname = _nl_current_default_domain;
+
+#if defined HAVE_TSEARCH || defined _LIBC
+  msgid_len = strlen (msgid1) + 1;
+
+  /* Try to find the translation among those which we found at
+     some time.  */
+  search = (struct known_translation_t *)
+	   alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
+  memcpy (search->msgid, msgid1, msgid_len);
+  search->domainname = (char *) domainname;
+  search->category = category;
+
+  /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
+     tsearch calls can be fatal.  */
+  __libc_rwlock_define_initialized (static, tree_lock);
+  __libc_rwlock_rdlock (tree_lock);
+
+  foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
+
+  __libc_rwlock_unlock (tree_lock);
+
+  freea (search);
+  if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
+    {
+      /* Now deal with plural.  */
+      if (plural)
+	retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
+				(*foundp)->translation_length);
+      else
+	retval = (char *) (*foundp)->translation;
+
+      __libc_rwlock_unlock (_nl_state_lock);
+      return retval;
+    }
+#endif
+
+  /* Preserve the `errno' value.  */
+  saved_errno = errno;
+
+  /* See whether this is a SUID binary or not.  */
+  DETERMINE_SECURE;
+
+  /* First find matching binding.  */
+  for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
+    {
+      int compare = strcmp (domainname, binding->domainname);
+      if (compare == 0)
+	/* We found it!  */
+	break;
+      if (compare < 0)
+	{
+	  /* It is not in the list.  */
+	  binding = NULL;
+	  break;
+	}
+    }
+
+  if (binding == NULL)
+    dirname = (char *) _nl_default_dirname;
+  else if (IS_ABSOLUTE_PATH(binding->dirname))
+    dirname = binding->dirname;
+  else
+    {
+      /* We have a relative path.  Make it absolute now.  */
+      size_t dirname_len = strlen (binding->dirname) + 1;
+      size_t path_max;
+      char *ret;
+
+      path_max = (unsigned int) PATH_MAX;
+      path_max += 2;		/* The getcwd docs say to do this.  */
+
+      for (;;)
+	{
+	  dirname = (char *) alloca (path_max + dirname_len);
+	  ADD_BLOCK (block_list, dirname);
+
+	  __set_errno (0);
+	  ret = getcwd (dirname, path_max);
+	  if (ret != NULL || errno != ERANGE)
+	    break;
+
+	  path_max += path_max / 2;
+	  path_max += PATH_INCR;
+	}
+
+      if (ret == NULL)
+	{
+	  /* We cannot get the current working directory.  Don't signal an
+	     error but simply return the default string.  */
+	  FREE_BLOCKS (block_list);
+	  __libc_rwlock_unlock (_nl_state_lock);
+	  __set_errno (saved_errno);
+	  return (plural == 0
+		  ? (char *) msgid1
+		  /* Use the Germanic plural rule.  */
+		  : n == 1 ? (char *) msgid1 : (char *) msgid2);
+	}
+
+      stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
+    }
+
+  /* Now determine the symbolic name of CATEGORY and its value.  */
+  categoryname = category_to_name (category);
+  categoryvalue = guess_category_value (category, categoryname);
+
+  domainname_len = strlen (domainname);
+  xdomainname = (char *) alloca (strlen (categoryname)
+				 + domainname_len + 5);
+  ADD_BLOCK (block_list, xdomainname);
+
+  stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
+		  domainname, domainname_len),
+	  ".mo");
+
+  /* Creating working area.  */
+  single_locale = (char *) alloca (strlen (categoryvalue) + 1);
+  ADD_BLOCK (block_list, single_locale);
+
+
+  /* Search for the given string.  This is a loop because we perhaps
+     got an ordered list of languages to consider for the translation.  */
+  while (1)
+    {
+      /* Make CATEGORYVALUE point to the next element of the list.  */
+      while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
+	++categoryvalue;
+      if (categoryvalue[0] == '\0')
+	{
+	  /* The whole contents of CATEGORYVALUE has been searched but
+	     no valid entry has been found.  We solve this situation
+	     by implicitly appending a "C" entry, i.e. no translation
+	     will take place.  */
+	  single_locale[0] = 'C';
+	  single_locale[1] = '\0';
+	}
+      else
+	{
+	  char *cp = single_locale;
+	  while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
+	    *cp++ = *categoryvalue++;
+	  *cp = '\0';
+
+	  /* When this is a SUID binary we must not allow accessing files
+	     outside the dedicated directories.  */
+	  if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
+	    /* Ingore this entry.  */
+	    continue;
+	}
+
+      /* If the current locale value is C (or POSIX) we don't load a
+	 domain.  Return the MSGID.  */
+      if (strcmp (single_locale, "C") == 0
+	  || strcmp (single_locale, "POSIX") == 0)
+	{
+	  FREE_BLOCKS (block_list);
+	  __libc_rwlock_unlock (_nl_state_lock);
+	  __set_errno (saved_errno);
+	  return (plural == 0
+		  ? (char *) msgid1
+		  /* Use the Germanic plural rule.  */
+		  : n == 1 ? (char *) msgid1 : (char *) msgid2);
+	}
+
+
+      /* Find structure describing the message catalog matching the
+	 DOMAINNAME and CATEGORY.  */
+      domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
+
+      if (domain != NULL)
+	{
+	  retval = _nl_find_msg (domain, binding, msgid1, &retlen);
+
+	  if (retval == NULL)
+	    {
+	      int cnt;
+
+	      for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
+		{
+		  retval = _nl_find_msg (domain->successor[cnt], binding,
+					 msgid1, &retlen);
+
+		  if (retval != NULL)
+		    {
+		      domain = domain->successor[cnt];
+		      break;
+		    }
+		}
+	    }
+
+	  if (retval != NULL)
+	    {
+	      /* Found the translation of MSGID1 in domain DOMAIN:
+		 starting at RETVAL, RETLEN bytes.  */
+	      FREE_BLOCKS (block_list);
+#if defined HAVE_TSEARCH || defined _LIBC
+	      if (foundp == NULL)
+		{
+		  /* Create a new entry and add it to the search tree.  */
+		  struct known_translation_t *newp;
+
+		  newp = (struct known_translation_t *)
+		    malloc (offsetof (struct known_translation_t, msgid)
+			    + msgid_len + domainname_len + 1);
+		  if (newp != NULL)
+		    {
+		      newp->domainname =
+			mempcpy (newp->msgid, msgid1, msgid_len);
+		      memcpy (newp->domainname, domainname, domainname_len + 1);
+		      newp->category = category;
+		      newp->counter = _nl_msg_cat_cntr;
+		      newp->domain = domain;
+		      newp->translation = retval;
+		      newp->translation_length = retlen;
+
+		      __libc_rwlock_wrlock (tree_lock);
+
+		      /* Insert the entry in the search tree.  */
+		      foundp = (struct known_translation_t **)
+			tsearch (newp, &root, transcmp);
+
+		      __libc_rwlock_unlock (tree_lock);
+
+		      if (foundp == NULL
+			  || __builtin_expect (*foundp != newp, 0))
+			/* The insert failed.  */
+			free (newp);
+		    }
+		}
+	      else
+		{
+		  /* We can update the existing entry.  */
+		  (*foundp)->counter = _nl_msg_cat_cntr;
+		  (*foundp)->domain = domain;
+		  (*foundp)->translation = retval;
+		  (*foundp)->translation_length = retlen;
+		}
+#endif
+	      __set_errno (saved_errno);
+
+	      /* Now deal with plural.  */
+	      if (plural)
+		retval = plural_lookup (domain, n, retval, retlen);
+
+	      __libc_rwlock_unlock (_nl_state_lock);
+	      return retval;
+	    }
+	}
+    }
+  /* NOTREACHED */
+}
+
+
+char *
+internal_function
+_nl_find_msg (domain_file, domainbinding, msgid, lengthp)
+     struct loaded_l10nfile *domain_file;
+     struct binding *domainbinding;
+     const char *msgid;
+     size_t *lengthp;
+{
+  struct loaded_domain *domain;
+  nls_uint32 nstrings;
+  size_t act;
+  char *result;
+  size_t resultlen;
+
+  if (domain_file->decided <= 0)
+    _nl_load_domain (domain_file, domainbinding);
+
+  if (domain_file->data == NULL)
+    return NULL;
+
+  domain = (struct loaded_domain *) domain_file->data;
+
+  nstrings = domain->nstrings;
+
+  /* Locate the MSGID and its translation.  */
+  if (domain->hash_tab != NULL)
+    {
+      /* Use the hashing table.  */
+      nls_uint32 len = strlen (msgid);
+      nls_uint32 hash_val = __hash_string (msgid);
+      nls_uint32 idx = hash_val % domain->hash_size;
+      nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
+
+      while (1)
+	{
+	  nls_uint32 nstr =
+	    W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
+
+	  if (nstr == 0)
+	    /* Hash table entry is empty.  */
+	    return NULL;
+
+	  nstr--;
+
+	  /* Compare msgid with the original string at index nstr.
+	     We compare the lengths with >=, not ==, because plural entries
+	     are represented by strings with an embedded NUL.  */
+	  if (nstr < nstrings
+	      ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
+		&& (strcmp (msgid,
+			    domain->data + W (domain->must_swap,
+					      domain->orig_tab[nstr].offset))
+		    == 0)
+	      : domain->orig_sysdep_tab[nstr - nstrings].length > len
+		&& (strcmp (msgid,
+			    domain->orig_sysdep_tab[nstr - nstrings].pointer)
+		    == 0))
+	    {
+	      act = nstr;
+	      goto found;
+	    }
+
+	  if (idx >= domain->hash_size - incr)
+	    idx -= domain->hash_size - incr;
+	  else
+	    idx += incr;
+	}
+      /* NOTREACHED */
+    }
+  else
+    {
+      /* Try the default method:  binary search in the sorted array of
+	 messages.  */
+      size_t top, bottom;
+
+      bottom = 0;
+      top = nstrings;
+      while (bottom < top)
+	{
+	  int cmp_val;
+
+	  act = (bottom + top) / 2;
+	  cmp_val = strcmp (msgid, (domain->data
+				    + W (domain->must_swap,
+					 domain->orig_tab[act].offset)));
+	  if (cmp_val < 0)
+	    top = act;
+	  else if (cmp_val > 0)
+	    bottom = act + 1;
+	  else
+	    goto found;
+	}
+      /* No translation was found.  */
+      return NULL;
+    }
+
+ found:
+  /* The translation was found at index ACT.  If we have to convert the
+     string to use a different character set, this is the time.  */
+  if (act < nstrings)
+    {
+      result = (char *)
+	(domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
+      resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
+    }
+  else
+    {
+      result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
+      resultlen = domain->trans_sysdep_tab[act - nstrings].length;
+    }
+
+#if defined _LIBC || HAVE_ICONV
+  if (domain->codeset_cntr
+      != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
+    {
+      /* The domain's codeset has changed through bind_textdomain_codeset()
+	 since the message catalog was initialized or last accessed.  We
+	 have to reinitialize the converter.  */
+      _nl_free_domain_conv (domain);
+      _nl_init_domain_conv (domain_file, domain, domainbinding);
+    }
+
+  if (
+# ifdef _LIBC
+      domain->conv != (__gconv_t) -1
+# else
+#  if HAVE_ICONV
+      domain->conv != (iconv_t) -1
+#  endif
+# endif
+      )
+    {
+      /* We are supposed to do a conversion.  First allocate an
+	 appropriate table with the same structure as the table
+	 of translations in the file, where we can put the pointers
+	 to the converted strings in.
+	 There is a slight complication with plural entries.  They
+	 are represented by consecutive NUL terminated strings.  We
+	 handle this case by converting RESULTLEN bytes, including
+	 NULs.  */
+
+      if (domain->conv_tab == NULL
+	  && ((domain->conv_tab =
+		 (char **) calloc (nstrings + domain->n_sysdep_strings,
+				   sizeof (char *)))
+	      == NULL))
+	/* Mark that we didn't succeed allocating a table.  */
+	domain->conv_tab = (char **) -1;
+
+      if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
+	/* Nothing we can do, no more memory.  */
+	goto converted;
+
+      if (domain->conv_tab[act] == NULL)
+	{
+	  /* We haven't used this string so far, so it is not
+	     translated yet.  Do this now.  */
+	  /* We use a bit more efficient memory handling.
+	     We allocate always larger blocks which get used over
+	     time.  This is faster than many small allocations.   */
+	  __libc_lock_define_initialized (static, lock)
+# define INITIAL_BLOCK_SIZE	4080
+	  static unsigned char *freemem;
+	  static size_t freemem_size;
+
+	  const unsigned char *inbuf;
+	  unsigned char *outbuf;
+	  int malloc_count;
+# ifndef _LIBC
+	  transmem_block_t *transmem_list = NULL;
+# endif
+
+	  __libc_lock_lock (lock);
+
+	  inbuf = (const unsigned char *) result;
+	  outbuf = freemem + sizeof (size_t);
+
+	  malloc_count = 0;
+	  while (1)
+	    {
+	      transmem_block_t *newmem;
+# ifdef _LIBC
+	      size_t non_reversible;
+	      int res;
+
+	      if (freemem_size < sizeof (size_t))
+		goto resize_freemem;
+
+	      res = __gconv (domain->conv,
+			     &inbuf, inbuf + resultlen,
+			     &outbuf,
+			     outbuf + freemem_size - sizeof (size_t),
+			     &non_reversible);
+
+	      if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
+		break;
+
+	      if (res != __GCONV_FULL_OUTPUT)
+		{
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+
+	      inbuf = (const unsigned char *) result;
+# else
+#  if HAVE_ICONV
+	      const char *inptr = (const char *) inbuf;
+	      size_t inleft = resultlen;
+	      char *outptr = (char *) outbuf;
+	      size_t outleft;
+
+	      if (freemem_size < sizeof (size_t))
+		goto resize_freemem;
+
+	      outleft = freemem_size - sizeof (size_t);
+	      if (iconv (domain->conv,
+			 (ICONV_CONST char **) &inptr, &inleft,
+			 &outptr, &outleft)
+		  != (size_t) (-1))
+		{
+		  outbuf = (unsigned char *) outptr;
+		  break;
+		}
+	      if (errno != E2BIG)
+		{
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+#  endif
+# endif
+
+	    resize_freemem:
+	      /* We must allocate a new buffer or resize the old one.  */
+	      if (malloc_count > 0)
+		{
+		  ++malloc_count;
+		  freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
+		  newmem = (transmem_block_t *) realloc (transmem_list,
+							 freemem_size);
+# ifdef _LIBC
+		  if (newmem != NULL)
+		    transmem_list = transmem_list->next;
+		  else
+		    {
+		      struct transmem_list *old = transmem_list;
+
+		      transmem_list = transmem_list->next;
+		      free (old);
+		    }
+# endif
+		}
+	      else
+		{
+		  malloc_count = 1;
+		  freemem_size = INITIAL_BLOCK_SIZE;
+		  newmem = (transmem_block_t *) malloc (freemem_size);
+		}
+	      if (__builtin_expect (newmem == NULL, 0))
+		{
+		  freemem = NULL;
+		  freemem_size = 0;
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+
+# ifdef _LIBC
+	      /* Add the block to the list of blocks we have to free
+                 at some point.  */
+	      newmem->next = transmem_list;
+	      transmem_list = newmem;
+
+	      freemem = (unsigned char *) newmem->data;
+	      freemem_size -= offsetof (struct transmem_list, data);
+# else
+	      transmem_list = newmem;
+	      freemem = newmem;
+# endif
+
+	      outbuf = freemem + sizeof (size_t);
+	    }
+
+	  /* We have now in our buffer a converted string.  Put this
+	     into the table of conversions.  */
+	  *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
+	  domain->conv_tab[act] = (char *) freemem;
+	  /* Shrink freemem, but keep it aligned.  */
+	  freemem_size -= outbuf - freemem;
+	  freemem = outbuf;
+	  freemem += freemem_size & (alignof (size_t) - 1);
+	  freemem_size = freemem_size & ~ (alignof (size_t) - 1);
+
+	  __libc_lock_unlock (lock);
+	}
+
+      /* Now domain->conv_tab[act] contains the translation of all
+	 the plural variants.  */
+      result = domain->conv_tab[act] + sizeof (size_t);
+      resultlen = *(size_t *) domain->conv_tab[act];
+    }
+
+ converted:
+  /* The result string is converted.  */
+
+#endif /* _LIBC || HAVE_ICONV */
+
+  *lengthp = resultlen;
+  return result;
+}
+
+
+/* Look up a plural variant.  */
+static char *
+internal_function
+plural_lookup (domain, n, translation, translation_len)
+     struct loaded_l10nfile *domain;
+     unsigned long int n;
+     const char *translation;
+     size_t translation_len;
+{
+  struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
+  unsigned long int index;
+  const char *p;
+
+  index = plural_eval (domaindata->plural, n);
+  if (index >= domaindata->nplurals)
+    /* This should never happen.  It means the plural expression and the
+       given maximum value do not match.  */
+    index = 0;
+
+  /* Skip INDEX strings at TRANSLATION.  */
+  p = translation;
+  while (index-- > 0)
+    {
+#ifdef _LIBC
+      p = __rawmemchr (p, '\0');
+#else
+      p = strchr (p, '\0');
+#endif
+      /* And skip over the NUL byte.  */
+      p++;
+
+      if (p >= translation + translation_len)
+	/* This should never happen.  It means the plural expression
+	   evaluated to a value larger than the number of variants
+	   available for MSGID1.  */
+	return (char *) translation;
+    }
+  return (char *) p;
+}
+
+#ifndef _LIBC
+/* Return string representation of locale CATEGORY.  */
+static const char *
+internal_function
+category_to_name (category)
+     int category;
+{
+  const char *retval;
+
+  switch (category)
+  {
+#ifdef LC_COLLATE
+  case LC_COLLATE:
+    retval = "LC_COLLATE";
+    break;
+#endif
+#ifdef LC_CTYPE
+  case LC_CTYPE:
+    retval = "LC_CTYPE";
+    break;
+#endif
+#ifdef LC_MONETARY
+  case LC_MONETARY:
+    retval = "LC_MONETARY";
+    break;
+#endif
+#ifdef LC_NUMERIC
+  case LC_NUMERIC:
+    retval = "LC_NUMERIC";
+    break;
+#endif
+#ifdef LC_TIME
+  case LC_TIME:
+    retval = "LC_TIME";
+    break;
+#endif
+#ifdef LC_MESSAGES
+  case LC_MESSAGES:
+    retval = "LC_MESSAGES";
+    break;
+#endif
+#ifdef LC_RESPONSE
+  case LC_RESPONSE:
+    retval = "LC_RESPONSE";
+    break;
+#endif
+#ifdef LC_ALL
+  case LC_ALL:
+    /* This might not make sense but is perhaps better than any other
+       value.  */
+    retval = "LC_ALL";
+    break;
+#endif
+  default:
+    /* If you have a better idea for a default value let me know.  */
+    retval = "LC_XXX";
+  }
+
+  return retval;
+}
+#endif
+
+/* Guess value of current locale from value of the environment variables.  */
+static const char *
+internal_function
+guess_category_value (category, categoryname)
+     int category;
+     const char *categoryname;
+{
+  const char *language;
+  const char *retval;
+
+  /* The highest priority value is the `LANGUAGE' environment
+     variable.  But we don't use the value if the currently selected
+     locale is the C locale.  This is a GNU extension.  */
+  language = getenv ("LANGUAGE");
+  if (language != NULL && language[0] == '\0')
+    language = NULL;
+
+  /* We have to proceed with the POSIX methods of looking to `LC_ALL',
+     `LC_xxx', and `LANG'.  On some systems this can be done by the
+     `setlocale' function itself.  */
+#ifdef _LIBC
+  retval = __current_locale_name (category);
+#else
+  retval = _nl_locale_name (category, categoryname);
+#endif
+
+  return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
+}
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library.  So we
+   avoid the non-standard function stpcpy.  In GNU C Library this
+   function is available, though.  Also allow the symbol HAVE_STPCPY
+   to be defined.  */
+#if (!defined(_LIBC) || !_LIBC) && !HAVE_STPCPY
+static char *
+stpcpy (dest, src)
+     char *dest;
+     const char *src;
+{
+  while ((*dest++ = *src++) != '\0')
+    /* Do nothing. */ ;
+  return dest - 1;
+}
+#endif
+
+#if (!defined(_LIBC) || !_LIBC) && !HAVE_MEMPCPY
+static void *
+mempcpy (dest, src, n)
+     void *dest;
+     const void *src;
+     size_t n;
+{
+  return (void *) ((char *) memcpy (dest, src, n) + n);
+}
+#endif
+
+
+#ifdef _LIBC
+/* If we want to free all resources we have to do some work at
+   program's end.  */
+libc_freeres_fn (free_mem)
+{
+  void *old;
+
+  while (_nl_domain_bindings != NULL)
+    {
+      struct binding *oldp = _nl_domain_bindings;
+      _nl_domain_bindings = _nl_domain_bindings->next;
+      if (oldp->dirname != _nl_default_dirname)
+	/* Yes, this is a pointer comparison.  */
+	free (oldp->dirname);
+      free (oldp->codeset);
+      free (oldp);
+    }
+
+  if (_nl_current_default_domain != _nl_default_default_domain)
+    /* Yes, again a pointer comparison.  */
+    free ((char *) _nl_current_default_domain);
+
+  /* Remove the search tree with the known translations.  */
+  __tdestroy (root, free);
+  root = NULL;
+
+  while (transmem_list != NULL)
+    {
+      old = transmem_list;
+      transmem_list = transmem_list->next;
+      free (old);
+    }
+}
+#endif
Index: /trunk/libc/src/glibc/intl/dcngettext.c
===================================================================
--- /trunk/libc/src/glibc/intl/dcngettext.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/dcngettext.c	(revision 2448)
@@ -0,0 +1,61 @@
+/* Implementation of the dcngettext(3) function.
+   Copyright (C) 1995-1999, 2000, 2001, 2002 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
+
+#include "gettextP.h"
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define DCNGETTEXT __dcngettext
+# define DCIGETTEXT __dcigettext
+#else
+# define DCNGETTEXT libintl_dcngettext
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+   locale.  */
+char *
+DCNGETTEXT (domainname, msgid1, msgid2, n, category)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+     int category;
+{
+  return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__dcngettext, dcngettext);
+#endif
Index: /trunk/libc/src/glibc/intl/dgettext.c
===================================================================
--- /trunk/libc/src/glibc/intl/dgettext.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/dgettext.c	(revision 2448)
@@ -0,0 +1,60 @@
+/* Implementation of the dgettext(3) function.
+   Copyright (C) 1995-1997, 2000, 2001, 2002 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
+
+#include <locale.h>
+
+#include "gettextP.h"
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define DGETTEXT __dgettext
+# define DCGETTEXT INTUSE(__dcgettext)
+#else
+# define DGETTEXT libintl_dgettext
+# define DCGETTEXT libintl_dcgettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog of the current
+   LC_MESSAGES locale.  */
+char *
+DGETTEXT (domainname, msgid)
+     const char *domainname;
+     const char *msgid;
+{
+  return DCGETTEXT (domainname, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__dgettext, dgettext);
+#endif
Index: /trunk/libc/src/glibc/intl/dngettext.c
===================================================================
--- /trunk/libc/src/glibc/intl/dngettext.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/dngettext.c	(revision 2448)
@@ -0,0 +1,62 @@
+/* Implementation of the dngettext(3) function.
+   Copyright (C) 1995-1997, 2000, 2001, 2002 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
+
+#include <locale.h>
+
+#include "gettextP.h"
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define DNGETTEXT __dngettext
+# define DCNGETTEXT __dcngettext
+#else
+# define DNGETTEXT libintl_dngettext
+# define DCNGETTEXT libintl_dcngettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog of the current
+   LC_MESSAGES locale and skip message according to the plural form.  */
+char *
+DNGETTEXT (domainname, msgid1, msgid2, n)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+{
+  return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__dngettext, dngettext);
+#endif
Index: /trunk/libc/src/glibc/intl/explodename.c
===================================================================
--- /trunk/libc/src/glibc/intl/explodename.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/explodename.c	(revision 2448)
@@ -0,0 +1,136 @@
+/* Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+   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 <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "loadinfo.h"
+
+/* On some strange systems still no definition of NULL is found.  Sigh!  */
+#ifndef NULL
+# if defined __STDC__ && __STDC__
+#  define NULL ((void *) 0)
+# else
+#  define NULL 0
+# endif
+#endif
+
+/* @@ end of prolog @@ */
+
+static char *_nl_find_language PARAMS ((const char *name));
+
+static char *
+_nl_find_language (name)
+     const char *name;
+{
+  while (name[0] != '\0' && name[0] != '_' && name[0] != '@' && name[0] != '.')
+    ++name;
+
+  return (char *) name;
+}
+
+
+int
+_nl_explode_name (name, language, modifier, territory, codeset,
+		  normalized_codeset)
+     char *name;
+     const char **language;
+     const char **modifier;
+     const char **territory;
+     const char **codeset;
+     const char **normalized_codeset;
+{
+  char *cp;
+  int mask;
+
+  *modifier = NULL;
+  *territory = NULL;
+  *codeset = NULL;
+  *normalized_codeset = NULL;
+
+  /* Now we determine the single parts of the locale name.  First
+     look for the language.  Termination symbols are `_', '.', and `@'.  */
+  mask = 0;
+  *language = cp = name;
+  cp = _nl_find_language (*language);
+
+  if (*language == cp)
+    /* This does not make sense: language has to be specified.  Use
+       this entry as it is without exploding.  Perhaps it is an alias.  */
+    cp = strchr (*language, '\0');
+  else if (cp[0] != '@')
+    {
+      if (cp[0] == '_')
+	{
+	  /* Next is the territory.  */
+	  cp[0] = '\0';
+	  *territory = ++cp;
+
+	  while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@')
+	    ++cp;
+
+	  mask |= XPG_TERRITORY;
+	}
+
+      if (cp[0] == '.')
+	{
+	  /* Next is the codeset.  */
+	  cp[0] = '\0';
+	  *codeset = ++cp;
+
+	  while (cp[0] != '\0' && cp[0] != '@')
+	    ++cp;
+
+	  mask |= XPG_CODESET;
+
+	  if (*codeset != cp && (*codeset)[0] != '\0')
+	    {
+	      *normalized_codeset = _nl_normalize_codeset (*codeset,
+							   cp - *codeset);
+	      if (strcmp (*codeset, *normalized_codeset) == 0)
+		free ((char *) *normalized_codeset);
+	      else
+		mask |= XPG_NORM_CODESET;
+	    }
+	}
+    }
+
+  if (cp[0] == '@')
+    {
+      /* Next is the modifier.  */
+      cp[0] = '\0';
+      *modifier = ++cp;
+
+      if (cp[0] != '\0')
+	mask |= XPG_MODIFIER;
+    }
+
+  if (*territory != NULL && (*territory)[0] == '\0')
+    mask &= ~XPG_TERRITORY;
+
+  if (*codeset != NULL && (*codeset)[0] == '\0')
+    mask &= ~XPG_CODESET;
+
+  return mask;
+}
Index: /trunk/libc/src/glibc/intl/finddomain.c
===================================================================
--- /trunk/libc/src/glibc/intl/finddomain.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/finddomain.c	(revision 2448)
@@ -0,0 +1,210 @@
+/* Handle list of needed message catalogs
+   Copyright (C) 1995-1999, 2000, 2001, 2002, 2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Ulrich Drepper <drepper@gnu.org>, 1995.
+
+   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 <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include "gettextP.h"
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#else
+# define __libc_rwlock_define_initialized(a,b)  do {} while (0)
+#define  __libc_rwlock_rdlock(l)                do {} while (0)
+#define  __libc_rwlock_wrlock(l)                do {} while (0)
+#define  __libc_rwlock_unlock(l)                do {} while (0)
+#endif
+
+/* @@ end of prolog @@ */
+/* List of already loaded domains.  */
+static struct loaded_l10nfile *_nl_loaded_domains;
+
+
+/* Return a data structure describing the message catalog described by
+   the DOMAINNAME and CATEGORY parameters with respect to the currently
+   established bindings.  */
+struct loaded_l10nfile *
+internal_function
+_nl_find_domain (dirname, locale, domainname, domainbinding)
+     const char *dirname;
+     char *locale;
+     const char *domainname;
+     struct binding *domainbinding;
+{
+  struct loaded_l10nfile *retval;
+  const char *language;
+  const char *modifier;
+  const char *territory;
+  const char *codeset;
+  const char *normalized_codeset;
+  const char *alias_value;
+  int mask;
+
+  /* LOCALE can consist of up to four recognized parts for the XPG syntax:
+
+		language[_territory[.codeset]][@modifier]
+
+     Beside the first part all of them are allowed to be missing.  If
+     the full specified locale is not found, the less specific one are
+     looked for.  The various parts will be stripped off according to
+     the following order:
+		(1) codeset
+		(2) normalized codeset
+		(3) territory
+		(4) modifier
+   */
+
+  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
+  __libc_rwlock_define_initialized (static, lock);
+  __libc_rwlock_rdlock (lock);
+
+  /* If we have already tested for this locale entry there has to
+     be one data set in the list of loaded domains.  */
+  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
+			       strlen (dirname) + 1, 0, locale, NULL, NULL,
+			       NULL, NULL, domainname, 0);
+  __libc_rwlock_unlock (lock);
+
+  if (retval != NULL)
+    {
+      /* We know something about this locale.  */
+      int cnt;
+
+      if (retval->decided <= 0)
+	_nl_load_domain (retval, domainbinding);
+
+      if (retval->data != NULL)
+	return retval;
+
+      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
+	{
+	  if (retval->successor[cnt]->decided <= 0)
+	    _nl_load_domain (retval->successor[cnt], domainbinding);
+
+	  if (retval->successor[cnt]->data != NULL)
+	    break;
+	}
+
+      return cnt >= 0 ? retval : NULL;
+      /* NOTREACHED */
+    }
+
+  /* See whether the locale value is an alias.  If yes its value
+     *overwrites* the alias name.  No test for the original value is
+     done.  */
+  alias_value = _nl_expand_alias (locale);
+  if (alias_value != NULL)
+    {
+#if defined _LIBC || defined HAVE_STRDUP
+      locale = strdup (alias_value);
+      if (locale == NULL)
+	return NULL;
+#else
+      size_t len = strlen (alias_value) + 1;
+      locale = (char *) malloc (len);
+      if (locale == NULL)
+	return NULL;
+
+      memcpy (locale, alias_value, len);
+#endif
+    }
+
+  /* Now we determine the single parts of the locale name.  First
+     look for the language.  Termination symbols are `_' and `@' if
+     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
+  mask = _nl_explode_name (locale, &language, &modifier, &territory,
+			   &codeset, &normalized_codeset);
+
+  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
+  __libc_rwlock_wrlock (lock);
+
+  /* Create all possible locale entries which might be interested in
+     generalization.  */
+  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
+			       strlen (dirname) + 1, mask, language, territory,
+			       codeset, normalized_codeset, modifier,
+			       domainname, 1);
+  __libc_rwlock_unlock (lock);
+
+  if (retval == NULL)
+    /* This means we are out of core.  */
+    return NULL;
+
+  if (retval->decided <= 0)
+    _nl_load_domain (retval, domainbinding);
+  if (retval->data == NULL)
+    {
+      int cnt;
+      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
+	{
+	  if (retval->successor[cnt]->decided <= 0)
+	    _nl_load_domain (retval->successor[cnt], domainbinding);
+	  if (retval->successor[cnt]->data != NULL)
+	    break;
+	}
+    }
+
+  /* The room for an alias was dynamically allocated.  Free it now.  */
+  if (alias_value != NULL)
+    free (locale);
+
+  /* The space for normalized_codeset is dynamically allocated.  Free it.  */
+  if (mask & XPG_NORM_CODESET)
+    free ((void *) normalized_codeset);
+
+  return retval;
+}
+
+
+#ifdef _LIBC
+/* This is called from iconv/gconv_db.c's free_mem, as locales must
+   be freed before freeing gconv steps arrays.  */
+void __libc_freeres_fn_section
+_nl_finddomain_subfreeres ()
+{
+  struct loaded_l10nfile *runp = _nl_loaded_domains;
+
+  while (runp != NULL)
+    {
+      struct loaded_l10nfile *here = runp;
+      if (runp->data != NULL)
+	_nl_unload_domain ((struct loaded_domain *) runp->data);
+      runp = runp->next;
+      free ((char *) here->filename);
+      free (here);
+    }
+}
+#endif
Index: /trunk/libc/src/glibc/intl/gettext.c
===================================================================
--- /trunk/libc/src/glibc/intl/gettext.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/gettext.c	(revision 2448)
@@ -0,0 +1,65 @@
+/* Implementation of gettext(3) function.
+   Copyright (C) 1995, 1997, 2000, 2001, 2002 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
+
+#ifdef _LIBC
+# define __need_NULL
+# include <stddef.h>
+#else
+# include <stdlib.h>		/* Just for NULL.  */
+#endif
+
+#include "gettextP.h"
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define GETTEXT __gettext
+# define DCGETTEXT INTUSE(__dcgettext)
+#else
+# define GETTEXT libintl_gettext
+# define DCGETTEXT libintl_dcgettext
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+   LC_MESSAGES locale.  If not found, returns MSGID itself (the default
+   text).  */
+char *
+GETTEXT (msgid)
+     const char *msgid;
+{
+  return DCGETTEXT (NULL, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__gettext, gettext);
+#endif
Index: /trunk/libc/src/glibc/intl/gettextP.h
===================================================================
--- /trunk/libc/src/glibc/intl/gettextP.h	(revision 2448)
+++ /trunk/libc/src/glibc/intl/gettextP.h	(revision 2448)
@@ -0,0 +1,253 @@
+/* Header describing internals of libintl library.
+   Copyright (C) 1995-1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+   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 _GETTEXTP_H
+#define _GETTEXTP_H
+
+#include <stddef.h>		/* Get size_t.  */
+
+#ifdef _LIBC
+# include "../iconv/gconv_int.h"
+#else
+# if HAVE_ICONV
+#  include <iconv.h>
+# endif
+#endif
+
+#include "loadinfo.h"
+
+#include "gmo.h"		/* Get nls_uint32.  */
+
+#include <locale.h> //bird hack
+
+/* @@ end of prolog @@ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+/* Tell the compiler when a conditional or integer expression is
+   almost always true or almost always false.  */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+#ifndef W
+# define W(flag, data) ((flag) ? SWAP (data) : (data))
+#endif
+
+
+#ifdef _LIBC
+# include <byteswap.h>
+# define SWAP(i) bswap_32 (i)
+#else
+static nls_uint32 SWAP PARAMS ((nls_uint32 i));
+
+static inline nls_uint32
+SWAP (i)
+     nls_uint32 i;
+{
+  return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
+}
+#endif
+
+
+/* In-memory representation of system dependent string.  */
+struct sysdep_string_desc
+{
+  /* Length of addressed string, including the trailing NUL.  */
+  size_t length;
+  /* Pointer to addressed string.  */
+  const char *pointer;
+};
+
+/* The representation of an opened message catalog.  */
+struct loaded_domain
+{
+  /* Pointer to memory containing the .mo file.  */
+  const char *data;
+  /* 1 if the memory is mmap()ed, 0 if the memory is malloc()ed.  */
+  int use_mmap;
+  /* Size of mmap()ed memory.  */
+  size_t mmap_size;
+  /* 1 if the .mo file uses a different endianness than this machine.  */
+  int must_swap;
+  /* Pointer to additional malloc()ed memory.  */
+  void *malloced;
+
+  /* Number of static strings pairs.  */
+  nls_uint32 nstrings;
+  /* Pointer to descriptors of original strings in the file.  */
+  const struct string_desc *orig_tab;
+  /* Pointer to descriptors of translated strings in the file.  */
+  const struct string_desc *trans_tab;
+
+  /* Number of system dependent strings pairs.  */
+  nls_uint32 n_sysdep_strings;
+  /* Pointer to descriptors of original sysdep strings.  */
+  const struct sysdep_string_desc *orig_sysdep_tab;
+  /* Pointer to descriptors of translated sysdep strings.  */
+  const struct sysdep_string_desc *trans_sysdep_tab;
+
+  /* Size of hash table.  */
+  nls_uint32 hash_size;
+  /* Pointer to hash table.  */
+  const nls_uint32 *hash_tab;
+  /* 1 if the hash table uses a different endianness than this machine.  */
+  int must_swap_hash_tab;
+
+  int codeset_cntr;
+#ifdef _LIBC
+  __gconv_t conv;
+#else
+# if HAVE_ICONV
+  iconv_t conv;
+# endif
+#endif
+  char **conv_tab;
+
+  struct expression *plural;
+  unsigned long int nplurals;
+};
+
+/* We want to allocate a string at the end of the struct.  But ISO C
+   doesn't allow zero sized arrays.  */
+#if defined(__GNUC__) && !defined(IN_INNOTEK_LIBC)
+# define ZERO 0
+#else
+# define ZERO 1
+#endif
+
+/* A set of settings bound to a message domain.  Used to store settings
+   from bindtextdomain() and bind_textdomain_codeset().  */
+struct binding
+{
+  struct binding *next;
+  char *dirname;
+  int codeset_cntr;	/* Incremented each time codeset changes.  */
+  char *codeset;
+  char domainname[ZERO];
+};
+
+/* A counter which is incremented each time some previous translations
+   become invalid.
+   This variable is part of the external ABI of the GNU libintl.  */
+extern int _nl_msg_cat_cntr;
+
+#ifndef _LIBC
+const char *_nl_locale_name PARAMS ((int category, const char *categoryname));
+#endif
+
+#define _nl_find_domain __libc_nl_find_domain /* bird */
+struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
+						 char *__locale,
+						 const char *__domainname,
+					      struct binding *__domainbinding))
+     internal_function;
+#define _nl_load_domain __libc_nl_load_domain /* bird */
+void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain,
+			      struct binding *__domainbinding))
+     internal_function;
+#define _nl_init_domain_conv __libc_nl_init_domain_conv /* bird */
+const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file,
+					  struct loaded_domain *__domain,
+					  struct binding *__domainbinding))
+     internal_function;
+#define _nl_free_domain_conv __libc_nl_free_domain_conv /* bird */
+void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain))
+     internal_function;
+
+#define _nl_find_msg __libc_nl_find_msg /* bird */
+char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
+			    struct binding *domainbinding,
+			    const char *msgid, size_t *lengthp))
+     internal_function;
+
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+extern char *__gettext PARAMS ((const char *__msgid));
+extern char *__dgettext PARAMS ((const char *__domainname,
+				 const char *__msgid));
+extern char *__dcgettext PARAMS ((const char *__domainname,
+				  const char *__msgid, int __category));
+extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2,
+				 unsigned long int __n));
+extern char *__dngettext PARAMS ((const char *__domainname,
+				  const char *__msgid1, const char *__msgid2,
+				  unsigned long int n));
+extern char *__dcngettext PARAMS ((const char *__domainname,
+				   const char *__msgid1, const char *__msgid2,
+				   unsigned long int __n, int __category));
+extern char *__dcigettext PARAMS ((const char *__domainname,
+				   const char *__msgid1, const char *__msgid2,
+				   int __plural, unsigned long int __n,
+				   int __category));
+extern char *__textdomain PARAMS ((const char *__domainname));
+extern char *__bindtextdomain PARAMS ((const char *__domainname,
+				       const char *__dirname));
+extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname,
+						const char *__codeset));
+extern void _nl_finddomain_subfreeres PARAMS ((void)) attribute_hidden;
+extern void _nl_unload_domain PARAMS ((struct loaded_domain *__domain))
+     internal_function attribute_hidden;
+#else
+extern char *libintl_gettext PARAMS ((const char *__msgid));
+extern char *libintl_dgettext PARAMS ((const char *__domainname,
+				       const char *__msgid));
+extern char *libintl_dcgettext PARAMS ((const char *__domainname,
+					const char *__msgid, int __category));
+extern char *libintl_ngettext PARAMS ((const char *__msgid1,
+				       const char *__msgid2,
+				       unsigned long int __n));
+extern char *libintl_dngettext PARAMS ((const char *__domainname,
+					const char *__msgid1,
+					const char *__msgid2,
+					unsigned long int __n));
+extern char *libintl_dcngettext PARAMS ((const char *__domainname,
+					 const char *__msgid1,
+					 const char *__msgid2,
+					 unsigned long int __n,
+					 int __category));
+extern char *libintl_dcigettext PARAMS ((const char *__domainname,
+					 const char *__msgid1,
+					 const char *__msgid2,
+					 int __plural, unsigned long int __n,
+					 int __category));
+extern char *libintl_textdomain PARAMS ((const char *__domainname));
+extern char *libintl_bindtextdomain PARAMS ((const char *__domainname,
+					     const char *__dirname));
+extern char *libintl_bind_textdomain_codeset PARAMS ((const char *__domainname,
+						      const char *__codeset));
+#endif
+
+/* @@ begin of epilog @@ */
+
+#endif /* gettextP.h  */
Index: /trunk/libc/src/glibc/intl/gmo.h
===================================================================
--- /trunk/libc/src/glibc/intl/gmo.h	(revision 2448)
+++ /trunk/libc/src/glibc/intl/gmo.h	(revision 2448)
@@ -0,0 +1,150 @@
+/* Internal header for GNU gettext internationalization functions.
+   Copyright (C) 1995, 1997, 2000-2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   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 _GETTEXT_H
+#define _GETTEXT_H 1
+
+#include <limits.h>
+
+/* @@ end of prolog @@ */
+
+/* The magic number of the GNU message catalog format.  */
+#define _MAGIC 0x950412de
+#define _MAGIC_SWAPPED 0xde120495
+
+/* Revision number of the currently used .mo (binary) file format.  */
+#define MO_REVISION_NUMBER 0
+#define MO_REVISION_NUMBER_WITH_SYSDEP_I 1
+
+/* The following contortions are an attempt to use the C preprocessor
+   to determine an unsigned integral type that is 32 bits wide.  An
+   alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+   as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work
+   when cross-compiling.  */
+
+#if __STDC__
+# define UINT_MAX_32_BITS 4294967295U
+#else
+# define UINT_MAX_32_BITS 0xFFFFFFFF
+#endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+   This should be valid for all systems GNU cares about because
+   that doesn't include 16-bit systems, and only modern systems
+   (that certainly have <limits.h>) have 64+-bit integral types.  */
+
+#ifndef UINT_MAX
+# define UINT_MAX UINT_MAX_32_BITS
+#endif
+
+#if UINT_MAX == UINT_MAX_32_BITS
+typedef unsigned nls_uint32;
+#else
+# if USHRT_MAX == UINT_MAX_32_BITS
+typedef unsigned short nls_uint32;
+# else
+#  if ULONG_MAX == UINT_MAX_32_BITS
+typedef unsigned long nls_uint32;
+#  else
+  /* The following line is intended to throw an error.  Using #error is
+     not portable enough.  */
+  "Cannot determine unsigned 32-bit data type."
+#  endif
+# endif
+#endif
+
+
+/* Header for binary .mo file format.  */
+struct mo_file_header
+{
+  /* The magic number.  */
+  nls_uint32 magic;
+  /* The revision number of the file format.  */
+  nls_uint32 revision;
+
+  /* The following are only used in .mo files with major revision 0 or 1.  */
+
+  /* The number of strings pairs.  */
+  nls_uint32 nstrings;
+  /* Offset of table with start offsets of original strings.  */
+  nls_uint32 orig_tab_offset;
+  /* Offset of table with start offsets of translated strings.  */
+  nls_uint32 trans_tab_offset;
+  /* Size of hash table.  */
+  nls_uint32 hash_tab_size;
+  /* Offset of first hash table entry.  */
+  nls_uint32 hash_tab_offset;
+
+  /* The following are only used in .mo files with minor revision >= 1.  */
+
+  /* The number of system dependent segments.  */
+  nls_uint32 n_sysdep_segments;
+  /* Offset of table describing system dependent segments.  */
+  nls_uint32 sysdep_segments_offset;
+  /* The number of system dependent strings pairs.  */
+  nls_uint32 n_sysdep_strings;
+  /* Offset of table with start offsets of original sysdep strings.  */
+  nls_uint32 orig_sysdep_tab_offset;
+  /* Offset of table with start offsets of translated sysdep strings.  */
+  nls_uint32 trans_sysdep_tab_offset;
+};
+
+/* Descriptor for static string contained in the binary .mo file.  */
+struct string_desc
+{
+  /* Length of addressed string, not including the trailing NUL.  */
+  nls_uint32 length;
+  /* Offset of string in file.  */
+  nls_uint32 offset;
+};
+
+/* The following are only used in .mo files with minor revision >= 1.  */
+
+/* Descriptor for system dependent string segment.  */
+struct sysdep_segment
+{
+  /* Length of addressed string, including the trailing NUL.  */
+  nls_uint32 length;
+  /* Offset of string in file.  */
+  nls_uint32 offset;
+};
+
+/* Descriptor for system dependent string.  */
+struct sysdep_string
+{
+  /* Offset of static string segments in file.  */
+  nls_uint32 offset;
+  /* Alternating sequence of static and system dependent segments.
+     The last segment is a static segment, including the trailing NUL.  */
+  struct segment_pair
+  {
+    /* Size of static segment.  */
+    nls_uint32 segsize;
+    /* Reference to system dependent string segment, or ~0 at the end.  */
+    nls_uint32 sysdepref;
+  } segments[1];
+};
+
+/* Marker for the end of the segments[] array.  This has the value 0xFFFFFFFF,
+   regardless whether 'int' is 16 bit, 32 bit, or 64 bit.  */
+#define SEGMENTS_END ((nls_uint32) ~0)
+
+/* @@ begin of epilog @@ */
+
+#endif	/* gettext.h  */
Index: /trunk/libc/src/glibc/intl/hash-string.c
===================================================================
--- /trunk/libc/src/glibc/intl/hash-string.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/hash-string.c	(revision 2448)
@@ -0,0 +1,47 @@
+/* Implements a string hashing function.
+   Copyright (C) 1995, 1997, 1998, 2000, 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.  */
+
+#include "hash-string.h"
+
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+   [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+   1986, 1987 Bell Telephone Laboratories, Inc.]  */
+unsigned long int
+__hash_string (str_param)
+     const char *str_param;
+{
+  unsigned long int hval, g;
+  const char *str = str_param;
+
+  /* Compute the hash value for the given string.  */
+  hval = 0;
+  while (*str != '\0')
+    {
+      hval <<= 4;
+      hval += (unsigned char) *str++;
+      g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+      if (g != 0)
+	{
+	  hval ^= g >> (HASHWORDBITS - 8);
+	  hval ^= g;
+	}
+    }
+  return hval;
+}
Index: /trunk/libc/src/glibc/intl/hash-string.h
===================================================================
--- /trunk/libc/src/glibc/intl/hash-string.h	(revision 2448)
+++ /trunk/libc/src/glibc/intl/hash-string.h	(revision 2448)
@@ -0,0 +1,43 @@
+/* Implements a string hashing function.
+   Copyright (C) 1995, 1997, 1998, 2000, 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.  */
+
+/* @@ end of prolog @@ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(Args) Args
+# else
+#  define PARAMS(Args) ()
+# endif
+#endif
+
+/* We assume to have `unsigned long int' value with at least 32 bits.  */
+#define HASHWORDBITS 32
+
+#ifndef attribute_hidden
+#define attribute_hidden
+#endif
+
+#define __hash_string __libc_hash_string //bird
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+   [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+   1986, 1987 Bell Telephone Laboratories, Inc.]  */
+extern unsigned long int __hash_string PARAMS ((const char *__str_param))
+     attribute_hidden;
Index: /trunk/libc/src/glibc/intl/intl.smak
===================================================================
--- /trunk/libc/src/glibc/intl/intl.smak	(revision 2448)
+++ /trunk/libc/src/glibc/intl/intl.smak	(revision 2448)
@@ -0,0 +1,5 @@
+libc.TSRC += $(filter-out %plural-eval.c,$(wildcard src/glibc/intl/*.c))
+
+#$(foreach srcfile,$(wildcard src/glibc/intl/*.c), \
+#	$(eval .TCF.$(srcfile) :=  ))
+
Index: /trunk/libc/src/glibc/intl/l10nflist.c
===================================================================
--- /trunk/libc/src/glibc/intl/l10nflist.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/l10nflist.c	(revision 2448)
@@ -0,0 +1,382 @@
+/* Copyright (C) 1995-2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+   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.  */
+
+/* Tell glibc's <string.h> to provide a prototype for stpcpy().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#if defined _LIBC || defined HAVE_ARGZ_H
+# include <argz.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "loadinfo.h"
+
+/* On some strange systems still no definition of NULL is found.  Sigh!  */
+#ifndef NULL
+# if defined __STDC__ && __STDC__
+#  define NULL ((void *) 0)
+# else
+#  define NULL 0
+# endif
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions.  This is required by the standard
+   because some ANSI C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# ifndef stpcpy
+#  define stpcpy(dest, src) __stpcpy(dest, src)
+# endif
+#else
+# ifndef HAVE_STPCPY
+static char *stpcpy PARAMS ((char *dest, const char *src));
+# endif
+#endif
+
+/* Define function which are usually not available.  */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
+/* Returns the number of strings in ARGZ.  */
+static size_t argz_count__ PARAMS ((const char *argz, size_t len));
+
+static size_t
+argz_count__ (argz, len)
+     const char *argz;
+     size_t len;
+{
+  size_t count = 0;
+  while (len > 0)
+    {
+      size_t part_len = strlen (argz);
+      argz += part_len + 1;
+      len -= part_len + 1;
+      count++;
+    }
+  return count;
+}
+# undef __argz_count
+# define __argz_count(argz, len) argz_count__ (argz, len)
+#else
+# ifdef _LIBC
+#  define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
+# endif
+#endif	/* !_LIBC && !HAVE___ARGZ_COUNT */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
+/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
+   except the last into the character SEP.  */
+static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
+
+static void
+argz_stringify__ (argz, len, sep)
+     char *argz;
+     size_t len;
+     int sep;
+{
+  while (len > 0)
+    {
+      size_t part_len = strlen (argz);
+      argz += part_len;
+      len -= part_len + 1;
+      if (len > 0)
+	*argz++ = sep;
+    }
+}
+# undef __argz_stringify
+# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
+#else
+# ifdef _LIBC
+#  define __argz_stringify(argz, len, sep) \
+  INTUSE(__argz_stringify) (argz, len, sep)
+# endif
+#endif	/* !_LIBC && !HAVE___ARGZ_STRINGIFY */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
+static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
+				  const char *entry));
+
+static char *
+argz_next__ (argz, argz_len, entry)
+     char *argz;
+     size_t argz_len;
+     const char *entry;
+{
+  if (entry)
+    {
+      if (entry < argz + argz_len)
+        entry = strchr (entry, '\0') + 1;
+
+      return entry >= argz + argz_len ? NULL : (char *) entry;
+    }
+  else
+    if (argz_len > 0)
+      return argz;
+    else
+      return 0;
+}
+# undef __argz_next
+# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
+#endif	/* !_LIBC && !HAVE___ARGZ_NEXT */
+
+
+/* Return number of bits set in X.  */
+static int pop PARAMS ((int x));
+
+static inline int
+pop (x)
+     int x;
+{
+  /* We assume that no more than 16 bits are used.  */
+  x = ((x & ~0x5555) >> 1) + (x & 0x5555);
+  x = ((x & ~0x3333) >> 2) + (x & 0x3333);
+  x = ((x >> 4) + x) & 0x0f0f;
+  x = ((x >> 8) + x) & 0xff;
+
+  return x;
+}
+
+
+
+struct loaded_l10nfile *
+_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
+		    territory, codeset, normalized_codeset, modifier,
+		    filename, do_allocate)
+     struct loaded_l10nfile **l10nfile_list;
+     const char *dirlist;
+     size_t dirlist_len;
+     int mask;
+     const char *language;
+     const char *territory;
+     const char *codeset;
+     const char *normalized_codeset;
+     const char *modifier;
+     const char *filename;
+     int do_allocate;
+{
+  char *abs_filename;
+  struct loaded_l10nfile *last = NULL;
+  struct loaded_l10nfile *retval;
+  char *cp;
+  size_t entries;
+  int cnt;
+
+  /* Allocate room for the full file name.  */
+  abs_filename = (char *) malloc (dirlist_len
+				  + strlen (language)
+				  + ((mask & XPG_TERRITORY) != 0
+				     ? strlen (territory) + 1 : 0)
+				  + ((mask & XPG_CODESET) != 0
+				     ? strlen (codeset) + 1 : 0)
+				  + ((mask & XPG_NORM_CODESET) != 0
+				     ? strlen (normalized_codeset) + 1 : 0)
+				  + ((mask & XPG_MODIFIER) != 0
+				     ? strlen (modifier) + 1 : 0)
+				  + 1 + strlen (filename) + 1);
+
+  if (abs_filename == NULL)
+    return NULL;
+
+  retval = NULL;
+  last = NULL;
+
+  /* Construct file name.  */
+  memcpy (abs_filename, dirlist, dirlist_len);
+  __argz_stringify (abs_filename, dirlist_len, ':');
+  cp = abs_filename + (dirlist_len - 1);
+  *cp++ = '/';
+  cp = stpcpy (cp, language);
+
+  if ((mask & XPG_TERRITORY) != 0)
+    {
+      *cp++ = '_';
+      cp = stpcpy (cp, territory);
+    }
+  if ((mask & XPG_CODESET) != 0)
+    {
+      *cp++ = '.';
+      cp = stpcpy (cp, codeset);
+    }
+  if ((mask & XPG_NORM_CODESET) != 0)
+    {
+      *cp++ = '.';
+      cp = stpcpy (cp, normalized_codeset);
+    }
+  if ((mask & XPG_MODIFIER) != 0)
+    {
+      *cp++ = '@';
+      cp = stpcpy (cp, modifier);
+    }
+
+  *cp++ = '/';
+  stpcpy (cp, filename);
+
+  /* Look in list of already loaded domains whether it is already
+     available.  */
+  last = NULL;
+  for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
+    if (retval->filename != NULL)
+      {
+	int compare = strcmp (retval->filename, abs_filename);
+	if (compare == 0)
+	  /* We found it!  */
+	  break;
+	if (compare < 0)
+	  {
+	    /* It's not in the list.  */
+	    retval = NULL;
+	    break;
+	  }
+
+	last = retval;
+      }
+
+  if (retval != NULL || do_allocate == 0)
+    {
+      free (abs_filename);
+      return retval;
+    }
+
+  retval = (struct loaded_l10nfile *)
+    malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
+				* (1 << pop (mask))
+				* sizeof (struct loaded_l10nfile *)));
+  if (retval == NULL)
+    return NULL;
+
+  retval->filename = abs_filename;
+  /* If more than one directory is in the list this is a pseudo-entry
+     which just references others.  We do not try to load data for it,
+     ever.  */
+  retval->decided = (__argz_count (dirlist, dirlist_len) != 1
+		     || ((mask & XPG_CODESET) != 0
+			 && (mask & XPG_NORM_CODESET) != 0));
+  retval->data = NULL;
+
+  if (last == NULL)
+    {
+      retval->next = *l10nfile_list;
+      *l10nfile_list = retval;
+    }
+  else
+    {
+      retval->next = last->next;
+      last->next = retval;
+    }
+
+  entries = 0;
+  /* If the DIRLIST is a real list the RETVAL entry corresponds not to
+     a real file.  So we have to use the DIRLIST separation mechanism
+     of the inner loop.  */
+  cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
+  for (; cnt >= 0; --cnt)
+    if ((cnt & ~mask) == 0)
+      {
+	/* Iterate over all elements of the DIRLIST.  */
+	char *dir = NULL;
+
+	while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
+	       != NULL)
+	  retval->successor[entries++]
+	    = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
+				  language, territory, codeset,
+				  normalized_codeset, modifier, filename, 1);
+      }
+  retval->successor[entries] = NULL;
+
+  return retval;
+}
+
+
+/* Normalize codeset name.  There is no standard for the codeset
+   names.  Normalization allows the user to use any of the common
+   names.  The return value is dynamically allocated and has to be
+   freed by the caller.  */
+const char *
+_nl_normalize_codeset (codeset, name_len)
+     const char *codeset;
+     size_t name_len;
+{
+  int len = 0;
+  int only_digit = 1;
+  char *retval;
+  char *wp;
+  size_t cnt;
+
+  for (cnt = 0; cnt < name_len; ++cnt)
+    if (isalnum ((unsigned char) codeset[cnt]))
+      {
+	++len;
+
+	if (isalpha ((unsigned char) codeset[cnt]))
+	  only_digit = 0;
+      }
+
+  retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
+
+  if (retval != NULL)
+    {
+      if (only_digit)
+	wp = stpcpy (retval, "iso");
+      else
+	wp = retval;
+
+      for (cnt = 0; cnt < name_len; ++cnt)
+	if (isalpha ((unsigned char) codeset[cnt]))
+	  *wp++ = tolower ((unsigned char) codeset[cnt]);
+	else if (isdigit ((unsigned char) codeset[cnt]))
+	  *wp++ = codeset[cnt];
+
+      *wp = '\0';
+    }
+
+  return (const char *) retval;
+}
+
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library.  So we
+   avoid the non-standard function stpcpy.  In GNU C Library this
+   function is available, though.  Also allow the symbol HAVE_STPCPY
+   to be defined.  */
+#if (!defined(_LIBC) || !_LIBC) && !HAVE_STPCPY
+static char *
+stpcpy (dest, src)
+     char *dest;
+     const char *src;
+{
+  while ((*dest++ = *src++) != '\0')
+    /* Do nothing. */ ;
+  return dest - 1;
+}
+#endif
Index: /trunk/libc/src/glibc/intl/loadinfo.h
===================================================================
--- /trunk/libc/src/glibc/intl/loadinfo.h	(revision 2448)
+++ /trunk/libc/src/glibc/intl/loadinfo.h	(revision 2448)
@@ -0,0 +1,109 @@
+/* Copyright (C) 1996-2000, 2002, 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.  */
+
+#ifndef _LOADINFO_H
+#define _LOADINFO_H	1
+
+/* Declarations of locale dependent catalog lookup functions.
+   Implemented in
+
+     localealias.c    Possibly replace a locale name by another.
+     explodename.c    Split a locale name into its various fields.
+     l10nflist.c      Generate a list of filenames of possible message catalogs.
+     finddomain.c     Find and open the relevant message catalogs.
+
+   The main function _nl_find_domain() in finddomain.c is declared
+   in gettextP.h.
+ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+/* Tell the compiler when a conditional or integer expression is
+   almost always true or almost always false.  */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+/* Separator in PATH like lists of pathnames.  */
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
+# define PATH_SEPARATOR ';'
+#else
+  /* Unix */
+# define PATH_SEPARATOR ':'
+#endif
+
+/* Encoding of locale name parts.  */
+#define XPG_NORM_CODESET	1
+#define XPG_CODESET		2
+#define XPG_TERRITORY		4
+#define XPG_MODIFIER		8
+
+
+struct loaded_l10nfile
+{
+  const char *filename;
+  int decided;
+
+  const void *data;
+
+  struct loaded_l10nfile *next;
+  struct loaded_l10nfile *successor[1];
+};
+
+
+/* Normalize codeset name.  There is no standard for the codeset
+   names.  Normalization allows the user to use any of the common
+   names.  The return value is dynamically allocated and has to be
+   freed by the caller.  */
+extern const char *_nl_normalize_codeset PARAMS ((const char *codeset,
+						  size_t name_len));
+
+
+extern struct loaded_l10nfile *
+_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list,
+			    const char *dirlist, size_t dirlist_len, int mask,
+			    const char *language, const char *territory,
+			    const char *codeset,
+			    const char *normalized_codeset,
+			    const char *modifier, const char *filename,
+			    int do_allocate));
+
+
+extern const char *_nl_expand_alias PARAMS ((const char *name));
+
+/* normalized_codeset is dynamically allocated and has to be freed by
+   the caller.  */
+extern int _nl_explode_name PARAMS ((char *name, const char **language,
+				     const char **modifier,
+				     const char **territory,
+				     const char **codeset,
+				     const char **normalized_codeset));
+
+#endif	/* loadinfo.h */
Index: /trunk/libc/src/glibc/intl/loadmsgcat.c
===================================================================
--- /trunk/libc/src/glibc/intl/loadmsgcat.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/loadmsgcat.c	(revision 2448)
@@ -0,0 +1,1441 @@
+/* Load needed message catalogs.
+   Copyright (C) 1995-2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   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.  */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE    1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef __GNUC__
+# undef  alloca
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <langinfo.h>
+# include <locale.h>
+#endif
+
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
+    || (defined _LIBC && defined _POSIX_MAPPED_FILES)
+# include <sys/mman.h>
+# undef HAVE_MMAP
+# define HAVE_MMAP	1
+#else
+# undef HAVE_MMAP
+# ifdef IN_INNOTEK_LIBC
+#  define MAP_FAILED	((void *)-1)
+# endif
+#endif
+
+
+#if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
+# include <stdint.h>
+#endif
+#if defined HAVE_INTTYPES_H || defined _LIBC
+# include <inttypes.h>
+#endif
+
+#include "gmo.h"
+#include "gettextP.h"
+#include "hash-string.h"
+#include "plural-exp.h"
+
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# include <not-cancel.h>
+# include <bits/libc-lock.h>
+#else
+# define __libc_lock_define_initialized_recursive(a,b)  do {} while (0)
+# define __libc_lock_lock_recursive(l)                  do {} while (0)
+# define __libc_lock_unlock_recursive(l)                do {} while (0)
+#endif
+#include "localecharset.h"
+
+/* Provide fallback values for macros that ought to be defined in <inttypes.h>.
+   Note that our fallback values need not be literal strings, because we don't
+   use them with preprocessor string concatenation.  */
+#if !defined PRId8 || PRI_MACROS_BROKEN
+# undef PRId8
+# define PRId8 "d"
+#endif
+#if !defined PRIi8 || PRI_MACROS_BROKEN
+# undef PRIi8
+# define PRIi8 "i"
+#endif
+#if !defined PRIo8 || PRI_MACROS_BROKEN
+# undef PRIo8
+# define PRIo8 "o"
+#endif
+#if !defined PRIu8 || PRI_MACROS_BROKEN
+# undef PRIu8
+# define PRIu8 "u"
+#endif
+#if !defined PRIx8 || PRI_MACROS_BROKEN
+# undef PRIx8
+# define PRIx8 "x"
+#endif
+#if !defined PRIX8 || PRI_MACROS_BROKEN
+# undef PRIX8
+# define PRIX8 "X"
+#endif
+#if !defined PRId16 || PRI_MACROS_BROKEN
+# undef PRId16
+# define PRId16 "d"
+#endif
+#if !defined PRIi16 || PRI_MACROS_BROKEN
+# undef PRIi16
+# define PRIi16 "i"
+#endif
+#if !defined PRIo16 || PRI_MACROS_BROKEN
+# undef PRIo16
+# define PRIo16 "o"
+#endif
+#if !defined PRIu16 || PRI_MACROS_BROKEN
+# undef PRIu16
+# define PRIu16 "u"
+#endif
+#if !defined PRIx16 || PRI_MACROS_BROKEN
+# undef PRIx16
+# define PRIx16 "x"
+#endif
+#if !defined PRIX16 || PRI_MACROS_BROKEN
+# undef PRIX16
+# define PRIX16 "X"
+#endif
+#if !defined PRId32 || PRI_MACROS_BROKEN
+# undef PRId32
+# define PRId32 "d"
+#endif
+#if !defined PRIi32 || PRI_MACROS_BROKEN
+# undef PRIi32
+# define PRIi32 "i"
+#endif
+#if !defined PRIo32 || PRI_MACROS_BROKEN
+# undef PRIo32
+# define PRIo32 "o"
+#endif
+#if !defined PRIu32 || PRI_MACROS_BROKEN
+# undef PRIu32
+# define PRIu32 "u"
+#endif
+#if !defined PRIx32 || PRI_MACROS_BROKEN
+# undef PRIx32
+# define PRIx32 "x"
+#endif
+#if !defined PRIX32 || PRI_MACROS_BROKEN
+# undef PRIX32
+# define PRIX32 "X"
+#endif
+#if !defined PRId64 || PRI_MACROS_BROKEN
+# undef PRId64
+# define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
+#endif
+#if !defined PRIi64 || PRI_MACROS_BROKEN
+# undef PRIi64
+# define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
+#endif
+#if !defined PRIo64 || PRI_MACROS_BROKEN
+# undef PRIo64
+# define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
+#endif
+#if !defined PRIu64 || PRI_MACROS_BROKEN
+# undef PRIu64
+# define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
+#endif
+#if !defined PRIx64 || PRI_MACROS_BROKEN
+# undef PRIx64
+# define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
+#endif
+#if !defined PRIX64 || PRI_MACROS_BROKEN
+# undef PRIX64
+# define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
+#endif
+#if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
+# undef PRIdLEAST8
+# define PRIdLEAST8 "d"
+#endif
+#if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
+# undef PRIiLEAST8
+# define PRIiLEAST8 "i"
+#endif
+#if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
+# undef PRIoLEAST8
+# define PRIoLEAST8 "o"
+#endif
+#if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
+# undef PRIuLEAST8
+# define PRIuLEAST8 "u"
+#endif
+#if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
+# undef PRIxLEAST8
+# define PRIxLEAST8 "x"
+#endif
+#if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
+# undef PRIXLEAST8
+# define PRIXLEAST8 "X"
+#endif
+#if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
+# undef PRIdLEAST16
+# define PRIdLEAST16 "d"
+#endif
+#if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
+# undef PRIiLEAST16
+# define PRIiLEAST16 "i"
+#endif
+#if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
+# undef PRIoLEAST16
+# define PRIoLEAST16 "o"
+#endif
+#if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
+# undef PRIuLEAST16
+# define PRIuLEAST16 "u"
+#endif
+#if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
+# undef PRIxLEAST16
+# define PRIxLEAST16 "x"
+#endif
+#if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
+# undef PRIXLEAST16
+# define PRIXLEAST16 "X"
+#endif
+#if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
+# undef PRIdLEAST32
+# define PRIdLEAST32 "d"
+#endif
+#if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
+# undef PRIiLEAST32
+# define PRIiLEAST32 "i"
+#endif
+#if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
+# undef PRIoLEAST32
+# define PRIoLEAST32 "o"
+#endif
+#if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
+# undef PRIuLEAST32
+# define PRIuLEAST32 "u"
+#endif
+#if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
+# undef PRIxLEAST32
+# define PRIxLEAST32 "x"
+#endif
+#if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
+# undef PRIXLEAST32
+# define PRIXLEAST32 "X"
+#endif
+#if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
+# undef PRIdLEAST64
+# define PRIdLEAST64 PRId64
+#endif
+#if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
+# undef PRIiLEAST64
+# define PRIiLEAST64 PRIi64
+#endif
+#if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
+# undef PRIoLEAST64
+# define PRIoLEAST64 PRIo64
+#endif
+#if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
+# undef PRIuLEAST64
+# define PRIuLEAST64 PRIu64
+#endif
+#if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
+# undef PRIxLEAST64
+# define PRIxLEAST64 PRIx64
+#endif
+#if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
+# undef PRIXLEAST64
+# define PRIXLEAST64 PRIX64
+#endif
+#if !defined PRIdFAST8 || PRI_MACROS_BROKEN
+# undef PRIdFAST8
+# define PRIdFAST8 "d"
+#endif
+#if !defined PRIiFAST8 || PRI_MACROS_BROKEN
+# undef PRIiFAST8
+# define PRIiFAST8 "i"
+#endif
+#if !defined PRIoFAST8 || PRI_MACROS_BROKEN
+# undef PRIoFAST8
+# define PRIoFAST8 "o"
+#endif
+#if !defined PRIuFAST8 || PRI_MACROS_BROKEN
+# undef PRIuFAST8
+# define PRIuFAST8 "u"
+#endif
+#if !defined PRIxFAST8 || PRI_MACROS_BROKEN
+# undef PRIxFAST8
+# define PRIxFAST8 "x"
+#endif
+#if !defined PRIXFAST8 || PRI_MACROS_BROKEN
+# undef PRIXFAST8
+# define PRIXFAST8 "X"
+#endif
+#if !defined PRIdFAST16 || PRI_MACROS_BROKEN
+# undef PRIdFAST16
+# define PRIdFAST16 "d"
+#endif
+#if !defined PRIiFAST16 || PRI_MACROS_BROKEN
+# undef PRIiFAST16
+# define PRIiFAST16 "i"
+#endif
+#if !defined PRIoFAST16 || PRI_MACROS_BROKEN
+# undef PRIoFAST16
+# define PRIoFAST16 "o"
+#endif
+#if !defined PRIuFAST16 || PRI_MACROS_BROKEN
+# undef PRIuFAST16
+# define PRIuFAST16 "u"
+#endif
+#if !defined PRIxFAST16 || PRI_MACROS_BROKEN
+# undef PRIxFAST16
+# define PRIxFAST16 "x"
+#endif
+#if !defined PRIXFAST16 || PRI_MACROS_BROKEN
+# undef PRIXFAST16
+# define PRIXFAST16 "X"
+#endif
+#if !defined PRIdFAST32 || PRI_MACROS_BROKEN
+# undef PRIdFAST32
+# define PRIdFAST32 "d"
+#endif
+#if !defined PRIiFAST32 || PRI_MACROS_BROKEN
+# undef PRIiFAST32
+# define PRIiFAST32 "i"
+#endif
+#if !defined PRIoFAST32 || PRI_MACROS_BROKEN
+# undef PRIoFAST32
+# define PRIoFAST32 "o"
+#endif
+#if !defined PRIuFAST32 || PRI_MACROS_BROKEN
+# undef PRIuFAST32
+# define PRIuFAST32 "u"
+#endif
+#if !defined PRIxFAST32 || PRI_MACROS_BROKEN
+# undef PRIxFAST32
+# define PRIxFAST32 "x"
+#endif
+#if !defined PRIXFAST32 || PRI_MACROS_BROKEN
+# undef PRIXFAST32
+# define PRIXFAST32 "X"
+#endif
+#if !defined PRIdFAST64 || PRI_MACROS_BROKEN
+# undef PRIdFAST64
+# define PRIdFAST64 PRId64
+#endif
+#if !defined PRIiFAST64 || PRI_MACROS_BROKEN
+# undef PRIiFAST64
+# define PRIiFAST64 PRIi64
+#endif
+#if !defined PRIoFAST64 || PRI_MACROS_BROKEN
+# undef PRIoFAST64
+# define PRIoFAST64 PRIo64
+#endif
+#if !defined PRIuFAST64 || PRI_MACROS_BROKEN
+# undef PRIuFAST64
+# define PRIuFAST64 PRIu64
+#endif
+#if !defined PRIxFAST64 || PRI_MACROS_BROKEN
+# undef PRIxFAST64
+# define PRIxFAST64 PRIx64
+#endif
+#if !defined PRIXFAST64 || PRI_MACROS_BROKEN
+# undef PRIXFAST64
+# define PRIXFAST64 PRIX64
+#endif
+#if !defined PRIdMAX || PRI_MACROS_BROKEN
+# undef PRIdMAX
+# define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
+#endif
+#if !defined PRIiMAX || PRI_MACROS_BROKEN
+# undef PRIiMAX
+# define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
+#endif
+#if !defined PRIoMAX || PRI_MACROS_BROKEN
+# undef PRIoMAX
+# define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
+#endif
+#if !defined PRIuMAX || PRI_MACROS_BROKEN
+# undef PRIuMAX
+# define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
+#endif
+#if !defined PRIxMAX || PRI_MACROS_BROKEN
+# undef PRIxMAX
+# define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
+#endif
+#if !defined PRIXMAX || PRI_MACROS_BROKEN
+# undef PRIXMAX
+# define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
+#endif
+#if !defined PRIdPTR || PRI_MACROS_BROKEN
+# undef PRIdPTR
+# define PRIdPTR \
+  (sizeof (void *) == sizeof (long) ? "ld" : \
+   sizeof (void *) == sizeof (int) ? "d" : \
+   "lld")
+#endif
+#if !defined PRIiPTR || PRI_MACROS_BROKEN
+# undef PRIiPTR
+# define PRIiPTR \
+  (sizeof (void *) == sizeof (long) ? "li" : \
+   sizeof (void *) == sizeof (int) ? "i" : \
+   "lli")
+#endif
+#if !defined PRIoPTR || PRI_MACROS_BROKEN
+# undef PRIoPTR
+# define PRIoPTR \
+  (sizeof (void *) == sizeof (long) ? "lo" : \
+   sizeof (void *) == sizeof (int) ? "o" : \
+   "llo")
+#endif
+#if !defined PRIuPTR || PRI_MACROS_BROKEN
+# undef PRIuPTR
+# define PRIuPTR \
+  (sizeof (void *) == sizeof (long) ? "lu" : \
+   sizeof (void *) == sizeof (int) ? "u" : \
+   "llu")
+#endif
+#if !defined PRIxPTR || PRI_MACROS_BROKEN
+# undef PRIxPTR
+# define PRIxPTR \
+  (sizeof (void *) == sizeof (long) ? "lx" : \
+   sizeof (void *) == sizeof (int) ? "x" : \
+   "llx")
+#endif
+#if !defined PRIXPTR || PRI_MACROS_BROKEN
+# undef PRIXPTR
+# define PRIXPTR \
+  (sizeof (void *) == sizeof (long) ? "lX" : \
+   sizeof (void *) == sizeof (int) ? "X" : \
+   "llX")
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ISO C functions.  This is required by the standard
+   because some ISO C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# define open(name, flags)	open_not_cancel_2 (name, flags)
+# define close(fd)		close_not_cancel_no_status (fd)
+# define read(fd, buf, n)	read_not_cancel (fd, buf, n)
+# define mmap(addr, len, prot, flags, fd, offset) \
+  __mmap (addr, len, prot, flags, fd, offset)
+# define munmap(addr, len)	__munmap (addr, len)
+#endif
+
+/* For those losing systems which don't have `alloca' we have to add
+   some additional code emulating it.  */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+
+/* Prototypes for local functions.  Needed to ensure compiler checking of
+   function argument counts despite of K&R C function definition syntax.  */
+static const char *get_sysdep_segment_value PARAMS ((const char *name));
+
+
+/* We need a sign, whether a new catalog was loaded, which can be associated
+   with all translations.  This is important if the translations are
+   cached by one of GCC's features.  */
+int _nl_msg_cat_cntr;
+
+
+/* Expand a system dependent string segment.  Return NULL if unsupported.  */
+static const char *
+get_sysdep_segment_value (name)
+     const char *name;
+{
+  /* Test for an ISO C 99 section 7.8.1 format string directive.
+     Syntax:
+     P R I { d | i | o | u | x | X }
+     { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR }  */
+  /* We don't use a table of 14 times 6 'const char *' strings here, because
+     data relocations cost startup time.  */
+  if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
+    {
+      if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
+	  || name[3] == 'x' || name[3] == 'X')
+	{
+	  if (name[4] == '8' && name[5] == '\0')
+	    {
+	      if (name[3] == 'd')
+		return PRId8;
+	      if (name[3] == 'i')
+		return PRIi8;
+	      if (name[3] == 'o')
+		return PRIo8;
+	      if (name[3] == 'u')
+		return PRIu8;
+	      if (name[3] == 'x')
+		return PRIx8;
+	      if (name[3] == 'X')
+		return PRIX8;
+	      abort ();
+	    }
+	  if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
+	    {
+	      if (name[3] == 'd')
+		return PRId16;
+	      if (name[3] == 'i')
+		return PRIi16;
+	      if (name[3] == 'o')
+		return PRIo16;
+	      if (name[3] == 'u')
+		return PRIu16;
+	      if (name[3] == 'x')
+		return PRIx16;
+	      if (name[3] == 'X')
+		return PRIX16;
+	      abort ();
+	    }
+	  if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
+	    {
+	      if (name[3] == 'd')
+		return PRId32;
+	      if (name[3] == 'i')
+		return PRIi32;
+	      if (name[3] == 'o')
+		return PRIo32;
+	      if (name[3] == 'u')
+		return PRIu32;
+	      if (name[3] == 'x')
+		return PRIx32;
+	      if (name[3] == 'X')
+		return PRIX32;
+	      abort ();
+	    }
+	  if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
+	    {
+	      if (name[3] == 'd')
+		return PRId64;
+	      if (name[3] == 'i')
+		return PRIi64;
+	      if (name[3] == 'o')
+		return PRIo64;
+	      if (name[3] == 'u')
+		return PRIu64;
+	      if (name[3] == 'x')
+		return PRIx64;
+	      if (name[3] == 'X')
+		return PRIX64;
+	      abort ();
+	    }
+	  if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
+	      && name[7] == 'S' && name[8] == 'T')
+	    {
+	      if (name[9] == '8' && name[10] == '\0')
+		{
+		  if (name[3] == 'd')
+		    return PRIdLEAST8;
+		  if (name[3] == 'i')
+		    return PRIiLEAST8;
+		  if (name[3] == 'o')
+		    return PRIoLEAST8;
+		  if (name[3] == 'u')
+		    return PRIuLEAST8;
+		  if (name[3] == 'x')
+		    return PRIxLEAST8;
+		  if (name[3] == 'X')
+		    return PRIXLEAST8;
+		  abort ();
+		}
+	      if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
+		{
+		  if (name[3] == 'd')
+		    return PRIdLEAST16;
+		  if (name[3] == 'i')
+		    return PRIiLEAST16;
+		  if (name[3] == 'o')
+		    return PRIoLEAST16;
+		  if (name[3] == 'u')
+		    return PRIuLEAST16;
+		  if (name[3] == 'x')
+		    return PRIxLEAST16;
+		  if (name[3] == 'X')
+		    return PRIXLEAST16;
+		  abort ();
+		}
+	      if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
+		{
+		  if (name[3] == 'd')
+		    return PRIdLEAST32;
+		  if (name[3] == 'i')
+		    return PRIiLEAST32;
+		  if (name[3] == 'o')
+		    return PRIoLEAST32;
+		  if (name[3] == 'u')
+		    return PRIuLEAST32;
+		  if (name[3] == 'x')
+		    return PRIxLEAST32;
+		  if (name[3] == 'X')
+		    return PRIXLEAST32;
+		  abort ();
+		}
+	      if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
+		{
+		  if (name[3] == 'd')
+		    return PRIdLEAST64;
+		  if (name[3] == 'i')
+		    return PRIiLEAST64;
+		  if (name[3] == 'o')
+		    return PRIoLEAST64;
+		  if (name[3] == 'u')
+		    return PRIuLEAST64;
+		  if (name[3] == 'x')
+		    return PRIxLEAST64;
+		  if (name[3] == 'X')
+		    return PRIXLEAST64;
+		  abort ();
+		}
+	    }
+	  if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
+	      && name[7] == 'T')
+	    {
+	      if (name[8] == '8' && name[9] == '\0')
+		{
+		  if (name[3] == 'd')
+		    return PRIdFAST8;
+		  if (name[3] == 'i')
+		    return PRIiFAST8;
+		  if (name[3] == 'o')
+		    return PRIoFAST8;
+		  if (name[3] == 'u')
+		    return PRIuFAST8;
+		  if (name[3] == 'x')
+		    return PRIxFAST8;
+		  if (name[3] == 'X')
+		    return PRIXFAST8;
+		  abort ();
+		}
+	      if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
+		{
+		  if (name[3] == 'd')
+		    return PRIdFAST16;
+		  if (name[3] == 'i')
+		    return PRIiFAST16;
+		  if (name[3] == 'o')
+		    return PRIoFAST16;
+		  if (name[3] == 'u')
+		    return PRIuFAST16;
+		  if (name[3] == 'x')
+		    return PRIxFAST16;
+		  if (name[3] == 'X')
+		    return PRIXFAST16;
+		  abort ();
+		}
+	      if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
+		{
+		  if (name[3] == 'd')
+		    return PRIdFAST32;
+		  if (name[3] == 'i')
+		    return PRIiFAST32;
+		  if (name[3] == 'o')
+		    return PRIoFAST32;
+		  if (name[3] == 'u')
+		    return PRIuFAST32;
+		  if (name[3] == 'x')
+		    return PRIxFAST32;
+		  if (name[3] == 'X')
+		    return PRIXFAST32;
+		  abort ();
+		}
+	      if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
+		{
+		  if (name[3] == 'd')
+		    return PRIdFAST64;
+		  if (name[3] == 'i')
+		    return PRIiFAST64;
+		  if (name[3] == 'o')
+		    return PRIoFAST64;
+		  if (name[3] == 'u')
+		    return PRIuFAST64;
+		  if (name[3] == 'x')
+		    return PRIxFAST64;
+		  if (name[3] == 'X')
+		    return PRIXFAST64;
+		  abort ();
+		}
+	    }
+	  if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
+	      && name[7] == '\0')
+	    {
+	      if (name[3] == 'd')
+		return PRIdMAX;
+	      if (name[3] == 'i')
+		return PRIiMAX;
+	      if (name[3] == 'o')
+		return PRIoMAX;
+	      if (name[3] == 'u')
+		return PRIuMAX;
+	      if (name[3] == 'x')
+		return PRIxMAX;
+	      if (name[3] == 'X')
+		return PRIXMAX;
+	      abort ();
+	    }
+	  if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
+	      && name[7] == '\0')
+	    {
+	      if (name[3] == 'd')
+		return PRIdPTR;
+	      if (name[3] == 'i')
+		return PRIiPTR;
+	      if (name[3] == 'o')
+		return PRIoPTR;
+	      if (name[3] == 'u')
+		return PRIuPTR;
+	      if (name[3] == 'x')
+		return PRIxPTR;
+	      if (name[3] == 'X')
+		return PRIXPTR;
+	      abort ();
+	    }
+	}
+    }
+  /* Test for a glibc specific printf() format directive flag.  */
+  if (name[0] == 'I' && name[1] == '\0')
+    {
+#if defined _LIBC || (defined (__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)))
+      /* The 'I' flag, in numeric format directives, replaces ASCII digits
+	 with the 'outdigits' defined in the LC_CTYPE locale facet.  This is
+	 used for Farsi (Persian) and maybe Arabic.  */
+      return "I";
+#else
+      return "";
+#endif
+    }
+  /* Other system dependent strings are not valid.  */
+  return NULL;
+}
+
+/* Initialize the codeset dependent parts of an opened message catalog.
+   Return the header entry.  */
+const char *
+internal_function
+_nl_init_domain_conv (domain_file, domain, domainbinding)
+     struct loaded_l10nfile *domain_file;
+     struct loaded_domain *domain;
+     struct binding *domainbinding;
+{
+  /* Find out about the character set the file is encoded with.
+     This can be found (in textual form) in the entry "".  If this
+     entry does not exist or if this does not contain the `charset='
+     information, we will assume the charset matches the one the
+     current locale and we don't have to perform any conversion.  */
+  char *nullentry;
+  size_t nullentrylen;
+
+  /* Preinitialize fields, to avoid recursion during _nl_find_msg.  */
+  domain->codeset_cntr =
+    (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
+#ifdef _LIBC
+  domain->conv = (__gconv_t) -1;
+#else
+# if HAVE_ICONV
+  domain->conv = (iconv_t) -1;
+# endif
+#endif
+  domain->conv_tab = NULL;
+
+  /* Get the header entry.  */
+  nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
+
+  if (nullentry != NULL)
+    {
+#if defined _LIBC || HAVE_ICONV
+      const char *charsetstr;
+
+      charsetstr = strstr (nullentry, "charset=");
+      if (charsetstr != NULL)
+	{
+	  size_t len;
+	  char *charset;
+	  const char *outcharset;
+
+	  charsetstr += strlen ("charset=");
+	  len = strcspn (charsetstr, " \t\n");
+
+	  charset = (char *) alloca (len + 1);
+# if defined _LIBC || HAVE_MEMPCPY
+	  *((char *) mempcpy (charset, charsetstr, len)) = '\0';
+# else
+	  memcpy (charset, charsetstr, len);
+	  charset[len] = '\0';
+# endif
+
+	  /* The output charset should normally be determined by the
+	     locale.  But sometimes the locale is not used or not correctly
+	     set up, so we provide a possibility for the user to override
+	     this.  Moreover, the value specified through
+	     bind_textdomain_codeset overrides both.  */
+	  if (domainbinding != NULL && domainbinding->codeset != NULL)
+	    outcharset = domainbinding->codeset;
+	  else
+	    {
+	      outcharset = getenv ("OUTPUT_CHARSET");
+	      if (outcharset == NULL || outcharset[0] == '\0')
+		{
+# ifdef _LIBC
+		  outcharset = _NL_CURRENT (LC_CTYPE, CODESET);
+# else
+#  if HAVE_ICONV
+		  //extern const char *locale_charset PARAMS ((void));
+		  outcharset = locale_charset ();
+#  endif
+# endif
+		}
+	    }
+
+# ifdef _LIBC
+	  /* We always want to use transliteration.  */
+	  outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+	  charset = norm_add_slashes (charset, "");
+	  if (__gconv_open (outcharset, charset, &domain->conv,
+			    GCONV_AVOID_NOCONV)
+	      != __GCONV_OK)
+	    domain->conv = (__gconv_t) -1;
+# else
+#  if HAVE_ICONV
+	  /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
+	     we want to use transliteration.  */
+#   if (defined (__GLIBC__) && ( (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2)) \
+       || (defined (_LIBICONV_VERSION) && _LIBICONV_VERSION >= 0x0105)
+	  if (strchr (outcharset, '/') == NULL)
+	    {
+	      char *tmp;
+
+	      len = strlen (outcharset);
+	      tmp = (char *) alloca (len + 10 + 1);
+	      memcpy (tmp, outcharset, len);
+	      memcpy (tmp + len, "//TRANSLIT", 10 + 1);
+	      outcharset = tmp;
+
+	      domain->conv = iconv_open (outcharset, charset);
+
+	      freea (outcharset);
+	    }
+	  else
+#   endif
+	    domain->conv = iconv_open (outcharset, charset);
+#  endif
+# endif
+
+	  freea (charset);
+	}
+#endif /* _LIBC || HAVE_ICONV */
+    }
+
+  return nullentry;
+}
+
+/* Frees the codeset dependent parts of an opened message catalog.  */
+void
+internal_function
+_nl_free_domain_conv (domain)
+     struct loaded_domain *domain;
+{
+  if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
+    free (domain->conv_tab);
+
+#ifdef _LIBC
+  if (domain->conv != (__gconv_t) -1)
+    __gconv_close (domain->conv);
+#else
+# if HAVE_ICONV
+  if (domain->conv != (iconv_t) -1)
+    iconv_close (domain->conv);
+# endif
+#endif
+}
+
+/* Load the message catalogs specified by FILENAME.  If it is no valid
+   message catalog do nothing.  */
+void
+internal_function
+_nl_load_domain (domain_file, domainbinding)
+     struct loaded_l10nfile *domain_file;
+     struct binding *domainbinding;
+{
+  __libc_lock_define_initialized_recursive (static, lock);
+  int fd = -1;
+  size_t size;
+#ifdef _LIBC
+  struct stat64 st;
+#else
+  struct stat st;
+#endif
+  struct mo_file_header *data = (struct mo_file_header *) -1;
+  int use_mmap = 0;
+  struct loaded_domain *domain;
+  int revision;
+  const char *nullentry;
+
+  __libc_lock_lock_recursive (lock);
+  if (domain_file->decided != 0)
+    {
+      /* There are two possibilities:
+
+         + is is the same thread calling again during this
+	   initialization via _nl_init_domain_conv and _nl_find_msg.  We
+	   have initialized everything this call needs.
+
+	 + this is another thread which tried to initialize this object.
+           Not necessary anymore since if the lock is available this
+	   is finished.
+      */
+      __libc_lock_unlock_recursive (lock);
+      return;
+    }
+
+  domain_file->decided = -1;
+  domain_file->data = NULL;
+
+  /* Note that it would be useless to store domainbinding in domain_file
+     because domainbinding might be == NULL now but != NULL later (after
+     a call to bind_textdomain_codeset).  */
+
+  /* If the record does not represent a valid locale the FILENAME
+     might be NULL.  This can happen when according to the given
+     specification the locale file name is different for XPG and CEN
+     syntax.  */
+  if (domain_file->filename == NULL)
+    goto out;
+
+  /* Try to open the addressed file.  */
+  fd = open (domain_file->filename, O_RDONLY);
+  if (fd == -1)
+    goto out;
+
+  /* We must know about the size of the file.  */
+  if (
+#ifdef _LIBC
+      __builtin_expect (fstat64 (fd, &st) != 0, 0)
+#else
+      __builtin_expect (fstat (fd, &st) != 0, 0)
+#endif
+      || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
+      || __builtin_expect (size < sizeof (struct mo_file_header), 0))
+    /* Something went wrong.  */
+    goto out;;
+
+#ifdef HAVE_MMAP
+  /* Now we are ready to load the file.  If mmap() is available we try
+     this first.  If not available or it failed we try to load it.  */
+  data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
+					 MAP_PRIVATE, fd, 0);
+
+  if (__builtin_expect (data != MAP_FAILED, 1))
+    {
+      /* mmap() call was successful.  */
+      close (fd);
+      fd = -1;
+      use_mmap = 1;
+    }
+#endif
+
+  /* If the data is not yet available (i.e. mmap'ed) we try to load
+     it manually.  */
+  if (data == MAP_FAILED)
+    {
+      size_t to_read;
+      char *read_ptr;
+
+      data = (struct mo_file_header *) malloc (size);
+      if (data == NULL)
+	goto out;
+
+      to_read = size;
+      read_ptr = (char *) data;
+      do
+	{
+	  long int nb = (long int) TEMP_FAILURE_RETRY (read (fd, read_ptr,
+							     to_read));
+	  if (nb <= 0)
+	    goto out;
+
+	  read_ptr += nb;
+	  to_read -= nb;
+	}
+      while (to_read > 0);
+
+      close (fd);
+      fd = -1;
+    }
+
+  /* Using the magic number we can test whether it really is a message
+     catalog file.  */
+  if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
+			0))
+    {
+      /* The magic number is wrong: not a message catalog file.  */
+#ifdef HAVE_MMAP
+      if (use_mmap)
+	munmap ((caddr_t) data, size);
+      else
+#endif
+	free (data);
+      goto out;
+    }
+
+  domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
+  if (domain == NULL)
+    goto out;
+  domain_file->data = domain;
+
+  domain->data = (char *) data;
+  domain->use_mmap = use_mmap;
+  domain->mmap_size = size;
+  domain->must_swap = data->magic != _MAGIC;
+  domain->malloced = NULL;
+
+  /* Fill in the information about the available tables.  */
+  revision = W (domain->must_swap, data->revision);
+  /* We support only the major revisions 0 and 1.  */
+  switch (revision >> 16)
+    {
+    case 0:
+    case 1:
+      domain->nstrings = W (domain->must_swap, data->nstrings);
+      domain->orig_tab = (const struct string_desc *)
+	((char *) data + W (domain->must_swap, data->orig_tab_offset));
+      domain->trans_tab = (const struct string_desc *)
+	((char *) data + W (domain->must_swap, data->trans_tab_offset));
+      domain->hash_size = W (domain->must_swap, data->hash_tab_size);
+      domain->hash_tab =
+	(domain->hash_size > 2
+	 ? (const nls_uint32 *)
+	   ((char *) data + W (domain->must_swap, data->hash_tab_offset))
+	 : NULL);
+      domain->must_swap_hash_tab = domain->must_swap;
+
+      /* Now dispatch on the minor revision.  */
+      switch (revision & 0xffff)
+	{
+	case 0:
+	  domain->n_sysdep_strings = 0;
+	  domain->orig_sysdep_tab = NULL;
+	  domain->trans_sysdep_tab = NULL;
+	  break;
+	case 1:
+	default:
+	  {
+	    nls_uint32 n_sysdep_strings;
+
+	    if (domain->hash_tab == NULL)
+	      /* This is invalid.  These minor revisions need a hash table.  */
+	      goto invalid;
+
+	    n_sysdep_strings =
+	      W (domain->must_swap, data->n_sysdep_strings);
+	    if (n_sysdep_strings > 0)
+	      {
+		nls_uint32 n_sysdep_segments;
+		const struct sysdep_segment *sysdep_segments;
+		const char **sysdep_segment_values;
+		const nls_uint32 *orig_sysdep_tab;
+		const nls_uint32 *trans_sysdep_tab;
+		nls_uint32 n_inmem_sysdep_strings;
+		size_t memneed;
+		char *mem;
+		struct sysdep_string_desc *inmem_orig_sysdep_tab;
+		struct sysdep_string_desc *inmem_trans_sysdep_tab;
+		nls_uint32 *inmem_hash_tab;
+		unsigned int i, j;
+
+		/* Get the values of the system dependent segments.  */
+		n_sysdep_segments =
+		  W (domain->must_swap, data->n_sysdep_segments);
+		sysdep_segments = (const struct sysdep_segment *)
+		  ((char *) data
+		   + W (domain->must_swap, data->sysdep_segments_offset));
+		sysdep_segment_values =
+		  alloca (n_sysdep_segments * sizeof (const char *));
+		for (i = 0; i < n_sysdep_segments; i++)
+		  {
+		    const char *name =
+		      (char *) data
+		      + W (domain->must_swap, sysdep_segments[i].offset);
+		    nls_uint32 namelen =
+		      W (domain->must_swap, sysdep_segments[i].length);
+
+		    if (!(namelen > 0 && name[namelen - 1] == '\0'))
+		      {
+			freea (sysdep_segment_values);
+			goto invalid;
+		      }
+
+		    sysdep_segment_values[i] = get_sysdep_segment_value (name);
+		  }
+
+		orig_sysdep_tab = (const nls_uint32 *)
+		  ((char *) data
+		   + W (domain->must_swap, data->orig_sysdep_tab_offset));
+		trans_sysdep_tab = (const nls_uint32 *)
+		  ((char *) data
+		   + W (domain->must_swap, data->trans_sysdep_tab_offset));
+
+		/* Compute the amount of additional memory needed for the
+		   system dependent strings and the augmented hash table.
+		   At the same time, also drop string pairs which refer to
+		   an undefined system dependent segment.  */
+		n_inmem_sysdep_strings = 0;
+		memneed = domain->hash_size * sizeof (nls_uint32);
+		for (i = 0; i < n_sysdep_strings; i++)
+		  {
+		    int valid = 1;
+		    size_t needs[2];
+
+		    for (j = 0; j < 2; j++)
+		      {
+			const struct sysdep_string *sysdep_string =
+			  (const struct sysdep_string *)
+			  ((char *) data
+			   + W (domain->must_swap,
+				j == 0
+				? orig_sysdep_tab[i]
+				: trans_sysdep_tab[i]));
+			size_t need = 0;
+			const struct segment_pair *p = sysdep_string->segments;
+
+			if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
+			  for (p = sysdep_string->segments;; p++)
+			    {
+			      nls_uint32 sysdepref;
+
+			      need += W (domain->must_swap, p->segsize);
+
+			      sysdepref = W (domain->must_swap, p->sysdepref);
+			      if (sysdepref == SEGMENTS_END)
+				break;
+
+			      if (sysdepref >= n_sysdep_segments)
+				{
+				  /* Invalid.  */
+				  freea (sysdep_segment_values);
+				  goto invalid;
+				}
+
+			      if (sysdep_segment_values[sysdepref] == NULL)
+				{
+				  /* This particular string pair is invalid.  */
+				  valid = 0;
+				  break;
+				}
+
+			      need += strlen (sysdep_segment_values[sysdepref]);
+			    }
+
+			needs[j] = need;
+			if (!valid)
+			  break;
+		      }
+
+		    if (valid)
+		      {
+			n_inmem_sysdep_strings++;
+			memneed += needs[0] + needs[1];
+		      }
+		  }
+		memneed += 2 * n_inmem_sysdep_strings
+			   * sizeof (struct sysdep_string_desc);
+
+		if (n_inmem_sysdep_strings > 0)
+		  {
+		    unsigned int k;
+
+		    /* Allocate additional memory.  */
+		    mem = (char *) malloc (memneed);
+		    if (mem == NULL)
+		      goto invalid;
+
+		    domain->malloced = mem;
+		    inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
+		    mem += n_inmem_sysdep_strings
+			   * sizeof (struct sysdep_string_desc);
+		    inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
+		    mem += n_inmem_sysdep_strings
+			   * sizeof (struct sysdep_string_desc);
+		    inmem_hash_tab = (nls_uint32 *) mem;
+		    mem += domain->hash_size * sizeof (nls_uint32);
+
+		    /* Compute the system dependent strings.  */
+		    k = 0;
+		    for (i = 0; i < n_sysdep_strings; i++)
+		      {
+			int valid = 1;
+
+			for (j = 0; j < 2; j++)
+			  {
+			    const struct sysdep_string *sysdep_string =
+			      (const struct sysdep_string *)
+			      ((char *) data
+			       + W (domain->must_swap,
+				    j == 0
+				    ? orig_sysdep_tab[i]
+				    : trans_sysdep_tab[i]));
+			    const struct segment_pair *p =
+			      sysdep_string->segments;
+
+			    if (W (domain->must_swap, p->sysdepref)
+				!= SEGMENTS_END)
+			      for (p = sysdep_string->segments;; p++)
+				{
+				  nls_uint32 sysdepref;
+
+				  sysdepref =
+				    W (domain->must_swap, p->sysdepref);
+				  if (sysdepref == SEGMENTS_END)
+				    break;
+
+				  if (sysdep_segment_values[sysdepref] == NULL)
+				    {
+				      /* This particular string pair is
+					 invalid.  */
+				      valid = 0;
+				      break;
+				    }
+				}
+
+			    if (!valid)
+			      break;
+			  }
+
+			if (valid)
+			  {
+			    for (j = 0; j < 2; j++)
+			      {
+				const struct sysdep_string *sysdep_string =
+				  (const struct sysdep_string *)
+				  ((char *) data
+				   + W (domain->must_swap,
+					j == 0
+					? orig_sysdep_tab[i]
+					: trans_sysdep_tab[i]));
+				const char *static_segments =
+				  (char *) data
+				  + W (domain->must_swap, sysdep_string->offset);
+				const struct segment_pair *p =
+				  sysdep_string->segments;
+
+				/* Concatenate the segments, and fill
+				   inmem_orig_sysdep_tab[k] (for j == 0) and
+				   inmem_trans_sysdep_tab[k] (for j == 1).  */
+
+				struct sysdep_string_desc *inmem_tab_entry =
+				  (j == 0
+				   ? inmem_orig_sysdep_tab
+				   : inmem_trans_sysdep_tab)
+				  + k;
+
+				if (W (domain->must_swap, p->sysdepref)
+				    == SEGMENTS_END)
+				  {
+				    /* Only one static segment.  */
+				    inmem_tab_entry->length =
+				      W (domain->must_swap, p->segsize);
+				    inmem_tab_entry->pointer = static_segments;
+				  }
+				else
+				  {
+				    inmem_tab_entry->pointer = mem;
+
+				    for (p = sysdep_string->segments;; p++)
+				      {
+					nls_uint32 segsize =
+					  W (domain->must_swap, p->segsize);
+					nls_uint32 sysdepref =
+					  W (domain->must_swap, p->sysdepref);
+					size_t n;
+
+					if (segsize > 0)
+					  {
+					    memcpy (mem, static_segments, segsize);
+					    mem += segsize;
+					    static_segments += segsize;
+					  }
+
+					if (sysdepref == SEGMENTS_END)
+					  break;
+
+					n = strlen (sysdep_segment_values[sysdepref]);
+					memcpy (mem, sysdep_segment_values[sysdepref], n);
+					mem += n;
+				      }
+
+				    inmem_tab_entry->length =
+				      mem - inmem_tab_entry->pointer;
+				  }
+			      }
+
+			    k++;
+			  }
+		      }
+		    if (k != n_inmem_sysdep_strings)
+		      abort ();
+
+		    /* Compute the augmented hash table.  */
+		    for (i = 0; i < domain->hash_size; i++)
+		      inmem_hash_tab[i] =
+			W (domain->must_swap_hash_tab, domain->hash_tab[i]);
+		    for (i = 0; i < n_inmem_sysdep_strings; i++)
+		      {
+			const char *msgid = inmem_orig_sysdep_tab[i].pointer;
+			nls_uint32 hash_val = __hash_string (msgid);
+			nls_uint32 idx = hash_val % domain->hash_size;
+			nls_uint32 incr =
+			  1 + (hash_val % (domain->hash_size - 2));
+
+			for (;;)
+			  {
+			    if (inmem_hash_tab[idx] == 0)
+			      {
+				/* Hash table entry is empty.  Use it.  */
+				inmem_hash_tab[idx] = 1 + domain->nstrings + i;
+				break;
+			      }
+
+			    if (idx >= domain->hash_size - incr)
+			      idx -= domain->hash_size - incr;
+			    else
+			      idx += incr;
+			  }
+		      }
+
+		    domain->n_sysdep_strings = n_inmem_sysdep_strings;
+		    domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
+		    domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
+
+		    domain->hash_tab = inmem_hash_tab;
+		    domain->must_swap_hash_tab = 0;
+		  }
+		else
+		  {
+		    domain->n_sysdep_strings = 0;
+		    domain->orig_sysdep_tab = NULL;
+		    domain->trans_sysdep_tab = NULL;
+		  }
+
+		freea (sysdep_segment_values);
+	      }
+	    else
+	      {
+		domain->n_sysdep_strings = 0;
+		domain->orig_sysdep_tab = NULL;
+		domain->trans_sysdep_tab = NULL;
+	      }
+	  }
+	  break;
+	}
+      break;
+    default:
+      /* This is an invalid revision.  */
+    invalid:
+      /* This is an invalid .mo file.  */
+      if (domain->malloced)
+	free (domain->malloced);
+#ifdef HAVE_MMAP
+      if (use_mmap)
+	munmap ((caddr_t) data, size);
+      else
+#endif
+	free (data);
+      free (domain);
+      domain_file->data = NULL;
+      goto out;
+    }
+
+  /* Now initialize the character set converter from the character set
+     the file is encoded with (found in the header entry) to the domain's
+     specified character set or the locale's character set.  */
+  nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
+
+  /* Also look for a plural specification.  */
+  EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
+
+ out:
+  if (fd != -1)
+    close (fd);
+
+  domain_file->decided = 1;
+
+  __libc_lock_unlock_recursive (lock);
+}
+
+
+#ifdef _LIBC
+void
+internal_function __libc_freeres_fn_section
+_nl_unload_domain (domain)
+     struct loaded_domain *domain;
+{
+  if (domain->plural != &__gettext_germanic_plural)
+    __gettext_free_exp (domain->plural);
+
+  _nl_free_domain_conv (domain);
+
+  if (domain->malloced)
+    free (domain->malloced);
+
+# ifdef _POSIX_MAPPED_FILES
+  if (domain->use_mmap)
+    munmap ((caddr_t) domain->data, domain->mmap_size);
+  else
+# endif	/* _POSIX_MAPPED_FILES */
+    free ((void *) domain->data);
+
+  free (domain);
+}
+#endif
Index: /trunk/libc/src/glibc/intl/locale.alias
===================================================================
--- /trunk/libc/src/glibc/intl/locale.alias	(revision 2448)
+++ /trunk/libc/src/glibc/intl/locale.alias	(revision 2448)
@@ -0,0 +1,75 @@
+# Locale name alias data base.
+# Copyright (C) 1996-2001,2003 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# The format of this file is the same as for the corresponding file of
+# the X Window System, which normally can be found in
+#	/usr/lib/X11/locale/locale.alias
+# A single line contains two fields: an alias and a substitution value.
+# All entries are case independent.
+
+# Note: This file is far from being complete.  If you have a value for
+# your own site which you think might be useful for others too, share
+# it with the rest of us.  Send it using the `glibcbug' script to
+# bugs@gnu.org.
+
+bokmal		nb_NO.ISO-8859-1
+bokmål		nb_NO.ISO-8859-1
+catalan		ca_ES.ISO-8859-1
+croatian	hr_HR.ISO-8859-2
+czech		cs_CZ.ISO-8859-2
+danish          da_DK.ISO-8859-1
+dansk		da_DK.ISO-8859-1
+deutsch		de_DE.ISO-8859-1
+dutch		nl_NL.ISO-8859-1
+eesti		et_EE.ISO-8859-1
+estonian	et_EE.ISO-8859-1
+finnish         fi_FI.ISO-8859-1
+français	fr_FR.ISO-8859-1
+french		fr_FR.ISO-8859-1
+galego		gl_ES.ISO-8859-1
+galician	gl_ES.ISO-8859-1
+german		de_DE.ISO-8859-1
+greek           el_GR.ISO-8859-7
+hebrew          he_IL.ISO-8859-8
+hrvatski	hr_HR.ISO-8859-2
+hungarian       hu_HU.ISO-8859-2
+icelandic       is_IS.ISO-8859-1
+italian         it_IT.ISO-8859-1
+japanese	ja_JP.eucJP
+japanese.euc	ja_JP.eucJP
+ja_JP		ja_JP.eucJP
+ja_JP.ujis	ja_JP.eucJP
+japanese.sjis	ja_JP.SJIS
+korean		ko_KR.eucKR
+korean.euc 	ko_KR.eucKR
+ko_KR		ko_KR.eucKR
+lithuanian      lt_LT.ISO-8859-13
+no_NO		nb_NO.ISO-8859-1
+no_NO.ISO-8859-1 nb_NO.ISO-8859-1
+norwegian       nb_NO.ISO-8859-1
+nynorsk		nn_NO.ISO-8859-1
+polish          pl_PL.ISO-8859-2
+portuguese      pt_PT.ISO-8859-1
+romanian        ro_RO.ISO-8859-2
+russian         ru_RU.ISO-8859-5
+slovak          sk_SK.ISO-8859-2
+slovene         sl_SI.ISO-8859-2
+slovenian       sl_SI.ISO-8859-2
+spanish         es_ES.ISO-8859-1
+swedish         sv_SE.ISO-8859-1
+thai		th_TH.TIS-620
+turkish         tr_TR.ISO-8859-9
Index: /trunk/libc/src/glibc/intl/localealias.c
===================================================================
--- /trunk/libc/src/glibc/intl/localealias.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/localealias.c	(revision 2448)
@@ -0,0 +1,414 @@
+/* Handle aliases for locale names.
+   Copyright (C) 1995-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.  */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE    1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#if defined _LIBC || defined HAVE___FSETLOCKING
+# include <stdio_ext.h>
+#endif
+#include <sys/types.h>
+
+#ifdef __GNUC__
+# undef alloca
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettextP.h"
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions.  This is required by the standard
+   because some ANSI C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# define strcasecmp __strcasecmp
+
+# ifndef mempcpy
+#  define mempcpy __mempcpy
+# endif
+# define HAVE_MEMPCPY	1
+# define HAVE___FSETLOCKING	1
+
+/* We need locking here since we can be called from different places.  */
+# include <bits/libc-lock.h>
+
+__libc_lock_define_initialized (static, lock);
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+/* Some optimizations for glibc.  */
+#ifdef _LIBC
+# define FEOF(fp)		feof_unlocked (fp)
+# define FGETS(buf, n, fp)	fgets_unlocked (buf, n, fp)
+#else
+# define FEOF(fp)		feof (fp)
+# define FGETS(buf, n, fp)	fgets (buf, n, fp)
+#endif
+
+/* For those losing systems which don't have `alloca' we have to add
+   some additional code emulating it.  */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED
+# undef fgets
+# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
+#endif
+#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED
+# undef feof
+# define feof(s) feof_unlocked (s)
+#endif
+
+
+struct alias_map
+{
+  const char *alias;
+  const char *value;
+};
+
+
+#ifndef _LIBC
+# define libc_freeres_ptr(decl) decl
+#endif
+
+libc_freeres_ptr (static char *string_space);
+static size_t string_space_act;
+static size_t string_space_max;
+libc_freeres_ptr (static struct alias_map *map);
+static size_t nmap;
+static size_t maxmap;
+
+
+/* Prototypes for local functions.  */
+static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
+     internal_function;
+static int extend_alias_table PARAMS ((void));
+static int alias_compare PARAMS ((const struct alias_map *map1,
+				  const struct alias_map *map2));
+
+
+const char *
+_nl_expand_alias (name)
+    const char *name;
+{
+  static const char *locale_alias_path = LOCALE_ALIAS_PATH;
+  struct alias_map *retval;
+  const char *result = NULL;
+  size_t added;
+
+#ifdef _LIBC
+  __libc_lock_lock (lock);
+#endif
+
+  do
+    {
+      struct alias_map item;
+
+      item.alias = name;
+
+      if (nmap > 0)
+	retval = (struct alias_map *) bsearch (&item, map, nmap,
+					       sizeof (struct alias_map),
+					       (int (*) PARAMS ((const void *,
+								 const void *))
+						) alias_compare);
+      else
+	retval = NULL;
+
+      /* We really found an alias.  Return the value.  */
+      if (retval != NULL)
+	{
+	  result = retval->value;
+	  break;
+	}
+
+      /* Perhaps we can find another alias file.  */
+      added = 0;
+      while (added == 0 && locale_alias_path[0] != '\0')
+	{
+	  const char *start;
+
+	  while (locale_alias_path[0] == PATH_SEPARATOR)
+	    ++locale_alias_path;
+	  start = locale_alias_path;
+
+	  while (locale_alias_path[0] != '\0'
+		 && locale_alias_path[0] != PATH_SEPARATOR)
+	    ++locale_alias_path;
+
+	  if (start < locale_alias_path)
+	    added = read_alias_file (start, locale_alias_path - start);
+	}
+    }
+  while (added != 0);
+
+#ifdef _LIBC
+  __libc_lock_unlock (lock);
+#endif
+
+  return result;
+}
+
+
+static size_t
+internal_function
+read_alias_file (fname, fname_len)
+     const char *fname;
+     int fname_len;
+{
+  FILE *fp;
+  char *full_fname;
+  size_t added;
+  static const char aliasfile[] = "/locale.alias";
+
+  full_fname = (char *) alloca (fname_len + sizeof aliasfile);
+#ifdef HAVE_MEMPCPY
+  mempcpy (mempcpy (full_fname, fname, fname_len),
+	   aliasfile, sizeof aliasfile);
+#else
+  memcpy (full_fname, fname, fname_len);
+  memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
+#endif
+
+  /* Note the file is opened with cancellation in the I/O functions
+     disabled.  */
+  fp = fopen (full_fname, "rc");
+  freea (full_fname);
+  if (fp == NULL)
+    return 0;
+
+#ifdef HAVE___FSETLOCKING
+  /* No threads present.  */
+  __fsetlocking (fp, FSETLOCKING_BYCALLER);
+#endif
+
+  added = 0;
+  while (!FEOF (fp))
+    {
+      /* It is a reasonable approach to use a fix buffer here because
+	 a) we are only interested in the first two fields
+	 b) these fields must be usable as file names and so must not
+	    be that long
+	 We avoid a multi-kilobyte buffer here since this would use up
+	 stack space which we might not have if the program ran out of
+	 memory.  */
+      char buf[400];
+      char *alias;
+      char *value;
+      char *cp;
+      int complete_line;
+
+      if (FGETS (buf, sizeof buf, fp) == NULL)
+	/* EOF reached.  */
+	break;
+
+      /* Determine whether the line is complete.  */
+      complete_line = strchr (buf, '\n') != NULL;
+
+      cp = buf;
+      /* Ignore leading white space.  */
+      while (isspace ((unsigned char) cp[0]))
+	++cp;
+
+      /* A leading '#' signals a comment line.  */
+      if (cp[0] != '\0' && cp[0] != '#')
+	{
+	  alias = cp++;
+	  while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
+	    ++cp;
+	  /* Terminate alias name.  */
+	  if (cp[0] != '\0')
+	    *cp++ = '\0';
+
+	  /* Now look for the beginning of the value.  */
+	  while (isspace ((unsigned char) cp[0]))
+	    ++cp;
+
+	  if (cp[0] != '\0')
+	    {
+	      size_t alias_len;
+	      size_t value_len;
+
+	      value = cp++;
+	      while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
+		++cp;
+	      /* Terminate value.  */
+	      if (cp[0] == '\n')
+		{
+		  /* This has to be done to make the following test
+		     for the end of line possible.  We are looking for
+		     the terminating '\n' which do not overwrite here.  */
+		  *cp++ = '\0';
+		  *cp = '\n';
+		}
+	      else if (cp[0] != '\0')
+		*cp++ = '\0';
+
+	      if (nmap >= maxmap)
+		if (__builtin_expect (extend_alias_table (), 0))
+		  return added;
+
+	      alias_len = strlen (alias) + 1;
+	      value_len = strlen (value) + 1;
+
+	      if (string_space_act + alias_len + value_len > string_space_max)
+		{
+		  /* Increase size of memory pool.  */
+		  size_t new_size = (string_space_max
+				     + (alias_len + value_len > 1024
+					? alias_len + value_len : 1024));
+		  char *new_pool = (char *) realloc (string_space, new_size);
+		  if (new_pool == NULL)
+		    return added;
+
+		  if (__builtin_expect (string_space != new_pool, 0))
+		    {
+		      size_t i;
+
+		      for (i = 0; i < nmap; i++)
+			{
+			  map[i].alias += new_pool - string_space;
+			  map[i].value += new_pool - string_space;
+			}
+		    }
+
+		  string_space = new_pool;
+		  string_space_max = new_size;
+		}
+
+	      map[nmap].alias = memcpy (&string_space[string_space_act],
+					alias, alias_len);
+	      string_space_act += alias_len;
+
+	      map[nmap].value = memcpy (&string_space[string_space_act],
+					value, value_len);
+	      string_space_act += value_len;
+
+	      ++nmap;
+	      ++added;
+	    }
+	}
+
+      /* Possibly not the whole line fits into the buffer.  Ignore
+	 the rest of the line.  */
+      if (! complete_line)
+	do
+	  if (FGETS (buf, sizeof buf, fp) == NULL)
+	    /* Make sure the inner loop will be left.  The outer loop
+	       will exit at the `feof' test.  */
+	    break;
+	while (strchr (buf, '\n') == NULL);
+    }
+
+  /* Should we test for ferror()?  I think we have to silently ignore
+     errors.  --drepper  */
+  fclose (fp);
+
+  if (added > 0)
+    qsort (map, nmap, sizeof (struct alias_map),
+	   (int (*) PARAMS ((const void *, const void *))) alias_compare);
+
+  return added;
+}
+
+
+static int
+extend_alias_table ()
+{
+  size_t new_size;
+  struct alias_map *new_map;
+
+  new_size = maxmap == 0 ? 100 : 2 * maxmap;
+  new_map = (struct alias_map *) realloc (map, (new_size
+						* sizeof (struct alias_map)));
+  if (new_map == NULL)
+    /* Simply don't extend: we don't have any more core.  */
+    return -1;
+
+  map = new_map;
+  maxmap = new_size;
+  return 0;
+}
+
+
+static int
+alias_compare (map1, map2)
+     const struct alias_map *map1;
+     const struct alias_map *map2;
+{
+#if defined _LIBC || defined HAVE_STRCASECMP
+  return strcasecmp (map1->alias, map2->alias);
+#else
+  const unsigned char *p1 = (const unsigned char *) map1->alias;
+  const unsigned char *p2 = (const unsigned char *) map2->alias;
+  unsigned char c1, c2;
+
+  if (p1 == p2)
+    return 0;
+
+  do
+    {
+      /* I know this seems to be odd but the tolower() function in
+	 some systems libc cannot handle nonalpha characters.  */
+      c1 = isupper (*p1) ? tolower (*p1) : *p1;
+      c2 = isupper (*p2) ? tolower (*p2) : *p2;
+      if (c1 == '\0')
+	break;
+      ++p1;
+      ++p2;
+    }
+  while (c1 == c2);
+
+  return c1 - c2;
+#endif
+}
Index: /trunk/libc/src/glibc/intl/localecharset.c
===================================================================
--- /trunk/libc/src/glibc/intl/localecharset.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/localecharset.c	(revision 2448)
@@ -0,0 +1,345 @@
+/* Determine a canonical name for the current locale's character encoding.
+
+   Copyright (C) 2000-2003 Free Software Foundation, Inc.
+
+   This program 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, or (at your option)
+   any later version.
+
+   This program 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 program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification.  */
+#include "localecharset.h"
+
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# undef WIN32   /* avoid warning on mingw32 */
+# define WIN32
+#endif
+
+#if defined __EMX__
+/* Assume EMX program runs on OS/2, even if compiled under DOS.  */
+# define OS2
+#endif
+
+#if !defined WIN32
+# if HAVE_LANGINFO_CODESET
+#  include <langinfo.h>
+# else
+#  if HAVE_SETLOCALE
+#   include <locale.h>
+#  endif
+# endif
+#elif defined WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+#if defined OS2
+# define INCL_DOS
+# include <os2.h>
+#endif
+
+#if defined(ENABLE_RELOCATABLE) && ENABLE_RELOCATABLE
+# include "relocatable.h"
+#else
+# define relocate(pathname) (pathname)
+#endif
+
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+#endif
+
+#ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+#endif
+
+#ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+#endif
+
+#if HAVE_DECL_GETC_UNLOCKED
+# undef getc
+# define getc getc_unlocked
+#endif
+
+/* The following static variable is declared 'volatile' to avoid a
+   possible multithread problem in the function get_charset_aliases. If we
+   are running in a threaded environment, and if two threads initialize
+   'charset_aliases' simultaneously, both will produce the same value,
+   and everything will be ok if the two assignments to 'charset_aliases'
+   are atomic. But I don't know what will happen if the two assignments mix.  */
+#if __STDC__ != 1
+# define volatile /* empty */
+#endif
+/* Pointer to the contents of the charset.alias file, if it has already been
+   read, else NULL.  Its format is:
+   ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0'  */
+static const char * volatile charset_aliases;
+
+/* Return a pointer to the contents of the charset.alias file.  */
+static const char *
+get_charset_aliases ()
+{
+  const char *cp;
+
+  cp = charset_aliases;
+  if (cp == NULL)
+    {
+#if !(defined VMS || defined WIN32)
+      FILE *fp;
+      const char *dir = relocate (LIBDIR);
+      const char *base = "charset.alias";
+      char *file_name;
+
+      /* Concatenate dir and base into freshly allocated file_name.  */
+      {
+	size_t dir_len = strlen (dir);
+	size_t base_len = strlen (base);
+	int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
+	file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
+	if (file_name != NULL)
+	  {
+	    memcpy (file_name, dir, dir_len);
+	    if (add_slash)
+	      file_name[dir_len] = DIRECTORY_SEPARATOR;
+	    memcpy (file_name + dir_len + add_slash, base, base_len + 1);
+	  }
+      }
+
+      if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL)
+	/* Out of memory or file not found, treat it as empty.  */
+	cp = "";
+      else
+	{
+	  /* Parse the file's contents.  */
+	  int c;
+	  char buf1[50+1];
+	  char buf2[50+1];
+	  char *res_ptr = NULL;
+	  size_t res_size = 0;
+	  size_t l1, l2;
+
+	  for (;;)
+	    {
+	      c = getc (fp);
+	      if (c == EOF)
+		break;
+	      if (c == '\n' || c == ' ' || c == '\t')
+		continue;
+	      if (c == '#')
+		{
+		  /* Skip comment, to end of line.  */
+		  do
+		    c = getc (fp);
+		  while (!(c == EOF || c == '\n'));
+		  if (c == EOF)
+		    break;
+		  continue;
+		}
+	      ungetc (c, fp);
+	      if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
+		break;
+	      l1 = strlen (buf1);
+	      l2 = strlen (buf2);
+	      if (res_size == 0)
+		{
+		  res_size = l1 + 1 + l2 + 1;
+		  res_ptr = (char *) malloc (res_size + 1);
+		}
+	      else
+		{
+		  res_size += l1 + 1 + l2 + 1;
+		  res_ptr = (char *) realloc (res_ptr, res_size + 1);
+		}
+	      if (res_ptr == NULL)
+		{
+		  /* Out of memory. */
+		  res_size = 0;
+		  break;
+		}
+	      strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
+	      strcpy (res_ptr + res_size - (l2 + 1), buf2);
+	    }
+	  fclose (fp);
+	  if (res_size == 0)
+	    cp = "";
+	  else
+	    {
+	      *(res_ptr + res_size) = '\0';
+	      cp = res_ptr;
+	    }
+	}
+
+      if (file_name != NULL)
+	free (file_name);
+
+#else
+
+# if defined VMS
+      /* To avoid the troubles of an extra file charset.alias_vms in the
+	 sources of many GNU packages, simply inline the aliases here.  */
+      /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
+	 "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
+	 section 10.7 "Handling Different Character Sets".  */
+      cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
+	   "ISO8859-2" "\0" "ISO-8859-2" "\0"
+	   "ISO8859-5" "\0" "ISO-8859-5" "\0"
+	   "ISO8859-7" "\0" "ISO-8859-7" "\0"
+	   "ISO8859-8" "\0" "ISO-8859-8" "\0"
+	   "ISO8859-9" "\0" "ISO-8859-9" "\0"
+	   /* Japanese */
+	   "eucJP" "\0" "EUC-JP" "\0"
+	   "SJIS" "\0" "SHIFT_JIS" "\0"
+	   "DECKANJI" "\0" "DEC-KANJI" "\0"
+	   "SDECKANJI" "\0" "EUC-JP" "\0"
+	   /* Chinese */
+	   "eucTW" "\0" "EUC-TW" "\0"
+	   "DECHANYU" "\0" "DEC-HANYU" "\0"
+	   "DECHANZI" "\0" "GB2312" "\0"
+	   /* Korean */
+	   "DECKOREAN" "\0" "EUC-KR" "\0";
+# endif
+
+# if defined WIN32
+      /* To avoid the troubles of installing a separate file in the same
+	 directory as the DLL and of retrieving the DLL's directory at
+	 runtime, simply inline the aliases here.  */
+
+      cp = "CP936" "\0" "GBK" "\0"
+	   "CP1361" "\0" "JOHAB" "\0"
+	   "CP20127" "\0" "ASCII" "\0"
+	   "CP20866" "\0" "KOI8-R" "\0"
+	   "CP21866" "\0" "KOI8-RU" "\0"
+	   "CP28591" "\0" "ISO-8859-1" "\0"
+	   "CP28592" "\0" "ISO-8859-2" "\0"
+	   "CP28593" "\0" "ISO-8859-3" "\0"
+	   "CP28594" "\0" "ISO-8859-4" "\0"
+	   "CP28595" "\0" "ISO-8859-5" "\0"
+	   "CP28596" "\0" "ISO-8859-6" "\0"
+	   "CP28597" "\0" "ISO-8859-7" "\0"
+	   "CP28598" "\0" "ISO-8859-8" "\0"
+	   "CP28599" "\0" "ISO-8859-9" "\0"
+	   "CP28605" "\0" "ISO-8859-15" "\0";
+# endif
+#endif
+
+      charset_aliases = cp;
+    }
+
+  return cp;
+}
+
+/* Determine the current locale's character encoding, and canonicalize it
+   into one of the canonical names listed in config.charset.
+   The result must not be freed; it is statically allocated.
+   If the canonical name cannot be determined, the result is a non-canonical
+   name.  */
+
+#ifdef STATIC
+STATIC
+#endif
+const char *
+locale_charset ()
+{
+  const char *codeset;
+  const char *aliases;
+
+#if !defined WIN32
+
+# if HAVE_LANGINFO_CODESET
+
+  /* Most systems support nl_langinfo (CODESET) nowadays.  */
+  codeset = nl_langinfo (CODESET);
+
+# else
+
+  /* On old systems which lack it, use setlocale or getenv.  */
+  const char *locale = NULL;
+
+  /* But most old systems don't have a complete set of locales.  Some
+     (like SunOS 4 or DJGPP) have only the C locale.  Therefore we don't
+     use setlocale here; it would return "C" when it doesn't support the
+     locale name the user has set.  */
+#  if HAVE_SETLOCALE && 0
+  locale = setlocale (LC_CTYPE, NULL);
+#  endif
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_ALL");
+      if (locale == NULL || locale[0] == '\0')
+	{
+	  locale = getenv ("LC_CTYPE");
+	  if (locale == NULL || locale[0] == '\0')
+	    locale = getenv ("LANG");
+	}
+    }
+
+  /* On some old systems, one used to set locale = "iso8859_1". On others,
+     you set it to "language_COUNTRY.charset". In any case, we resolve it
+     through the charset.alias file.  */
+  codeset = locale;
+
+# endif
+
+#elif defined WIN32
+
+  static char buf[2 + 10 + 1];
+
+  /* Woe32 has a function returning the locale's codepage as a number.  */
+  sprintf (buf, "CP%u", GetACP ());
+  codeset = buf;
+
+#endif
+
+  if (codeset == NULL)
+    /* The canonical name cannot be determined.  */
+    codeset = "";
+
+  /* Resolve alias. */
+  for (aliases = get_charset_aliases ();
+       *aliases != '\0';
+       aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
+    if (strcmp (codeset, aliases) == 0
+	|| (aliases[0] == '*' && aliases[1] == '\0'))
+      {
+	codeset = aliases + strlen (aliases) + 1;
+	break;
+      }
+
+  /* Don't return an empty string.  GNU libc and GNU libiconv interpret
+     the empty string as denoting "the locale's character encoding",
+     thus GNU libiconv would call this function a second time.  */
+  if (codeset[0] == '\0')
+    codeset = "ASCII";
+
+  return codeset;
+}
Index: /trunk/libc/src/glibc/intl/localecharset.h
===================================================================
--- /trunk/libc/src/glibc/intl/localecharset.h	(revision 2448)
+++ /trunk/libc/src/glibc/intl/localecharset.h	(revision 2448)
@@ -0,0 +1,43 @@
+/* Determine a canonical name for the current locale's character encoding.
+   Copyright (C) 2000-2003 Free Software Foundation, Inc.
+   This file is part of the GNU CHARSET Library.
+
+   This program 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, or (at your option)
+   any later version.
+
+   This program 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 program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifndef _LOCALCHARSET_H
+#define _LOCALCHARSET_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define locale_charset __libc_locale_charset //bird
+
+/* Determine the current locale's character encoding, and canonicalize it
+   into one of the canonical names listed in config.charset.
+   The result must not be freed; it is statically allocated.
+   If the canonical name cannot be determined, the result is a non-canonical
+   name.  */
+extern const char * locale_charset (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _LOCALCHARSET_H */
Index: /trunk/libc/src/glibc/intl/localename.c
===================================================================
--- /trunk/libc/src/glibc/intl/localename.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/localename.c	(revision 2448)
@@ -0,0 +1,773 @@
+/* Determine the current selected locale.
+   Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
+
+   This program 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, or (at your option)
+   any later version.
+
+   This program 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 program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* Written by Ulrich Drepper <drepper@gnu.org>, 1995.  */
+/* Win32 code written by Tor Lillqvist <tml@iki.fi>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <locale.h>
+
+#include "gettextP.h"
+
+#if defined _WIN32 || defined __WIN32__
+# undef WIN32   /* avoid warning on mingw32 */
+# define WIN32
+#endif
+
+#ifdef WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* Mingw headers don't have latest language and sublanguage codes.  */
+# ifndef LANG_AFRIKAANS
+# define LANG_AFRIKAANS 0x36
+# endif
+# ifndef LANG_ALBANIAN
+# define LANG_ALBANIAN 0x1c
+# endif
+# ifndef LANG_ARABIC
+# define LANG_ARABIC 0x01
+# endif
+# ifndef LANG_ARMENIAN
+# define LANG_ARMENIAN 0x2b
+# endif
+# ifndef LANG_ASSAMESE
+# define LANG_ASSAMESE 0x4d
+# endif
+# ifndef LANG_AZERI
+# define LANG_AZERI 0x2c
+# endif
+# ifndef LANG_BASQUE
+# define LANG_BASQUE 0x2d
+# endif
+# ifndef LANG_BELARUSIAN
+# define LANG_BELARUSIAN 0x23
+# endif
+# ifndef LANG_BENGALI
+# define LANG_BENGALI 0x45
+# endif
+# ifndef LANG_CATALAN
+# define LANG_CATALAN 0x03
+# endif
+# ifndef LANG_DIVEHI
+# define LANG_DIVEHI 0x65
+# endif
+# ifndef LANG_ESTONIAN
+# define LANG_ESTONIAN 0x25
+# endif
+# ifndef LANG_FAEROESE
+# define LANG_FAEROESE 0x38
+# endif
+# ifndef LANG_FARSI
+# define LANG_FARSI 0x29
+# endif
+# ifndef LANG_GALICIAN
+# define LANG_GALICIAN 0x56
+# endif
+# ifndef LANG_GEORGIAN
+# define LANG_GEORGIAN 0x37
+# endif
+# ifndef LANG_GUJARATI
+# define LANG_GUJARATI 0x47
+# endif
+# ifndef LANG_HEBREW
+# define LANG_HEBREW 0x0d
+# endif
+# ifndef LANG_HINDI
+# define LANG_HINDI 0x39
+# endif
+# ifndef LANG_INDONESIAN
+# define LANG_INDONESIAN 0x21
+# endif
+# ifndef LANG_KANNADA
+# define LANG_KANNADA 0x4b
+# endif
+# ifndef LANG_KASHMIRI
+# define LANG_KASHMIRI 0x60
+# endif
+# ifndef LANG_KAZAK
+# define LANG_KAZAK 0x3f
+# endif
+# ifndef LANG_KONKANI
+# define LANG_KONKANI 0x57
+# endif
+# ifndef LANG_KYRGYZ
+# define LANG_KYRGYZ 0x40
+# endif
+# ifndef LANG_LATVIAN
+# define LANG_LATVIAN 0x26
+# endif
+# ifndef LANG_LITHUANIAN
+# define LANG_LITHUANIAN 0x27
+# endif
+# ifndef LANG_MACEDONIAN
+# define LANG_MACEDONIAN 0x2f
+# endif
+# ifndef LANG_MALAY
+# define LANG_MALAY 0x3e
+# endif
+# ifndef LANG_MALAYALAM
+# define LANG_MALAYALAM 0x4c
+# endif
+# ifndef LANG_MANIPURI
+# define LANG_MANIPURI 0x58
+# endif
+# ifndef LANG_MARATHI
+# define LANG_MARATHI 0x4e
+# endif
+# ifndef LANG_MONGOLIAN
+# define LANG_MONGOLIAN 0x50
+# endif
+# ifndef LANG_NEPALI
+# define LANG_NEPALI 0x61
+# endif
+# ifndef LANG_ORIYA
+# define LANG_ORIYA 0x48
+# endif
+# ifndef LANG_PUNJABI
+# define LANG_PUNJABI 0x46
+# endif
+# ifndef LANG_SANSKRIT
+# define LANG_SANSKRIT 0x4f
+# endif
+# ifndef LANG_SERBIAN
+# define LANG_SERBIAN 0x1a
+# endif
+# ifndef LANG_SINDHI
+# define LANG_SINDHI 0x59
+# endif
+# ifndef LANG_SLOVAK
+# define LANG_SLOVAK 0x1b
+# endif
+# ifndef LANG_SORBIAN
+# define LANG_SORBIAN 0x2e
+# endif
+# ifndef LANG_SWAHILI
+# define LANG_SWAHILI 0x41
+# endif
+# ifndef LANG_SYRIAC
+# define LANG_SYRIAC 0x5a
+# endif
+# ifndef LANG_TAMIL
+# define LANG_TAMIL 0x49
+# endif
+# ifndef LANG_TATAR
+# define LANG_TATAR 0x44
+# endif
+# ifndef LANG_TELUGU
+# define LANG_TELUGU 0x4a
+# endif
+# ifndef LANG_THAI
+# define LANG_THAI 0x1e
+# endif
+# ifndef LANG_UKRAINIAN
+# define LANG_UKRAINIAN 0x22
+# endif
+# ifndef LANG_URDU
+# define LANG_URDU 0x20
+# endif
+# ifndef LANG_UZBEK
+# define LANG_UZBEK 0x43
+# endif
+# ifndef LANG_VIETNAMESE
+# define LANG_VIETNAMESE 0x2a
+# endif
+# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
+# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
+# endif
+# ifndef SUBLANG_ARABIC_IRAQ
+# define SUBLANG_ARABIC_IRAQ 0x02
+# endif
+# ifndef SUBLANG_ARABIC_EGYPT
+# define SUBLANG_ARABIC_EGYPT 0x03
+# endif
+# ifndef SUBLANG_ARABIC_LIBYA
+# define SUBLANG_ARABIC_LIBYA 0x04
+# endif
+# ifndef SUBLANG_ARABIC_ALGERIA
+# define SUBLANG_ARABIC_ALGERIA 0x05
+# endif
+# ifndef SUBLANG_ARABIC_MOROCCO
+# define SUBLANG_ARABIC_MOROCCO 0x06
+# endif
+# ifndef SUBLANG_ARABIC_TUNISIA
+# define SUBLANG_ARABIC_TUNISIA 0x07
+# endif
+# ifndef SUBLANG_ARABIC_OMAN
+# define SUBLANG_ARABIC_OMAN 0x08
+# endif
+# ifndef SUBLANG_ARABIC_YEMEN
+# define SUBLANG_ARABIC_YEMEN 0x09
+# endif
+# ifndef SUBLANG_ARABIC_SYRIA
+# define SUBLANG_ARABIC_SYRIA 0x0a
+# endif
+# ifndef SUBLANG_ARABIC_JORDAN
+# define SUBLANG_ARABIC_JORDAN 0x0b
+# endif
+# ifndef SUBLANG_ARABIC_LEBANON
+# define SUBLANG_ARABIC_LEBANON 0x0c
+# endif
+# ifndef SUBLANG_ARABIC_KUWAIT
+# define SUBLANG_ARABIC_KUWAIT 0x0d
+# endif
+# ifndef SUBLANG_ARABIC_UAE
+# define SUBLANG_ARABIC_UAE 0x0e
+# endif
+# ifndef SUBLANG_ARABIC_BAHRAIN
+# define SUBLANG_ARABIC_BAHRAIN 0x0f
+# endif
+# ifndef SUBLANG_ARABIC_QATAR
+# define SUBLANG_ARABIC_QATAR 0x10
+# endif
+# ifndef SUBLANG_AZERI_LATIN
+# define SUBLANG_AZERI_LATIN 0x01
+# endif
+# ifndef SUBLANG_AZERI_CYRILLIC
+# define SUBLANG_AZERI_CYRILLIC 0x02
+# endif
+# ifndef SUBLANG_CHINESE_MACAU
+# define SUBLANG_CHINESE_MACAU 0x05
+# endif
+# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
+# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
+# endif
+# ifndef SUBLANG_ENGLISH_JAMAICA
+# define SUBLANG_ENGLISH_JAMAICA 0x08
+# endif
+# ifndef SUBLANG_ENGLISH_CARIBBEAN
+# define SUBLANG_ENGLISH_CARIBBEAN 0x09
+# endif
+# ifndef SUBLANG_ENGLISH_BELIZE
+# define SUBLANG_ENGLISH_BELIZE 0x0a
+# endif
+# ifndef SUBLANG_ENGLISH_TRINIDAD
+# define SUBLANG_ENGLISH_TRINIDAD 0x0b
+# endif
+# ifndef SUBLANG_ENGLISH_ZIMBABWE
+# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
+# endif
+# ifndef SUBLANG_ENGLISH_PHILIPPINES
+# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
+# endif
+# ifndef SUBLANG_FRENCH_LUXEMBOURG
+# define SUBLANG_FRENCH_LUXEMBOURG 0x05
+# endif
+# ifndef SUBLANG_FRENCH_MONACO
+# define SUBLANG_FRENCH_MONACO 0x06
+# endif
+# ifndef SUBLANG_GERMAN_LUXEMBOURG
+# define SUBLANG_GERMAN_LUXEMBOURG 0x04
+# endif
+# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
+# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
+# endif
+# ifndef SUBLANG_KASHMIRI_INDIA
+# define SUBLANG_KASHMIRI_INDIA 0x02
+# endif
+# ifndef SUBLANG_MALAY_MALAYSIA
+# define SUBLANG_MALAY_MALAYSIA 0x01
+# endif
+# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
+# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
+# endif
+# ifndef SUBLANG_NEPALI_INDIA
+# define SUBLANG_NEPALI_INDIA 0x02
+# endif
+# ifndef SUBLANG_SERBIAN_LATIN
+# define SUBLANG_SERBIAN_LATIN 0x02
+# endif
+# ifndef SUBLANG_SERBIAN_CYRILLIC
+# define SUBLANG_SERBIAN_CYRILLIC 0x03
+# endif
+# ifndef SUBLANG_SPANISH_GUATEMALA
+# define SUBLANG_SPANISH_GUATEMALA 0x04
+# endif
+# ifndef SUBLANG_SPANISH_COSTA_RICA
+# define SUBLANG_SPANISH_COSTA_RICA 0x05
+# endif
+# ifndef SUBLANG_SPANISH_PANAMA
+# define SUBLANG_SPANISH_PANAMA 0x06
+# endif
+# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
+# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
+# endif
+# ifndef SUBLANG_SPANISH_VENEZUELA
+# define SUBLANG_SPANISH_VENEZUELA 0x08
+# endif
+# ifndef SUBLANG_SPANISH_COLOMBIA
+# define SUBLANG_SPANISH_COLOMBIA 0x09
+# endif
+# ifndef SUBLANG_SPANISH_PERU
+# define SUBLANG_SPANISH_PERU 0x0a
+# endif
+# ifndef SUBLANG_SPANISH_ARGENTINA
+# define SUBLANG_SPANISH_ARGENTINA 0x0b
+# endif
+# ifndef SUBLANG_SPANISH_ECUADOR
+# define SUBLANG_SPANISH_ECUADOR 0x0c
+# endif
+# ifndef SUBLANG_SPANISH_CHILE
+# define SUBLANG_SPANISH_CHILE 0x0d
+# endif
+# ifndef SUBLANG_SPANISH_URUGUAY
+# define SUBLANG_SPANISH_URUGUAY 0x0e
+# endif
+# ifndef SUBLANG_SPANISH_PARAGUAY
+# define SUBLANG_SPANISH_PARAGUAY 0x0f
+# endif
+# ifndef SUBLANG_SPANISH_BOLIVIA
+# define SUBLANG_SPANISH_BOLIVIA 0x10
+# endif
+# ifndef SUBLANG_SPANISH_EL_SALVADOR
+# define SUBLANG_SPANISH_EL_SALVADOR 0x11
+# endif
+# ifndef SUBLANG_SPANISH_HONDURAS
+# define SUBLANG_SPANISH_HONDURAS 0x12
+# endif
+# ifndef SUBLANG_SPANISH_NICARAGUA
+# define SUBLANG_SPANISH_NICARAGUA 0x13
+# endif
+# ifndef SUBLANG_SPANISH_PUERTO_RICO
+# define SUBLANG_SPANISH_PUERTO_RICO 0x14
+# endif
+# ifndef SUBLANG_SWEDISH_FINLAND
+# define SUBLANG_SWEDISH_FINLAND 0x02
+# endif
+# ifndef SUBLANG_URDU_PAKISTAN
+# define SUBLANG_URDU_PAKISTAN 0x01
+# endif
+# ifndef SUBLANG_URDU_INDIA
+# define SUBLANG_URDU_INDIA 0x02
+# endif
+# ifndef SUBLANG_UZBEK_LATIN
+# define SUBLANG_UZBEK_LATIN 0x01
+# endif
+# ifndef SUBLANG_UZBEK_CYRILLIC
+# define SUBLANG_UZBEK_CYRILLIC 0x02
+# endif
+#endif
+
+/* XPG3 defines the result of 'setlocale (category, NULL)' as:
+   "Directs 'setlocale()' to query 'category' and return the current
+    setting of 'local'."
+   However it does not specify the exact format.  Neither do SUSV2 and
+   ISO C 99.  So we can use this feature only on selected systems (e.g.
+   those using GNU C Library).  */
+#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2)
+# define HAVE_LOCALE_NULL
+#endif
+
+/* Determine the current locale's name, and canonicalize it into XPG syntax
+     language[_territory[.codeset]][@modifier]
+   The codeset part in the result is not reliable; the locale_charset()
+   should be used for codeset information instead.
+   The result must not be freed; it is statically allocated.  */
+
+const char *
+_nl_locale_name (int category, const char *categoryname)
+{
+  const char *retval;
+
+#ifndef WIN32
+
+  /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
+     On some systems this can be done by the 'setlocale' function itself.  */
+# if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
+  retval = setlocale (category, NULL);
+# else
+  /* Setting of LC_ALL overwrites all other.  */
+  retval = getenv ("LC_ALL");
+  if (retval == NULL || retval[0] == '\0')
+    {
+      /* Next comes the name of the desired category.  */
+      retval = getenv (categoryname);
+      if (retval == NULL || retval[0] == '\0')
+	{
+	  /* Last possibility is the LANG environment variable.  */
+	  retval = getenv ("LANG");
+	  if (retval == NULL || retval[0] == '\0')
+	    /* We use C as the default domain.  POSIX says this is
+	       implementation defined.  */
+	    retval = "C";
+	}
+    }
+# endif
+
+  return retval;
+
+#else /* WIN32 */
+
+  /* Return an XPG style locale name language[_territory][@modifier].
+     Don't even bother determining the codeset; it's not useful in this
+     context, because message catalogs are not specific to a single
+     codeset.  */
+
+  LCID lcid;
+  LANGID langid;
+  int primary, sub;
+
+  /* Let the user override the system settings through environment
+     variables, as on POSIX systems.  */
+  retval = getenv ("LC_ALL");
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+  retval = getenv (categoryname);
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+  retval = getenv ("LANG");
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+
+  /* Use native Win32 API locale ID.  */
+  lcid = GetThreadLocale ();
+
+  /* Strip off the sorting rules, keep only the language part.  */
+  langid = LANGIDFROMLCID (lcid);
+
+  /* Split into language and territory part.  */
+  primary = PRIMARYLANGID (langid);
+  sub = SUBLANGID (langid);
+
+  /* Dispatch on language.
+     See also http://www.unicode.org/unicode/onlinedat/languages.html .
+     For details about languages, see http://www.ethnologue.com/ .  */
+  switch (primary)
+    {
+    case LANG_AFRIKAANS: return "af_ZA";
+    case LANG_ALBANIAN: return "sq_AL";
+    case 0x5e: /* AMHARIC */ return "am_ET";
+    case LANG_ARABIC:
+      switch (sub)
+	{
+	case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
+	case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
+	case SUBLANG_ARABIC_EGYPT: return "ar_EG";
+	case SUBLANG_ARABIC_LIBYA: return "ar_LY";
+	case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
+	case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
+	case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
+	case SUBLANG_ARABIC_OMAN: return "ar_OM";
+	case SUBLANG_ARABIC_YEMEN: return "ar_YE";
+	case SUBLANG_ARABIC_SYRIA: return "ar_SY";
+	case SUBLANG_ARABIC_JORDAN: return "ar_JO";
+	case SUBLANG_ARABIC_LEBANON: return "ar_LB";
+	case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
+	case SUBLANG_ARABIC_UAE: return "ar_AE";
+	case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
+	case SUBLANG_ARABIC_QATAR: return "ar_QA";
+	}
+      return "ar";
+    case LANG_ARMENIAN: return "hy_AM";
+    case LANG_ASSAMESE: return "as_IN";
+    case LANG_AZERI:
+      switch (sub)
+	{
+	/* FIXME: Adjust this when Azerbaijani locales appear on Unix.  */
+	case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
+	case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
+	}
+      return "az";
+    case LANG_BASQUE:
+      return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR".  */
+    case LANG_BELARUSIAN: return "be_BY";
+    case LANG_BENGALI: return "bn_IN";
+    case LANG_BULGARIAN: return "bg_BG";
+    case 0x55: /* BURMESE */ return "my_MM";
+    case 0x53: /* CAMBODIAN */ return "km_KH";
+    case LANG_CATALAN: return "ca_ES";
+    case 0x5c: /* CHEROKEE */ return "chr_US";
+    case LANG_CHINESE:
+      switch (sub)
+	{
+	case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
+	case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
+	case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
+	case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
+	case SUBLANG_CHINESE_MACAU: return "zh_MO";
+	}
+      return "zh";
+    case LANG_CROATIAN:		/* LANG_CROATIAN == LANG_SERBIAN
+				 * What used to be called Serbo-Croatian
+				 * should really now be two separate
+				 * languages because of political reasons.
+				 * (Says tml, who knows nothing about Serbian
+				 * or Croatian.)
+				 * (I can feel those flames coming already.)
+				 */
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "hr_HR";
+	case SUBLANG_SERBIAN_LATIN: return "sr_YU";
+	case SUBLANG_SERBIAN_CYRILLIC: return "sr_YU@cyrillic";
+	}
+      return "hr";
+    case LANG_CZECH: return "cs_CZ";
+    case LANG_DANISH: return "da_DK";
+    case LANG_DIVEHI: return "div_MV";
+    case LANG_DUTCH:
+      switch (sub)
+	{
+	case SUBLANG_DUTCH: return "nl_NL";
+	case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
+	}
+      return "nl";
+    case 0x66: /* EDO */ return "bin_NG";
+    case LANG_ENGLISH:
+      switch (sub)
+	{
+	/* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
+	 * English was the language spoken in England.
+	 * Oh well.
+	 */
+	case SUBLANG_ENGLISH_US: return "en_US";
+	case SUBLANG_ENGLISH_UK: return "en_GB";
+	case SUBLANG_ENGLISH_AUS: return "en_AU";
+	case SUBLANG_ENGLISH_CAN: return "en_CA";
+	case SUBLANG_ENGLISH_NZ: return "en_NZ";
+	case SUBLANG_ENGLISH_EIRE: return "en_IE";
+	case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
+	case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
+	case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
+	case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
+	case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
+	case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
+	case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
+	}
+      return "en";
+    case LANG_ESTONIAN: return "et_EE";
+    case LANG_FAEROESE: return "fo_FO";
+    case LANG_FARSI: return "fa_IR";
+    case LANG_FINNISH: return "fi_FI";
+    case LANG_FRENCH:
+      switch (sub)
+	{
+	case SUBLANG_FRENCH: return "fr_FR";
+	case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
+	case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
+	case SUBLANG_FRENCH_SWISS: return "fr_CH";
+	case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
+	case SUBLANG_FRENCH_MONACO: return "fr_MC";
+	}
+      return "fr";
+    case 0x62: /* FRISIAN */ return "fy_NL";
+    case 0x67: /* FULFULDE */ return "ful_NG";
+    case 0x3c: /* GAELIC */
+      switch (sub)
+	{
+	case 0x01: /* SCOTTISH */ return "gd_GB";
+	case 0x02: /* IRISH */ return "ga_IE";
+	}
+      return "C";
+    case LANG_GALICIAN: return "gl_ES";
+    case LANG_GEORGIAN: return "ka_GE";
+    case LANG_GERMAN:
+      switch (sub)
+	{
+	case SUBLANG_GERMAN: return "de_DE";
+	case SUBLANG_GERMAN_SWISS: return "de_CH";
+	case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
+	case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
+	case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
+	}
+      return "de";
+    case LANG_GREEK: return "el_GR";
+    case 0x74: /* GUARANI */ return "gn_PY";
+    case LANG_GUJARATI: return "gu_IN";
+    case 0x68: /* HAUSA */ return "ha_NG";
+    case 0x75: /* HAWAIIAN */
+      /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
+	 or Hawaii Creole English ("cpe_US", 600000 speakers)?  */
+      return "cpe_US";
+    case LANG_HEBREW: return "he_IL";
+    case LANG_HINDI: return "hi_IN";
+    case LANG_HUNGARIAN: return "hu_HU";
+    case 0x69: /* IBIBIO */ return "nic_NG";
+    case LANG_ICELANDIC: return "is_IS";
+    case 0x70: /* IGBO */ return "ibo_NG";
+    case LANG_INDONESIAN: return "id_ID";
+    case 0x5d: /* INUKTITUT */ return "iu_CA";
+    case LANG_ITALIAN:
+      switch (sub)
+	{
+	case SUBLANG_ITALIAN: return "it_IT";
+	case SUBLANG_ITALIAN_SWISS: return "it_CH";
+	}
+      return "it";
+    case LANG_JAPANESE: return "ja_JP";
+    case LANG_KANNADA: return "kn_IN";
+    case 0x71: /* KANURI */ return "kau_NG";
+    case LANG_KASHMIRI:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "ks_PK";
+	case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
+	}
+      return "ks";
+    case LANG_KAZAK: return "kk_KZ";
+    case LANG_KONKANI:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "kok_IN";
+    case LANG_KOREAN: return "ko_KR";
+    case LANG_KYRGYZ: return "ky_KG";
+    case 0x54: /* LAO */ return "lo_LA";
+    case 0x76: /* LATIN */ return "la_VA";
+    case LANG_LATVIAN: return "lv_LV";
+    case LANG_LITHUANIAN: return "lt_LT";
+    case LANG_MACEDONIAN: return "mk_MK";
+    case LANG_MALAY:
+      switch (sub)
+	{
+	case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
+	case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
+	}
+      return "ms";
+    case LANG_MALAYALAM: return "ml_IN";
+    case 0x3a: /* MALTESE */ return "mt_MT";
+    case LANG_MANIPURI:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "mni_IN";
+    case LANG_MARATHI: return "mr_IN";
+    case LANG_MONGOLIAN:
+      return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN".  */
+    case LANG_NEPALI:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "ne_NP";
+	case SUBLANG_NEPALI_INDIA: return "ne_IN";
+	}
+      return "ne";
+    case LANG_NORWEGIAN:
+      switch (sub)
+	{
+	case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
+	case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
+	}
+      return "no";
+    case LANG_ORIYA: return "or_IN";
+    case 0x72: /* OROMO */ return "om_ET";
+    case 0x79: /* PAPIAMENTU */ return "pap_AN";
+    case 0x63: /* PASHTO */
+      return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF".  */
+    case LANG_POLISH: return "pl_PL";
+    case LANG_PORTUGUESE:
+      switch (sub)
+	{
+	case SUBLANG_PORTUGUESE: return "pt_PT";
+	/* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
+	   Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
+	case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
+	}
+      return "pt";
+    case LANG_PUNJABI: return "pa_IN";
+    case 0x17: /* RHAETO-ROMANCE */ return "rm_CH";
+    case LANG_ROMANIAN: return "ro_RO";
+    case LANG_RUSSIAN:
+      return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA".  */
+    case 0x3b: /* SAMI */ return "se_NO";
+    case LANG_SANSKRIT: return "sa_IN";
+    case LANG_SINDHI: return "sd";
+    case 0x5b: /* SINHALESE */ return "si_LK";
+    case LANG_SLOVAK: return "sk_SK";
+    case LANG_SLOVENIAN: return "sl_SI";
+    case 0x77: /* SOMALI */ return "so_SO";
+    case LANG_SORBIAN:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "wen_DE";
+    case LANG_SPANISH:
+      switch (sub)
+	{
+	case SUBLANG_SPANISH: return "es_ES";
+	case SUBLANG_SPANISH_MEXICAN: return "es_MX";
+	case SUBLANG_SPANISH_MODERN:
+	  return "es_ES@modern";	/* not seen on Unix */
+	case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
+	case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
+	case SUBLANG_SPANISH_PANAMA: return "es_PA";
+	case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
+	case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
+	case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
+	case SUBLANG_SPANISH_PERU: return "es_PE";
+	case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
+	case SUBLANG_SPANISH_ECUADOR: return "es_EC";
+	case SUBLANG_SPANISH_CHILE: return "es_CL";
+	case SUBLANG_SPANISH_URUGUAY: return "es_UY";
+	case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
+	case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
+	case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
+	case SUBLANG_SPANISH_HONDURAS: return "es_HN";
+	case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
+	case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
+	}
+      return "es";
+    case 0x30: /* SUTU */ return "bnt_TZ";
+    case LANG_SWAHILI: return "sw_KE";
+    case LANG_SWEDISH:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "sv_SE";
+	case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
+	}
+      return "sv";
+    case LANG_SYRIAC: return "syr_TR"; /* An extinct language.  */
+    case 0x64: /* TAGALOG */ return "tl_PH";
+    case 0x28: /* TAJIK */ return "tg_TJ";
+    case 0x5f: /* TAMAZIGHT */ return "ber_MA";
+    case LANG_TAMIL:
+      return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG".  */
+    case LANG_TATAR: return "tt_RU";
+    case LANG_TELUGU: return "te_IN";
+    case LANG_THAI: return "th_TH";
+    case 0x51: /* TIBETAN */ return "bo_CN";
+    case 0x73: /* TIGRINYA */ return "ti_ET";
+    case 0x31: /* TSONGA */ return "ts_ZA";
+    case LANG_TURKISH: return "tr_TR";
+    case 0x42: /* TURKMEN */ return "tk_TM";
+    case LANG_UKRAINIAN: return "uk_UA";
+    case LANG_URDU:
+      switch (sub)
+	{
+	case SUBLANG_URDU_PAKISTAN: return "ur_PK";
+	case SUBLANG_URDU_INDIA: return "ur_IN";
+	}
+      return "ur";
+    case LANG_UZBEK:
+      switch (sub)
+	{
+	/* FIXME: Adjust this when Uzbek locales appear on Unix.  */
+	case SUBLANG_UZBEK_LATIN: return "uz_UZ@latin";
+	case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
+	}
+      return "uz";
+    case 0x33: /* VENDA */ return "ven_ZA";
+    case LANG_VIETNAMESE: return "vi_VN";
+    case 0x52: /* WELSH */ return "cy_GB";
+    case 0x34: /* XHOSA */ return "xh_ZA";
+    case 0x78: /* YI */ return "sit_CN";
+    case 0x3d: /* YIDDISH */ return "yi_IL";
+    case 0x6a: /* YORUBA */ return "yo_NG";
+    case 0x35: /* ZULU */ return "zu_ZA";
+    default: return "C";
+    }
+
+#endif
+}
+
Index: /trunk/libc/src/glibc/intl/ngettext.c
===================================================================
--- /trunk/libc/src/glibc/intl/ngettext.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/ngettext.c	(revision 2448)
@@ -0,0 +1,69 @@
+/* Implementation of ngettext(3) function.
+   Copyright (C) 1995, 1997, 2000, 2001, 2002 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
+
+#ifdef _LIBC
+# define __need_NULL
+# include <stddef.h>
+#else
+# include <stdlib.h>		/* Just for NULL.  */
+#endif
+
+#include "gettextP.h"
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+#include <locale.h>
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define NGETTEXT __ngettext
+# define DCNGETTEXT __dcngettext
+#else
+# define NGETTEXT libintl_ngettext
+# define DCNGETTEXT libintl_dcngettext
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+   LC_MESSAGES locale.  If not found, returns MSGID itself (the default
+   text).  */
+char *
+NGETTEXT (msgid1, msgid2, n)
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+{
+  return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__ngettext, ngettext);
+#endif
Index: /trunk/libc/src/glibc/intl/plural-eval.c
===================================================================
--- /trunk/libc/src/glibc/intl/plural-eval.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/plural-eval.c	(revision 2448)
@@ -0,0 +1,101 @@
+/* Plural expression evaluation.
+   Copyright (C) 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.  */
+
+static unsigned long int plural_eval (struct expression *pexp,
+				      unsigned long int n)
+     internal_function;
+
+static unsigned long int
+internal_function
+plural_eval (pexp, n)
+     struct expression *pexp;
+     unsigned long int n;
+{
+  switch (pexp->nargs)
+    {
+    case 0:
+      switch (pexp->operation)
+	{
+	case var:
+	  return n;
+	case num:
+	  return pexp->val.num;
+	default:
+	  break;
+	}
+      /* NOTREACHED */
+      break;
+    case 1:
+      {
+	/* pexp->operation must be lnot.  */
+	unsigned long int arg = plural_eval (pexp->val.args[0], n);
+	return ! arg;
+      }
+    case 2:
+      {
+	unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
+	if (pexp->operation == lor)
+	  return leftarg || plural_eval (pexp->val.args[1], n);
+	else if (pexp->operation == land)
+	  return leftarg && plural_eval (pexp->val.args[1], n);
+	else
+	  {
+	    unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
+
+	    switch (pexp->operation)
+	      {
+	      case mult:
+		return leftarg * rightarg;
+	      case divide:
+		return leftarg / rightarg;
+	      case module:
+		return leftarg % rightarg;
+	      case plus:
+		return leftarg + rightarg;
+	      case minus:
+		return leftarg - rightarg;
+	      case less_than:
+		return leftarg < rightarg;
+	      case greater_than:
+		return leftarg > rightarg;
+	      case less_or_equal:
+		return leftarg <= rightarg;
+	      case greater_or_equal:
+		return leftarg >= rightarg;
+	      case equal:
+		return leftarg == rightarg;
+	      case not_equal:
+		return leftarg != rightarg;
+	      default:
+		break;
+	      }
+	  }
+	/* NOTREACHED */
+	break;
+      }
+    case 3:
+      {
+	/* pexp->operation must be qmop.  */
+	unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
+	return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
+      }
+    }
+  /* NOTREACHED */
+  return 0;
+}
Index: /trunk/libc/src/glibc/intl/plural-exp.c
===================================================================
--- /trunk/libc/src/glibc/intl/plural-exp.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/plural-exp.c	(revision 2448)
@@ -0,0 +1,157 @@
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+   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
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "plural-exp.h"
+
+#if (defined __GNUC__ && !defined __APPLE_CC__) \
+    || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+
+/* These structs are the constant expression for the germanic plural
+   form determination.  It represents the expression  "n != 1".  */
+static const struct expression plvar =
+{
+  .nargs = 0,
+  .operation = var,
+};
+static const struct expression plone =
+{
+  .nargs = 0,
+  .operation = num,
+  .val =
+  {
+    .num = 1
+  }
+};
+struct expression GERMANIC_PLURAL =
+{
+  .nargs = 2,
+  .operation = not_equal,
+  .val =
+  {
+    .args =
+    {
+      [0] = (struct expression *) &plvar,
+      [1] = (struct expression *) &plone
+    }
+  }
+};
+
+# define INIT_GERMANIC_PLURAL()
+
+#else
+
+/* For compilers without support for ISO C 99 struct/union initializers:
+   Initialization at run-time.  */
+
+static struct expression plvar;
+static struct expression plone;
+struct expression GERMANIC_PLURAL;
+
+static void
+init_germanic_plural ()
+{
+  if (plone.val.num == 0)
+    {
+      plvar.nargs = 0;
+      plvar.operation = var;
+
+      plone.nargs = 0;
+      plone.operation = num;
+      plone.val.num = 1;
+
+      GERMANIC_PLURAL.nargs = 2;
+      GERMANIC_PLURAL.operation = not_equal;
+      GERMANIC_PLURAL.val.args[0] = &plvar;
+      GERMANIC_PLURAL.val.args[1] = &plone;
+    }
+}
+
+# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
+
+#endif
+
+void
+internal_function
+EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp)
+     const char *nullentry;
+     struct expression **pluralp;
+     unsigned long int *npluralsp;
+{
+  if (nullentry != NULL)
+    {
+      const char *plural;
+      const char *nplurals;
+
+      plural = strstr (nullentry, "plural=");
+      nplurals = strstr (nullentry, "nplurals=");
+      if (plural == NULL || nplurals == NULL)
+	goto no_plural;
+      else
+	{
+	  char *endp;
+	  unsigned long int n;
+	  struct parse_args args;
+
+	  /* First get the number.  */
+	  nplurals += 9;
+	  while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
+	    ++nplurals;
+	  if (!(*nplurals >= '0' && *nplurals <= '9'))
+	    goto no_plural;
+#if defined HAVE_STRTOUL || defined _LIBC
+	  n = strtoul (nplurals, &endp, 10);
+#else
+	  for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
+	    n = n * 10 + (*endp - '0');
+#endif
+	  if (nplurals == endp)
+	    goto no_plural;
+	  *npluralsp = n;
+
+	  /* Due to the restrictions bison imposes onto the interface of the
+	     scanner function we have to put the input string and the result
+	     passed up from the parser into the same structure which address
+	     is passed down to the parser.  */
+	  plural += 7;
+	  args.cp = plural;
+	  if (PLURAL_PARSE (&args) != 0)
+	    goto no_plural;
+	  *pluralp = args.res;
+	}
+    }
+  else
+    {
+      /* By default we are using the Germanic form: singular form only
+         for `one', the plural form otherwise.  Yes, this is also what
+         English is using since English is a Germanic language.  */
+    no_plural:
+      INIT_GERMANIC_PLURAL ();
+      *pluralp = &GERMANIC_PLURAL;
+      *npluralsp = 2;
+    }
+}
Index: /trunk/libc/src/glibc/intl/plural-exp.h
===================================================================
--- /trunk/libc/src/glibc/intl/plural-exp.h	(revision 2448)
+++ /trunk/libc/src/glibc/intl/plural-exp.h	(revision 2448)
@@ -0,0 +1,129 @@
+/* Expression parsing and evaluation for plural form selection.
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+   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.  */
+
+#ifndef _PLURAL_EXP_H
+#define _PLURAL_EXP_H
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+
+/* This is the representation of the expressions to determine the
+   plural form.  */
+struct expression
+{
+  int nargs;			/* Number of arguments.  */
+  enum operator
+  {
+    /* Without arguments:  */
+    var,			/* The variable "n".  */
+    num,			/* Decimal number.  */
+    /* Unary operators:  */
+    lnot,			/* Logical NOT.  */
+    /* Binary operators:  */
+    mult,			/* Multiplication.  */
+    divide,			/* Division.  */
+    module,			/* Modulo operation.  */
+    plus,			/* Addition.  */
+    minus,			/* Subtraction.  */
+    less_than,			/* Comparison.  */
+    greater_than,		/* Comparison.  */
+    less_or_equal,		/* Comparison.  */
+    greater_or_equal,		/* Comparison.  */
+    equal,			/* Comparison for equality.  */
+    not_equal,			/* Comparison for inequality.  */
+    land,			/* Logical AND.  */
+    lor,			/* Logical OR.  */
+    /* Ternary operators:  */
+    qmop			/* Question mark operator.  */
+  } operation;
+  union
+  {
+    unsigned long int num;	/* Number value for `num'.  */
+    struct expression *args[3];	/* Up to three arguments.  */
+  } val;
+};
+
+/* This is the data structure to pass information to the parser and get
+   the result in a thread-safe way.  */
+struct parse_args
+{
+  const char *cp;
+  struct expression *res;
+};
+
+
+/* Names for the libintl functions are a problem.  This source code is used
+   1. in the GNU C Library library,
+   2. in the GNU libintl library,
+   3. in the GNU gettext tools.
+   The function names in each situation must be different, to allow for
+   binary incompatible changes in 'struct expression'.  Furthermore,
+   1. in the GNU C Library library, the names have a __ prefix,
+   2.+3. in the GNU libintl library and in the GNU gettext tools, the names
+         must follow ANSI C and not start with __.
+   So we have to distinguish the three cases.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define FREE_EXPRESSION __gettext_free_exp
+# define PLURAL_PARSE __gettextparse
+# define GERMANIC_PLURAL __gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural
+#elif defined (IN_LIBINTL)
+# define FREE_EXPRESSION libintl_gettext_free_exp
+# define PLURAL_PARSE libintl_gettextparse
+# define GERMANIC_PLURAL libintl_gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION libintl_gettext_extract_plural
+#else
+# define FREE_EXPRESSION free_plural_expression
+# define PLURAL_PARSE parse_plural_expression
+# define GERMANIC_PLURAL germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION extract_plural_expression
+#endif
+
+extern void FREE_EXPRESSION PARAMS ((struct expression *exp))
+     internal_function;
+extern int PLURAL_PARSE PARAMS ((void *arg));
+extern struct expression GERMANIC_PLURAL attribute_hidden;
+extern void EXTRACT_PLURAL_EXPRESSION PARAMS ((const char *nullentry,
+					       struct expression **pluralp,
+					       unsigned long int *npluralsp))
+     internal_function;
+
+#if 0 //bird
+#if !defined (_LIBC) && !defined (IN_LIBINTL)
+extern unsigned long int plural_eval PARAMS ((struct expression *pexp,
+					      unsigned long int n));
+#endif
+#endif //bird
+
+#endif /* _PLURAL_EXP_H */
Index: /trunk/libc/src/glibc/intl/plural.c
===================================================================
--- /trunk/libc/src/glibc/intl/plural.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/plural.c	(revision 2448)
@@ -0,0 +1,1522 @@
+/* A Bison parser, made from plural.y
+   by GNU bison 1.35.  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+#define yyparse __gettextparse
+#define yylex __gettextlex
+#define yyerror __gettexterror
+#define yylval __gettextlval
+#define yychar __gettextchar
+#define yydebug __gettextdebug
+#define yynerrs __gettextnerrs
+# define	EQUOP2	257
+# define	CMPOP2	258
+# define	ADDOP2	259
+# define	MULOP2	260
+# define	NUMBER	261
+
+#line 1 "plural.y"
+
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+   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.  */
+
+/* The bison generated parser uses alloca.  AIX 3 forces us to put this
+   declaration at the beginning of the file.  The declaration in bison's
+   skeleton file comes too late.  This must come before <config.h>
+   because <config.h> may include arbitrary system headers.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+   but we want it to be called PLURAL_PARSE.  */
+#if !defined(_LIBC) && !defined(IN_INNOTEK_LIBC)
+# define __gettextparse PLURAL_PARSE
+#endif
+
+#define YYLEX_PARAM	&((struct parse_args *) arg)->cp
+#define YYPARSE_PARAM	arg
+
+#line 49 "plural.y"
+#ifndef YYSTYPE
+typedef union {
+  unsigned long int num;
+  enum operator op;
+  struct expression *exp;
+} yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+#line 55 "plural.y"
+
+/* Prototypes for local functions.  */
+static struct expression *new_exp PARAMS ((int nargs, enum operator op,
+					   struct expression * const *args));
+static inline struct expression *new_exp_0 PARAMS ((enum operator op));
+static inline struct expression *new_exp_1 PARAMS ((enum operator op,
+						   struct expression *right));
+static struct expression *new_exp_2 PARAMS ((enum operator op,
+					     struct expression *left,
+					     struct expression *right));
+static inline struct expression *new_exp_3 PARAMS ((enum operator op,
+						   struct expression *bexp,
+						   struct expression *tbranch,
+						   struct expression *fbranch));
+static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
+static void yyerror PARAMS ((const char *str));
+
+/* Allocation of expressions.  */
+
+static struct expression *
+new_exp (nargs, op, args)
+     int nargs;
+     enum operator op;
+     struct expression * const *args;
+{
+  int i;
+  struct expression *newp;
+
+  /* If any of the argument could not be malloc'ed, just return NULL.  */
+  for (i = nargs - 1; i >= 0; i--)
+    if (args[i] == NULL)
+      goto fail;
+
+  /* Allocate a new expression.  */
+  newp = (struct expression *) malloc (sizeof (*newp));
+  if (newp != NULL)
+    {
+      newp->nargs = nargs;
+      newp->operation = op;
+      for (i = nargs - 1; i >= 0; i--)
+	newp->val.args[i] = args[i];
+      return newp;
+    }
+
+ fail:
+  for (i = nargs - 1; i >= 0; i--)
+    FREE_EXPRESSION (args[i]);
+
+  return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (op)
+     enum operator op;
+{
+  return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (op, right)
+     enum operator op;
+     struct expression *right;
+{
+  struct expression *args[1];
+
+  args[0] = right;
+  return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (op, left, right)
+     enum operator op;
+     struct expression *left;
+     struct expression *right;
+{
+  struct expression *args[2];
+
+  args[0] = left;
+  args[1] = right;
+  return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (op, bexp, tbranch, fbranch)
+     enum operator op;
+     struct expression *bexp;
+     struct expression *tbranch;
+     struct expression *fbranch;
+{
+  struct expression *args[3];
+
+  args[0] = bexp;
+  args[1] = tbranch;
+  args[2] = fbranch;
+  return new_exp (3, op, args);
+}
+
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+
+
+#define	YYFINAL		27
+#define	YYFLAG		-32768
+#define	YYNTBASE	16
+
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
+#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18)
+
+/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */
+static const char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    10,     2,     2,     2,     2,     5,     2,
+      14,    15,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    12,     2,
+       2,     2,     2,     3,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+      13,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     4,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     6,     7,     8,
+       9,    11
+};
+
+#if YYDEBUG
+static const short yyprhs[] =
+{
+       0,     0,     2,     8,    12,    16,    20,    24,    28,    32,
+      35,    37,    39
+};
+static const short yyrhs[] =
+{
+      17,     0,    17,     3,    17,    12,    17,     0,    17,     4,
+      17,     0,    17,     5,    17,     0,    17,     6,    17,     0,
+      17,     7,    17,     0,    17,     8,    17,     0,    17,     9,
+      17,     0,    10,    17,     0,    13,     0,    11,     0,    14,
+      17,    15,     0
+};
+
+#endif
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const short yyrline[] =
+{
+       0,   174,   182,   186,   190,   194,   198,   202,   206,   210,
+     214,   218,   223
+};
+#endif
+
+
+#if (YYDEBUG) || defined YYERROR_VERBOSE
+
+/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */
+static const char *const yytname[] =
+{
+  "$", "error", "$undefined.", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2",
+  "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'",
+  "start", "exp", 0
+};
+#endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const short yyr1[] =
+{
+       0,    16,    17,    17,    17,    17,    17,    17,    17,    17,
+      17,    17,    17
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const short yyr2[] =
+{
+       0,     1,     5,     3,     3,     3,     3,     3,     3,     2,
+       1,     1,     3
+};
+
+/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
+   doesn't specify something else to do.  Zero means the default is an
+   error. */
+static const short yydefact[] =
+{
+       0,     0,    11,    10,     0,     1,     9,     0,     0,     0,
+       0,     0,     0,     0,     0,    12,     0,     3,     4,     5,
+       6,     7,     8,     0,     2,     0,     0,     0
+};
+
+static const short yydefgoto[] =
+{
+      25,     5
+};
+
+static const short yypact[] =
+{
+      -9,    -9,-32768,-32768,    -9,    34,-32768,    11,    -9,    -9,
+      -9,    -9,    -9,    -9,    -9,-32768,    24,    39,    43,    16,
+      26,    -3,-32768,    -9,    34,    21,    53,-32768
+};
+
+static const short yypgoto[] =
+{
+  -32768,    -1
+};
+
+
+#define	YYLAST		53
+
+
+static const short yytable[] =
+{
+       6,     1,     2,     7,     3,     4,    14,    16,    17,    18,
+      19,    20,    21,    22,     8,     9,    10,    11,    12,    13,
+      14,    26,    24,    12,    13,    14,    15,     8,     9,    10,
+      11,    12,    13,    14,    13,    14,    23,     8,     9,    10,
+      11,    12,    13,    14,    10,    11,    12,    13,    14,    11,
+      12,    13,    14,    27
+};
+
+static const short yycheck[] =
+{
+       1,    10,    11,     4,    13,    14,     9,     8,     9,    10,
+      11,    12,    13,    14,     3,     4,     5,     6,     7,     8,
+       9,     0,    23,     7,     8,     9,    15,     3,     4,     5,
+       6,     7,     8,     9,     8,     9,    12,     3,     4,     5,
+       6,     7,     8,     9,     5,     6,     7,     8,     9,     6,
+       7,     8,     9,     0
+};
+#define YYPURE 1
+
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/castro/street/H-alpha-linux/share/bison/bison.simple"
+
+/* Skeleton output parser for bison,
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software
+   Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser when
+   the %semantic_parser declaration is not specified in the grammar.
+   It was written by Richard Stallman by simplifying the hairy parser
+   used when %semantic_parser is specified.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE)
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC malloc
+#  define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+	 || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+# if YYLSP_NEEDED
+  YYLTYPE yyls;
+# endif
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# if YYLSP_NEEDED
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))	\
+      + 2 * YYSTACK_GAP_MAX)
+# else
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
+      + YYSTACK_GAP_MAX)
+# endif
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  register YYSIZE_T yyi;		\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX;	\
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (0)
+
+#endif
+
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		-2
+#define YYEOF		0
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT 	goto yyabortlab
+#define YYERROR		goto yyerrlab1
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL		goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yychar1 = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { 								\
+      yyerror ("syntax error: cannot back up");			\
+      YYERROR;							\
+    }								\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).
+
+   When YYLLOC_DEFAULT is run, CURRENT is set the location of the
+   first token.  By default, to implement support for ranges, extend
+   its range to the last symbol.  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)       	\
+   Current.last_line   = Rhs[N].last_line;	\
+   Current.last_column = Rhs[N].last_column;
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#if YYPURE
+# if YYLSP_NEEDED
+#  ifdef YYLEX_PARAM
+#   define YYLEX		yylex (&yylval, &yylloc, YYLEX_PARAM)
+#  else
+#   define YYLEX		yylex (&yylval, &yylloc)
+#  endif
+# else /* !YYLSP_NEEDED */
+#  ifdef YYLEX_PARAM
+#   define YYLEX		yylex (&yylval, YYLEX_PARAM)
+#  else
+#   define YYLEX		yylex (&yylval)
+#  endif
+# endif /* !YYLSP_NEEDED */
+#else /* !YYPURE */
+# define YYLEX			yylex ()
+#endif /* !YYPURE */
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (0)
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#ifdef YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+#endif
+
+
+#line 315 "/castro/street/H-alpha-linux/share/bison/bison.simple"
+
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+# ifdef YYPARSE_PARAM
+int yyparse (void *);
+# else
+int yyparse (void);
+# endif
+#endif
+
+/* YY_DECL_VARIABLES -- depending whether we use a pure parser,
+   variables are global, or local to YYPARSE.  */
+
+#define YY_DECL_NON_LSP_VARIABLES			\
+/* The lookahead symbol.  */				\
+int yychar;						\
+							\
+/* The semantic value of the lookahead symbol. */	\
+YYSTYPE yylval;						\
+							\
+/* Number of parse errors so far.  */			\
+int yynerrs;
+
+#if YYLSP_NEEDED
+# define YY_DECL_VARIABLES			\
+YY_DECL_NON_LSP_VARIABLES			\
+						\
+/* Location data for the lookahead symbol.  */	\
+YYLTYPE yylloc;
+#else
+# define YY_DECL_VARIABLES			\
+YY_DECL_NON_LSP_VARIABLES
+#endif
+
+
+/* If nonreentrant, generate the variables here. */
+
+#if !YYPURE
+YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  /* If reentrant, generate the variables here. */
+#if YYPURE
+  YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack. */
+  short	yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+#if YYLSP_NEEDED
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+#endif
+
+#if YYLSP_NEEDED
+# define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+# define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+#if YYLSP_NEEDED
+  YYLTYPE yyloc;
+#endif
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule. */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+#if YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack. Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	short *yyss1 = yyss;
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  */
+# if YYLSP_NEEDED
+	YYLTYPE *yyls1 = yyls;
+	/* This used to be a conditional around just the two extra args,
+	   but that might be undefined if yyoverflow is a macro.  */
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yyls1, yysize * sizeof (*yylsp),
+		    &yystacksize);
+	yyls = yyls1;
+# else
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yystacksize);
+# endif
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+	goto yyoverflowlab;
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	short *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyoverflowlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+# if YYLSP_NEEDED
+	YYSTACK_RELOCATE (yyls);
+# endif
+# undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+#if YYLSP_NEEDED
+      yylsp = yyls + yysize - 1;
+#endif
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyssp >= yyss + yystacksize - 1)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)		/* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;		/* Don't call YYLEX any more */
+
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE (yychar);
+
+#if YYDEBUG
+     /* We have to keep this `#if YYDEBUG', since we use variables
+	which are defined only if `YYDEBUG' is set.  */
+      if (yydebug)
+	{
+	  YYFPRINTF (stderr, "Next token is %d (%s",
+		     yychar, yytname[yychar1]);
+	  /* Give the individual parser a way to print the precise
+	     meaning of a token, for further debugging info.  */
+# ifdef YYPRINT
+	  YYPRINT (stderr, yychar, yylval);
+# endif
+	  YYFPRINTF (stderr, ")\n");
+	}
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+	      yychar, yytname[yychar1]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to the semantic value of
+     the lookahead token.  This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+#if YYLSP_NEEDED
+  /* Similarly for the default location.  Let the user run additional
+     commands if for instance locations are ranges.  */
+  yyloc = yylsp[1-yylen];
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+#endif
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
+  if (yydebug)
+    {
+      int yyi;
+
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+		 yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++)
+	YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+  switch (yyn) {
+
+case 1:
+#line 175 "plural.y"
+{
+	    if (yyvsp[0].exp == NULL)
+	      YYABORT;
+	    ((struct parse_args *) arg)->res = yyvsp[0].exp;
+	  }
+    break;
+case 2:
+#line 183 "plural.y"
+{
+	    yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 3:
+#line 187 "plural.y"
+{
+	    yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 4:
+#line 191 "plural.y"
+{
+	    yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 5:
+#line 195 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 6:
+#line 199 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 7:
+#line 203 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 8:
+#line 207 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 9:
+#line 211 "plural.y"
+{
+	    yyval.exp = new_exp_1 (lnot, yyvsp[0].exp);
+	  }
+    break;
+case 10:
+#line 215 "plural.y"
+{
+	    yyval.exp = new_exp_0 (var);
+	  }
+    break;
+case 11:
+#line 219 "plural.y"
+{
+	    if ((yyval.exp = new_exp_0 (num)) != NULL)
+	      yyval.exp->val.num = yyvsp[0].num;
+	  }
+    break;
+case 12:
+#line 224 "plural.y"
+{
+	    yyval.exp = yyvsp[-1].exp;
+	  }
+    break;
+}
+
+#line 705 "/castro/street/H-alpha-linux/share/bison/bison.simple"
+
+
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#if YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+	YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+#if YYLSP_NEEDED
+  *++yylsp = yyloc;
+#endif
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+	{
+	  YYSIZE_T yysize = 0;
+	  char *yymsg;
+	  int yyx, yycount;
+
+	  yycount = 0;
+	  /* Start YYX at -YYN if negative to avoid negative indexes in
+	     YYCHECK.  */
+	  for (yyx = yyn < 0 ? -yyn : 0;
+	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+	    if (yycheck[yyx + yyn] == yyx)
+	      yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+	  yysize += yystrlen ("parse error, unexpected ") + 1;
+	  yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);
+	  yymsg = (char *) YYSTACK_ALLOC (yysize);
+	  if (yymsg != 0)
+	    {
+	      char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+	      yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);
+
+	      if (yycount < 5)
+		{
+		  yycount = 0;
+		  for (yyx = yyn < 0 ? -yyn : 0;
+		       yyx < (int) (sizeof (yytname) / sizeof (char *));
+		       yyx++)
+		    if (yycheck[yyx + yyn] == yyx)
+		      {
+			const char *yyq = ! yycount ? ", expecting " : " or ";
+			yyp = yystpcpy (yyp, yyq);
+			yyp = yystpcpy (yyp, yytname[yyx]);
+			yycount++;
+		      }
+		}
+	      yyerror (yymsg);
+	      YYSTACK_FREE (yymsg);
+	    }
+	  else
+	    yyerror ("parse error; also virtual memory exhausted");
+	}
+      else
+#endif /* defined (YYERROR_VERBOSE) */
+	yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*--------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action |
+`--------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+	YYABORT;
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+		  yychar, yytname[yychar1]));
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;		/* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+
+/*-------------------------------------------------------------------.
+| yyerrdefault -- current state does not do anything special for the |
+| error token.                                                       |
+`-------------------------------------------------------------------*/
+yyerrdefault:
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+
+  /* If its default is to accept any token, ok.  Otherwise pop it.  */
+  yyn = yydefact[yystate];
+  if (yyn)
+    goto yydefault;
+#endif
+
+
+/*---------------------------------------------------------------.
+| yyerrpop -- pop the current state because it cannot handle the |
+| error token                                                    |
+`---------------------------------------------------------------*/
+yyerrpop:
+  if (yyssp == yyss)
+    YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#if YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "Error: state stack now");
+      while (yyssp1 != yyssp)
+	YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+/*--------------.
+| yyerrhandle.  |
+`--------------*/
+yyerrhandle:
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+#line 229 "plural.y"
+
+
+void
+internal_function
+FREE_EXPRESSION (exp)
+     struct expression *exp;
+{
+  if (exp == NULL)
+    return;
+
+  /* Handle the recursive case.  */
+  switch (exp->nargs)
+    {
+    case 3:
+      FREE_EXPRESSION (exp->val.args[2]);
+      /* FALLTHROUGH */
+    case 2:
+      FREE_EXPRESSION (exp->val.args[1]);
+      /* FALLTHROUGH */
+    case 1:
+      FREE_EXPRESSION (exp->val.args[0]);
+      /* FALLTHROUGH */
+    default:
+      break;
+    }
+
+  free (exp);
+}
+
+
+static int
+yylex (lval, pexp)
+     YYSTYPE *lval;
+     const char **pexp;
+{
+  const char *exp = *pexp;
+  int result;
+
+  while (1)
+    {
+      if (exp[0] == '\0')
+	{
+	  *pexp = exp;
+	  return YYEOF;
+	}
+
+      if (exp[0] != ' ' && exp[0] != '\t')
+	break;
+
+      ++exp;
+    }
+
+  result = *exp++;
+  switch (result)
+    {
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      {
+	unsigned long int n = result - '0';
+	while (exp[0] >= '0' && exp[0] <= '9')
+	  {
+	    n *= 10;
+	    n += exp[0] - '0';
+	    ++exp;
+	  }
+	lval->num = n;
+	result = NUMBER;
+      }
+      break;
+
+    case '=':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = equal;
+	  result = EQUOP2;
+	}
+      else
+	result = YYERRCODE;
+      break;
+
+    case '!':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = not_equal;
+	  result = EQUOP2;
+	}
+      break;
+
+    case '&':
+    case '|':
+      if (exp[0] == result)
+	++exp;
+      else
+	result = YYERRCODE;
+      break;
+
+    case '<':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = less_or_equal;
+	}
+      else
+	lval->op = less_than;
+      result = CMPOP2;
+      break;
+
+    case '>':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = greater_or_equal;
+	}
+      else
+	lval->op = greater_than;
+      result = CMPOP2;
+      break;
+
+    case '*':
+      lval->op = mult;
+      result = MULOP2;
+      break;
+
+    case '/':
+      lval->op = divide;
+      result = MULOP2;
+      break;
+
+    case '%':
+      lval->op = module;
+      result = MULOP2;
+      break;
+
+    case '+':
+      lval->op = plus;
+      result = ADDOP2;
+      break;
+
+    case '-':
+      lval->op = minus;
+      result = ADDOP2;
+      break;
+
+    case 'n':
+    case '?':
+    case ':':
+    case '(':
+    case ')':
+      /* Nothing, just return the character.  */
+      break;
+
+    case ';':
+    case '\n':
+    case '\0':
+      /* Be safe and let the user call this function again.  */
+      --exp;
+      result = YYEOF;
+      break;
+
+    default:
+      result = YYERRCODE;
+#if YYDEBUG != 0
+      --exp;
+#endif
+      break;
+    }
+
+  *pexp = exp;
+
+  return result;
+}
+
+
+static void
+yyerror (str)
+     const char *str;
+{
+  /* Do nothing.  We don't print error messages here.  */
+}
Index: /trunk/libc/src/glibc/intl/plural.y
===================================================================
--- /trunk/libc/src/glibc/intl/plural.y	(revision 2448)
+++ /trunk/libc/src/glibc/intl/plural.y	(revision 2448)
@@ -0,0 +1,410 @@
+%{
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+   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.  */
+
+/* The bison generated parser uses alloca.  AIX 3 forces us to put this
+   declaration at the beginning of the file.  The declaration in bison's
+   skeleton file comes too late.  This must come before <config.h>
+   because <config.h> may include arbitrary system headers.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+   but we want it to be called PLURAL_PARSE.  */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
+#endif
+
+#define YYLEX_PARAM	&((struct parse_args *) arg)->cp
+#define YYPARSE_PARAM	arg
+%}
+%pure_parser
+%expect 7
+
+%union {
+  unsigned long int num;
+  enum operator op;
+  struct expression *exp;
+}
+
+%{
+/* Prototypes for local functions.  */
+static struct expression *new_exp PARAMS ((int nargs, enum operator op,
+					   struct expression * const *args));
+static inline struct expression *new_exp_0 PARAMS ((enum operator op));
+static inline struct expression *new_exp_1 PARAMS ((enum operator op,
+						   struct expression *right));
+static struct expression *new_exp_2 PARAMS ((enum operator op,
+					     struct expression *left,
+					     struct expression *right));
+static inline struct expression *new_exp_3 PARAMS ((enum operator op,
+						   struct expression *bexp,
+						   struct expression *tbranch,
+						   struct expression *fbranch));
+static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
+static void yyerror PARAMS ((const char *str));
+
+/* Allocation of expressions.  */
+
+static struct expression *
+new_exp (nargs, op, args)
+     int nargs;
+     enum operator op;
+     struct expression * const *args;
+{
+  int i;
+  struct expression *newp;
+
+  /* If any of the argument could not be malloc'ed, just return NULL.  */
+  for (i = nargs - 1; i >= 0; i--)
+    if (args[i] == NULL)
+      goto fail;
+
+  /* Allocate a new expression.  */
+  newp = (struct expression *) malloc (sizeof (*newp));
+  if (newp != NULL)
+    {
+      newp->nargs = nargs;
+      newp->operation = op;
+      for (i = nargs - 1; i >= 0; i--)
+	newp->val.args[i] = args[i];
+      return newp;
+    }
+
+ fail:
+  for (i = nargs - 1; i >= 0; i--)
+    FREE_EXPRESSION (args[i]);
+
+  return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (op)
+     enum operator op;
+{
+  return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (op, right)
+     enum operator op;
+     struct expression *right;
+{
+  struct expression *args[1];
+
+  args[0] = right;
+  return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (op, left, right)
+     enum operator op;
+     struct expression *left;
+     struct expression *right;
+{
+  struct expression *args[2];
+
+  args[0] = left;
+  args[1] = right;
+  return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (op, bexp, tbranch, fbranch)
+     enum operator op;
+     struct expression *bexp;
+     struct expression *tbranch;
+     struct expression *fbranch;
+{
+  struct expression *args[3];
+
+  args[0] = bexp;
+  args[1] = tbranch;
+  args[2] = fbranch;
+  return new_exp (3, op, args);
+}
+
+%}
+
+/* This declares that all operators have the same associativity and the
+   precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
+   There is no unary minus and no bitwise operators.
+   Operators with the same syntactic behaviour have been merged into a single
+   token, to save space in the array generated by bison.  */
+%right '?'		/*   ?		*/
+%left '|'		/*   ||		*/
+%left '&'		/*   &&		*/
+%left EQUOP2		/*   == !=	*/
+%left CMPOP2		/*   < > <= >=	*/
+%left ADDOP2		/*   + -	*/
+%left MULOP2		/*   * / %	*/
+%right '!'		/*   !		*/
+
+%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
+%token <num> NUMBER
+%type <exp> exp
+
+%%
+
+start:	  exp
+	  {
+	    if ($1 == NULL)
+	      YYABORT;
+	    ((struct parse_args *) arg)->res = $1;
+	  }
+	;
+
+exp:	  exp '?' exp ':' exp
+	  {
+	    $$ = new_exp_3 (qmop, $1, $3, $5);
+	  }
+	| exp '|' exp
+	  {
+	    $$ = new_exp_2 (lor, $1, $3);
+	  }
+	| exp '&' exp
+	  {
+	    $$ = new_exp_2 (land, $1, $3);
+	  }
+	| exp EQUOP2 exp
+	  {
+	    $$ = new_exp_2 ($2, $1, $3);
+	  }
+	| exp CMPOP2 exp
+	  {
+	    $$ = new_exp_2 ($2, $1, $3);
+	  }
+	| exp ADDOP2 exp
+	  {
+	    $$ = new_exp_2 ($2, $1, $3);
+	  }
+	| exp MULOP2 exp
+	  {
+	    $$ = new_exp_2 ($2, $1, $3);
+	  }
+	| '!' exp
+	  {
+	    $$ = new_exp_1 (lnot, $2);
+	  }
+	| 'n'
+	  {
+	    $$ = new_exp_0 (var);
+	  }
+	| NUMBER
+	  {
+	    if (($$ = new_exp_0 (num)) != NULL)
+	      $$->val.num = $1;
+	  }
+	| '(' exp ')'
+	  {
+	    $$ = $2;
+	  }
+	;
+
+%%
+
+void
+internal_function
+FREE_EXPRESSION (exp)
+     struct expression *exp;
+{
+  if (exp == NULL)
+    return;
+
+  /* Handle the recursive case.  */
+  switch (exp->nargs)
+    {
+    case 3:
+      FREE_EXPRESSION (exp->val.args[2]);
+      /* FALLTHROUGH */
+    case 2:
+      FREE_EXPRESSION (exp->val.args[1]);
+      /* FALLTHROUGH */
+    case 1:
+      FREE_EXPRESSION (exp->val.args[0]);
+      /* FALLTHROUGH */
+    default:
+      break;
+    }
+
+  free (exp);
+}
+
+
+static int
+yylex (lval, pexp)
+     YYSTYPE *lval;
+     const char **pexp;
+{
+  const char *exp = *pexp;
+  int result;
+
+  while (1)
+    {
+      if (exp[0] == '\0')
+	{
+	  *pexp = exp;
+	  return YYEOF;
+	}
+
+      if (exp[0] != ' ' && exp[0] != '\t')
+	break;
+
+      ++exp;
+    }
+
+  result = *exp++;
+  switch (result)
+    {
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      {
+	unsigned long int n = result - '0';
+	while (exp[0] >= '0' && exp[0] <= '9')
+	  {
+	    n *= 10;
+	    n += exp[0] - '0';
+	    ++exp;
+	  }
+	lval->num = n;
+	result = NUMBER;
+      }
+      break;
+
+    case '=':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = equal;
+	  result = EQUOP2;
+	}
+      else
+	result = YYERRCODE;
+      break;
+
+    case '!':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = not_equal;
+	  result = EQUOP2;
+	}
+      break;
+
+    case '&':
+    case '|':
+      if (exp[0] == result)
+	++exp;
+      else
+	result = YYERRCODE;
+      break;
+
+    case '<':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = less_or_equal;
+	}
+      else
+	lval->op = less_than;
+      result = CMPOP2;
+      break;
+
+    case '>':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = greater_or_equal;
+	}
+      else
+	lval->op = greater_than;
+      result = CMPOP2;
+      break;
+
+    case '*':
+      lval->op = mult;
+      result = MULOP2;
+      break;
+
+    case '/':
+      lval->op = divide;
+      result = MULOP2;
+      break;
+
+    case '%':
+      lval->op = module;
+      result = MULOP2;
+      break;
+
+    case '+':
+      lval->op = plus;
+      result = ADDOP2;
+      break;
+
+    case '-':
+      lval->op = minus;
+      result = ADDOP2;
+      break;
+
+    case 'n':
+    case '?':
+    case ':':
+    case '(':
+    case ')':
+      /* Nothing, just return the character.  */
+      break;
+
+    case ';':
+    case '\n':
+    case '\0':
+      /* Be safe and let the user call this function again.  */
+      --exp;
+      result = YYEOF;
+      break;
+
+    default:
+      result = YYERRCODE;
+#if YYDEBUG != 0
+      --exp;
+#endif
+      break;
+    }
+
+  *pexp = exp;
+
+  return result;
+}
+
+
+static void
+yyerror (str)
+     const char *str;
+{
+  /* Do nothing.  We don't print error messages here.  */
+}
Index: /trunk/libc/src/glibc/intl/textdomain.c
===================================================================
--- /trunk/libc/src/glibc/intl/textdomain.c	(revision 2448)
+++ /trunk/libc/src/glibc/intl/textdomain.c	(revision 2448)
@@ -0,0 +1,143 @@
+/* Implementation of the textdomain(3) function.
+   Copyright (C) 1995-1998, 2000, 2001, 2002 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
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "gettextP.h"
+
+#ifdef _LIBC
+/* We have to handle multi-threaded applications.  */
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_rwlock_define(CLASS, NAME)
+# define __libc_rwlock_wrlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#endif
+
+/* The internal variables in the standalone libintl.a must have different
+   names than the internal variables in GNU libc, otherwise programs
+   using libintl.a cannot be linked statically.  */
+#if !defined(_LIBC) && !defined(IN_INNOTEK_LIBC)
+# define _nl_default_default_domain libintl_nl_default_default_domain
+# define _nl_current_default_domain libintl_nl_current_default_domain
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Name of the default text domain.  */
+extern const char _nl_default_default_domain[] attribute_hidden;
+
+/* Default text domain in which entries for gettext(3) are to be found.  */
+extern const char *_nl_current_default_domain attribute_hidden;
+
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#if defined(_LIBC) || defined(IN_INNOTEK_LIBC)
+# define TEXTDOMAIN __textdomain
+# ifndef strdup
+#  define strdup(str) __strdup (str)
+# endif
+#else
+# define TEXTDOMAIN libintl_textdomain
+#endif
+
+/* Lock variable to protect the global data in the gettext implementation.  */
+__libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
+
+/* Set the current default message catalog to DOMAINNAME.
+   If DOMAINNAME is null, return the current default.
+   If DOMAINNAME is "", reset to the default of "messages".  */
+char *
+TEXTDOMAIN (domainname)
+     const char *domainname;
+{
+  char *new_domain;
+  char *old_domain;
+
+  /* A NULL pointer requests the current setting.  */
+  if (domainname == NULL)
+    return (char *) _nl_current_default_domain;
+
+  __libc_rwlock_wrlock (_nl_state_lock);
+
+  old_domain = (char *) _nl_current_default_domain;
+
+  /* If domain name is the null string set to default domain "messages".  */
+  if (domainname[0] == '\0'
+      || strcmp (domainname, _nl_default_default_domain) == 0)
+    {
+      _nl_current_default_domain = _nl_default_default_domain;
+      new_domain = (char *) _nl_current_default_domain;
+    }
+  else if (strcmp (domainname, old_domain) == 0)
+    /* This can happen and people will use it to signal that some
+       environment variable changed.  */
+    new_domain = old_domain;
+  else
+    {
+      /* If the following malloc fails `_nl_current_default_domain'
+	 will be NULL.  This value will be returned and so signals we
+	 are out of core.  */
+#if defined _LIBC || defined HAVE_STRDUP
+      new_domain = strdup (domainname);
+#else
+      size_t len = strlen (domainname) + 1;
+      new_domain = (char *) malloc (len);
+      if (new_domain != NULL)
+	memcpy (new_domain, domainname, len);
+#endif
+
+      if (new_domain != NULL)
+	_nl_current_default_domain = new_domain;
+    }
+
+  /* We use this possibility to signal a change of the loaded catalogs
+     since this is most likely the case and there is no other easy we
+     to do it.  Do it only when the call was successful.  */
+  if (new_domain != NULL)
+    {
+      ++_nl_msg_cat_cntr;
+
+      if (old_domain != new_domain && old_domain != _nl_default_default_domain)
+	free (old_domain);
+    }
+
+  __libc_rwlock_unlock (_nl_state_lock);
+
+  return new_domain;
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__textdomain, textdomain);
+#endif
Index: /trunk/libc/src/glibc/malloc/malloc.smak
===================================================================
--- /trunk/libc/src/glibc/malloc/malloc.smak	(revision 2448)
+++ /trunk/libc/src/glibc/malloc/malloc.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/glibc/malloc/*.c)
Index: /trunk/libc/src/glibc/malloc/obstack.c
===================================================================
--- /trunk/libc/src/glibc/malloc/obstack.c	(revision 2448)
+++ /trunk/libc/src/glibc/malloc/obstack.c	(revision 2448)
@@ -0,0 +1,432 @@
+/* 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 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.  Its master source is NOT part of
+   the C library, however.  The master source lives in /gd/gnu/lib.
+
+   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
+
+#ifdef _LIBC
+# include <obstack.h>
+# include <shlib-compat.h>
+#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
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* Determine default alignment.  */
+struct fooalign {char x; double d;};
+# define DEFAULT_ALIGNMENT  \
+  ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
+/* 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.  */
+union fooround {long x; double d;};
+# define 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);
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+
+/* Exit value used when `print_and_abort' is used.  */
+# include <stdlib.h>
+# if defined _LIBC || defined __INNOTEK_LIBC__
+int obstack_exit_failure = 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 = (int) 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 = chunk->contents;
+  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 = (int) 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 = chunk->contents;
+  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 =
+    __INT_TO_PTR ((__PTR_TO_INT (new_chunk->contents) + h->alignment_mask)
+		  & ~ (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->object_base == old_chunk->contents && ! h->maybe_empty_object)
+    {
+      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.  */
+#ifndef __INNOTEK_LIBC__
+# ifdef _LIBC
+#  include <libintl.h>
+# else
+#  include "gettext.h"
+# endif
+# ifndef _
+#  define _(msgid) gettext (msgid)
+# endif
+#else /* __INNOTEK_LIBC__ */
+# undef _
+# define _(x)  (x)
+#endif /* __INNOTEK_LIBC__ */
+
+
+# ifdef _LIBC
+#  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 USE_IN_LIBIO
+  if (_IO_fwide (stderr, 0) > 0)
+    __fwprintf (stderr, L"%s\n", _("memory exhausted"));
+  else
+# endif
+    fprintf (stderr, "%s\n", _("memory exhausted"));
+  exit (obstack_exit_failure);
+}
+
+#endif	/* !ELIDE_CODE */
Index: /trunk/libc/src/glibc/math/cabsl.c
===================================================================
--- /trunk/libc/src/glibc/math/cabsl.c	(revision 2448)
+++ /trunk/libc/src/glibc/math/cabsl.c	(revision 2448)
@@ -0,0 +1,30 @@
+/* Return the complex absolute value of long double complex value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+long double
+_STD(cabsl) (long double _Complex z)
+{
+  return __hypotl (__real__ z, __imag__ z);
+}
+/*  w e a k _ a l i a s (__cabsl, cabsl) */
Index: /trunk/libc/src/glibc/math/carg.c
===================================================================
--- /trunk/libc/src/glibc/math/carg.c	(revision 2448)
+++ /trunk/libc/src/glibc/math/carg.c	(revision 2448)
@@ -0,0 +1,34 @@
+/* Compute argument of complex double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+double
+_STD(carg) (__complex__ double x)
+{
+  return __atan2 (__imag__ x, __real__ x);
+}
+/*  w e a k _ a l i a s (__carg, carg) */
+#ifdef NO_LONG_DOUBLE
+/*  s t r o n g _ a l i a s (__carg, __cargl) */
+/* w e a k _ a l i a s (__carg, cargl) */
+#endif
Index: /trunk/libc/src/glibc/math/cargl.c
===================================================================
--- /trunk/libc/src/glibc/math/cargl.c	(revision 2448)
+++ /trunk/libc/src/glibc/math/cargl.c	(revision 2448)
@@ -0,0 +1,30 @@
+/* Compute argument of complex long double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+long double
+_STD(cargl) (__complex__ long double x)
+{
+  return __atan2l (__imag__ x, __real__ x);
+}
+/*w e a k _ a l i a s (__cargl, cargl) */
Index: /trunk/libc/src/glibc/math/math.smak
===================================================================
--- /trunk/libc/src/glibc/math/math.smak	(revision 2448)
+++ /trunk/libc/src/glibc/math/math.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/glibc/math/*.c)
Index: /trunk/libc/src/glibc/misc/error.c
===================================================================
--- /trunk/libc/src/glibc/misc/error.c	(revision 2448)
+++ /trunk/libc/src/glibc/misc/error.c	(revision 2448)
@@ -0,0 +1,407 @@
+/* Error handler for noninteractive utilities
+   Copyright (C) 1990-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.  Its master source is NOT part of
+   the C library, however.  The master source lives in /gd/gnu/lib.
+
+   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>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#ifndef __EMX__                         /* bird */
+#include <libintl.h>
+#endif                                  /* bird */
+#ifdef _LIBC
+# include <wchar.h>
+# define mbsrtowcs __mbsrtowcs
+#endif
+
+#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
+# if __STDC__
+#  include <stdarg.h>
+#  define VA_START(args, lastarg) va_start(args, lastarg)
+# else
+#  include <varargs.h>
+#  define VA_START(args, lastarg) va_start(args)
+# endif
+#else
+# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
+# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
+#endif
+
+#if STDC_HEADERS || _LIBC
+# include <stdlib.h>
+# include <string.h>
+#else
+void exit ();
+#endif
+
+#include "error.h"
+
+#ifndef _
+# define _(String) String
+#endif
+
+/* 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) (
+#if __STDC__ - 0
+			      void
+#endif
+			      );
+
+/* This variable is incremented each time `error' is called.  */
+unsigned int error_message_count;
+
+#ifdef _LIBC
+/* In the GNU C library, there is a predefined variable for this.  */
+# define program_name program_invocation_name
+# include <errno.h>
+# include <libio/libioP.h>
+
+/* In GNU libc we want do not want to use the common name `error' directly.
+   Instead make it a weak alias.  */
+extern void __error (int status, int errnum, const char *message, ...)
+     __attribute__ ((__format__ (__printf__, 3, 4)));
+extern void __error_at_line (int status, int errnum, const char *file_name,
+			     unsigned int line_number, const char *message,
+			     ...)
+     __attribute__ ((__format__ (__printf__, 5, 6)));
+# define error __error
+# define error_at_line __error_at_line
+
+# include <libio/iolibio.h>
+# define fflush(s) INTUSE(_IO_fflush) (s)
+# undef putc
+# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
+
+#else /* not _LIBC */
+
+# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
+#  ifndef HAVE_DECL_STRERROR_R
+"this configure-time declaration test was not run"
+#  endif
+char *strerror_r ();
+# endif
+
+#ifndef __EMX__ /* bird */
+/* The calling program should define program_name and set it to the
+   name of the executing program.  */
+extern char *program_name;
+#else /* __EMX__ */                     /* bird */
+/* Use the BSD _getprogname() which the Innotek LIBC also implements.
+   Using this save the time used to maintain the two program_* vars
+   which GLIBC have. */
+extern const char *_getprogname(void);
+#define program_name    _getprogname()
+
+/* In GNU libc we want do not want to use the common name `error' directly.
+   Instead make it a weak alias.  */
+extern void __error (int status, int errnum, const char *message, ...)
+     __attribute__ ((__format__ (__printf__, 3, 4)));
+extern void __error_at_line (int status, int errnum, const char *file_name,
+			     unsigned int line_number, const char *message,
+			     ...)
+     __attribute__ ((__format__ (__printf__, 5, 6)));
+# define error __error
+# define error_at_line __error_at_line
+#endif /* __EMX__ */                     /* bird */
+
+
+#ifndef __EMX__ /* bird */
+# if HAVE_STRERROR_R || defined strerror_r
+#  define __strerror_r strerror_r
+# else
+#  if HAVE_STRERROR
+#   ifndef HAVE_DECL_STRERROR
+"this configure-time declaration test was not run"
+#   endif
+#   if !HAVE_DECL_STRERROR
+char *strerror ();
+#   endif
+#  else
+static char *
+private_strerror (int errnum)
+{
+  extern char *sys_errlist[];
+  extern int sys_nerr;
+
+  if (errnum > 0 && errnum <= sys_nerr)
+    return _(sys_errlist[errnum]);
+  return _("Unknown system error");
+}
+#   define strerror private_strerror
+#  endif /* HAVE_STRERROR */
+# endif	/* HAVE_STRERROR_R || defined strerror_r */
+#endif /* !__EMX__ */ /* bird */
+#endif	/* not _LIBC */
+
+static void
+print_errno_message (int errnum)
+{
+  char const *s;
+
+#if defined HAVE_STRERROR_R || _LIBC
+  char errbuf[1024];
+# if STRERROR_R_CHAR_P || (defined _LIBC && _LIBC)
+  s = __strerror_r (errnum, errbuf, sizeof errbuf);
+# else
+  if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
+    s = errbuf;
+  else
+    s = 0;
+# endif
+#else
+  s = strerror (errnum);
+#endif
+
+#if !defined _LIBC || !_LIBC
+  if (! s)
+    s = _("Unknown system error");
+#endif
+
+#if defined _LIBC && _LIBC
+  if (_IO_fwide (stderr, 0) > 0)
+    {
+      __fwprintf (stderr, L": %s", s);
+      return;
+    }
+#endif
+
+  fprintf (stderr, ": %s", s);
+}
+
+#ifdef VA_START
+static void
+error_tail (int status, int errnum, const char *message, va_list args)
+{
+# if HAVE_VPRINTF || (defined _LIBC && _LIBC)
+#  if defined _LIBC && _LIBC
+  if (_IO_fwide (stderr, 0) > 0)
+    {
+#   define ALLOCA_LIMIT	2000
+      size_t len = strlen (message) + 1;
+      wchar_t *wmessage = NULL;
+      mbstate_t st;
+      size_t res;
+      const char *tmp;
+
+      do
+	{
+	  if (len < ALLOCA_LIMIT)
+	    wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
+	  else
+	    {
+	      if (wmessage != NULL && len / 2 < ALLOCA_LIMIT)
+		wmessage = NULL;
+
+	      wmessage = (wchar_t *) realloc (wmessage,
+					      len * sizeof (wchar_t));
+
+	      if (wmessage == NULL)
+		{
+		  fputws_unlocked (L"out of memory\n", stderr);
+		  return;
+		}
+	    }
+
+	  memset (&st, '\0', sizeof (st));
+	  tmp =message;
+	}
+      while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len);
+
+      if (res == (size_t) -1)
+	/* The string cannot be converted.  */
+	wmessage = (wchar_t *) L"???";
+
+      __vfwprintf (stderr, wmessage, args);
+    }
+  else
+#  endif
+    vfprintf (stderr, message, args);
+# else
+  _doprnt (message, args, stderr);
+# endif
+  va_end (args);
+
+  ++error_message_count;
+  if (errnum)
+    print_errno_message (errnum);
+# if defined _LIBC && _LIBC
+  if (_IO_fwide (stderr, 0) > 0)
+    putwc (L'\n', stderr);
+  else
+# endif
+    putc ('\n', stderr);
+  fflush (stderr);
+  if (status)
+    exit (status);
+}
+#endif
+
+
+/* Print the program name and error message MESSAGE, which is a printf-style
+   format string with optional args.
+   If ERRNUM is nonzero, print its corresponding system error message.
+   Exit with status STATUS if it is nonzero.  */
+/* VARARGS */
+void
+#if defined VA_START && __STDC__
+error (int status, int errnum, const char *message, ...)
+#else
+error (status, errnum, message, va_alist)
+     int status;
+     int errnum;
+     char *message;
+     va_dcl
+#endif
+{
+#ifdef VA_START
+  va_list args;
+#endif
+
+  fflush (stdout);
+#ifdef _LIBC
+  _IO_flockfile (stderr);
+#endif
+  if (error_print_progname)
+    (*error_print_progname) ();
+  else
+    {
+#if defined _LIBC && _LIBC
+      if (_IO_fwide (stderr, 0) > 0)
+	__fwprintf (stderr, L"%s: ", program_name);
+      else
+#endif
+	fprintf (stderr, "%s: ", program_name);
+    }
+
+#ifdef VA_START
+  VA_START (args, message);
+  error_tail (status, errnum, message, args);
+#else
+  fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
+
+  ++error_message_count;
+  if (errnum)
+    print_errno_message (errnum);
+  putc ('\n', stderr);
+  fflush (stderr);
+  if (status)
+    exit (status);
+#endif
+
+#ifdef _LIBC
+  _IO_funlockfile (stderr);
+#endif
+}
+
+
+/* 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;
+
+void
+#if defined VA_START && __STDC__
+error_at_line (int status, int errnum, const char *file_name,
+	       unsigned int line_number, const char *message, ...)
+#else
+error_at_line (status, errnum, file_name, line_number, message, va_alist)
+     int status;
+     int errnum;
+     const char *file_name;
+     unsigned int line_number;
+     char *message;
+     va_dcl
+#endif
+{
+#ifdef VA_START
+  va_list args;
+#endif
+
+  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) == 0))
+	/* Simply return and print nothing.  */
+	return;
+
+      old_file_name = file_name;
+      old_line_number = line_number;
+    }
+
+  fflush (stdout);
+#ifdef _LIBC
+  _IO_flockfile (stderr);
+#endif
+  if (error_print_progname)
+    (*error_print_progname) ();
+  else
+    {
+#if defined _LIBC && _LIBC
+      if (_IO_fwide (stderr, 0) > 0)
+	__fwprintf (stderr, L"%s: ", program_name);
+      else
+#endif
+	fprintf (stderr, "%s:", program_name);
+    }
+
+  if (file_name != NULL)
+    {
+#if defined _LIBC && _LIBC
+      if (_IO_fwide (stderr, 0) > 0)
+	__fwprintf (stderr, L"%s:%d: ", file_name, line_number);
+      else
+#endif
+	fprintf (stderr, "%s:%d: ", file_name, line_number);
+    }
+
+#ifdef VA_START
+  VA_START (args, message);
+  error_tail (status, errnum, message, args);
+#else
+  fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
+
+  ++error_message_count;
+  if (errnum)
+    print_errno_message (errnum);
+  putc ('\n', stderr);
+  fflush (stderr);
+  if (status)
+    exit (status);
+#endif
+
+#ifdef _LIBC
+  _IO_funlockfile (stderr);
+#endif
+}
+
+#ifdef _LIBC
+/* Make the weak alias.  */
+# undef error
+# undef error_at_line
+weak_alias (__error, error)
+weak_alias (__error_at_line, error_at_line)
+#endif
Index: /trunk/libc/src/glibc/misc/misc.smak
===================================================================
--- /trunk/libc/src/glibc/misc/misc.smak	(revision 2448)
+++ /trunk/libc/src/glibc/misc/misc.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/glibc/misc/*.c)
Index: /trunk/libc/src/glibc/posix/getopt.c
===================================================================
--- /trunk/libc/src/glibc/posix/getopt.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/getopt.c	(revision 2448)
@@ -0,0 +1,1275 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to drepper@gnu.org
+   before changing it!
+   Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004
+   	Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   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.  */
+
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+   Ditto for AIX 3.2 and <stdlib.h>.  */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.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.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#if defined __GNU_LIBRARY__ || defined __INNOTEK_LIBC__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+# include <stdlib.h>
+# include <unistd.h>
+#endif	/* GNU C library.  */
+
+#include <string.h>
+
+#ifdef VMS
+# include <unixlib.h>
+#endif
+
+#ifndef __INNOTEK_LIBC__
+#ifndef	_LIBC
+# include <libintl.h>
+#else
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+#endif
+#else /* __INNOTEK_LIBC__ */
+# define _(msgid) msgid
+#endif /* __INNOTEK_LIBC__ */
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+#include "getopt_int.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* 1003.2 says this must be 1 before any call.  */
+int optind = 1;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Keep a global copy of all internal members of getopt_data.  */
+
+static struct _getopt_data getopt_data;
+
+/* BSD interface. When set the state will be reset on the next call. */
+
+int optreset = 0;
+
+
+
+#ifndef __GNU_LIBRARY__
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+
+#endif /* not __GNU_LIBRARY__ */
+
+
+#ifdef _LIBC
+/* Stored original parameters.
+   XXX This is no good solution.  We should rather copy the args so
+   that we can compare them later.  But we must not use malloc(3).  */
+extern int __libc_argc;
+extern char **__libc_argv;
+
+/* Bash 2.0 gives us an environment variable containing flags
+   indicating ARGV elements that should not be considered arguments.  */
+
+# ifdef USE_NONOPTION_FLAGS
+/* Defined in getopt_init.c  */
+extern char *__getopt_nonoption_flags;
+# endif
+
+# ifdef USE_NONOPTION_FLAGS
+#  define SWAP_FLAGS(ch1, ch2) \
+  if (d->__nonoption_flags_len > 0)					      \
+    {									      \
+      char __tmp = __getopt_nonoption_flags[ch1];			      \
+      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \
+      __getopt_nonoption_flags[ch2] = __tmp;				      \
+    }
+# else
+#  define SWAP_FLAGS(ch1, ch2)
+# endif
+#else	/* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif	/* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (char **argv, struct _getopt_data *d)
+{
+  int bottom = d->__first_nonopt;
+  int middle = d->__last_nonopt;
+  int top = d->optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  /* First make sure the handling of the `__getopt_nonoption_flags'
+     string can work normally.  Our top argument must be in the range
+     of the string.  */
+  if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
+    {
+      /* We must extend the array.  The user plays games with us and
+	 presents new arguments.  */
+      char *new_str = malloc (top + 1);
+      if (new_str == NULL)
+	d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
+      else
+	{
+	  memset (__mempcpy (new_str, __getopt_nonoption_flags,
+			     d->__nonoption_flags_max_len),
+		  '\0', top + 1 - d->__nonoption_flags_max_len);
+	  d->__nonoption_flags_max_len = top + 1;
+	  __getopt_nonoption_flags = new_str;
+	}
+    }
+#endif
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	      SWAP_FLAGS (bottom + i, middle + i);
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  d->__first_nonopt += (d->optind - d->__last_nonopt);
+  d->__last_nonopt = d->optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+static const char *
+_getopt_initialize (int argc, char *const *argv, const char *optstring,
+		    struct _getopt_data *d)
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  d->__first_nonopt = d->__last_nonopt = d->optind;
+
+  d->__nextchar = NULL;
+
+  d->__posixly_correct = !!getenv ("POSIXLY_CORRECT");
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      d->__ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      d->__ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (d->__posixly_correct)
+    d->__ordering = REQUIRE_ORDER;
+  else
+    d->__ordering = PERMUTE;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  if (!d->__posixly_correct
+      && argc == __libc_argc && argv == __libc_argv)
+    {
+      if (d->__nonoption_flags_max_len == 0)
+	{
+	  if (__getopt_nonoption_flags == NULL
+	      || __getopt_nonoption_flags[0] == '\0')
+	    d->__nonoption_flags_max_len = -1;
+	  else
+	    {
+	      const char *orig_str = __getopt_nonoption_flags;
+	      int len = d->__nonoption_flags_max_len = strlen (orig_str);
+	      if (d->__nonoption_flags_max_len < argc)
+		d->__nonoption_flags_max_len = argc;
+	      __getopt_nonoption_flags =
+		(char *) malloc (d->__nonoption_flags_max_len);
+	      if (__getopt_nonoption_flags == NULL)
+		d->__nonoption_flags_max_len = -1;
+	      else
+		memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+			'\0', d->__nonoption_flags_max_len - len);
+	    }
+	}
+      d->__nonoption_flags_len = d->__nonoption_flags_max_len;
+    }
+  else
+    d->__nonoption_flags_len = 0;
+#endif
+
+  return optstring;
+}
+
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns -1.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal_r (int argc, char *const *argv, const char *optstring,
+		    const struct option *longopts, int *longind,
+		    int long_only, struct _getopt_data *d)
+{
+  int print_errors = d->opterr;
+  if (optstring[0] == ':')
+    print_errors = 0;
+
+  if (argc < 1)
+    return -1;
+
+  d->optarg = NULL;
+
+  if (d->optind == 0 || !d->__initialized)
+    {
+      if (d->optind == 0)
+	d->optind = 1;	/* Don't scan ARGV[0], the program name.  */
+      optstring = _getopt_initialize (argc, argv, optstring, d);
+      d->__initialized = 1;
+    }
+
+  /* Test whether ARGV[optind] points to a non-option argument.
+     Either it does not have option syntax, or there is an environment flag
+     from the shell indicating it is not an option.  The later information
+     is only used when the used in the GNU libc.  */
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
+		      || (d->optind < d->__nonoption_flags_len		      \
+			  && __getopt_nonoption_flags[d->optind] == '1'))
+#else
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
+#endif
+
+  if (d->__nextchar == NULL || *d->__nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+	 moved back by the user (who may also have changed the arguments).  */
+      if (d->__last_nonopt > d->optind)
+	d->__last_nonopt = d->optind;
+      if (d->__first_nonopt > d->optind)
+	d->__first_nonopt = d->optind;
+
+      if (d->__ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (d->__first_nonopt != d->__last_nonopt
+	      && d->__last_nonopt != d->optind)
+	    exchange ((char **) argv, d);
+	  else if (d->__last_nonopt != d->optind)
+	    d->__first_nonopt = d->optind;
+
+	  /* Skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (d->optind < argc && NONOPTION_P)
+	    d->optind++;
+	  d->__last_nonopt = d->optind;
+	}
+
+      /* The special ARGV-element `--' means premature end of options.
+	 Skip it like a null option,
+	 then exchange with previous non-options as if it were an option,
+	 then skip everything else like a non-option.  */
+
+      if (d->optind != argc && !strcmp (argv[d->optind], "--"))
+	{
+	  d->optind++;
+
+	  if (d->__first_nonopt != d->__last_nonopt
+	      && d->__last_nonopt != d->optind)
+	    exchange ((char **) argv, d);
+	  else if (d->__first_nonopt == d->__last_nonopt)
+	    d->__first_nonopt = d->optind;
+	  d->__last_nonopt = argc;
+
+	  d->optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+	 and back over any non-options that we skipped and permuted.  */
+
+      if (d->optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (d->__first_nonopt != d->__last_nonopt)
+	    d->optind = d->__first_nonopt;
+	  return -1;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+	 either stop the scan or describe it to the caller and pass it by.  */
+
+      if (NONOPTION_P)
+	{
+	  if (d->__ordering == REQUIRE_ORDER)
+	    return -1;
+	  d->optarg = argv[d->optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+	 Skip the initial punctuation.  */
+
+      d->__nextchar = (argv[d->optind] + 1
+		  + (longopts != NULL && argv[d->optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[d->optind][1] == '-'
+	  || (long_only && (argv[d->optind][2]
+			    || !strchr (optstring, argv[d->optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = -1;
+      int option_index;
+
+      for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
+	/* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+	 or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+	  {
+	    if ((unsigned int) (nameend - d->__nextchar)
+		== (unsigned int) strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else if (long_only
+		     || pfound->has_arg != p->has_arg
+		     || pfound->flag != p->flag
+		     || pfound->val != p->val)
+	      /* Second or later nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (print_errors)
+	    {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+
+	      if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
+			      argv[0], argv[d->optind]) >= 0)
+		{
+		  _IO_flockfile (stderr);
+
+		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		  if (_IO_fwide (stderr, 0) > 0)
+		    __fwprintf (stderr, L"%s", buf);
+		  else
+		    fputs (buf, stderr);
+
+		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		  _IO_funlockfile (stderr);
+
+		  free (buf);
+		}
+#else
+	      fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+		       argv[0], argv[d->optind]);
+#endif
+	    }
+	  d->__nextchar += strlen (d->__nextchar);
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  d->optind++;
+	  if (*nameend)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+		 allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		d->optarg = nameend + 1;
+	      else
+		{
+		  if (print_errors)
+		    {
+#if defined _LIBC && defined USE_IN_LIBIO
+		      char *buf;
+		      int n;
+#endif
+
+		      if (argv[d->optind - 1][1] == '-')
+			{
+			  /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+			  n = __asprintf (&buf, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+					  argv[0], pfound->name);
+#else
+			  fprintf (stderr, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+				   argv[0], pfound->name);
+#endif
+			}
+		      else
+			{
+			  /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+			  n = __asprintf (&buf, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+					  argv[0], argv[d->optind - 1][0],
+					  pfound->name);
+#else
+			  fprintf (stderr, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+				   argv[0], argv[d->optind - 1][0],
+				   pfound->name);
+#endif
+			}
+
+#if defined _LIBC && defined USE_IN_LIBIO
+		      if (n >= 0)
+			{
+			  _IO_flockfile (stderr);
+
+			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			  ((_IO_FILE *) stderr)->_flags2
+			    |= _IO_FLAGS2_NOTCANCEL;
+
+			  if (_IO_fwide (stderr, 0) > 0)
+			    __fwprintf (stderr, L"%s", buf);
+			  else
+			    fputs (buf, stderr);
+
+			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			  _IO_funlockfile (stderr);
+
+			  free (buf);
+			}
+#endif
+		    }
+
+		  d->__nextchar += strlen (d->__nextchar);
+
+		  d->optopt = pfound->val;
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (d->optind < argc)
+		d->optarg = argv[d->optind++];
+	      else
+		{
+		  if (print_errors)
+		    {
+#if defined _LIBC && defined USE_IN_LIBIO
+		      char *buf;
+
+		      if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+				      argv[0], argv[d->optind - 1]) >= 0)
+			{
+			  _IO_flockfile (stderr);
+
+			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			  ((_IO_FILE *) stderr)->_flags2
+			    |= _IO_FLAGS2_NOTCANCEL;
+
+			  if (_IO_fwide (stderr, 0) > 0)
+			    __fwprintf (stderr, L"%s", buf);
+			  else
+			    fputs (buf, stderr);
+
+			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			  _IO_funlockfile (stderr);
+
+			  free (buf);
+			}
+#else
+		      fprintf (stderr,
+			       _("%s: option `%s' requires an argument\n"),
+			       argv[0], argv[d->optind - 1]);
+#endif
+		    }
+		  d->__nextchar += strlen (d->__nextchar);
+		  d->optopt = pfound->val;
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  d->__nextchar += strlen (d->__nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short
+	 option, then it's an error.
+	 Otherwise interpret it as a short option.  */
+      if (!long_only || argv[d->optind][1] == '-'
+	  || strchr (optstring, *d->__nextchar) == NULL)
+	{
+	  if (print_errors)
+	    {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+	      int n;
+#endif
+
+	      if (argv[d->optind][1] == '-')
+		{
+		  /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+		  n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
+				  argv[0], d->__nextchar);
+#else
+		  fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+			   argv[0], d->__nextchar);
+#endif
+		}
+	      else
+		{
+		  /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+		  n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
+				  argv[0], argv[d->optind][0], d->__nextchar);
+#else
+		  fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+			   argv[0], argv[d->optind][0], d->__nextchar);
+#endif
+		}
+
+#if defined _LIBC && defined USE_IN_LIBIO
+	      if (n >= 0)
+		{
+		  _IO_flockfile (stderr);
+
+		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		  if (_IO_fwide (stderr, 0) > 0)
+		    __fwprintf (stderr, L"%s", buf);
+		  else
+		    fputs (buf, stderr);
+
+		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		  _IO_funlockfile (stderr);
+
+		  free (buf);
+		}
+#endif
+	    }
+	  d->__nextchar = (char *) "";
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *d->__nextchar++;
+    char *temp = strchr (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*d->__nextchar == '\0')
+      ++d->optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (print_errors)
+	  {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+	      int n;
+#endif
+
+	    if (d->__posixly_correct)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
+				argv[0], c);
+#else
+		fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
+#endif
+	      }
+	    else
+	      {
+#if defined _LIBC && defined USE_IN_LIBIO
+		n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
+				argv[0], c);
+#else
+		fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
+#endif
+	      }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+	    if (n >= 0)
+	      {
+		_IO_flockfile (stderr);
+
+		int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		if (_IO_fwide (stderr, 0) > 0)
+		  __fwprintf (stderr, L"%s", buf);
+		else
+		  fputs (buf, stderr);
+
+		((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		_IO_funlockfile (stderr);
+
+		free (buf);
+	      }
+#endif
+	  }
+	d->optopt = c;
+	return '?';
+      }
+    /* Convenience. Treat POSIX -W foo same as long option --foo */
+    if (temp[0] == 'W' && temp[1] == ';')
+      {
+	char *nameend;
+	const struct option *p;
+	const struct option *pfound = NULL;
+	int exact = 0;
+	int ambig = 0;
+	int indfound = 0;
+	int option_index;
+
+	/* This is an option that requires an argument.  */
+	if (*d->__nextchar != '\0')
+	  {
+	    d->optarg = d->__nextchar;
+	    /* If we end this ARGV-element by taking the rest as an arg,
+	       we must advance to the next element now.  */
+	    d->optind++;
+	  }
+	else if (d->optind == argc)
+	  {
+	    if (print_errors)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		char *buf;
+
+		if (__asprintf (&buf,
+				_("%s: option requires an argument -- %c\n"),
+				argv[0], c) >= 0)
+		  {
+		    _IO_flockfile (stderr);
+
+		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		    if (_IO_fwide (stderr, 0) > 0)
+		      __fwprintf (stderr, L"%s", buf);
+		    else
+		      fputs (buf, stderr);
+
+		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		    _IO_funlockfile (stderr);
+
+		    free (buf);
+		  }
+#else
+		fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+			 argv[0], c);
+#endif
+	      }
+	    d->optopt = c;
+	    if (optstring[0] == ':')
+	      c = ':';
+	    else
+	      c = '?';
+	    return c;
+	  }
+	else
+	  /* We already incremented `d->optind' once;
+	     increment it again when taking next ARGV-elt as argument.  */
+	  d->optarg = argv[d->optind++];
+
+	/* optarg is now the argument, see if it's in the
+	   table of longopts.  */
+
+	for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
+	     nameend++)
+	  /* Do nothing.  */ ;
+
+	/* Test all long options for either exact match
+	   or abbreviated matches.  */
+	for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	  if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+	    {
+	      if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
+		{
+		  /* Exact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		  exact = 1;
+		  break;
+		}
+	      else if (pfound == NULL)
+		{
+		  /* First nonexact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		}
+	      else
+		/* Second or later nonexact match found.  */
+		ambig = 1;
+	    }
+	if (ambig && !exact)
+	  {
+	    if (print_errors)
+	      {
+#if defined _LIBC && defined USE_IN_LIBIO
+		char *buf;
+
+		if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
+				argv[0], argv[d->optind]) >= 0)
+		  {
+		    _IO_flockfile (stderr);
+
+		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		    if (_IO_fwide (stderr, 0) > 0)
+		      __fwprintf (stderr, L"%s", buf);
+		    else
+		      fputs (buf, stderr);
+
+		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		    _IO_funlockfile (stderr);
+
+		    free (buf);
+		  }
+#else
+		fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+			 argv[0], argv[d->optind]);
+#endif
+	      }
+	    d->__nextchar += strlen (d->__nextchar);
+	    d->optind++;
+	    return '?';
+	  }
+	if (pfound != NULL)
+	  {
+	    option_index = indfound;
+	    if (*nameend)
+	      {
+		/* Don't test has_arg with >, because some C compilers don't
+		   allow it to be used on enums.  */
+		if (pfound->has_arg)
+		  d->optarg = nameend + 1;
+		else
+		  {
+		    if (print_errors)
+		      {
+#if defined _LIBC && defined USE_IN_LIBIO
+			char *buf;
+
+			if (__asprintf (&buf, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+					argv[0], pfound->name) >= 0)
+			  {
+			    _IO_flockfile (stderr);
+
+			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			    ((_IO_FILE *) stderr)->_flags2
+			      |= _IO_FLAGS2_NOTCANCEL;
+
+			    if (_IO_fwide (stderr, 0) > 0)
+			      __fwprintf (stderr, L"%s", buf);
+			    else
+			      fputs (buf, stderr);
+
+			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			    _IO_funlockfile (stderr);
+
+			    free (buf);
+			  }
+#else
+			fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+				 argv[0], pfound->name);
+#endif
+		      }
+
+		    d->__nextchar += strlen (d->__nextchar);
+		    return '?';
+		  }
+	      }
+	    else if (pfound->has_arg == 1)
+	      {
+		if (d->optind < argc)
+		  d->optarg = argv[d->optind++];
+		else
+		  {
+		    if (print_errors)
+		      {
+#if defined _LIBC && defined USE_IN_LIBIO
+			char *buf;
+
+			if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+					argv[0], argv[d->optind - 1]) >= 0)
+			  {
+			    _IO_flockfile (stderr);
+
+			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			    ((_IO_FILE *) stderr)->_flags2
+			      |= _IO_FLAGS2_NOTCANCEL;
+
+			    if (_IO_fwide (stderr, 0) > 0)
+			      __fwprintf (stderr, L"%s", buf);
+			    else
+			      fputs (buf, stderr);
+
+			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			    _IO_funlockfile (stderr);
+
+			    free (buf);
+			  }
+#else
+			fprintf (stderr,
+				 _("%s: option `%s' requires an argument\n"),
+				 argv[0], argv[d->optind - 1]);
+#endif
+		      }
+		    d->__nextchar += strlen (d->__nextchar);
+		    return optstring[0] == ':' ? ':' : '?';
+		  }
+	      }
+	    d->__nextchar += strlen (d->__nextchar);
+	    if (longind != NULL)
+	      *longind = option_index;
+	    if (pfound->flag)
+	      {
+		*(pfound->flag) = pfound->val;
+		return 0;
+	      }
+	    return pfound->val;
+	  }
+	  d->__nextchar = NULL;
+	  return 'W';	/* Let the application handle it.   */
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*d->__nextchar != '\0')
+	      {
+		d->optarg = d->__nextchar;
+		d->optind++;
+	      }
+	    else
+	      d->optarg = NULL;
+	    d->__nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*d->__nextchar != '\0')
+	      {
+		d->optarg = d->__nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		d->optind++;
+	      }
+	    else if (d->optind == argc)
+	      {
+		if (print_errors)
+		  {
+		    /* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		    char *buf;
+
+		    if (__asprintf (&buf, _("\
+%s: option requires an argument -- %c\n"),
+				    argv[0], c) >= 0)
+		      {
+			_IO_flockfile (stderr);
+
+			int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+			if (_IO_fwide (stderr, 0) > 0)
+			  __fwprintf (stderr, L"%s", buf);
+			else
+			  fputs (buf, stderr);
+
+			((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			_IO_funlockfile (stderr);
+
+			free (buf);
+		      }
+#else
+		    fprintf (stderr,
+			     _("%s: option requires an argument -- %c\n"),
+			     argv[0], c);
+#endif
+		  }
+		d->optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+		 increment it again when taking next ARGV-elt as argument.  */
+	      d->optarg = argv[d->optind++];
+	    d->__nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+_getopt_internal (int argc, char *const *argv, const char *optstring,
+		  const struct option *longopts, int *longind, int long_only)
+{
+  int result;
+
+  /* BSD extention, same as setting optind to 0. */
+  if (optreset)
+    {
+      optreset = 0;
+      optind = 0;
+    }
+
+  getopt_data.optind = optind;
+  getopt_data.opterr = opterr;
+
+  result = _getopt_internal_r (argc, argv, optstring, longopts,
+			       longind, long_only, &getopt_data);
+
+  optind = getopt_data.optind;
+  optarg = getopt_data.optarg;
+  optopt = getopt_data.optopt;
+
+  return result;
+}
+
+int
+_STD(getopt) (int argc, char *const *argv, const char *optstring)
+{
+  return _getopt_internal (argc, argv, optstring,
+			   (const struct option *) 0,
+			   (int *) 0,
+			   0);
+}
+
+#endif	/* Not ELIDE_CODE.  */
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (int argc, char **argv)
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /trunk/libc/src/glibc/posix/getopt1.c
===================================================================
--- /trunk/libc/src/glibc/posix/getopt1.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/getopt1.c	(revision 2448)
@@ -0,0 +1,194 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
+     Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   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
+
+#ifdef _LIBC
+# include <getopt.h>
+#else
+# include "getopt.h"
+#endif
+#include "getopt_int.h"
+
+#include <stdio.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.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef	NULL
+#define NULL 0
+#endif
+
+int
+_STD(getopt_long) (int argc, char *const *argv, const char *options,
+	     const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+int
+_getopt_long_r (int argc, char *const *argv, const char *options,
+		const struct option *long_options, int *opt_index,
+		struct _getopt_data *d)
+{
+  return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+			     0, d);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+_STD(getopt_long_only) (int argc, char *const *argv, const char *options,
+		  const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+int
+_getopt_long_only_r (int argc, char *const *argv, const char *options,
+		     const struct option *long_options, int *opt_index,
+		     struct _getopt_data *d)
+{
+  return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+			     1, d);
+}
+
+#endif	/* Not ELIDE_CODE.  */
+
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /trunk/libc/src/glibc/posix/getopt_int.h
===================================================================
--- /trunk/libc/src/glibc/posix/getopt_int.h	(revision 2448)
+++ /trunk/libc/src/glibc/posix/getopt_int.h	(revision 2448)
@@ -0,0 +1,131 @@
+/* Internal declarations for getopt.
+   Copyright (C) 1989-1994,1996-1999,2001,2003,2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   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 _GETOPT_INT_H
+#define _GETOPT_INT_H	1
+
+extern int _getopt_internal (int ___argc, char *const *___argv,
+			     const char *__shortopts,
+		             const struct option *__longopts, int *__longind,
+			     int __long_only);
+
+
+
+/* Reentrant versions which can handle parsing multiple argument
+   vectors at the same time.  */
+
+/* Data type for reentrant functions.  */
+struct _getopt_data
+{
+  /* These have exactly the same meaning as the corresponding global
+     variables, except that they are used for the reentrant
+     versions of getopt.  */
+  int optind;
+  int opterr;
+  int optopt;
+  char *optarg;
+
+  /* Internal members.  */
+
+  /* True if the internal members have been initialized.  */
+  int __initialized;
+
+  /* The next char to be scanned in the option-element
+     in which the last option character we returned was found.
+     This allows us to pick up the scan where we left off.
+
+     If this is zero, or a null string, it means resume the scan
+     by advancing to the next ARGV-element.  */
+  char *__nextchar;
+
+  /* Describe how to deal with options that follow non-option ARGV-elements.
+
+     If the caller did not specify anything,
+     the default is REQUIRE_ORDER if the environment variable
+     POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+     REQUIRE_ORDER means don't recognize them as options;
+     stop option processing when the first non-option is seen.
+     This is what Unix does.
+     This mode of operation is selected by either setting the environment
+     variable POSIXLY_CORRECT, or using `+' as the first character
+     of the list of option characters.
+
+     PERMUTE is the default.  We permute the contents of ARGV as we
+     scan, so that eventually all the non-options are at the end.
+     This allows options to be given in any order, even with programs
+     that were not written to expect this.
+
+     RETURN_IN_ORDER is an option available to programs that were
+     written to expect options and other ARGV-elements in any order
+     and that care about the ordering of the two.  We describe each
+     non-option ARGV-element as if it were the argument of an option
+     with character code 1.  Using `-' as the first character of the
+     list of option characters selects this mode of operation.
+
+     The special argument `--' forces an end of option-scanning regardless
+     of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+     `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
+
+  enum
+    {
+      REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+    } __ordering;
+
+  /* If the POSIXLY_CORRECT environment variable is set.  */
+  int __posixly_correct;
+
+
+  /* Handle permutation of arguments.  */
+
+  /* Describe the part of ARGV that contains non-options that have
+     been skipped.  `first_nonopt' is the index in ARGV of the first
+     of them; `last_nonopt' is the index after the last of them.  */
+
+  int __first_nonopt;
+  int __last_nonopt;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  int __nonoption_flags_max_len;
+  int __nonoption_flags_len;
+# endif
+};
+
+/* The initializer is necessary to set OPTIND and OPTERR to their
+   default values and to clear the initialization flag.  */
+#define _GETOPT_DATA_INITIALIZER	{ 1, 1 }
+
+extern int _getopt_internal_r (int ___argc, char *const *___argv,
+			       const char *__shortopts,
+			       const struct option *__longopts, int *__longind,
+			       int __long_only, struct _getopt_data *__data);
+
+extern int _getopt_long_r (int ___argc, char *const *___argv,
+			   const char *__shortopts,
+			   const struct option *__longopts, int *__longind,
+			   struct _getopt_data *__data);
+
+extern int _getopt_long_only_r (int ___argc, char *const *___argv,
+				const char *__shortopts,
+				const struct option *__longopts,
+				int *__longind,
+				struct _getopt_data *__data);
+
+#endif /* getopt_int.h */
Index: /trunk/libc/src/glibc/posix/posix.smak
===================================================================
--- /trunk/libc/src/glibc/posix/posix.smak	(revision 2448)
+++ /trunk/libc/src/glibc/posix/posix.smak	(revision 2448)
@@ -0,0 +1,2 @@
+libc.TSRC += $(filter-out $(addprefix src/glibc/posix/,regcomp.c regexec.c regex_internal.c), \
+	$(wildcard src/glibc/posix/*.c))
Index: /trunk/libc/src/glibc/posix/re_comp.h
===================================================================
--- /trunk/libc/src/glibc/posix/re_comp.h	(revision 2448)
+++ /trunk/libc/src/glibc/posix/re_comp.h	(revision 2448)
@@ -0,0 +1,26 @@
+/*  Copyright (C) 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 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 _RE_COMP_H
+#define _RE_COMP_H	1
+
+/* This is only a wrapper around the <regex.h> file.  XPG4.2 mentions
+   this name.  */
+#include <regex.h>
+
+#endif /* re_comp.h */
Index: /trunk/libc/src/glibc/posix/regcomp.c
===================================================================
--- /trunk/libc/src/glibc/posix/regcomp.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/regcomp.c	(revision 2448)
@@ -0,0 +1,3939 @@
+/* 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 re_compile_internal (regex_t *preg, const char * pattern,
+					  int 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, int pat_len);
+static void init_word_char (re_dfa_t *dfa);
+#ifdef RE_ENABLE_I18N
+static void free_charset (re_charset_t *cset);
+#endif /* RE_ENABLE_I18N */
+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 create_initial_state (re_dfa_t *dfa);
+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 reg_errcode_t duplicate_node_closure (re_dfa_t *dfa, int top_org_node,
+					     int top_clone_node, int root_node,
+					     unsigned int constraint);
+static reg_errcode_t duplicate_node (int *new_idx, re_dfa_t *dfa, int org_idx,
+				     unsigned int constraint);
+static int search_duplicated_node (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 void fetch_token (re_token_t *result, re_string_t *input,
+			 reg_syntax_t syntax);
+static int peek_token (re_token_t *token, re_string_t *input,
+			reg_syntax_t syntax);
+static int peek_token_bracket (re_token_t *token, re_string_t *input,
+			       reg_syntax_t syntax);
+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);
+#ifndef _LIBC
+# ifdef RE_ENABLE_I18N
+static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset,
+				      re_charset_t *mbcset, int *range_alloc,
+				      bracket_elem_t *start_elem,
+				      bracket_elem_t *end_elem);
+static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset,
+					     re_charset_t *mbcset,
+					     int *coll_sym_alloc,
+					     const unsigned char *name);
+# else /* not RE_ENABLE_I18N */
+static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset,
+				      bracket_elem_t *start_elem,
+				      bracket_elem_t *end_elem);
+static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset,
+					     const unsigned char *name);
+# endif /* not RE_ENABLE_I18N */
+#endif /* not _LIBC */
+#ifdef RE_ENABLE_I18N
+static reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset,
+					re_charset_t *mbcset,
+					int *equiv_class_alloc,
+					const unsigned char *name);
+static reg_errcode_t build_charclass (unsigned RE_TRANSLATE_TYPE trans,
+				      re_bitset_ptr_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 (re_bitset_ptr_t sbcset,
+					const unsigned char *name);
+static reg_errcode_t build_charclass (unsigned RE_TRANSLATE_TYPE trans,
+				      re_bitset_ptr_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,
+				       unsigned 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?  */
+
+const char __re_error_msgid[] attribute_hidden =
+  {
+#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 */
+  };
+
+const size_t __re_error_msgid_idx[] attribute_hidden =
+  {
+    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 *
+_STD(re_compile_pattern) (pattern, length, bufp)
+    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]);
+}
+#ifdef _LIBC
+/* w e a k _alias (__re_compile_pattern, re_compile_pattern)*/
+#endif
+
+/* 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 _STD(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
+_STD(re_set_syntax) (syntax)
+    reg_syntax_t syntax;
+{
+  reg_syntax_t ret = re_syntax_options;
+
+  re_syntax_options = syntax;
+  return ret;
+}
+#ifdef _LIBC
+/*  w e a k _ a l i a s (__re_set_syntax, re_set_syntax) */
+#endif
+
+int
+_STD(re_compile_fastmap) (bufp)
+    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;
+}
+#ifdef _LIBC
+/* w e a k _ a l i a s (__re_compile_fastmap, re_compile_fastmap) */
+#endif
+
+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 (bufp, init_state, fastmap)
+     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, j, ch;
+	  for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
+	    for (j = 0; j < UINT_BITS; ++j, ++ch)
+	      if (dfa->nodes[node].opr.sbcset[i] & (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)
+	    {
+# ifdef _LIBC
+	      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'.  */
+		  int j, ch;
+		  const int32_t *table = (const int32_t *)
+		    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+		  for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
+		    for (j = 0; j < UINT_BITS; ++j, ++ch)
+		      if (table[ch] < 0)
+			re_set_fastmap (fastmap, icase, ch);
+		}
+# 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 /* not _LIBC */
+	    }
+	  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 /* RE_ENABLE_I18N */
+	       || 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
+_STD(regcomp) (preg, pattern, cflags)
+    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;
+}
+#ifdef _LIBC
+/* w e a k _ a l i a s (__regcomp, regcomp) */
+#endif
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   We don't use PREG here.  */
+
+size_t
+_STD(regerror) (errcode, preg, errbuf, errbuf_size)
+    int errcode;
+    const regex_t *preg;
+    char *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))
+	{
+#if defined HAVE_MEMPCPY || defined _LIBC
+	  *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
+#else
+	  memcpy (errbuf, msg, errbuf_size - 1);
+	  errbuf[errbuf_size - 1] = 0;
+#endif
+	}
+      else
+	memcpy (errbuf, msg, msg_size);
+    }
+
+  return msg_size;
+}
+#ifdef _LIBC
+/* w e a k _ a l i a s (__regerror, regerror) */
+#endif
+
+
+#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 utf8_sb_map =
+{
+  /* Set the first 128 bits.  */
+# if UINT_MAX == 0xffffffff
+  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+# else
+#  error "Add case for new unsigned int size"
+# endif
+};
+#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
+_STD(regfree) (preg)
+    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;
+}
+#ifdef _LIBC
+/* w e a k_alias (__regfree, regfree) */
+#endif
+
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#if defined _REGEX_RE_COMP || defined _LIBC || defined __INNOTEK_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 above without link errors.  */
+weak_function
+# endif
+_STD(re_comp) (s)
+     const char *s;
+{
+  reg_errcode_t ret;
+  char *fastmap;
+
+  if (!s)
+    {
+      if (!re_comp_buf.buffer)
+	return gettext ("No previous regular expression");
+      return 0;
+    }
+
+  if (re_comp_buf.buffer)
+    {
+      fastmap = re_comp_buf.fastmap;
+      re_comp_buf.fastmap = NULL;
+      __regfree (&re_comp_buf);
+      memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
+      re_comp_buf.fastmap = fastmap;
+    }
+
+  if (re_comp_buf.fastmap == NULL)
+    {
+      re_comp_buf.fastmap = (char *) malloc (SBC_MAX);
+      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;
+
+  ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
+
+  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]);
+}
+
+#ifdef _LIBC
+libc_freeres_fn (free_mem)
+{
+  __regfree (&re_comp_buf);
+}
+#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 (preg, pattern, length, syntax)
+     regex_t *preg;
+     const char * pattern;
+     int 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);
+
+  /* __libc_lock_init (dfa->lock); - why init before memsetting the whole thing? */
+
+  err = init_dfa (dfa, length);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_dfa_content (dfa);
+      preg->buffer = NULL;
+      preg->allocated = 0;
+      return err;
+    }
+  __libc_lock_init (dfa->lock); /* bird */
+
+#ifdef DEBUG
+  dfa->re_str = re_malloc (char, length + 1);
+  strncpy (dfa->re_str, pattern, length + 1);
+#endif
+
+  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 (dfa, pat_len)
+     re_dfa_t *dfa;
+     int pat_len;
+{
+  int table_size;
+#ifndef _LIBC
+  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;
+
+  dfa->nodes_alloc = pat_len + 1;
+  dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
+
+  dfa->states_alloc = pat_len + 1;
+
+  /*  table_size = 2 ^ ceil(log pat_len) */
+  for (table_size = 1; table_size > 0; 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;
+#ifdef _LIBC
+  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 = (re_bitset_ptr_t) calloc (sizeof (bitset), 1);
+	  if (BE (dfa->sb_char == NULL, 0))
+	    return REG_ESPACE;
+
+	  /* Clear all bits by, then set those corresponding to single
+	     byte chars.  */
+	  bitset_empty (dfa->sb_char);
+
+	  for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
+	    for (j = 0; j < UINT_BITS; ++j, ++ch)
+	      {
+		wint_t wch = __btowc (ch);
+		if (wch != WEOF)
+		  dfa->sb_char[i] |= 1 << j;
+# if !defined (_LIBC) && !defined (__INNOTEK_LIBC__)
+		if (isascii (ch) && wch != (wchar_t) 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
+init_word_char (dfa)
+     re_dfa_t *dfa;
+{
+  int i, j, ch;
+  dfa->word_ops_used = 1;
+  for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
+    for (j = 0; j < UINT_BITS; ++j, ++ch)
+      if (isalnum (ch) || ch == '_')
+	dfa->word_char[i] |= 1 << j;
+}
+
+/* Free the work area which are only used while compiling.  */
+
+static void
+free_workarea_compile (preg)
+     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 (dfa)
+     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 (dfa)
+     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.  */
+        for (i = 0x80 / UINT_BITS; i < BITSET_UINTS; ++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 (preg)
+     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 (root, fn, extra)
+     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 (root, fn, extra)
+     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 (extra, node)
+     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 < 8 * sizeof (dfa->used_bkref_map))
+	dfa->used_bkref_map &= ~(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 (extra, node)
+     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 (err, preg, node)
+     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 >= 8 * sizeof (dfa->used_bkref_map)
+	  || !(dfa->used_bkref_map & (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 (extra, node)
+     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 (extra, node)
+     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 (extra, node)
+     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
+duplicate_node_closure (dfa, top_org_node, top_clone_node, root_node,
+			init_constraint)
+     re_dfa_t *dfa;
+     int top_org_node, top_clone_node, root_node;
+     unsigned int init_constraint;
+{
+  reg_errcode_t err;
+  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);
+	  err = duplicate_node (&clone_dest, dfa, org_dest, constraint);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	  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;
+	    }
+	  err = duplicate_node (&clone_dest, dfa, org_dest, constraint);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	  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.  */
+	      err = duplicate_node (&clone_dest, dfa, org_dest, constraint);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	      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];
+	  err = duplicate_node (&clone_dest, dfa, org_dest, constraint);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	  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 (dfa, org_node, constraint)
+     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.
+   The new index will be stored in NEW_IDX and return REG_NOERROR if succeeded,
+   otherwise return the error code.  */
+
+static reg_errcode_t
+duplicate_node (new_idx, dfa, org_idx, constraint)
+     re_dfa_t *dfa;
+     int *new_idx, org_idx;
+     unsigned int constraint;
+{
+  int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
+  if (BE (dup_idx == -1, 0))
+    return REG_ESPACE;
+  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;
+  *new_idx = dup_idx;
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+calc_inveclosure (dfa)
+     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 (dfa)
+     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 (new_set, dfa, node, root)
+     re_node_set *new_set;
+     re_dfa_t *dfa;
+     int node, 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)
+    {
+      int org_node, cur_node;
+      org_node = cur_node = node;
+      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
+fetch_token (result, input, syntax)
+     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
+peek_token (token, input, syntax)
+     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
+peek_token_bracket (token, input, syntax)
+     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 /* RE_ENABLE_I18N */
+
+  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 (regexp, preg, syntax, err)
+     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 (regexp, preg, token, syntax, nest, err)
+     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 (regexp, preg, token, syntax, nest, err)
+     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 (regexp, preg, token, syntax, nest, err)
+     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 (regexp, preg, token, syntax, nest, err)
+     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;
+    }
+  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 (elem, regexp, dfa, token, syntax, err)
+     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
+
+#ifndef _LIBC
+  /* Local function for parse_bracket_exp only used in case of NOT _LIBC.
+     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
+# ifdef RE_ENABLE_I18N
+build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
+     re_charset_t *mbcset;
+     int *range_alloc;
+# else /* not RE_ENABLE_I18N */
+build_range_exp (sbcset, start_elem, end_elem)
+# endif /* not RE_ENABLE_I18N */
+     re_bitset_ptr_t sbcset;
+     bracket_elem_t *start_elem, *end_elem;
+{
+  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
+  {
+    wint_t wc, start_wc, 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 !_LIBC 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 /* not _LIBC */
+
+#ifndef _LIBC
+/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
+   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
+# ifdef RE_ENABLE_I18N
+build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)
+     re_charset_t *mbcset;
+     int *coll_sym_alloc;
+# else /* not RE_ENABLE_I18N */
+build_collating_symbol (sbcset, name)
+# endif /* not RE_ENABLE_I18N */
+     re_bitset_ptr_t sbcset;
+     const unsigned char *name;
+{
+  size_t name_len = strlen ((const char *) name);
+  if (BE (name_len != 1, 0))
+    return REG_ECOLLATE;
+  else
+    {
+      bitset_set (sbcset, name[0]);
+      return REG_NOERROR;
+    }
+}
+#endif /* not _LIBC */
+
+/* This function parse bracket expression like "[abc]", "[a-c]",
+   "[[.a-a.]]" etc.  */
+
+static bin_tree_t *
+parse_bracket_exp (regexp, dfa, token, syntax, err)
+     re_string_t *regexp;
+     re_dfa_t *dfa;
+     re_token_t *token;
+     reg_syntax_t syntax;
+     reg_errcode_t *err;
+{
+#ifdef _LIBC
+  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 _LIBC environement.
+     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 (name, name_len)
+	 const unsigned char *name;
+	 size_t name_len;
+    {
+      int32_t hash = elem_hash ((const char *) name, name_len);
+      int32_t elem = hash % table_size;
+      int32_t second = hash % (table_size - 2);
+      while (symb_table[2 * elem] != 0)
+	{
+	  /* 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;
+	}
+      return elem;
+    }
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     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 (br_elem)
+	 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 _LIBC environement.
+     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 (sbcset, mbcset, range_alloc, start_elem, end_elem)
+	 re_charset_t *mbcset;
+	 int *range_alloc;
+	 re_bitset_ptr_t sbcset;
+	 bracket_elem_t *start_elem, *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 _LIBC environement.
+     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 (sbcset, mbcset, coll_sym_alloc, name)
+	 re_charset_t *mbcset;
+	 int *coll_sym_alloc;
+	 re_bitset_ptr_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 /* not RE_ENABLE_I18N */
+  int non_match = 0;
+  bin_tree_t *work_tree;
+  int token_len;
+  int first_round = 1;
+#ifdef _LIBC
+  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 = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS);
+#ifdef RE_ENABLE_I18N
+  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+#endif /* RE_ENABLE_I18N */
+#ifdef RE_ENABLE_I18N
+  if (BE (sbcset == NULL || mbcset == NULL, 0))
+#else
+  if (BE (sbcset == NULL, 0))
+#endif /* RE_ENABLE_I18N */
+    {
+      *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 /* not RE_ENABLE_I18N */
+      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);
+
+#ifdef _LIBC
+	  *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 /* RE_ENABLE_I18N */
+	  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 /* RE_ENABLE_I18N */
+					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 /* RE_ENABLE_I18N */
+					     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 /* RE_ENABLE_I18N */
+				      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_UINTS; ++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_UINTS)
+	{
+          /* 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 /* RE_ENABLE_I18N */
+  return NULL;
+}
+
+/* Parse an element in the bracket expression.  */
+
+static reg_errcode_t
+parse_bracket_element (elem, regexp, token, token_len, dfa, syntax,
+		       accept_hyphen)
+     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 (elem, regexp, token)
+     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 (sbcset, mbcset, equiv_class_alloc, name)
+     re_charset_t *mbcset;
+     int *equiv_class_alloc;
+#else /* not RE_ENABLE_I18N */
+build_equiv_class (sbcset, name)
+#endif /* not RE_ENABLE_I18N */
+     re_bitset_ptr_t sbcset;
+     const unsigned char *name;
+{
+#if defined _LIBC
+  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 /* _LIBC */
+    {
+      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 (trans, sbcset, mbcset, char_class_alloc, class_name, syntax)
+     re_charset_t *mbcset;
+     int *char_class_alloc;
+#else /* not RE_ENABLE_I18N */
+build_charclass (trans, sbcset, class_name, syntax)
+#endif /* not RE_ENABLE_I18N */
+     unsigned RE_TRANSLATE_TYPE trans;
+     re_bitset_ptr_t sbcset;
+     const unsigned char *class_name;
+     reg_syntax_t syntax;
+{
+  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)	\
+    for (i = 0; i < SBC_MAX; ++i)		\
+      {						\
+	if (ctype_func (i))			\
+	  {					\
+	    int ch = trans ? trans[i] : i;	\
+	    bitset_set (sbcset, ch);		\
+	  }					\
+      }
+
+  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 (dfa, trans, class_name, extra, non_match, err)
+     re_dfa_t *dfa;
+     unsigned 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 /* not RE_ENABLE_I18N */
+  reg_errcode_t ret;
+  re_token_t br_token;
+  bin_tree_t *tree;
+
+  sbcset = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS);
+#ifdef RE_ENABLE_I18N
+  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+#endif /* RE_ENABLE_I18N */
+
+#ifdef RE_ENABLE_I18N
+  if (BE (sbcset == NULL || mbcset == NULL, 0))
+#else /* not RE_ENABLE_I18N */
+  if (BE (sbcset == NULL, 0))
+#endif /* not RE_ENABLE_I18N */
+    {
+      *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 /* not RE_ENABLE_I18N */
+    }
+
+  /* We don't care the syntax in this case.  */
+  ret = build_charclass (trans, sbcset,
+#ifdef RE_ENABLE_I18N
+			 mbcset, &alloc,
+#endif /* RE_ENABLE_I18N */
+			 class_name, 0);
+
+  if (BE (ret != REG_NOERROR, 0))
+    {
+      re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+      free_charset (mbcset);
+#endif /* RE_ENABLE_I18N */
+      *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 /* not RE_ENABLE_I18N */
+
+ build_word_op_espace:
+  re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+  free_charset (mbcset);
+#endif /* RE_ENABLE_I18N */
+  *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 (input, token, syntax)
+     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);
+# ifdef _LIBC
+  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 (dfa, left, right, type)
+     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 (dfa, left, right, token)
+     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 (extra, node)
+     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 /* RE_ENABLE_I18N */
+    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 (root, dfa)
+     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;
+	}
+    }
+}
Index: /trunk/libc/src/glibc/posix/regex.c
===================================================================
--- /trunk/libc/src/glibc/posix/regex.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/regex.c	(revision 2448)
@@ -0,0 +1,104 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003 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.  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define RE_ENABLE_I18N 1
+
+/* BSD 4.2, not delcared in the header */
+char * re_comp (const char *);
+int re_exec (const char *);
+
+
+#ifdef _AIX
+#pragma alloca
+#else
+# ifndef allocax           /* predefined by HP cc +Olibcalls */
+#  ifdef __GNUC__
+#   define alloca(size) __builtin_alloca (size)
+#  else
+#   if HAVE_ALLOCA_H
+#    include <alloca.h>
+#   else
+#    ifdef __hpux
+        void *alloca ();
+#    else
+#     if !defined __OS2__ && !defined WIN32
+        char *alloca ();
+#     else
+#      include <malloc.h>       /* OS/2 defines alloca in here */
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+#ifdef _LIBC
+/* We have to keep the namespace clean.  */
+# define regfree(preg) __regfree (preg)
+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
+# define regerror(errcode, preg, errbuf, errbuf_size) \
+	__regerror(errcode, preg, errbuf, errbuf_size)
+# define re_set_registers(bu, re, nu, st, en) \
+	__re_set_registers (bu, re, nu, st, en)
+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
+	__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+# define re_match(bufp, string, size, pos, regs) \
+	__re_match (bufp, string, size, pos, regs)
+# define re_search(bufp, string, size, startpos, range, regs) \
+	__re_search (bufp, string, size, startpos, range, regs)
+# define re_compile_pattern(pattern, length, bufp) \
+	__re_compile_pattern (pattern, length, bufp)
+# define re_set_syntax(syntax) __re_set_syntax (syntax)
+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
+	__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
+
+# include "../locale/localeinfo.h"
+#endif
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+   <regex.h>.  */
+#include <sys/types.h>
+
+/* 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"
+
+/* Binary backward compatibility.  */
+#if defined _LIBC && _LIBC
+# include <shlib-compat.h>
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
+link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
+int re_max_failures = 2000;
+# endif
+#endif
Index: /trunk/libc/src/glibc/posix/regex_internal.c
===================================================================
--- /trunk/libc/src/glibc/posix/regex_internal.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/regex_internal.c	(revision 2448)
@@ -0,0 +1,1679 @@
+/* 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 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;
+#ifdef RE_ENABLE_I18N
+static int re_string_skip_chars (re_string_t *pstr, int new_raw_idx,
+				 wint_t *last_wc) internal_function;
+#endif /* RE_ENABLE_I18N */
+static reg_errcode_t register_state (re_dfa_t *dfa, re_dfastate_t *newstate,
+				     unsigned int hash) internal_function;
+static re_dfastate_t *create_ci_newstate (re_dfa_t *dfa,
+					  const re_node_set *nodes,
+					  unsigned int hash) internal_function;
+static re_dfastate_t *create_cd_newstate (re_dfa_t *dfa,
+					  const re_node_set *nodes,
+					  unsigned int context,
+					  unsigned int hash) internal_function;
+static unsigned int inline calc_state_hash (const re_node_set *nodes,
+					    unsigned int context) 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
+re_string_allocate (pstr, str, len, init_len, trans, icase, dfa)
+     re_string_t *pstr;
+     const char *str;
+     int len, init_len, icase;
+     RE_TRANSLATE_TYPE trans;
+     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
+re_string_construct (pstr, str, len, trans, icase, dfa)
+     re_string_t *pstr;
+     const char *str;
+     int len, icase;
+     RE_TRANSLATE_TYPE trans;
+     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 /* RE_ENABLE_I18N  */
+	{
+	  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
+re_string_realloc_buffers (pstr, new_buf_len)
+     re_string_t *pstr;
+     int new_buf_len;
+{
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1)
+    {
+      wint_t *new_array = re_realloc (pstr->wcs, wint_t, new_buf_len);
+      if (BE (new_array == NULL, 0))
+	return REG_ESPACE;
+      pstr->wcs = new_array;
+      if (pstr->offsets != NULL)
+	{
+	  int *new_array = re_realloc (pstr->offsets, int, new_buf_len);
+	  if (BE (new_array == NULL, 0))
+	    return REG_ESPACE;
+	  pstr->offsets = new_array;
+	}
+    }
+#endif /* RE_ENABLE_I18N  */
+  if (pstr->mbs_allocated)
+    {
+      unsigned char *new_array = re_realloc (pstr->mbs, unsigned char,
+					     new_buf_len);
+      if (BE (new_array == NULL, 0))
+	return REG_ESPACE;
+      pstr->mbs = new_array;
+    }
+  pstr->bufs_len = new_buf_len;
+  return REG_NOERROR;
+}
+
+
+static void
+re_string_construct_common (str, len, pstr, trans, icase, dfa)
+     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 = (unsigned RE_TRANSLATE_TYPE) 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
+build_wcs_buffer (pstr)
+     re_string_t *pstr;
+{
+#ifdef _LIBC
+  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 int
+build_wcs_upper_buffer (pstr)
+     re_string_t *pstr;
+{
+  mbstate_t prev_st;
+  int src_idx, byte_idx, end_idx, remain_len;
+  size_t mbclen;
+#ifdef _LIBC
+  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
+re_string_skip_chars (pstr, new_raw_idx, last_wc)
+     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
+build_upper_buffer (pstr)
+     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
+re_string_translate_buffer (pstr)
+     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
+re_string_reconstruct (pstr, idx, eflags)
+     re_string_t *pstr;
+     int idx, 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 /* RE_ENABLE_I18N */
+      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 /* RE_ENABLE_I18N */
+	  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 //bird
+	  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, *q, *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);
+		  for (p = raw + offset - 1; p >= end; --p)
+		    if ((*p & 0xc0) != 0x80)
+		      {
+			mbstate_t cur_state;
+			wchar_t wc2;
+			int mlen = raw + pstr->len - p;
+			unsigned char buf[6];
+
+			q = p;
+			if (BE (pstr->trans != NULL, 0))
+			  {
+			    int i = mlen < 6 ? mlen : 6;
+			    while (--i >= 0)
+			      buf[i] = pstr->trans[p[i]];
+			    q = buf;
+			  }
+			/* XXX Don't use mbrtowc, we know which conversion
+			   to use (UTF-8 -> UCS4).  */
+			memset (&cur_state, 0, sizeof (cur_state));
+			mlen = (mbrtowc (&wc2, (const char *) p, mlen,
+					 &cur_state)
+				- (raw + offset - p));
+			if (mlen >= 0)
+			  {
+			    memset (&pstr->cur_state, '\0',
+				    sizeof (mbstate_t));
+			    pstr->valid_len = mlen;
+			    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)
+	{
+	  int ret = build_wcs_upper_buffer (pstr);
+	  if (BE (ret != REG_NOERROR, 0))
+	    return ret;
+	}
+      else
+	build_wcs_buffer (pstr);
+    }
+  else
+#endif /* RE_ENABLE_I18N */
+  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
+re_string_peek_byte_case (pstr, idx)
+     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
+re_string_fetch_byte_case (pstr)
+     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
+re_string_destruct (pstr)
+     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
+re_string_context_at (input, idx, eflags)
+     const re_string_t *input;
+     int idx, 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);
+    }
+  else
+#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
+re_node_set_alloc (set, size)
+     re_node_set *set;
+     int size;
+{
+  set->alloc = size;
+  set->nelem = 0;
+  set->elems = re_malloc (int, size);
+  if (BE (set->elems == NULL, 0))
+    return REG_ESPACE;
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+re_node_set_init_1 (set, elem)
+     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
+re_node_set_init_2 (set, elem1, elem2)
+     re_node_set *set;
+     int elem1, 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
+re_node_set_init_copy (dest, src)
+     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
+re_node_set_add_intersect (dest, src1, src2)
+     re_node_set *dest;
+     const re_node_set *src1, *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
+re_node_set_init_union (dest, src1, src2)
+     re_node_set *dest;
+     const re_node_set *src1, *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);
+      else if (src2 != NULL && src2->nelem > 0)
+	return re_node_set_init_copy (dest, src2);
+      else
+	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
+re_node_set_merge (dest, src)
+     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
+re_node_set_insert (set, elem)
+     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;
+      else
+	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_array;
+      set->alloc = set->alloc * 2;
+      new_array = re_realloc (set->elems, int, set->alloc);
+      if (BE (new_array == NULL, 0))
+	return -1;
+      set->elems = new_array;
+    }
+
+  /* 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
+re_node_set_insert_last (set, elem)
+     re_node_set *set;
+     int elem;
+{
+  /* Realloc if we need.  */
+  if (set->alloc == set->nelem)
+    {
+      int *new_array;
+      set->alloc = (set->alloc + 1) * 2;
+      new_array = re_realloc (set->elems, int, set->alloc);
+      if (BE (new_array == NULL, 0))
+	return -1;
+      set->elems = new_array;
+    }
+
+  /* Insert the new element.  */
+  set->elems[set->nelem++] = elem;
+  return 1;
+}
+
+/* Compare two node sets SET1 and SET2.
+   return 1 if SET1 and SET2 are equivalent, return 0 otherwise.  */
+
+static int
+re_node_set_compare (set1, set2)
+     const re_node_set *set1, *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
+re_node_set_contains (set, elem)
+     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
+re_node_set_remove_at (set, idx)
+     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
+re_dfa_add_node (dfa, token)
+     re_dfa_t *dfa;
+     re_token_t token;
+{
+#ifdef RE_ENABLE_I18N //bird
+  int type = token.type;
+#endif
+  if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
+    {
+      int new_nodes_alloc = dfa->nodes_alloc * 2;
+      int *new_nexts, *new_indices;
+      re_node_set *new_edests, *new_eclosures;
+
+      re_token_t *new_array = re_realloc (dfa->nodes, re_token_t,
+					  new_nodes_alloc);
+      if (BE (new_array == NULL, 0))
+	return -1;
+      dfa->nodes = new_array;
+      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 unsigned int inline
+calc_state_hash (nodes, context)
+     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*
+re_acquire_state (err, dfa, nodes)
+     reg_errcode_t *err;
+     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, 1))
+    return new_state;
+  else
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+}
+
+/* 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*
+re_acquire_state_context (err, dfa, nodes, context)
+     reg_errcode_t *err;
+     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, 1))
+    return new_state;
+  else
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+}
+
+/* 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 (dfa, newstate, hash)
+     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;
+}
+
+/* Create the new state which is independ of contexts.
+   Return the new state if succeeded, otherwise return NULL.  */
+
+static re_dfastate_t *
+create_ci_newstate (dfa, nodes, hash)
+     re_dfa_t *dfa;
+     const re_node_set *nodes;
+     unsigned int hash;
+{
+  int i;
+  reg_errcode_t err;
+  re_dfastate_t *newstate;
+
+  newstate = (re_dfastate_t *) 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 /* 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 || 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 *
+create_cd_newstate (dfa, nodes, context, hash)
+     re_dfa_t *dfa;
+     const re_node_set *nodes;
+     unsigned int context, hash;
+{
+  int i, nctx_nodes = 0;
+  reg_errcode_t err;
+  re_dfastate_t *newstate;
+
+  newstate = (re_dfastate_t *) 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;
+}
+
+static void
+free_state (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);
+}
Index: /trunk/libc/src/glibc/posix/regex_internal.h
===================================================================
--- /trunk/libc/src/glibc/posix/regex_internal.h	(revision 2448)
+++ /trunk/libc/src/glibc/posix/regex_internal.h	(revision 2448)
@@ -0,0 +1,810 @@
+/* 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 || defined _LIBC
+# include <langinfo.h>
+#endif
+#if defined HAVE_LOCALE_H || defined _LIBC
+# include <locale.h>
+#endif
+#if defined HAVE_WCHAR_H || defined _LIBC
+# include <wchar.h>
+#endif /* HAVE_WCHAR_H || _LIBC */
+#if defined HAVE_WCTYPE_H || defined _LIBC
+# include <wctype.h>
+#endif /* HAVE_WCTYPE_H || _LIBC */
+#if defined _LIBC || defined __INNOTEK_LIBC__
+# 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
+
+/* In case that the system doesn't have isblank().  */
+#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank
+# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
+#endif
+
+#ifdef _LIBC
+# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
+#  define _RE_DEFINE_LOCALE_FUNCTIONS 1
+#   include <locale/localeinfo.h>
+#   include <locale/elem-hash.h>
+#   include <locale/coll-lookup.h>
+# endif
+#endif
+
+/* This is for other GNU distributions with internationalized messages.  */
+#if !defined(__INNOTEK_LIBC__) && (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
+# include <libintl.h>
+# ifdef _LIBC
+#  undef gettext
+#  define gettext(msgid) \
+  INTUSE(__dcgettext) (_libc_intl_domainname, 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
+
+#ifndef __INNOTEK_LIBC__
+#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC
+# define RE_ENABLE_I18N
+#endif
+#endif
+
+#if __GNUC__ >= 3
+# define BE(expr, val) __builtin_expect (expr, val)
+#else
+# define BE(expr, val) (expr)
+# define inline
+#endif
+
+/* Number of bits in a byte.  */
+#define BYTE_BITS 8
+/* 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'
+
+/* Rename to standard API for using out of glibc.  */
+#ifndef _LIBC
+# define __wctype wctype
+# define __iswctype iswctype
+# define __btowc btowc
+# define __mempcpy mempcpy
+# define __wcrtomb wcrtomb
+# define __regfree regfree
+# define attribute_hidden
+#endif /* not _LIBC */
+
+#ifdef __GNUC__
+# define __attribute(arg) __attribute__ (arg)
+#else
+# define __attribute(arg)
+#endif
+
+extern const char __re_error_msgid[] attribute_hidden;
+extern const size_t __re_error_msgid_idx[] attribute_hidden;
+
+/* Number of bits in an unsinged int.  */
+#define UINT_BITS (sizeof (unsigned int) * BYTE_BITS)
+/* Number of unsigned int in an bit_set.  */
+#define BITSET_UINTS ((SBC_MAX + UINT_BITS - 1) / UINT_BITS)
+typedef unsigned int bitset[BITSET_UINTS];
+typedef unsigned int *re_bitset_ptr_t;
+typedef const unsigned int *re_const_bitset_ptr_t;
+
+#define bitset_set(set,i) (set[i / UINT_BITS] |= 1 << i % UINT_BITS)
+#define bitset_clear(set,i) (set[i / UINT_BITS] &= ~(1 << i % UINT_BITS))
+#define bitset_contain(set,i) (set[i / UINT_BITS] & (1 << i % UINT_BITS))
+#define bitset_empty(set) memset (set, 0, sizeof (unsigned int) * BITSET_UINTS)
+#define bitset_set_all(set) \
+  memset (set, 255, sizeof (unsigned int) * BITSET_UINTS)
+#define bitset_copy(dest,src) \
+  memcpy (dest, src, sizeof (unsigned int) * BITSET_UINTS)
+static inline void bitset_not (bitset set);
+static inline void bitset_merge (bitset dest, const bitset src);
+static inline void bitset_not_merge (bitset dest, const bitset src);
+static inline void bitset_mask (bitset dest, const bitset src);
+
+#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.  */
+# ifdef _LIBC
+  int32_t *coll_syms;
+# endif
+
+  /* Equivalence classes. */
+# ifdef _LIBC
+  int32_t *equiv_classes;
+# endif
+
+  /* Range expressions. */
+# ifdef _LIBC
+  uint32_t *range_starts;
+  uint32_t *range_ends;
+# else /* not _LIBC */
+  wchar_t *range_starts;
+  wchar_t *range_ends;
+# endif /* not _LIBC */
+
+  /* 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.  */
+  unsigned 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;
+
+#ifndef _LIBC
+# if defined __i386__ && !defined __INNOTEK_LIBC__
+#  define internal_function   __attribute ((regparm (3), stdcall))
+# else
+#  define internal_function
+# endif
+#endif
+
+#ifndef RE_NO_INTERNAL_PROTOTYPES
+static reg_errcode_t 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)
+     internal_function;
+static reg_errcode_t re_string_construct (re_string_t *pstr, const char *str,
+					  int len, RE_TRANSLATE_TYPE trans,
+					  int icase, const re_dfa_t *dfa)
+     internal_function;
+static reg_errcode_t re_string_reconstruct (re_string_t *pstr, int idx,
+					    int eflags) internal_function;
+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 int 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 void re_string_destruct (re_string_t *pstr) internal_function;
+# ifdef RE_ENABLE_I18N
+static int re_string_elem_size_at (const re_string_t *pstr, int idx)
+     internal_function __attribute ((pure));
+static inline int re_string_char_size_at (const re_string_t *pstr, int idx)
+     internal_function __attribute ((pure));
+static inline wint_t re_string_wchar_at (const re_string_t *pstr, int idx)
+     internal_function __attribute ((pure));
+# endif /* RE_ENABLE_I18N */
+static unsigned int re_string_context_at (const re_string_t *input, int idx,
+					  int eflags)
+     internal_function __attribute ((pure));
+static unsigned char re_string_peek_byte_case (const re_string_t *pstr,
+					       int idx)
+     internal_function __attribute ((pure));
+static unsigned char re_string_fetch_byte_case (re_string_t *pstr)
+     internal_function __attribute ((pure));
+#endif
+#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))
+
+#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;
+  int next_last_offset;
+  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;
+#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+  re_dfa_t *const dfa;
+#else
+  re_dfa_t *dfa;
+#endif
+  /* 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;
+  int nodes_alloc;
+  int 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 states_alloc;
+  int init_node;
+  int nbackref; /* The number of backreference in this dfa.  */
+
+  /* Bitmap expressing which backreference is used.  */
+  unsigned int used_bkref_map;
+  unsigned int 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 word_char;
+  reg_syntax_t syntax;
+  int *subexp_map;
+#ifdef DEBUG
+  char* re_str;
+#endif
+  __libc_lock_define (, lock)
+};
+
+#ifndef RE_NO_INTERNAL_PROTOTYPES
+static reg_errcode_t re_node_set_alloc (re_node_set *set, int size) internal_function;
+static reg_errcode_t re_node_set_init_1 (re_node_set *set, int elem) internal_function;
+static reg_errcode_t re_node_set_init_2 (re_node_set *set, int elem1,
+					 int elem2) internal_function;
+#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
+static reg_errcode_t re_node_set_init_copy (re_node_set *dest,
+					    const re_node_set *src) internal_function;
+static reg_errcode_t re_node_set_add_intersect (re_node_set *dest,
+						const re_node_set *src1,
+						const re_node_set *src2) internal_function;
+static reg_errcode_t re_node_set_init_union (re_node_set *dest,
+					     const re_node_set *src1,
+					     const re_node_set *src2) internal_function;
+static reg_errcode_t re_node_set_merge (re_node_set *dest,
+					const re_node_set *src) internal_function;
+static int re_node_set_insert (re_node_set *set, int elem) internal_function;
+static int re_node_set_insert_last (re_node_set *set,
+				    int elem) internal_function;
+static int re_node_set_compare (const re_node_set *set1,
+				const re_node_set *set2)
+     internal_function __attribute ((pure));
+static int re_node_set_contains (const re_node_set *set, int elem)
+     internal_function __attribute ((pure));
+static void re_node_set_remove_at (re_node_set *set, int idx) internal_function;
+#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)
+static int re_dfa_add_node (re_dfa_t *dfa, re_token_t token) internal_function;
+static re_dfastate_t *re_acquire_state (reg_errcode_t *err, re_dfa_t *dfa,
+					const re_node_set *nodes) internal_function;
+static re_dfastate_t *re_acquire_state_context (reg_errcode_t *err,
+						re_dfa_t *dfa,
+						const re_node_set *nodes,
+						unsigned int context) internal_function;
+static void free_state (re_dfastate_t *state) internal_function;
+#endif
+
+
+
+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;
+    wchar_t wch;
+  } opr;
+} bracket_elem_t;
+
+
+/* Inline functions for bitset operation.  */
+static inline void
+bitset_not (bitset set)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
+    set[bitset_i] = ~set[bitset_i];
+}
+
+static inline void
+bitset_merge (bitset dest, const bitset src)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
+    dest[bitset_i] |= src[bitset_i];
+}
+
+static inline void
+bitset_not_merge (bitset dest, const bitset src)
+{
+  int i;
+  for (i = 0; i < BITSET_UINTS; ++i)
+    dest[i] |= ~src[i];
+}
+
+static inline void
+bitset_mask (bitset dest, const bitset src)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
+    dest[bitset_i] &= src[bitset_i];
+}
+
+#if defined RE_ENABLE_I18N && !defined RE_NO_INTERNAL_PROTOTYPES
+/* Inline functions for re_string.  */
+static inline int
+internal_function
+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
+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
+re_string_elem_size_at (const re_string_t *pstr, int idx)
+{
+#ifdef _LIBC
+  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;
+    }
+  else
+#endif /* _LIBC */
+    return 1;
+}
+#endif /* RE_ENABLE_I18N */
+
+#endif /*  _REGEX_INTERNAL_H */
Index: /trunk/libc/src/glibc/posix/regexec.c
===================================================================
--- /trunk/libc/src/glibc/posix/regexec.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/regexec.c	(revision 2448)
@@ -0,0 +1,4346 @@
+/* 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 (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 inline re_dfastate_t *acquire_init_state_context
+     (reg_errcode_t *err, const re_match_context_t *mctx, int idx)
+     __attribute ((always_inline)) 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_node_context (const re_dfa_t *dfa, int node,
+				    unsigned int context) 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 (re_dfa_t *dfa, regmatch_t *pmatch,
+			 regmatch_t *prev_idx_match, int cur_node,
+			 int cur_idx, int nmatch) internal_function;
+static int 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) 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 int pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, 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 /* RE_ENABLE_I18N */
+static reg_errcode_t sift_states_backward (re_match_context_t *mctx,
+					   re_sift_context_t *sctx) internal_function;
+static reg_errcode_t build_sifted_states (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 (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 (re_dfa_t *dfa,
+					    re_node_set *dest_nodes,
+					    const re_node_set *candidates) internal_function;
+static reg_errcode_t sub_epsilon_src_nodes (re_dfa_t *dfa, int node,
+					    re_node_set *dest_nodes,
+					    const re_node_set *and_nodes) internal_function;
+static int check_dst_limits (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 (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 (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 (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 (re_match_context_t *mctx,
+					re_sift_context_t *sctx,
+					int str_idx, const re_node_set *candidates) internal_function;
+static reg_errcode_t clean_state_log_if_needed (re_match_context_t *mctx,
+					        int next_state_log_idx) internal_function;
+static reg_errcode_t merge_state_array (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 /* RE_ENABLE_I18N */
+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 (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 (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 (re_dfa_t *dfa,
+			  re_dfastate_t *state) internal_function;
+#ifdef RE_ENABLE_I18N
+static int check_node_accept_bytes (re_dfa_t *dfa, int node_idx,
+				    const re_string_t *input, int idx) internal_function;
+# ifdef _LIBC
+static unsigned int find_collation_sequence_value (const unsigned char *mbs,
+						   size_t name_len) internal_function;
+# endif /* _LIBC */
+#endif /* RE_ENABLE_I18N */
+static int group_nodes_into_DFAstates (re_dfa_t *dfa,
+				       const re_dfastate_t *state,
+				       re_node_set *states_node,
+				       bitset *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
+_STD(regexec) (preg, string, nmatch, pmatch, eflags)
+    const regex_t *__restrict preg;
+    const char *__restrict string;
+    size_t nmatch;
+    regmatch_t pmatch[];
+    int eflags;
+{
+  reg_errcode_t err;
+  int start, length;
+  re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
+
+  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;
+}
+
+#ifdef _LIBC
+# include <shlib-compat.h>
+versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+__typeof__ (__regexec) __compat_regexec;
+
+int
+attribute_compat_text_section
+__compat_regexec (const regex_t *__restrict preg,
+		  const char *__restrict string, size_t nmatch,
+		  regmatch_t pmatch[], int eflags)
+{
+  return regexec (preg, string, nmatch, pmatch,
+		  eflags & (REG_NOTBOL | REG_NOTEOL));
+}
+compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
+# endif
+#endif
+
+/* 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
+_STD(re_match) (bufp, string, length, start, regs)
+    struct re_pattern_buffer *bufp;
+    const char *string;
+    int length, start;
+    struct re_registers *regs;
+{
+  return re_search_stub (bufp, string, length, start, 0, length, regs, 1);
+}
+#ifdef _LIBC
+/* w e a k _alias (__re_match, re_match) */
+#endif
+
+int
+_STD(re_search) (bufp, string, length, start, range, regs)
+    struct re_pattern_buffer *bufp;
+    const char *string;
+    int length, start, range;
+    struct re_registers *regs;
+{
+  return re_search_stub (bufp, string, length, start, range, length, regs, 0);
+}
+#ifdef _LIBC
+/* w e a k _alias (__re_search, re_search) */
+#endif
+
+int
+_STD(re_match_2) (bufp, string1, length1, string2, length2, start, regs, stop)
+    struct re_pattern_buffer *bufp;
+    const char *string1, *string2;
+    int length1, length2, start, stop;
+    struct re_registers *regs;
+{
+  return re_search_2_stub (bufp, string1, length1, string2, length2,
+			   start, 0, regs, stop, 1);
+}
+#ifdef _LIBC
+/*  w e a k _alias (__re_match_2, re_match_2)*/
+#endif
+
+int
+_STD(re_search_2) (bufp, string1, length1, string2, length2, start, range, regs, stop)
+    struct re_pattern_buffer *bufp;
+    const char *string1, *string2;
+    int length1, length2, start, range, stop;
+    struct re_registers *regs;
+{
+  return re_search_2_stub (bufp, string1, length1, string2, length2,
+			   start, range, regs, stop, 0);
+}
+#ifdef _LIBC
+/* w e a k _alias (__re_search_2, re_search_2) */
+#endif
+
+static int
+re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs,
+		  stop, ret_len)
+    struct re_pattern_buffer *bufp;
+    const char *string1, *string2;
+    int length1, length2, start, range, stop, ret_len;
+    struct re_registers *regs;
+{
+  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
+re_search_stub (bufp, string, length, start, range, stop, regs, ret_len)
+    struct re_pattern_buffer *bufp;
+    const char *string;
+    int length, start, range, stop, ret_len;
+    struct re_registers *regs;
+{
+  reg_errcode_t result;
+  regmatch_t *pmatch;
+  int nregs, rval;
+  int eflags = 0;
+  re_dfa_t *dfa = (re_dfa_t *)bufp->buffer;
+
+  /* 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
+re_copy_regs (regs, pmatch, nregs, regs_allocated)
+    struct re_registers *regs;
+    regmatch_t *pmatch;
+    int nregs, 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
+_STD(re_set_registers) (bufp, regs, num_regs, starts, ends)
+    struct re_pattern_buffer *bufp;
+    struct re_registers *regs;
+    unsigned num_regs;
+    regoff_t *starts, *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;
+    }
+}
+#ifdef _LIBC
+/* w e a k_alias (__re_set_registers, re_set_registers) */
+#endif
+
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#if defined _REGEX_RE_COMP || defined _LIBC || __INNOTEK_LIBC__
+int
+# ifdef _LIBC
+weak_function
+# endif
+_STD(re_exec) (s)
+     const char *s;
+{
+  return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);
+}
+#endif /* _REGEX_RE_COMP */
+
+
+/* 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
+re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
+		    eflags)
+    const regex_t *preg;
+    const char *string;
+    int length, start, range, stop, eflags;
+    size_t nmatch;
+    regmatch_t pmatch[];
+{
+  reg_errcode_t err;
+  re_dfa_t *dfa = (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;
+#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+  re_match_context_t mctx = { .dfa = dfa };
+#else
+  re_match_context_t mctx;
+#endif
+  char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate
+		   && range && !preg->can_be_null) ? preg->fastmap : NULL;
+  unsigned RE_TRANSLATE_TYPE t = (unsigned RE_TRANSLATE_TYPE) preg->translate;
+
+#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
+  memset (&mctx, '\0', sizeof (re_match_context_t));
+  mctx.dfa = dfa;
+#endif
+
+  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))
+	      {
+		if (pmatch[reg_idx].rm_so == mctx.input.valid_len)
+		  pmatch[reg_idx].rm_so += mctx.input.valid_raw_len - mctx.input.valid_len;
+		else
+		  pmatch[reg_idx].rm_so = mctx.input.offsets[pmatch[reg_idx].rm_so];
+		if (pmatch[reg_idx].rm_eo == mctx.input.valid_len)
+		  pmatch[reg_idx].rm_eo += mctx.input.valid_raw_len - mctx.input.valid_len;
+		else
+		  pmatch[reg_idx].rm_eo = 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
+prune_impossible_nodes (mctx)
+     re_match_context_t *mctx;
+{
+  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 *
+acquire_init_state_context (err, mctx, idx)
+     reg_errcode_t *err;
+     const re_match_context_t *mctx;
+     int idx;
+{
+  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
+check_matching (mctx, fl_longest_match, p_match_first)
+    re_match_context_t *mctx;
+    int fl_longest_match;
+    int *p_match_first;
+{
+  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 check_halt_node_context (dfa, 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
+check_halt_state_context (mctx, state, idx)
+    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
+proceed_next_node (mctx, nregs, regs, pidx, node, eps_via_nodes, fs)
+    const re_match_context_t *mctx;
+    regmatch_t *regs;
+    int nregs, *pidx, node;
+    re_node_set *eps_via_nodes;
+    struct re_fail_stack_t *fs;
+{
+  re_dfa_t *const dfa = mctx->dfa;
+  int i, err, dest_node;
+  dest_node = -1;
+  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)
+	    {
+	      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))
+	{
+	  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
+push_fail_stack (fs, str_idx, dest_node, nregs, regs, eps_via_nodes)
+     struct re_fail_stack_t *fs;
+     int str_idx, dest_node, 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
+pop_fail_stack (fs, pidx, nregs, regs, eps_via_nodes)
+     struct re_fail_stack_t *fs;
+     int *pidx, 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
+set_regs (preg, mctx, nmatch, pmatch, fl_backtrack)
+     const regex_t *preg;
+     const re_match_context_t *mctx;
+     size_t nmatch;
+     regmatch_t *pmatch;
+     int fl_backtrack;
+{
+  re_dfa_t *dfa = (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;
+
+#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);
+
+  prev_idx_match = (regmatch_t *) alloca (sizeof (regmatch_t) * nmatch);
+  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);
+		  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);
+	      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);
+	      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);
+	      return REG_NOMATCH;
+	    }
+	}
+    }
+  re_node_set_free (&eps_via_nodes);
+  return free_fail_stack_return (fs);
+}
+
+static reg_errcode_t
+free_fail_stack_return (fs)
+     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
+update_regs (dfa, pmatch, prev_idx_match, cur_node, cur_idx, nmatch)
+     re_dfa_t *dfa;
+     regmatch_t *pmatch, *prev_idx_match;
+     int cur_node, cur_idx, 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
+sift_states_backward (mctx, sctx)
+     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
+build_sifted_states (mctx, sctx, str_idx, cur_dest)
+     re_match_context_t *mctx;
+     re_sift_context_t *sctx;
+     int str_idx;
+     re_node_set *cur_dest;
+{
+  re_dfa_t *const dfa = mctx->dfa;
+  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
+clean_state_log_if_needed (mctx, next_state_log_idx)
+    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
+merge_state_array (dfa, dst, src, num)
+     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
+update_cur_sifted_state (mctx, sctx, str_idx, dest_nodes)
+     re_match_context_t *mctx;
+     re_sift_context_t *sctx;
+     int str_idx;
+     re_node_set *dest_nodes;
+{
+  re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  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
+add_epsilon_src_nodes (dfa, dest_nodes, candidates)
+     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
+sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates)
+     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
+check_dst_limits (mctx, limits, dst_node, dst_idx, src_node, src_idx)
+     re_match_context_t *mctx;
+     re_node_set *limits;
+     int dst_node, dst_idx, src_node, src_idx;
+{
+  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
+check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, from_node, bkref_idx)
+     re_match_context_t *mctx;
+     int boundaries, subexp_idx, from_node, bkref_idx;
+{
+  re_dfa_t *const dfa = mctx->dfa;
+  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 <= 8 * sizeof (ent->eps_reachable_subexps_map)
+		      && !(ent->eps_reachable_subexps_map & (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;
+
+		  ent->eps_reachable_subexps_map &= ~(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
+check_dst_limits_calc_pos (mctx, limit, subexp_idx, from_node, str_idx, bkref_idx)
+     re_match_context_t *mctx;
+     int limit, subexp_idx, from_node, str_idx, 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
+check_subexp_limits (dfa, dest_nodes, candidates, limits, bkref_ents, str_idx)
+     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
+sift_states_bkref (mctx, sctx, str_idx, candidates)
+     re_match_context_t *mctx;
+     re_sift_context_t *sctx;
+     int str_idx;
+     const re_node_set *candidates;
+{
+  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, to_idx, dst_node;
+	  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;
+	  err = re_node_set_insert (&local_sctx.limits, enabled_idx);
+	  if (BE (err < 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
+sift_states_iter_mb (mctx, sctx, node_idx, str_idx, max_str_idx)
+    const re_match_context_t *mctx;
+    re_sift_context_t *sctx;
+    int node_idx, str_idx, max_str_idx;
+{
+  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 *
+transit_state (err, mctx, 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 */
+static re_dfastate_t *
+merge_state_with_log (err, mctx, next_state)
+     reg_errcode_t *err;
+     re_match_context_t *mctx;
+     re_dfastate_t *next_state;
+{
+  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 *
+find_recover_state (err, mctx)
+     reg_errcode_t *err;
+     re_match_context_t *mctx;
+{
+  re_dfastate_t *cur_state = NULL;
+  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
+check_subexp_matching_top (mctx, cur_nodes, str_idx)
+     re_match_context_t *mctx;
+     re_node_set *cur_nodes;
+     int str_idx;
+{
+  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 < (8 * sizeof (dfa->used_bkref_map))
+	  && dfa->used_bkref_map & (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 (err, mctx, state)
+     reg_errcode_t *err;
+     re_match_context_t *mctx;
+     re_dfastate_t *state;
+{
+  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
+transit_state_mb (mctx, pstate)
+    re_match_context_t *mctx;
+    re_dfastate_t *pstate;
+{
+  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
+transit_state_bkref (mctx, nodes)
+    re_match_context_t *mctx;
+    const re_node_set *nodes;
+{
+  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
+get_subexp (mctx, bkref_node, bkref_str_idx)
+     re_match_context_t *mctx;
+     int bkref_node, bkref_str_idx;
+{
+  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)
+		break; /* We don't need to search this sub expression any more.  */
+	    }
+	  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
+get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str)
+     re_match_context_t *mctx;
+     const re_sub_match_top_t *sub_top;
+     re_sub_match_last_t *sub_last;
+     int bkref_node, 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
+find_subexp_node (dfa, nodes, subexp_idx, type)
+     const re_dfa_t *dfa;
+     const re_node_set *nodes;
+     int subexp_idx, 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
+check_arrival (mctx, path, top_node, top_str, last_node, last_str,
+	       type)
+     re_match_context_t *mctx;
+     state_array_t *path;
+     int top_node, top_str, last_node, last_str, type;
+{
+  re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  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 (new_array == NULL)
+	{
+	  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 == 0 ? top_str : path->next_idx;
+
+  /* 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
+check_arrival_add_next_nodes (mctx, str_idx, cur_nodes, next_nodes)
+     re_match_context_t *mctx;
+     int str_idx;
+     re_node_set *cur_nodes, *next_nodes;
+{
+  re_dfa_t *const dfa = mctx->dfa;
+  int result;
+  int cur_idx;
+#ifdef RE_ENABLE_I18N
+  reg_errcode_t err;
+#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
+check_arrival_expand_ecl (dfa, cur_nodes, ex_subexp, type)
+     re_dfa_t *dfa;
+     re_node_set *cur_nodes;
+     int ex_subexp, 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];
+      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
+check_arrival_expand_ecl_sub (dfa, dst_nodes, target, ex_subexp, type)
+     re_dfa_t *dfa;
+     int target, ex_subexp, type;
+     re_node_set *dst_nodes;
+{
+  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
+expand_bkref_cache (mctx, cur_nodes, cur_str, subexp_num,
+		    type)
+     re_match_context_t *mctx;
+     int cur_str, subexp_num, type;
+     re_node_set *cur_nodes;
+{
+  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
+build_trtable (dfa, state)
+    re_dfa_t *dfa;
+    re_dfastate_t *state;
+{
+  reg_errcode_t err;
+  int i, j, ch, need_word_trtable = 0;
+  unsigned int elem, mask;
+  int dests_node_malloced = 0, dest_states_malloced = 0;
+  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 *dests_ch;
+  bitset acceptable;
+
+  /* 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.  */
+#ifdef _LIBC
+  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX))
+    dests_node = (re_node_set *)
+      alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX);
+  else
+#endif
+    {
+      dests_node = (re_node_set *)
+	malloc ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX);
+      if (BE (dests_node == NULL, 0))
+	return 0;
+      dests_node_malloced = 1;
+    }
+  dests_ch = (bitset *) (dests_node + SBC_MAX);
+
+  /* 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_node);
+      /* 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;
+
+#ifdef _LIBC
+  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX
+			 + ndests * 3 * sizeof (re_dfastate_t *)))
+    dest_states = (re_dfastate_t **)
+      alloca (ndests * 3 * sizeof (re_dfastate_t *));
+  else
+#endif
+    {
+      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_node);
+	  return 0;
+	}
+      dest_states_malloced = 1;
+    }
+  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 =
+	(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
+      if (BE (trtable == NULL, 0))
+	goto out_free;
+
+      /* For all characters ch...:  */
+      for (i = 0; i < BITSET_UINTS; ++i)
+	for (ch = i * UINT_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 =
+	(re_dfastate_t **) 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_UINTS; ++i)
+	for (ch = i * UINT_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_node);
+
+  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
+group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch)
+    re_dfa_t *dfa;
+    const re_dfastate_t *state;
+    re_node_set *dests_node;
+    bitset *dests_ch;
+{
+  reg_errcode_t err;
+  int result;
+  int i, j, k;
+  int ndests; /* Number of the destinations from `state'.  */
+  bitset 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, 255, sizeof (unsigned int) * BITSET_UINTS / 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)
+	    {
+	      int 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)
+	    {
+	      unsigned int 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_UINTS; ++j)
+		  any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
+	      else
+#endif
+		for (j = 0; j < BITSET_UINTS; ++j)
+		  any_set |= (accepts[j] &= dfa->word_char[j]);
+	      if (!any_set)
+		continue;
+	    }
+	  if (constraint & NEXT_NOTWORD_CONSTRAINT)
+	    {
+	      unsigned int 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_UINTS; ++j)
+		  any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
+	      else
+#endif
+		for (j = 0; j < BITSET_UINTS; ++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 intersec; /* Intersection sets, see below.  */
+	  bitset remains;
+	  /* Flags, see below.  */
+	  int 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_UINTS; ++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_UINTS; ++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
+check_node_accept_bytes (dfa, node_idx, input, str_idx)
+    re_dfa_t *dfa;
+    int node_idx, str_idx;
+    const re_string_t *input;
+{
+  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;
+# ifdef _LIBC
+      const unsigned char *pin
+	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
+      int j;
+      uint32_t nrules;
+# endif /* _LIBC */
+      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;
+	    }
+	}
+
+# ifdef _LIBC
+      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 /* _LIBC */
+	{
+	  /* match with range expression?  */
+#if __GNUC__ >= 2
+	  wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
+#else
+	  wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
+	  cmp_buf[2] = wc;
+#endif
+	  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;
+      else
+	{
+	  if (match_len > 0)
+	    return 0;
+	  else
+	    return (elem_len > char_len) ? elem_len : char_len;
+	}
+    }
+  return 0;
+}
+
+# ifdef _LIBC
+static unsigned int
+find_collation_sequence_value (mbs, mbs_len)
+    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 /* _LIBC */
+#endif /* RE_ENABLE_I18N */
+
+/* Check whether the node accepts the byte which is IDX-th
+   byte of the INPUT.  */
+
+static int
+check_node_accept (mctx, node, idx)
+    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
+extend_buffers (mctx)
+     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
+match_ctx_init (mctx, eflags, n)
+    re_match_context_t *mctx;
+    int eflags, 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
+match_ctx_clean (mctx)
+    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
+match_ctx_free (mctx)
+    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
+match_ctx_add_entry (mctx, node, str_idx, from, to)
+     re_match_context_t *mctx;
+     int node, str_idx, from, 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
+search_cur_bkref_entry (mctx, str_idx)
+     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
+match_ctx_add_subtop (mctx, node, str_idx)
+     re_match_context_t *mctx;
+     int node, 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 *
+match_ctx_add_sublast (subtop, node, str_idx)
+     re_sub_match_top_t *subtop;
+     int node, 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
+sift_ctx_init (sctx, sifted_sts, limited_sts, last_node, last_str_idx)
+    re_sift_context_t *sctx;
+    re_dfastate_t **sifted_sts, **limited_sts;
+    int last_node, 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);
+}
Index: /trunk/libc/src/glibc/posix/spawn.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawn.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawn.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include "spawn_int.h"
+
+/* Spawn a new process executing PATH with the attributes describes in *ATTRP.
+   Before running the process perform the actions described in FILE-ACTIONS. */
+int
+posix_spawn (pid_t *pid, const char *path,
+	     const posix_spawn_file_actions_t *file_actions,
+	     const posix_spawnattr_t *attrp, char *const argv[],
+	     char *const envp[])
+{
+  return __spawni (pid, path, file_actions, attrp, argv, envp, 0);
+}
Index: /trunk/libc/src/glibc/posix/spawn_faction_addclose.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawn_faction_addclose.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawn_faction_addclose.c	(revision 2448)
@@ -0,0 +1,57 @@
+/* Copyright (C) 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 <errno.h>
+#include <spawn.h>
+#include <unistd.h>
+
+#include "spawn_int.h"
+
+/* Add an action to FILE-ACTIONS which tells the implementation to call
+   `close' for the given file descriptor during the `spawn' call.  */
+int
+posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions,
+				   int fd)
+{
+#ifndef __EMX__
+  int maxfd = __sysconf (_SC_OPEN_MAX);
+#else
+#define maxfd 65536
+#endif
+  struct __spawn_action *rec;
+
+  /* Test for the validity of the file descriptor.  */
+  if (fd < 0 || fd >= maxfd)
+    return EBADF;
+
+  /* Allocate more memory if needed.  */
+  if (file_actions->__used == file_actions->__allocated
+      && __posix_spawn_file_actions_realloc (file_actions) != 0)
+    /* This can only mean we ran out of memory.  */
+    return ENOMEM;
+
+  /* Add the new value.  */
+  rec = &file_actions->__actions[file_actions->__used];
+  rec->tag = spawn_do_close;
+  rec->action.open_action.fd = fd;
+
+  /* Account for the new entry.  */
+  ++file_actions->__used;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawn_faction_adddup2.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawn_faction_adddup2.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawn_faction_adddup2.c	(revision 2448)
@@ -0,0 +1,58 @@
+/* Copyright (C) 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 <errno.h>
+#include <spawn.h>
+#include <unistd.h>
+
+#include "spawn_int.h"
+
+/* Add an action to FILE-ACTIONS which tells the implementation to call
+   `dup2' for the given file descriptors during the `spawn' call.  */
+int
+posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions,
+				  int fd, int newfd)
+{
+#ifndef __EMX__
+  int maxfd = __sysconf (_SC_OPEN_MAX);
+#else
+#define maxfd 65536
+#endif
+  struct __spawn_action *rec;
+
+  /* Test for the validity of the file descriptor.  */
+  if (fd < 0 || newfd < 0 || fd >= maxfd || newfd >= maxfd)
+    return EBADF;
+
+  /* Allocate more memory if needed.  */
+  if (file_actions->__used == file_actions->__allocated
+      && __posix_spawn_file_actions_realloc (file_actions) != 0)
+    /* This can only mean we ran out of memory.  */
+    return ENOMEM;
+
+  /* Add the new value.  */
+  rec = &file_actions->__actions[file_actions->__used];
+  rec->tag = spawn_do_dup2;
+  rec->action.dup2_action.fd = fd;
+  rec->action.dup2_action.newfd = newfd;
+
+  /* Account for the new entry.  */
+  ++file_actions->__used;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawn_faction_addopen.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawn_faction_addopen.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawn_faction_addopen.c	(revision 2448)
@@ -0,0 +1,61 @@
+/* Copyright (C) 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 <errno.h>
+#include <spawn.h>
+#include <unistd.h>
+
+#include "spawn_int.h"
+
+/* Add an action to FILE-ACTIONS which tells the implementation to call
+   `open' for the given file during the `spawn' call.  */
+int
+posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
+				  int fd, const char *path, int oflag,
+				  mode_t mode)
+{
+#ifndef __EMX__
+  int maxfd = __sysconf (_SC_OPEN_MAX);
+#else
+#   define maxfd 65535
+#endif
+  struct __spawn_action *rec;
+
+  /* Test for the validity of the file descriptor.  */
+  if (fd < 0 || fd >= maxfd)
+    return EBADF;
+
+  /* Allocate more memory if needed.  */
+  if (file_actions->__used == file_actions->__allocated
+      && __posix_spawn_file_actions_realloc (file_actions) != 0)
+    /* This can only mean we ran out of memory.  */
+    return ENOMEM;
+
+  /* Add the new value.  */
+  rec = &file_actions->__actions[file_actions->__used];
+  rec->tag = spawn_do_open;
+  rec->action.open_action.fd = fd;
+  rec->action.open_action.path = path;
+  rec->action.open_action.oflag = oflag;
+  rec->action.open_action.mode = mode;
+
+  /* Account for the new entry.  */
+  ++file_actions->__used;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawn_faction_destroy.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawn_faction_destroy.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawn_faction_destroy.c	(revision 2448)
@@ -0,0 +1,29 @@
+/* Copyright (C) 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 <spawn.h>
+#include <stdlib.h>
+
+/* Initialize data structure for file attribute for `spawn' call.  */
+int
+posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions)
+{
+  /* Free the memory allocated.  */
+  free (file_actions->__actions);
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawn_faction_init.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawn_faction_init.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawn_faction_init.c	(revision 2448)
@@ -0,0 +1,54 @@
+/* Copyright (C) 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 <errno.h>
+#include <spawn.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "spawn_int.h"
+
+
+/* Function used to increase the size of the allocated array.  This
+   function is called from the `add'-functions.  */
+int
+__posix_spawn_file_actions_realloc (posix_spawn_file_actions_t *file_actions)
+{
+  int newalloc = file_actions->__allocated + 8;
+  void *newmem = realloc (file_actions->__actions,
+			  newalloc * sizeof (struct __spawn_action));
+
+  if (newmem == NULL)
+    /* Not enough memory.  */
+    return ENOMEM;
+
+  file_actions->__actions = (struct __spawn_action *) newmem;
+  file_actions->__allocated = newalloc;
+
+  return 0;
+}
+
+
+/* Initialize data structure for file attribute for `spawn' call.  */
+int
+posix_spawn_file_actions_init (posix_spawn_file_actions_t *file_actions)
+{
+  /* Simply clear all the elements.  */
+  memset (file_actions, '\0', sizeof (*file_actions));
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawn_int.h
===================================================================
--- /trunk/libc/src/glibc/posix/spawn_int.h	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawn_int.h	(revision 2448)
@@ -0,0 +1,38 @@
+/* Data structure to contain the action information.  */
+struct __spawn_action
+{
+  enum
+  {
+    spawn_do_close,
+    spawn_do_dup2,
+    spawn_do_open
+  } tag;
+
+  union
+  {
+    struct
+    {
+      int fd;
+    } close_action;
+    struct
+    {
+      int fd;
+      int newfd;
+    } dup2_action;
+    struct
+    {
+      int fd;
+      const char *path;
+      int oflag;
+      mode_t mode;
+    } open_action;
+  } action;
+};
+
+extern int __posix_spawn_file_actions_realloc (posix_spawn_file_actions_t *
+					       file_actions);
+
+extern int __spawni (pid_t *pid, const char *path,
+		     const posix_spawn_file_actions_t *file_actions,
+		     const posix_spawnattr_t *attrp, char *const argv[],
+		     char *const envp[], int use_path);
Index: /trunk/libc/src/glibc/posix/spawnattr_destroy.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_destroy.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_destroy.c	(revision 2448)
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <spawn.h>
+
+/* Initialize data structure for file attribute for `spawn' call.  */
+int
+posix_spawnattr_destroy (posix_spawnattr_t *attr)
+{
+  /* Nothing to do in the moment.  */
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_getdefault.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_getdefault.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_getdefault.c	(revision 2448)
@@ -0,0 +1,32 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Store signal mask for signals with default handling from ATTR in
+   SIGDEFAULT.  */
+int
+posix_spawnattr_getsigdefault (const posix_spawnattr_t *attr,
+			       sigset_t *sigdefault)
+{
+  /* Copy the sigset_t data to the user buffer.  */
+  memcpy (sigdefault, &attr->__sd, sizeof (sigset_t));
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_getflags.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_getflags.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_getflags.c	(revision 2448)
@@ -0,0 +1,30 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Get flag word from the attribute structure.  */
+int
+posix_spawnattr_getflags (const posix_spawnattr_t *attr, short int *flags)
+{
+  /* Copy the flag word.  */
+  *flags = attr->__flags;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_getpgroup.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_getpgroup.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_getpgroup.c	(revision 2448)
@@ -0,0 +1,30 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Get process group ID from the attribute structure.  */
+int
+posix_spawnattr_getpgroup (const posix_spawnattr_t *attr, pid_t *pgroup)
+{
+  /* Copy the process group ID.  */
+  *pgroup = attr->__pgrp;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_getschedparam.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_getschedparam.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_getschedparam.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Get scheduling parameters from the attribute structure.  */
+int
+posix_spawnattr_getschedparam (const posix_spawnattr_t *attr,
+			       struct sched_param *schedparam)
+{
+  /* Copy the scheduling parameters.  */
+  memcpy (schedparam, &attr->__sp, sizeof (*attr));
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_getschedpolicy.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_getschedpolicy.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_getschedpolicy.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Get scheduling policy from the attribute structure.  */
+int
+posix_spawnattr_getschedpolicy (const posix_spawnattr_t *attr,
+				int *schedpolicy)
+{
+  /* Copy the scheduling policy.  */
+  *schedpolicy = attr->__policy;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_getsigmask.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_getsigmask.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_getsigmask.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Store signal mask for the new process from ATTR in SIGMASK.  */
+int
+posix_spawnattr_getsigmask (const posix_spawnattr_t *attr,
+			    sigset_t *sigmask)
+{
+  /* Copy the sigset_t data to the user buffer.  */
+  memcpy (sigmask, &attr->__ss, sizeof (sigset_t));
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_init.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_init.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_init.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Initialize data structure for file attribute for `spawn' call.  */
+int
+posix_spawnattr_init (posix_spawnattr_t *attr)
+{
+  /* All elements have to be initialized to the default values which
+     is generally zero.  */
+  memset (attr, '\0', sizeof (*attr));
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_setdefault.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_setdefault.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_setdefault.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Set signal mask for signals with default handling in ATTR to SIGDEFAULT.  */
+int
+posix_spawnattr_setsigdefault (posix_spawnattr_t *attr,
+			       const sigset_t *sigdefault)
+{
+  /* Copy the sigset_t data to the user buffer.  */
+  memcpy (&attr->__sd, sigdefault, sizeof (sigset_t));
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_setflags.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_setflags.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_setflags.c	(revision 2448)
@@ -0,0 +1,30 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Store flags in the attribute structure.  */
+int
+posix_spawnattr_setflags (posix_spawnattr_t *attr, short int flags)
+{
+  /* Store the flag word.  */
+  attr->__flags = flags;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_setpgroup.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_setpgroup.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_setpgroup.c	(revision 2448)
@@ -0,0 +1,30 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Store process group ID in the attribute structure.  */
+int
+posix_spawnattr_setpgroup (posix_spawnattr_t *attr, pid_t pgroup)
+{
+  /* Store the process group ID.  */
+  attr->__pgrp = pgroup;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_setschedparam.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_setschedparam.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_setschedparam.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Store scheduling parameters in the attribute structure.  */
+int
+posix_spawnattr_setschedparam (posix_spawnattr_t *attr,
+			       const struct sched_param *schedparam)
+{
+  /* Store the scheduling parameters.  */
+  attr->__sp = *schedparam;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_setschedpolicy.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_setschedpolicy.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_setschedpolicy.c	(revision 2448)
@@ -0,0 +1,34 @@
+/* Copyright (C) 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 <errno.h>
+#include <spawn.h>
+
+/* Store scheduling policy in the attribute structure.  */
+int
+posix_spawnattr_setschedpolicy (posix_spawnattr_t *attr, int schedpolicy)
+{
+  if (schedpolicy != SCHED_OTHER && schedpolicy != SCHED_FIFO
+      && schedpolicy != SCHED_RR)
+    return EINVAL;
+
+  /* Store the policy.  */
+  attr->__policy = schedpolicy;
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnattr_setsigmask.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnattr_setsigmask.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnattr_setsigmask.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include <string.h>
+
+/* Set signal mask for the new process in ATTR to SIGMASK.  */
+int
+posix_spawnattr_setsigmask (posix_spawnattr_t *attr,
+			    const sigset_t *sigmask)
+{
+  /* Copy the sigset_t data to the user buffer.  */
+  memcpy (&attr->__ss, sigmask, sizeof (sigset_t));
+
+  return 0;
+}
Index: /trunk/libc/src/glibc/posix/spawnp.c
===================================================================
--- /trunk/libc/src/glibc/posix/spawnp.c	(revision 2448)
+++ /trunk/libc/src/glibc/posix/spawnp.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Copyright (C) 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 <spawn.h>
+#include "spawn_int.h"
+
+/* Spawn a new process executing FILE with the attributes describes in *ATTRP.
+   Before running the process perform the actions described in FILE-ACTIONS. */
+int
+posix_spawnp (pid_t *pid, const char *file,
+	      const posix_spawn_file_actions_t *file_actions,
+	      const posix_spawnattr_t *attrp, char *const argv[],
+	      char *const envp[])
+{
+  return __spawni (pid, file, file_actions, attrp, argv, envp, 1);
+}
Index: /trunk/libc/src/glibc/string/argz-addsep.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-addsep.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-addsep.c	(revision 2448)
@@ -0,0 +1,62 @@
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+error_t
+__argz_add_sep (char **argz, size_t *argz_len, const char *string, int delim)
+{
+  size_t nlen = strlen (string) + 1;
+
+  if (nlen > 1)
+    {
+      const char *rp;
+      char *wp;
+
+      *argz = (char *) realloc (*argz, *argz_len + nlen);
+      if (*argz == NULL)
+	return ENOMEM;
+
+      wp = *argz + *argz_len;
+      rp = string;
+      do
+	if (*rp == delim)
+	  {
+	    if (wp > *argz && wp[-1] != '\0')
+	      *wp++ = '\0';
+	    else
+	      --nlen;
+	  }
+	else
+	  *wp++ = *rp;
+      while (*rp++ != '\0');
+
+      *argz_len += nlen;
+    }
+
+  return 0;
+}
+weak_alias (__argz_add_sep, argz_add_sep)
Index: /trunk/libc/src/glibc/string/argz-append.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-append.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-append.c	(revision 2448)
@@ -0,0 +1,53 @@
+/* Routines for dealing with '\0' separated arg vectors.
+   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Add BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN.  */
+error_t
+__argz_append (char **argz, size_t *argz_len, const char *buf, size_t buf_len)
+{
+  size_t new_argz_len = *argz_len + buf_len;
+  char *new_argz = realloc (*argz, new_argz_len);
+  if (new_argz)
+    {
+      memcpy (new_argz + *argz_len, buf, buf_len);
+      *argz = new_argz;
+      *argz_len = new_argz_len;
+      return 0;
+    }
+  else
+    return ENOMEM;
+}
+weak_alias (__argz_append, argz_append)
+
+/* Add STR to the argz vector in ARGZ & ARGZ_LEN.  This should be moved into
+   argz.c in libshouldbelibc.  */
+error_t
+__argz_add (char **argz, size_t *argz_len, const char *str)
+{
+  return __argz_append (argz, argz_len, str, strlen (str) + 1);
+}
+weak_alias (__argz_add, argz_add)
Index: /trunk/libc/src/glibc/string/argz-count.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-count.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-count.c	(revision 2448)
@@ -0,0 +1,42 @@
+/* Routines for dealing with '\0' separated arg vectors.
+   Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+#include <string.h>
+
+/* Returns the number of strings in ARGZ.  */
+size_t
+__argz_count (const char *argz, size_t len)
+{
+  size_t count = 0;
+  while (len > 0)
+    {
+      size_t part_len = strlen(argz);
+      argz += part_len + 1;
+      len -= part_len + 1;
+      count++;
+    }
+  return count;
+}
+INTDEF(__argz_count)
+weak_alias (__argz_count, argz_count)
Index: /trunk/libc/src/glibc/string/argz-create.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-create.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-create.c	(revision 2448)
@@ -0,0 +1,58 @@
+/* Routines for dealing with '\0' separated arg vectors.
+   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+
+#include <argz.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Make a '\0' separated arg vector from a unix argv vector, returning it in
+   ARGZ, and the total length in LEN.  If a memory allocation error occurs,
+   ENOMEM is returned, otherwise 0.  */
+error_t
+__argz_create (char *const argv[], char **argz, size_t *len)
+{
+  int argc;
+  size_t tlen = 0;
+  char *const *ap;
+  char *p;
+
+  for (argc = 0; argv[argc] != NULL; ++argc)
+    tlen += strlen (argv[argc]) + 1;
+
+  if (tlen == 0)
+    *argz = NULL;
+  else
+    {
+      *argz = malloc (tlen);
+      if (*argz == NULL)
+	return ENOMEM;
+
+      for (p = *argz, ap = argv; *ap; ++ap, ++p)
+	p = __stpcpy (p, *ap);
+    }
+  *len = tlen;
+
+  return 0;
+}
+weak_alias (__argz_create, argz_create)
Index: /trunk/libc/src/glibc/string/argz-ctsep.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-ctsep.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-ctsep.c	(revision 2448)
@@ -0,0 +1,74 @@
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+error_t
+__argz_create_sep (const char *string, int delim, char **argz, size_t *len)
+{
+  size_t nlen = strlen (string) + 1;
+
+  if (nlen > 1)
+    {
+      const char *rp;
+      char *wp;
+
+      *argz = (char *) malloc (nlen);
+      if (*argz == NULL)
+	return ENOMEM;
+
+      rp = string;
+      wp = *argz;
+      do
+	if (*rp == delim)
+	  {
+	    if (wp > *argz && wp[-1] != '\0')
+	      *wp++ = '\0';
+	    else
+	      --nlen;
+	  }
+	else
+	  *wp++ = *rp;
+      while (*rp++ != '\0');
+
+      if (nlen == 0)
+	{
+	  free (*argz);
+	  *argz = NULL;
+	  *len = 0;
+	}
+
+      *len = nlen;
+    }
+  else
+    {
+      *argz = NULL;
+      *len = 0;
+    }
+
+  return 0;
+}
+weak_alias (__argz_create_sep, argz_create_sep)
Index: /trunk/libc/src/glibc/string/argz-delete.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-delete.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-delete.c	(revision 2448)
@@ -0,0 +1,45 @@
+/* Routines for dealing with '\0' separated arg vectors.
+   Copyright (C) 1995,96,97,2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.org>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Delete ENTRY from ARGZ & ARGZ_LEN, if any.  */
+void
+argz_delete (char **argz, size_t *argz_len, char *entry)
+{
+  if (entry)
+    /* Get rid of the old value for NAME.  */
+    {
+      size_t entry_len = strlen (entry) + 1;
+      *argz_len -= entry_len;
+      memmove (entry, entry + entry_len, *argz_len - (entry - *argz));
+      if (*argz_len == 0)
+	{
+	  free (*argz);
+	  *argz = 0;
+	}
+    }
+}
+libc_hidden_def (argz_delete)
Index: /trunk/libc/src/glibc/string/argz-extract.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-extract.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-extract.c	(revision 2448)
@@ -0,0 +1,40 @@
+/* Routines for dealing with '\0' separated arg vectors.
+   Copyright (C) 1995, 96, 97, 98 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.org>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+
+/* Puts pointers to each string in ARGZ, plus a terminating 0 element, into
+   ARGV, which must be large enough to hold them all.  */
+void
+__argz_extract (const char *argz, size_t len, char **argv)
+{
+  while (len > 0)
+    {
+      size_t part_len = strlen (argz);
+      *argv++ = (char *) argz;
+      argz += part_len + 1;
+      len -= part_len + 1;
+    }
+  *argv = 0;
+}
+weak_alias (__argz_extract, argz_extract)
Index: /trunk/libc/src/glibc/string/argz-insert.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-insert.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-insert.c	(revision 2448)
@@ -0,0 +1,67 @@
+/* Routines for dealing with '\0' separated arg vectors.
+   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
+   existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
+   Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
+   ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ.  If BEFORE is not
+   in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
+   ARGZ, ENOMEM is returned, else 0.  */
+error_t
+__argz_insert (char **argz, size_t *argz_len, char *before, const char *entry)
+{
+  if (! before)
+    return __argz_add (argz, argz_len, entry);
+
+  if (before < *argz || before >= *argz + *argz_len)
+    return EINVAL;
+
+  if (before > *argz)
+    /* Make sure before is actually the beginning of an entry.  */
+    while (before[-1])
+      before--;
+
+  {
+    size_t after_before = *argz_len - (before - *argz);
+    size_t entry_len = strlen  (entry) + 1;
+    size_t new_argz_len = *argz_len + entry_len;
+    char *new_argz = realloc (*argz, new_argz_len);
+
+    if (new_argz)
+      {
+	before = new_argz + (before - *argz);
+	memmove (before + entry_len, before, after_before);
+	memmove (before, entry, entry_len);
+	*argz = new_argz;
+	*argz_len = new_argz_len;
+	return 0;
+      }
+    else
+      return ENOMEM;
+  }
+}
+weak_alias (__argz_insert, argz_insert)
Index: /trunk/libc/src/glibc/string/argz-next.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-next.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-next.c	(revision 2448)
@@ -0,0 +1,43 @@
+/* Iterate through the elements of an argz block.
+   Copyright (C) 1995, 96, 97, 98 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.org>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+#include <string.h>
+
+char *
+__argz_next (const char *argz, size_t argz_len, const char *entry)
+{
+  if (entry)
+    {
+      if (entry < argz + argz_len)
+	entry = strchr (entry, '\0') + 1;
+
+      return entry >= argz + argz_len ? NULL : (char *) entry;
+    }
+  else
+    if (argz_len > 0)
+      return (char *) argz;
+    else
+      return NULL;
+}
+weak_alias (__argz_next, argz_next)
Index: /trunk/libc/src/glibc/string/argz-replace.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-replace.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-replace.c	(revision 2448)
@@ -0,0 +1,139 @@
+/* String replacement in an argz vector
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <argz.h>
+
+/* Append BUF, of length BUF_LEN to *TO, of length *TO_LEN, reallocating and
+   updating *TO & *TO_LEN appropriately.  If an allocation error occurs,
+   *TO's old value is freed, and *TO is set to 0.  */
+static void
+str_append (char **to, size_t *to_len, const char *buf, const size_t buf_len)
+{
+  size_t new_len = *to_len + buf_len;
+  char *new_to = realloc (*to, new_len + 1);
+
+  if (new_to)
+    {
+      *((char *) __mempcpy (new_to + *to_len, buf, buf_len)) = '\0';
+      *to = new_to;
+      *to_len = new_len;
+    }
+  else
+    {
+      free (*to);
+      *to = 0;
+    }
+}
+
+/* Replace any occurrences of the string STR in ARGZ with WITH, reallocating
+   ARGZ as necessary.  If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be
+   incremented by number of replacements performed.  */
+error_t
+__argz_replace (char **argz, size_t *argz_len, const char *str, const char *with,
+		unsigned *replace_count)
+{
+  error_t err = 0;
+
+  if (str && *str)
+    {
+      char *arg = 0;
+      char *src = *argz;
+      size_t src_len = *argz_len;
+      char *dst = 0;
+      size_t dst_len = 0;
+      int delayed_copy = 1;	/* True while we've avoided copying anything.  */
+      size_t str_len = strlen (str), with_len = strlen (with);
+
+      while (!err && (arg = argz_next (src, src_len, arg)))
+	{
+	  char *match = strstr (arg, str);
+	  if (match)
+	    {
+	      char *from = match + str_len;
+	      size_t to_len = match - arg;
+	      char *to = __strndup (arg, to_len);
+
+	      while (to && from)
+		{
+		  str_append (&to, &to_len, with, with_len);
+		  if (to)
+		    {
+		      match = strstr (from, str);
+		      if (match)
+			{
+			  str_append (&to, &to_len, from, match - from);
+			  from = match + str_len;
+			}
+		      else
+			{
+			  str_append (&to, &to_len, from, strlen (from));
+			  from = 0;
+			}
+		    }
+		}
+
+	      if (to)
+		{
+		  if (delayed_copy)
+		    /* We avoided copying SRC to DST until we found a match;
+                       now that we've done so, copy everything from the start
+                       of SRC.  */
+		    {
+		      if (arg > src)
+			err = __argz_append (&dst, &dst_len, src, (arg - src));
+		      delayed_copy = 0;
+		    }
+		  if (! err)
+		    err = __argz_add (&dst, &dst_len, to);
+		  free (to);
+		}
+	      else
+		err = ENOMEM;
+
+	      if (replace_count)
+		(*replace_count)++;
+	    }
+	  else if (! delayed_copy)
+	    err = __argz_add (&dst, &dst_len, arg);
+	}
+
+      if (! err)
+	{
+	  if (! delayed_copy)
+	    /* We never found any instances of str.  */
+	    {
+	      if (src)
+		free (src);
+	      *argz = dst;
+	      *argz_len = dst_len;
+	    }
+	}
+      else if (dst_len > 0)
+	free (dst);
+    }
+
+  return err;
+}
+weak_alias (__argz_replace, argz_replace)
Index: /trunk/libc/src/glibc/string/argz-stringify.c
===================================================================
--- /trunk/libc/src/glibc/string/argz-stringify.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/argz-stringify.c	(revision 2448)
@@ -0,0 +1,44 @@
+/* Routines for dealing with '\0' separated arg vectors.
+   Copyright (C) 1995,96,97,2000,2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Miles Bader <miles@gnu.org>
+
+   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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#include <argz.h>
+#include <string.h>
+
+/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
+   except the last into the character SEP.  */
+void
+__argz_stringify (char *argz, size_t len, int sep)
+{
+  if (len > 0)
+    while (1)
+      {
+	size_t part_len = __strnlen (argz, len);
+	argz += part_len;
+	len -= part_len;
+	if (len-- <= 1)		/* includes final '\0' we want to stop at */
+	  break;
+	*argz++ = sep;
+      }
+}
+INTDEF(__argz_stringify)
+weak_alias (__argz_stringify, argz_stringify)
Index: /trunk/libc/src/glibc/string/string.smak
===================================================================
--- /trunk/libc/src/glibc/string/string.smak	(revision 2448)
+++ /trunk/libc/src/glibc/string/string.smak	(revision 2448)
@@ -0,0 +1,1 @@
+libc.TSRC += $(wildcard src/glibc/string/*.c)
Index: /trunk/libc/src/glibc/string/strndup.c
===================================================================
--- /trunk/libc/src/glibc/string/strndup.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/strndup.c	(revision 2448)
@@ -0,0 +1,62 @@
+/* Copyright (C) 1996, 1997, 1998, 2001, 2002 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 __EMX__
+#include "libc-alias-glibc.h"
+#endif
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if defined _LIBC || defined STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#else
+char *malloc ();
+#endif
+
+#undef __strndup
+#undef strndup
+
+#ifndef weak_alias
+# define __strndup strndup
+#endif
+
+char *
+__strndup (s, n)
+     const char *s;
+     size_t n;
+{
+  size_t len = __strnlen (s, n);
+  char *new = (char *) malloc (len + 1);
+
+  if (new == NULL)
+    return NULL;
+
+  new[len] = '\0';
+  return (char *) memcpy (new, s, len);
+}
+#ifdef libc_hidden_def
+libc_hidden_def (__strndup)
+#endif
+#ifdef weak_alias
+weak_alias (__strndup, strndup)
+#endif
Index: /trunk/libc/src/glibc/string/strverscmp.c
===================================================================
--- /trunk/libc/src/glibc/string/strverscmp.c	(revision 2448)
+++ /trunk/libc/src/glibc/string/strverscmp.c	(revision 2448)
@@ -0,0 +1,114 @@
+/* Compare strings while treating digits characters numerically.
+   Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <string.h>
+#include <ctype.h>
+
+/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
+           fractionnal parts, S_Z: idem but with leading Zeroes only */
+#define  S_N    0x0
+#define  S_I    0x4
+#define  S_F    0x8
+#define  S_Z    0xC
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define  CMP    2
+#define  LEN    3
+
+
+/* Compare S1 and S2 as strings holding indices/version numbers,
+   returning less than, equal to or greater than zero if S1 is less than,
+   equal to or greater than S2 (for more info, see the texinfo doc).
+*/
+
+int
+__strverscmp (s1, s2)
+     const char *s1;
+     const char *s2;
+{
+  const unsigned char *p1 = (const unsigned char *) s1;
+  const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+  int state;
+  int diff;
+
+  /* Symbol(s)    0       [1-9]   others  (padding)
+     Transition   (10) 0  (01) d  (00) x  (11) -   */
+  static const unsigned int next_state[] =
+  {
+      /* state    x    d    0    - */
+      /* S_N */  S_N, S_I, S_Z, S_N,
+      /* S_I */  S_N, S_I, S_I, S_I,
+      /* S_F */  S_N, S_F, S_F, S_F,
+      /* S_Z */  S_N, S_F, S_Z, S_Z
+  };
+
+  static const int result_type[] =
+  {
+      /* state   x/x  x/d  x/0  x/-  d/x  d/d  d/0  d/-
+                 0/x  0/d  0/0  0/-  -/x  -/d  -/0  -/- */
+
+      /* S_N */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+      /* S_I */  CMP, -1,  -1,  CMP, +1,  LEN, LEN, CMP,
+                 +1,  LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+      /* S_F */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+      /* S_Z */  CMP, +1,  +1,  CMP, -1,  CMP, CMP, CMP,
+                 -1,  CMP, CMP, CMP
+  };
+
+  if (p1 == p2)
+    return 0;
+
+  c1 = *p1++;
+  c2 = *p2++;
+  /* Hint: '0' is a digit too.  */
+  state = S_N | ((c1 == '0') + (isdigit (c1) != 0));
+
+  while ((diff = c1 - c2) == 0 && c1 != '\0')
+    {
+      state = next_state[state];
+      c1 = *p1++;
+      c2 = *p2++;
+      state |= (c1 == '0') + (isdigit (c1) != 0);
+    }
+
+  state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))];
+
+  switch (state)
+  {
+    case CMP:
+      return diff;
+
+    case LEN:
+      while (isdigit (*p1++))
+	if (!isdigit (*p2++))
+	  return 1;
+
+      return isdigit (*p2) ? -1 : diff;
+
+    default:
+      return state;
+  }
+}
+libc_hidden_def (__strverscmp)
+weak_alias (__strverscmp, strverscmp)
Index: /trunk/libc/src/glibc/sysdeps/generic/bp-sym.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/bp-sym.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/bp-sym.h	(revision 2448)
@@ -0,0 +1,26 @@
+/* Bounded-pointer symbol modifier.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Greg McGary <greg@mcgary.org>
+
+   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 BP_SYM(name) _BP_SYM (name)
+#if __BOUNDED_POINTERS__
+# define _BP_SYM(name) __BP_##name
+#else
+# define _BP_SYM(name) name
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/cargf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/cargf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/cargf.c	(revision 2448)
@@ -0,0 +1,30 @@
+/* Compute argument of complex float value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+float
+_STD(cargf) (__complex__ float x)
+{
+  return __atan2f (__imag__ x, __real__ x);
+}
+/* w e a k _ a  l i a s (__cargf, cargf) */
Index: /trunk/libc/src/glibc/sysdeps/generic/fpu_control.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/fpu_control.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/fpu_control.c	(revision 2448)
@@ -0,0 +1,26 @@
+/* Default FPU control word initialization.
+   Copyright (C) 1996, 1997, 1999 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 "libc-alias-glibc.h"
+#include <math.h>
+#include <fpu_control.h>
+
+/* This module defines `__fpu_control' with the default value.  */
+
+fpu_control_t __fpu_control = _FPU_DEFAULT;
Index: /trunk/libc/src/glibc/sysdeps/generic/math_private.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/math_private.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/math_private.h	(revision 2448)
@@ -0,0 +1,7 @@
+#include "../../../msun/src/math_private.h"
+#ifdef __INNOTEK_LIBC__
+# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+# define _strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+#endif
+
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cacos.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cacos.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cacos.c	(revision 2448)
@@ -0,0 +1,42 @@
+/* Return cosine of complex double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+__complex__ double
+_STD(cacos) (__complex__ double x)
+{
+  __complex__ double y;
+  __complex__ double res;
+
+  y = __casin (x);
+
+  __real__ res = (double) M_PI_2 - __real__ y;
+  __imag__ res = -__imag__ y;
+
+  return res;
+}
+/* w e a k _ a l i a s  (__cacos, cacos) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__cacos, __cacosl)
+/* w e a k _ a l i a s  (__cacos, cacosl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cacosf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cacosf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cacosf.c	(revision 2448)
@@ -0,0 +1,40 @@
+/* Return cosine of complex float value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+__complex__ float
+_STD(cacosf) (__complex__ float x)
+{
+  __complex__ float y;
+  __complex__ float res;
+
+  y = __casinf (x);
+
+  __real__ res = (float) M_PI_2 - __real__ y;
+  __imag__ res = -__imag__ y;
+
+  return res;
+}
+#ifndef __cacosf
+/* w e a k _ a l i a s  (__cacosf, cacosf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cacosh.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cacosh.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cacosh.c	(revision 2448)
@@ -0,0 +1,90 @@
+/* Return arc hyperbole cosine for double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+#define __nan(x) __builtin_nan(x)
+
+
+__complex__ double
+_STD(cacosh) (__complex__ double x)
+{
+  __complex__ double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VAL;
+
+	  if (rcls == FP_NAN)
+	    __imag__ res = __nan ("");
+	  else
+	    __imag__ res = __copysign ((rcls == FP_INFINITE
+					? (__real__ x < 0.0
+					   ? M_PI - M_PI_4 : M_PI_4)
+					: M_PI_2), __imag__ x);
+	}
+      else if (rcls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VAL;
+
+	  if (icls >= FP_ZERO)
+	    __imag__ res = __copysign (signbit (__real__ x) ? M_PI : 0.0,
+				       __imag__ x);
+	  else
+	    __imag__ res = __nan ("");
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      __real__ res = 0.0;
+      __imag__ res = __copysign (M_PI_2, __imag__ x);
+    }
+  else
+    {
+      __complex__ double y;
+
+      __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0;
+      __imag__ y = 2.0 * __real__ x * __imag__ x;
+
+      y = __csqrt (y);
+
+      __real__ y += __real__ x;
+      __imag__ y += __imag__ x;
+
+      res = __clog (y);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__cacosh, cacosh) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__cacosh, __cacoshl)
+/* w e a k _ a l i a s  (__cacosh, cacoshl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cacoshf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cacoshf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cacoshf.c	(revision 2448)
@@ -0,0 +1,102 @@
+/* Return arc hyperbole cosine for float value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+__complex__ float
+_STD(cacoshf) (__complex__ float x)
+{
+  __complex__ float res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VALF;
+
+	  if (rcls == FP_NAN)
+	    __imag__ res = __nanf ("");
+	  else
+	    __imag__ res = __copysignf ((rcls == FP_INFINITE
+					 ? (__real__ x < 0.0
+					    ? M_PI - M_PI_4 : M_PI_4)
+					 : M_PI_2), __imag__ x);
+	}
+      else if (rcls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VALF;
+
+	  if (icls >= FP_ZERO)
+	    __imag__ res = __copysignf (signbit (__real__ x) ? M_PI : 0.0,
+					__imag__ x);
+	  else
+	    __imag__ res = __nanf ("");
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      __real__ res = 0.0;
+      __imag__ res = __copysignf (M_PI_2, __imag__ x);
+    }
+  else
+    {
+#if 1
+      __complex__ float y;
+
+      __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0;
+      __imag__ y = 2.0 * __real__ x * __imag__ x;
+
+      y = __csqrtf (y);
+
+      __real__ y += __real__ x;
+      __imag__ y += __imag__ x;
+
+      res = __clogf (y);
+#else
+      float re2 = __real__ x * __real__ x;
+      float im2 = __imag__ x * __imag__ x;
+      float sq = re2 - im2 - 1.0;
+      float ro = __ieee754_sqrtf (sq * sq + 4 * re2 * im2);
+      float a = __ieee754_sqrtf ((sq + ro) / 2.0);
+      float b = __ieee754_sqrtf ((-sq + ro) / 2.0);
+
+      __real__ res = 0.5 * __ieee754_logf (re2 + __real__ x * 2 * a
+					   + im2 + __imag__ x * 2 * b
+					   + ro);
+      __imag__ res = __ieee754_atan2f (__imag__ x + b, __real__ x + a);
+#endif
+    }
+
+  return res;
+}
+#ifndef __cacoshf
+/*w e a k _ a l i a s (__cacoshf, cacoshf)*/
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cacoshl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cacoshl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cacoshl.c	(revision 2448)
@@ -0,0 +1,85 @@
+/* Return arc hyperbole cosine for long double value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ long double
+__cacoshl (__complex__ long double x)
+{
+  __complex__ long double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VALL;
+
+	  if (rcls == FP_NAN)
+	    __imag__ res = __nanl ("");
+	  else
+	    __imag__ res = __copysignl ((rcls == FP_INFINITE
+					 ? (__real__ x < 0.0
+					    ? M_PIl - M_PI_4l : M_PI_4l)
+					 : M_PI_2l), __imag__ x);
+	}
+      else if (rcls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VALL;
+
+	  if (icls >= FP_ZERO)
+	    __imag__ res = __copysignl (signbit (__real__ x) ? M_PIl : 0.0,
+					__imag__ x);
+	  else
+	    __imag__ res = __nanl ("");
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      __real__ res = 0.0;
+      __imag__ res = __copysignl (M_PI_2l, __imag__ x);
+    }
+  else
+    {
+      __complex__ long double y;
+
+      __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0;
+      __imag__ y = 2.0 * __real__ x * __imag__ x;
+
+      y = __csqrtl (y);
+
+      __real__ y += __real__ x;
+      __imag__ y += __imag__ x;
+
+      res = __clogl (y);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__cacoshl, cacoshl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cacosl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cacosl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cacosl.c	(revision 2448)
@@ -0,0 +1,38 @@
+/* Return cosine of complex long double value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+__complex__ long double
+__cacosl (__complex__ long double x)
+{
+  __complex__ long double y;
+  __complex__ long double res;
+
+  y = __casinl (x);
+
+  __real__ res = M_PI_2l - __real__ y;
+  __imag__ res = -__imag__ y;
+
+  return res;
+}
+/* w e a k _ a l i a s  (__cacosl, cacosl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_casin.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_casin.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_casin.c	(revision 2448)
@@ -0,0 +1,67 @@
+/* Return arc sine of complex double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+#define __nan(x) __builtin_nan(x)
+
+__complex__ double
+_STD(casin) (__complex__ double x)
+{
+  __complex__ double res;
+
+  if (isnan (__real__ x) || isnan (__imag__ x))
+    {
+      if (__real__ x == 0.0)
+	{
+	  res = x;
+	}
+      else if (__isinf (__real__ x) || __isinf (__imag__ x))
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __copysign (HUGE_VAL, __imag__ x);
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+	}
+    }
+  else
+    {
+      __complex__ double y;
+
+      __real__ y = -__imag__ x;
+      __imag__ y = __real__ x;
+
+      y = __casinh (y);
+
+      __real__ res = __imag__ y;
+      __imag__ res = -__real__ y;
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__casin, casin) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__casin, __casinl)
+/* w e a k _ a l i a s  (__casin, casinl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_casinf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_casinf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_casinf.c	(revision 2448)
@@ -0,0 +1,65 @@
+/* Return arc sine of complex float value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ float
+_STD(casinf) (__complex__ float x)
+{
+  __complex__ float res;
+
+  if (isnan (__real__ x) || isnan (__imag__ x))
+    {
+      if (__real__ x == 0.0)
+	{
+	  res = x;
+	}
+      else if (__isinff (__real__ x) || __isinff (__imag__ x))
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __copysignf (HUGE_VALF, __imag__ x);
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+	}
+    }
+  else
+    {
+      __complex__ float y;
+
+      __real__ y = -__imag__ x;
+      __imag__ y = __real__ x;
+
+      y = __casinhf (y);
+
+      __real__ res = __imag__ y;
+      __imag__ res = -__real__ y;
+    }
+
+  return res;
+}
+#ifndef __casinf
+/* w e a k _ a l i a s  (__casinf, casinf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_casinh.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_casinh.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_casinh.c	(revision 2448)
@@ -0,0 +1,85 @@
+/* Return arc hyperbole sine for double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+#define __nan(x) __builtin_nan(x)
+
+__complex__ double
+_STD(casinh) (__complex__ double x)
+{
+  __complex__ double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = __copysign (HUGE_VAL, __real__ x);
+
+	  if (rcls == FP_NAN)
+	    __imag__ res = __nan ("");
+	  else
+	    __imag__ res = __copysign (rcls >= FP_ZERO ? M_PI_2 : M_PI_4,
+				       __imag__ x);
+	}
+      else if (rcls <= FP_INFINITE)
+	{
+	  __real__ res = __real__ x;
+	  if ((rcls == FP_INFINITE && icls >= FP_ZERO)
+	      || (rcls == FP_NAN && icls == FP_ZERO))
+	    __imag__ res = __copysign (0.0, __imag__ x);
+	  else
+	    __imag__ res = __nan ("");
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      __complex__ double y;
+
+      __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) + 1.0;
+      __imag__ y = 2.0 * __real__ x * __imag__ x;
+
+      y = __csqrt (y);
+
+      __real__ y += __real__ x;
+      __imag__ y += __imag__ x;
+
+      res = __clog (y);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__casinh, casinh) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__casinh, __casinhl)
+/* w e a k _ a l i a s  (__casinh, casinhl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_casinhf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_casinhf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_casinhf.c	(revision 2448)
@@ -0,0 +1,83 @@
+/* Return arc hyperbole sine for float value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ float
+_STD(casinhf) (__complex__ float x)
+{
+  __complex__ float res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = __copysignf (HUGE_VALF, __real__ x);
+
+	  if (rcls == FP_NAN)
+	    __imag__ res = __nanf ("");
+	  else
+	    __imag__ res = __copysignf (rcls >= FP_ZERO ? M_PI_2 : M_PI_4,
+					__imag__ x);
+	}
+      else if (rcls <= FP_INFINITE)
+	{
+	  __real__ res = __real__ x;
+	  if ((rcls == FP_INFINITE && icls >= FP_ZERO)
+	      || (rcls == FP_NAN && icls == FP_ZERO))
+	    __imag__ res = __copysignf (0.0, __imag__ x);
+	  else
+	    __imag__ res = __nanf ("");
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      __complex__ float y;
+
+      __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) + 1.0;
+      __imag__ y = 2.0 * __real__ x * __imag__ x;
+
+      y = __csqrtf (y);
+
+      __real__ y += __real__ x;
+      __imag__ y += __imag__ x;
+
+      res = __clogf (y);
+    }
+
+  return res;
+}
+#ifndef __casinhf
+/* w e a k _ a l i a s  (__casinhf, casinhf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_casinhl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_casinhl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_casinhl.c	(revision 2448)
@@ -0,0 +1,81 @@
+/* Return arc hyperbole sine for long double value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ long double
+__casinhl (__complex__ long double x)
+{
+  __complex__ long double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = __copysignl (HUGE_VALL, __real__ x);
+
+	  if (rcls == FP_NAN)
+	    __imag__ res = __nanl ("");
+	  else
+	    __imag__ res = __copysignl (rcls >= FP_ZERO ? M_PI_2l : M_PI_4l,
+					__imag__ x);
+	}
+      else if (rcls <= FP_INFINITE)
+	{
+	  __real__ res = __real__ x;
+	  if ((rcls == FP_INFINITE && icls >= FP_ZERO)
+	      || (rcls == FP_NAN && icls == FP_ZERO))
+	    __imag__ res = __copysignl (0.0, __imag__ x);
+	  else
+	    __imag__ res = __nanl ("");
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      __complex__ long double y;
+
+      __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) + 1.0;
+      __imag__ y = 2.0 * __real__ x * __imag__ x;
+
+      y = __csqrtl (y);
+
+      __real__ y += __real__ x;
+      __imag__ y += __imag__ x;
+
+      res = __clogl (y);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__casinhl, casinhl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_casinl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_casinl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_casinl.c	(revision 2448)
@@ -0,0 +1,63 @@
+/* Return arc sine of complex long double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ long double
+__casinl (__complex__ long double x)
+{
+  __complex__ long double res;
+
+  if (isnan (__real__ x) || isnan (__imag__ x))
+    {
+      if (__real__ x == 0.0)
+	{
+	  res = x;
+	}
+      else if (__isinfl (__real__ x) || __isinfl (__imag__ x))
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __copysignl (HUGE_VALL, __imag__ x);
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+	}
+    }
+  else
+    {
+      __complex__ long double y;
+
+      __real__ y = -__imag__ x;
+      __imag__ y = __real__ x;
+
+      y = __casinhl (y);
+
+      __real__ res = __imag__ y;
+      __imag__ res = -__real__ y;
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__casinl, casinl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_catan.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_catan.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_catan.c	(revision 2448)
@@ -0,0 +1,91 @@
+/* Return arc tangent of complex double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+#define __nan(x) __builtin_nan(x)
+
+
+__complex__ double
+_STD(catan) (__complex__ double x)
+{
+  __complex__ double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (rcls == FP_INFINITE)
+	{
+	  __real__ res = __copysign (M_PI_2, __real__ x);
+	  __imag__ res = __copysign (0.0, __imag__ x);
+	}
+      else if (icls == FP_INFINITE)
+	{
+	  if (rcls >= FP_ZERO)
+	    __real__ res = __copysign (M_PI_2, __real__ x);
+	  else
+	    __real__ res = __nan ("");
+	  __imag__ res = __copysign (0.0, __imag__ x);
+	}
+      else if (icls == FP_ZERO || icls == FP_INFINITE)
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __copysign (0.0, __imag__ x);
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      double r2, num, den;
+
+      r2 = __real__ x * __real__ x;
+
+      den = 1 - r2 - __imag__ x * __imag__ x;
+
+      __real__ res = 0.5 * __ieee754_atan2 (2.0 * __real__ x, den);
+
+      num = __imag__ x + 1.0;
+      num = r2 + num * num;
+
+      den = __imag__ x - 1.0;
+      den = r2 + den * den;
+
+      __imag__ res = 0.25 * __ieee754_log (num / den);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__catan, catan) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__catan, __catanl)
+/* w e a k _ a l i a s  (__catan, catanl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_catanf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_catanf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_catanf.c	(revision 2448)
@@ -0,0 +1,88 @@
+/* Return arc tangent of complex float value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(catanf) (__complex__ float x)
+{
+  __complex__ float res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (rcls == FP_INFINITE)
+	{
+	  __real__ res = __copysignf (M_PI_2, __real__ x);
+	  __imag__ res = __copysignf (0.0, __imag__ x);
+	}
+      else if (icls == FP_INFINITE)
+	{
+	  if (rcls >= FP_ZERO)
+	    __real__ res = __copysignf (M_PI_2, __real__ x);
+	  else
+	    __real__ res = __nanf ("");
+	  __imag__ res = __copysignf (0.0, __imag__ x);
+	}
+      else if (icls == FP_ZERO || icls == FP_INFINITE)
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __copysignf (0.0, __imag__ x);
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      float r2, num, den;
+
+      r2 = __real__ x * __real__ x;
+
+      den = 1 - r2 - __imag__ x * __imag__ x;
+
+      __real__ res = 0.5 * __ieee754_atan2f (2.0 * __real__ x, den);
+
+      num = __imag__ x + 1.0;
+      num = r2 + num * num;
+
+      den = __imag__ x - 1.0;
+      den = r2 + den * den;
+
+      __imag__ res = 0.25 * __ieee754_logf (num / den);
+    }
+
+  return res;
+}
+#ifndef __catanf
+/* w e a k _ a l i a s  (__catanf, catanf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_catanh.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_catanh.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_catanh.c	(revision 2448)
@@ -0,0 +1,88 @@
+/* Return arc hyperbole tangent for double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#define __nan(x) __builtin_nan(x)
+
+
+#include "math_private.h"
+
+
+__complex__ double
+_STD(catanh) (__complex__ double x)
+{
+  __complex__ double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = __copysign (0.0, __real__ x);
+	  __imag__ res = __copysign (M_PI_2, __imag__ x);
+	}
+      else if (rcls == FP_INFINITE || rcls == FP_ZERO)
+	{
+	  __real__ res = __copysign (0.0, __real__ x);
+	  if (icls >= FP_ZERO)
+	    __imag__ res = __copysign (M_PI_2, __imag__ x);
+	  else
+	    __imag__ res = __nan ("");
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      double i2, num, den;
+
+      i2 = __imag__ x * __imag__ x;
+
+      num = 1.0 + __real__ x;
+      num = i2 + num * num;
+
+      den = 1.0 - __real__ x;
+      den = i2 + den * den;
+
+      __real__ res = 0.25 * (__ieee754_log (num) - __ieee754_log (den));
+
+      den = 1 - __real__ x * __real__ x - i2;
+
+      __imag__ res = 0.5 * __ieee754_atan2 (2.0 * __imag__ x, den);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__catanh, catanh) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__catanh, __catanhl)
+/* w e a k _ a l i a s  (__catanh, catanhl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_catanhf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_catanhf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_catanhf.c	(revision 2448)
@@ -0,0 +1,83 @@
+/* Return arc hyperbole tangent for float value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(catanhf) (__complex__ float x)
+{
+  __complex__ float res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = __copysignf (0.0, __real__ x);
+	  __imag__ res = __copysignf (M_PI_2, __imag__ x);
+	}
+      else if (rcls == FP_INFINITE || rcls == FP_ZERO)
+	{
+	  __real__ res = __copysignf (0.0, __real__ x);
+	  if (icls >= FP_ZERO)
+	    __imag__ res = __copysignf (M_PI_2, __imag__ x);
+	  else
+	    __imag__ res = __nanf ("");
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      float i2, num, den;
+
+      i2 = __imag__ x * __imag__ x;
+
+      num = 1.0 + __real__ x;
+      num = i2 + num * num;
+
+      den = 1.0 - __real__ x;
+      den = i2 + den * den;
+
+      __real__ res = 0.25 * (__ieee754_logf (num) - __ieee754_logf (den));
+
+      den = 1 - __real__ x * __real__ x - i2;
+
+      __imag__ res = 0.5 * __ieee754_atan2f (2.0 * __imag__ x, den);
+    }
+
+  return res;
+}
+#ifndef __catanhf
+/* w e a k _ a l i a s  (__catanhf, catanhf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_catanhl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_catanhl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_catanhl.c	(revision 2448)
@@ -0,0 +1,81 @@
+/* Return arc hyperbole tangent for long double value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(catanhl) (__complex__ long double x)
+{
+  __complex__ long double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = __copysignl (0.0, __real__ x);
+	  __imag__ res = __copysignl (M_PI_2l, __imag__ x);
+	}
+      else if (rcls == FP_INFINITE || rcls == FP_ZERO)
+	{
+	  __real__ res = __copysignl (0.0, __real__ x);
+	  if (icls >= FP_ZERO)
+	    __imag__ res = __copysignl (M_PI_2l, __imag__ x);
+	  else
+	    __imag__ res = __nanl ("");
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      long double i2, num, den;
+
+      i2 = __imag__ x * __imag__ x;
+
+      num = 1.0 + __real__ x;
+      num = i2 + num * num;
+
+      den = 1.0 - __real__ x;
+      den = i2 + den * den;
+
+      __real__ res = 0.25 * (__ieee754_logl (num) - __ieee754_logl (den));
+
+      den = 1 - __real__ x * __real__ x - i2;
+
+      __imag__ res = 0.5 * __ieee754_atan2l (2.0 * __imag__ x, den);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__catanhl, catanhl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_catanl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_catanl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_catanl.c	(revision 2448)
@@ -0,0 +1,86 @@
+/* Return arc tangent of complex long double value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+__catanl (__complex__ long double x)
+{
+  __complex__ long double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (rcls == FP_INFINITE)
+	{
+	  __real__ res = __copysignl (M_PI_2l, __real__ x);
+	  __imag__ res = __copysignl (0.0, __imag__ x);
+	}
+      else if (icls == FP_INFINITE)
+	{
+	  if (rcls >= FP_ZERO)
+	    __real__ res = __copysignl (M_PI_2l, __real__ x);
+	  else
+	    __real__ res = __nanl ("");
+	  __imag__ res = __copysignl (0.0, __imag__ x);
+	}
+      else if (icls == FP_ZERO || icls == FP_INFINITE)
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __copysignl (0.0, __imag__ x);
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      long double r2, num, den;
+
+      r2 = __real__ x * __real__ x;
+
+      den = 1 - r2 - __imag__ x * __imag__ x;
+
+      __real__ res = 0.5 * __ieee754_atan2l (2.0 * __real__ x, den);
+
+      num = __imag__ x + 1.0;
+      num = r2 + num * num;
+
+      den = __imag__ x - 1.0;
+      den = r2 + den * den;
+
+      __imag__ res = 0.25 * __ieee754_logl (num / den);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__catanl, catanl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ccos.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ccos.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ccos.c	(revision 2448)
@@ -0,0 +1,82 @@
+/* Return cosine of complex double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+#define __nan(x) __builtin_nan(x)
+
+
+__complex__ double
+_STD(ccos) (__complex__ double x)
+{
+  __complex__ double res;
+
+  if (!isfinite (__real__ x) || __isnan (__imag__ x))
+    {
+      if (__real__ x == 0.0 || __imag__ x == 0.0)
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = 0.0;
+
+#ifdef FE_INVALID
+	  if (__isinf (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+      else if (__isinf (__imag__ x))
+	{
+	  __real__ res = HUGE_VAL;
+	  __imag__ res = __nan ("");
+
+#ifdef FE_INVALID
+	  if (__isinf (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+
+#ifdef FE_INVALID
+	  if (isfinite (__imag__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __complex__ double y;
+
+      __real__ y = -__imag__ x;
+      __imag__ y = __real__ x;
+
+      res = __ccosh (y);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__ccos, ccos) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__ccos, __ccosl)
+/* w e a k _ a l i a s  (__ccos, ccosl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ccosf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ccosf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ccosf.c	(revision 2448)
@@ -0,0 +1,79 @@
+/* Return cosine of complex float value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+
+__complex__ float
+_STD(ccosf) (__complex__ float x)
+{
+  __complex__ float res;
+
+  if (!isfinite (__real__ x) || __isnanf (__imag__ x))
+    {
+      if (__real__ x == 0.0 || __imag__ x == 0.0)
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = 0.0;
+
+#ifdef FE_INVALID
+	  if (__isinff (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+      else if (__isinff (__imag__ x))
+	{
+	  __real__ res = HUGE_VALF;
+	  __imag__ res = __nanf ("");
+
+#ifdef FE_INVALID
+	  if (__isinff (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+
+#ifdef FE_INVALID
+	  if (isfinite (__imag__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __complex__ float y;
+
+      __real__ y = -__imag__ x;
+      __imag__ y = __real__ x;
+
+      res = __ccoshf (y);
+    }
+
+  return res;
+}
+#ifndef __ccosf
+/* w e a k _ a l i a s  (__ccosf, ccosf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ccosh.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ccosh.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ccosh.c	(revision 2448)
@@ -0,0 +1,109 @@
+/* Complex cosine hyperbole function for double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#define __nan(x) __builtin_nan(x)
+
+
+#include "math_private.h"
+
+
+__complex__ double
+_STD(ccosh) (__complex__ double x)
+{
+  __complex__ double retval;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls >= FP_ZERO)
+    {
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  double sinh_val = __ieee754_sinh (__real__ x);
+	  double cosh_val = __ieee754_cosh (__real__ x);
+	  double sinix, cosix;
+
+	  __sincos (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * cosix;
+	  __imag__ retval = sinh_val * sinix;
+	}
+      else
+	{
+	  __imag__ retval = __real__ x == 0.0 ? 0.0 : __nan ("");
+	  __real__ retval = __nan ("") + __nan ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (icls == FP_ZERO)
+	{
+	  /* Imaginary part is 0.0.  */
+	  __real__ retval = HUGE_VAL;
+	  __imag__ retval = __imag__ x * __copysign (1.0, __real__ x);
+	}
+      else if (icls > FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  double sinix, cosix;
+
+	  __sincos (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysign (HUGE_VAL, cosix);
+	  __imag__ retval = (__copysign (HUGE_VAL, sinix)
+			     * __copysign (1.0, __real__ x));
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = HUGE_VAL;
+	  __imag__ retval = __nan ("") + __nan ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __real__ retval = __nan ("");
+      __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nan ("");
+    }
+
+  return retval;
+}
+/* w e a k _ a l i a s  (__ccosh, ccosh) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__ccosh, __ccoshl)
+/* w e a k _ a l i a s  (__ccosh, ccoshl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ccoshf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ccoshf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ccoshf.c	(revision 2448)
@@ -0,0 +1,104 @@
+/* Complex cosine hyperbole function for float.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(ccoshf) (__complex__ float x)
+{
+  __complex__ float retval;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls >= FP_ZERO)
+    {
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  float sinh_val = __ieee754_sinhf (__real__ x);
+	  float cosh_val = __ieee754_coshf (__real__ x);
+	  float sinix, cosix;
+
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * cosix;
+	  __imag__ retval = sinh_val * sinix;
+	}
+      else
+	{
+	  __imag__ retval = __real__ x == 0.0 ? 0.0 : __nanf ("");
+	  __real__ retval = __nanf ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (icls == FP_ZERO)
+	{
+	  /* Imaginary part is 0.0.  */
+	  __real__ retval = HUGE_VALF;
+	  __imag__ retval = __imag__ x * __copysignf (1.0, __real__ x);
+	}
+      else if (icls > FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  float sinix, cosix;
+
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignf (HUGE_VALF, cosix);
+	  __imag__ retval = (__copysignf (HUGE_VALF, sinix)
+			     * __copysignf (1.0, __real__ x));
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = HUGE_VALF;
+	  __imag__ retval = __nanf ("") + __nanf ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __real__ retval = __nanf ("");
+      __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nanf ("");
+    }
+
+  return retval;
+}
+#ifndef __ccoshf
+/* w e a k _ a l i a s  (__ccoshf, ccoshf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ccoshl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ccoshl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ccoshl.c	(revision 2448)
@@ -0,0 +1,102 @@
+/* Complex cosine hyperbole function for long double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(ccoshl) (__complex__ long double x)
+{
+  __complex__ long double retval;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls >= FP_ZERO)
+    {
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  long double sinh_val = __ieee754_sinhl (__real__ x);
+	  long double cosh_val = __ieee754_coshl (__real__ x);
+	  long double sinix, cosix;
+
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * cosix;
+	  __imag__ retval = sinh_val * sinix;
+	}
+      else
+	{
+	  __imag__ retval = __real__ x == 0.0 ? 0.0 : __nanl ("");
+	  __real__ retval = __nanl ("") + __nanl ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (icls == FP_ZERO)
+	{
+	  /* Imaginary part is 0.0.  */
+	  __real__ retval = HUGE_VALL;
+	  __imag__ retval = __imag__ x * __copysignl (1.0, __real__ x);
+	}
+      else if (icls > FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  long double sinix, cosix;
+
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignl (HUGE_VALL, cosix);
+	  __imag__ retval = (__copysignl (HUGE_VALL, sinix)
+			     * __copysignl (1.0, __real__ x));
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = HUGE_VALL;
+	  __imag__ retval = __nanl ("") + __nanl ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __real__ retval = __nanl ("");
+      __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nanl ("");
+    }
+
+  return retval;
+}
+/* w e a k _ a l i a s  (__ccoshl, ccoshl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ccosl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ccosl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ccosl.c	(revision 2448)
@@ -0,0 +1,77 @@
+/* Return cosine of complex long double value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+
+__complex__ long double
+_STD(ccosl) (__complex__ long double x)
+{
+  __complex__ long double res;
+
+  if (!isfinite (__real__ x) || __isnanl (__imag__ x))
+    {
+      if (__real__ x == 0.0 || __imag__ x == 0.0)
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = 0.0;
+
+#ifdef FE_INVALID
+	  if (__isinfl (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+      else if (__isinfl (__imag__ x))
+	{
+	  __real__ res = HUGE_VALL;
+	  __imag__ res = __nanl ("");
+
+#ifdef FE_INVALID
+	  if (__isinfl (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+
+#ifdef FE_INVALID
+	  if (isfinite (__imag__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __complex__ long double y;
+
+      __real__ y = -__imag__ x;
+      __imag__ y = __real__ x;
+
+      res = __ccoshl (y);
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__ccosl, ccosl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cexpf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cexpf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cexpf.c	(revision 2448)
@@ -0,0 +1,126 @@
+/* Return value of complex exponential function for float complex value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(cexpf) (__complex__ float x)
+{
+  __complex__ float retval;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls >= FP_ZERO)
+    {
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  float exp_val = __ieee754_expf (__real__ x);
+	  float sinix, cosix;
+
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  if (isfinite (exp_val))
+	    {
+	      __real__ retval = exp_val * cosix;
+	      __imag__ retval = exp_val * sinix;
+	    }
+	  else
+	    {
+	      __real__ retval = __copysignf (exp_val, cosix);
+	      __imag__ retval = __copysignf (exp_val, sinix);
+	    }
+	}
+      else
+	{
+	  /* If the imaginary part is +-inf or NaN and the real part
+	     is not +-inf the result is NaN + iNaN.  */
+	  __real__ retval = __nanf ("");
+	  __imag__ retval = __nanf ("");
+
+#ifdef FE_INVALID
+	  feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  float value = signbit (__real__ x) ? 0.0 : HUGE_VALF;
+
+	  if (icls == FP_ZERO)
+	    {
+	      /* Imaginary part is 0.0.  */
+	      __real__ retval = value;
+	      __imag__ retval = __imag__ x;
+	    }
+	  else
+	    {
+	      float sinix, cosix;
+
+	      __sincosf (__imag__ x, &sinix, &cosix);
+
+	      __real__ retval = __copysignf (value, cosix);
+	      __imag__ retval = __copysignf (value, sinix);
+	    }
+	}
+      else if (signbit (__real__ x) == 0)
+	{
+	  __real__ retval = HUGE_VALF;
+	  __imag__ retval = __nanf ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+      else
+	{
+	  __real__ retval = 0.0;
+	  __imag__ retval = __copysignf (0.0, __imag__ x);
+	}
+    }
+  else
+    {
+      /* If the real part is NaN the result is NaN + iNaN.  */
+      __real__ retval = __nanf ("");
+      __imag__ retval = __nanf ("");
+
+#ifdef FE_INVALID
+      if (rcls != FP_NAN || icls != FP_NAN)
+	feraiseexcept (FE_INVALID);
+#endif
+    }
+
+  return retval;
+}
+#ifndef __cexpf
+/* w e a k _ a l i a s  (__cexpf, cexpf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cexpl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cexpl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cexpl.c	(revision 2448)
@@ -0,0 +1,124 @@
+/* Return value of complex exponential function for long double complex value.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(cexpl) (__complex__ long double x)
+{
+  __complex__ long double retval;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls >= FP_ZERO)
+    {
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  long double exp_val = __ieee754_expl (__real__ x);
+	  long double sinix, cosix;
+
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  if (isfinite (exp_val))
+	    {
+	      __real__ retval = exp_val * cosix;
+	      __imag__ retval = exp_val * sinix;
+	    }
+	  else
+	    {
+	      __real__ retval = __copysignl (exp_val, cosix);
+	      __imag__ retval = __copysignl (exp_val, sinix);
+	    }
+	}
+      else
+	{
+	  /* If the imaginary part is +-inf or NaN and the real part
+	     is not +-inf the result is NaN + iNaN.  */
+	  __real__ retval = __nanl ("");
+	  __imag__ retval = __nanl ("");
+
+#ifdef FE_INVALID
+	  feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  long double value = signbit (__real__ x) ? 0.0 : HUGE_VALL;
+
+	  if (icls == FP_ZERO)
+	    {
+	      /* Imaginary part is 0.0.  */
+	      __real__ retval = value;
+	      __imag__ retval = __imag__ x;
+	    }
+	  else
+	    {
+	      long double sinix, cosix;
+
+	      __sincosl (__imag__ x, &sinix, &cosix);
+
+	      __real__ retval = __copysignl (value, cosix);
+	      __imag__ retval = __copysignl (value, sinix);
+	    }
+	}
+      else if (signbit (__real__ x) == 0)
+	{
+	  __real__ retval = HUGE_VALL;
+	  __imag__ retval = __nanl ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+      else
+	{
+	  __real__ retval = 0.0;
+	  __imag__ retval = __copysignl (0.0, __imag__ x);
+	}
+    }
+  else
+    {
+      /* If the real part is NaN the result is NaN + iNaN.  */
+      __real__ retval = __nanl ("");
+      __imag__ retval = __nanl ("");
+
+#ifdef FE_INVALID
+      if (rcls != FP_NAN || icls != FP_NAN)
+	feraiseexcept (FE_INVALID);
+#endif
+    }
+
+  return retval;
+}
+/* w e a k _ a l i a s  (__cexpl, cexpl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_clog.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_clog.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_clog.c	(revision 2448)
@@ -0,0 +1,67 @@
+/* Compute complex natural logarithm.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+#define __nan(x) __builtin_nan(x)
+
+
+__complex__ double
+__clog (__complex__ double x)
+{
+  __complex__ double result;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      /* Real and imaginary part are 0.0.  */
+      __imag__ result = signbit (__real__ x) ? M_PI : 0.0;
+      __imag__ result = __copysign (__imag__ result, __imag__ x);
+      /* Yes, the following line raises an exception.  */
+      __real__ result = -1.0 / fabs (__real__ x);
+    }
+  else if (rcls != FP_NAN && icls != FP_NAN)
+    {
+      /* Neither real nor imaginary part is NaN.  */
+      __real__ result = __ieee754_log (__ieee754_hypot (__real__ x,
+							__imag__ x));
+      __imag__ result = __ieee754_atan2 (__imag__ x, __real__ x);
+    }
+  else
+    {
+      __imag__ result = __nan ("");
+      if (rcls == FP_INFINITE || icls == FP_INFINITE)
+	/* Real or imaginary part is infinite.  */
+	__real__ result = HUGE_VAL;
+      else
+	__real__ result = __nan ("");
+    }
+
+  return result;
+}
+/* w e a k _ a l i a s  (__clog, clog) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__clog, __clogl)
+/* w e a k _ a l i a s  (__clog, clogl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_clog10.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_clog10.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_clog10.c	(revision 2448)
@@ -0,0 +1,69 @@
+/* Compute complex base 10 logarithm.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#define __nan(x) __builtin_nan(x)
+
+
+#include "math_private.h"
+
+
+__complex__ double
+_STD(clog10) (__complex__ double x)
+{
+  __complex__ double result;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      /* Real and imaginary part are 0.0.  */
+      __imag__ result = signbit (__real__ x) ? M_PI : 0.0;
+      __imag__ result = __copysign (__imag__ result, __imag__ x);
+      /* Yes, the following line raises an exception.  */
+      __real__ result = -1.0 / fabs (__real__ x);
+    }
+  else if (rcls != FP_NAN && icls != FP_NAN)
+    {
+      /* Neither real nor imaginary part is NaN.  */
+      __real__ result = __ieee754_log10 (__ieee754_hypot (__real__ x,
+							  __imag__ x));
+      __imag__ result = M_LOG10E * __ieee754_atan2 (__imag__ x, __real__ x);
+    }
+  else
+    {
+      __imag__ result = __nan ("");
+      if (rcls == FP_INFINITE || icls == FP_INFINITE)
+	/* Real or imaginary part is infinite.  */
+	__real__ result = HUGE_VAL;
+      else
+	__real__ result = __nan ("");
+    }
+
+  return result;
+}
+/* w e a k _ a l i a s  (__clog10, clog10) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__clog10, __clog10l)
+/* w e a k _ a l i a s  (__clog10, clog10l) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_clog10f.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_clog10f.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_clog10f.c	(revision 2448)
@@ -0,0 +1,64 @@
+/* Compute complex base 10 logarithm.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(clog10f) (__complex__ float x)
+{
+  __complex__ float result;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      /* Real and imaginary part are 0.0.  */
+      __imag__ result = signbit (__real__ x) ? M_PI : 0.0;
+      __imag__ result = __copysignf (__imag__ result, __imag__ x);
+      /* Yes, the following line raises an exception.  */
+      __real__ result = -1.0 / fabsf (__real__ x);
+    }
+  else if (rcls != FP_NAN && icls != FP_NAN)
+    {
+      /* Neither real nor imaginary part is NaN.  */
+      __real__ result = __ieee754_log10f (__ieee754_hypotf (__real__ x,
+							    __imag__ x));
+      __imag__ result = M_LOG10E * __ieee754_atan2f (__imag__ x, __real__ x);
+    }
+  else
+    {
+      __imag__ result = __nanf ("");
+      if (rcls == FP_INFINITE || icls == FP_INFINITE)
+	/* Real or imaginary part is infinite.  */
+	__real__ result = HUGE_VALF;
+      else
+	__real__ result = __nanf ("");
+    }
+
+  return result;
+}
+#ifndef __clog10f
+/* w e a k _ a l i a s  (__clog10f, clog10f) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_clog10l.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_clog10l.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_clog10l.c	(revision 2448)
@@ -0,0 +1,62 @@
+/* Compute complex base 10 logarithm.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(clog10l) (__complex__ long double x)
+{
+  __complex__ long double result;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      /* Real and imaginary part are 0.0.  */
+      __imag__ result = signbit (__real__ x) ? M_PIl : 0.0;
+      __imag__ result = __copysignl (__imag__ result, __imag__ x);
+      /* Yes, the following line raises an exception.  */
+      __real__ result = -1.0 / fabsl (__real__ x);
+    }
+  else if (rcls != FP_NAN && icls != FP_NAN)
+    {
+      /* Neither real nor imaginary part is NaN.  */
+      __real__ result = __ieee754_log10l (__ieee754_hypotl (__real__ x,
+							    __imag__ x));
+      __imag__ result = M_LOG10El * __ieee754_atan2l (__imag__ x, __real__ x);
+    }
+  else
+    {
+      __imag__ result = __nanl ("");
+      if (rcls == FP_INFINITE || icls == FP_INFINITE)
+	/* Real or imaginary part is infinite.  */
+	__real__ result = HUGE_VALL;
+      else
+	__real__ result = __nanl ("");
+    }
+
+  return result;
+}
+/* w e a k _ a l i a s  (__clog10l, clog10l) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_clogf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_clogf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_clogf.c	(revision 2448)
@@ -0,0 +1,64 @@
+/* Compute complex natural logarithm.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+__clogf (__complex__ float x)
+{
+  __complex__ float result;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      /* Real and imaginary part are 0.0.  */
+      __imag__ result = signbit (__real__ x) ? M_PI : 0.0;
+      __imag__ result = __copysignf (__imag__ result, __imag__ x);
+      /* Yes, the following line raises an exception.  */
+      __real__ result = -1.0 / fabsf (__real__ x);
+    }
+  else if (rcls != FP_NAN && icls != FP_NAN)
+    {
+      /* Neither real nor imaginary part is NaN.  */
+      __real__ result = __ieee754_logf (__ieee754_hypotf (__real__ x,
+							  __imag__ x));
+      __imag__ result = __ieee754_atan2f (__imag__ x, __real__ x);
+    }
+  else
+    {
+      __imag__ result = __nanf ("");
+      if (rcls == FP_INFINITE || icls == FP_INFINITE)
+	/* Real or imaginary part is infinite.  */
+	__real__ result = HUGE_VALF;
+      else
+	__real__ result = __nanf ("");
+    }
+
+  return result;
+}
+#ifndef __clogf
+/* w e a k _ a l i a s  (__clogf, clogf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_clogl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_clogl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_clogl.c	(revision 2448)
@@ -0,0 +1,62 @@
+/* Compute complex natural logarithm.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+__clogl (__complex__ long double x)
+{
+  __complex__ long double result;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      /* Real and imaginary part are 0.0.  */
+      __imag__ result = signbit (__real__ x) ? M_PIl : 0.0;
+      __imag__ result = __copysignl (__imag__ result, __imag__ x);
+      /* Yes, the following line raises an exception.  */
+      __real__ result = -1.0 / fabsl (__real__ x);
+    }
+  else if (rcls != FP_NAN && icls != FP_NAN)
+    {
+      /* Neither real nor imaginary part is NaN.  */
+      __real__ result = __ieee754_logl (__ieee754_hypotl (__real__ x,
+							  __imag__ x));
+      __imag__ result = __ieee754_atan2l (__imag__ x, __real__ x);
+    }
+  else
+    {
+      __imag__ result = __nanl ("");
+      if (rcls == FP_INFINITE || icls == FP_INFINITE)
+	/* Real or imaginary part is infinite.  */
+	__real__ result = HUGE_VALL;
+      else
+	__real__ result = __nanl ("");
+    }
+
+  return result;
+}
+/* w e a k _ a l i a s  (__clogl, clogl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cpow.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cpow.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cpow.c	(revision 2448)
@@ -0,0 +1,38 @@
+/* Complex power of double values.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#define __nan(x) __builtin_nan(x)
+
+
+
+__complex__ double
+_STD(cpow) (__complex__ double x, __complex__ double c)
+{
+  return __cexp (c * __clog (x));
+}
+/* w e a k _ a l i a s  (__cpow, cpow) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__cpow, __cpowl)
+/* w e a k _ a l i a s  (__cpow, cpowl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cpowf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cpowf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cpowf.c	(revision 2448)
@@ -0,0 +1,33 @@
+/* Complex power of float values.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ float
+_STD(cpowf) (__complex__ float x, __complex__ float c)
+{
+  return __cexpf (c * __clogf (x));
+}
+#ifndef __cpowf
+/* w e a k _ a l i a s  (__cpowf, cpowf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cpowl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cpowl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cpowl.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* Complex power of long double values.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ long double
+_STD(cpowl) (__complex__ long double x, __complex__ long double c)
+{
+  return __cexpl (c * __clogl (x));
+}
+/* w e a k _ a l i a s  (__cpowl, cpowl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cproj.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cproj.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cproj.c	(revision 2448)
@@ -0,0 +1,55 @@
+/* Compute projection of complex double value to Riemann sphere.
+   Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#define nan(x) __builtin_nan(x)
+
+
+
+__complex__ double
+_STD(cproj) (__complex__ double x)
+{
+  __complex__ double res;
+
+  if (isnan (__real__ x) && isnan (__imag__ x))
+    return x;
+  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      __real__ res = INFINITY;
+      __imag__ res = __copysign (0.0, __imag__ x);
+    }
+  else
+    {
+      double den = __real__ x * __real__ x + __imag__ x * __imag__ x + 1.0;
+
+      __real__ res = (2.0 * __real__ x) / den;
+      __imag__ res = (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__cproj, cproj) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__cproj, __cprojl)
+/* w e a k _ a l i a s  (__cproj, cprojl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cprojf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cprojf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cprojf.c	(revision 2448)
@@ -0,0 +1,50 @@
+/* Compute projection of complex float value to Riemann sphere.
+   Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ float
+_STD(cprojf) (__complex__ float x)
+{
+  __complex__ float res;
+
+  if (isnan (__real__ x) && isnan (__imag__ x))
+    return x;
+  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      __real__ res = INFINITY;
+      __imag__ res = __copysignf (0.0, __imag__ x);
+    }
+  else
+    {
+      float den = __real__ x * __real__ x + __imag__ x * __imag__ x + 1.0;
+
+      __real__ res = (2.0 * __real__ x) / den;
+      __imag__ res = (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+#ifndef __cprojf
+/* w e a k _ a l i a s  (__cprojf, cprojf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_cprojl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_cprojl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_cprojl.c	(revision 2448)
@@ -0,0 +1,49 @@
+/* Compute projection of complex long double value to Riemann sphere.
+   Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ long double
+_STD(cprojl) (__complex__ long double x)
+{
+  __complex__ long double res;
+
+  if (isnan (__real__ x) && isnan (__imag__ x))
+    return x;
+  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      __real__ res = INFINITY;
+      __imag__ res = __copysignl (0.0, __imag__ x);
+    }
+  else
+    {
+      long double den = (__real__ x * __real__ x + __imag__ x * __imag__ x
+			 + 1.0);
+
+      __real__ res = (2.0 * __real__ x) / den;
+      __imag__ res = (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__cprojl, cprojl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csin.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csin.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csin.c	(revision 2448)
@@ -0,0 +1,135 @@
+/* Complex sine function for double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#define __nan(x) __builtin_nan(x)
+
+
+#include "math_private.h"
+
+
+__complex__ double
+_STD(csin) (__complex__ double x)
+{
+  __complex__ double retval;
+  int negate = signbit (__real__ x);
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  __real__ x = fabs (__real__ x);
+
+  if (icls >= FP_ZERO)
+    {
+      /* Imaginary part is finite.  */
+      if (rcls >= FP_ZERO)
+	{
+	  /* Real part is finite.  */
+	  double sinh_val = __ieee754_sinh (__imag__ x);
+	  double cosh_val = __ieee754_cosh (__imag__ x);
+	  double sinix, cosix;
+
+	  __sincos (__real__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * sinix;
+	  __imag__ retval = sinh_val * cosix;
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  if (icls == FP_ZERO)
+	    {
+	      /* Imaginary part is 0.0.  */
+	      __real__ retval = __nan ("");
+	      __imag__ retval = __imag__ x;
+
+#ifdef FE_INVALID
+	      if (rcls == FP_INFINITE)
+		feraiseexcept (FE_INVALID);
+#endif
+	    }
+	  else
+	    {
+	      __real__ retval = __nan ("");
+	      __imag__ retval = __nan ("");
+
+#ifdef FE_INVALID
+	      feraiseexcept (FE_INVALID);
+#endif
+	    }
+	}
+    }
+  else if (icls == FP_INFINITE)
+    {
+      /* Imaginary part is infinite.  */
+      if (rcls == FP_ZERO)
+	{
+	  /* Real part is 0.0.  */
+	  __real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
+	  __imag__ retval = __imag__ x;
+	}
+      else if (rcls > FP_ZERO)
+	{
+	  /* Real part is finite.  */
+	  double sinix, cosix;
+
+	  __sincos (__real__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysign (HUGE_VAL, sinix);
+	  __imag__ retval = __copysign (HUGE_VAL, cosix);
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	  if (signbit (__imag__ x))
+	    __imag__ retval = -__imag__ retval;
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = __nan ("");
+	  __imag__ retval = HUGE_VAL;
+
+#ifdef FE_INVALID
+	  if (rcls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      if (rcls == FP_ZERO)
+	__real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
+      else
+	__real__ retval = __nan ("");
+      __imag__ retval = __nan ("");
+    }
+
+  return retval;
+}
+/* w e a k _ a l i a s  (__csin, csin) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__csin, __csinl)
+/* w e a k _ a l i a s  (__csin, csinl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csinf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csinf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csinf.c	(revision 2448)
@@ -0,0 +1,130 @@
+/* Complex sine function for float.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(csinf) (__complex__ float x)
+{
+  __complex__ float retval;
+  int negate = signbit (__real__ x);
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  __real__ x = fabsf (__real__ x);
+
+  if (icls >= FP_ZERO)
+    {
+      /* Imaginary part is finite.  */
+      if (rcls >= FP_ZERO)
+	{
+	  /* Real part is finite.  */
+	  float sinh_val = __ieee754_sinhf (__imag__ x);
+	  float cosh_val = __ieee754_coshf (__imag__ x);
+	  float sinix, cosix;
+
+	  __sincosf (__real__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * sinix;
+	  __imag__ retval = sinh_val * cosix;
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  if (icls == FP_ZERO)
+	    {
+	      /* Imaginary part is 0.0.  */
+	      __real__ retval = __nanf ("");
+	      __imag__ retval = __imag__ x;
+
+#ifdef FE_INVALID
+	      if (rcls == FP_INFINITE)
+		feraiseexcept (FE_INVALID);
+#endif
+	    }
+	  else
+	    {
+	      __real__ retval = __nanf ("");
+	      __imag__ retval = __nanf ("");
+
+#ifdef FE_INVALID
+	      feraiseexcept (FE_INVALID);
+#endif
+	    }
+	}
+    }
+  else if (icls == FP_INFINITE)
+    {
+      /* Imaginary part is infinite.  */
+      if (rcls == FP_ZERO)
+	{
+	  /* Real part is 0.0.  */
+	  __real__ retval = __copysignf (0.0, negate ? -1.0 : 1.0);
+	  __imag__ retval = __imag__ x;
+	}
+      else if (rcls > FP_ZERO)
+	{
+	  /* Real part is finite.  */
+	  float sinix, cosix;
+
+	  __sincosf (__real__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignf (HUGE_VALF, sinix);
+	  __imag__ retval = __copysignf (HUGE_VALF, cosix);
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	  if (signbit (__imag__ x))
+	    __imag__ retval = -__imag__ retval;
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = __nanf ("");
+	  __imag__ retval = HUGE_VALF;
+
+#ifdef FE_INVALID
+	  if (rcls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      if (rcls == FP_ZERO)
+	__real__ retval = __copysignf (0.0, negate ? -1.0 : 1.0);
+      else
+	__real__ retval = __nanf ("");
+      __imag__ retval = __nanf ("");
+    }
+
+  return retval;
+}
+#ifndef __csinf
+/* w e a k _ a l i a s  (__csinf, csinf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csinh.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csinh.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csinh.c	(revision 2448)
@@ -0,0 +1,130 @@
+/* Complex sine hyperbole function for double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#define __nan(x) __builtin_nan(x)
+
+
+#include "math_private.h"
+
+
+__complex__ double
+_STD(csinh) (__complex__ double x)
+{
+  __complex__ double retval;
+  int negate = signbit (__real__ x);
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  __real__ x = fabs (__real__ x);
+
+  if (rcls >= FP_ZERO)
+    {
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  double sinh_val = __ieee754_sinh (__real__ x);
+	  double cosh_val = __ieee754_cosh (__real__ x);
+	  double sinix, cosix;
+
+	  __sincos (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = sinh_val * cosix;
+	  __imag__ retval = cosh_val * sinix;
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  if (rcls == FP_ZERO)
+	    {
+	      /* Real part is 0.0.  */
+	      __real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
+	      __imag__ retval = __nan ("") + __nan ("");
+
+#ifdef FE_INVALID
+	      if (icls == FP_INFINITE)
+		feraiseexcept (FE_INVALID);
+#endif
+	    }
+	  else
+	    {
+	      __real__ retval = __nan ("");
+	      __imag__ retval = __nan ("");
+
+#ifdef FE_INVALID
+	      feraiseexcept (FE_INVALID);
+#endif
+	    }
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (icls == FP_ZERO)
+	{
+	  /* Imaginary part is 0.0.  */
+	  __real__ retval = negate ? -HUGE_VAL : HUGE_VAL;
+	  __imag__ retval = __imag__ x;
+	}
+      else if (icls > FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  double sinix, cosix;
+
+	  __sincos (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysign (HUGE_VAL, cosix);
+	  __imag__ retval = __copysign (HUGE_VAL, sinix);
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = HUGE_VAL;
+	  __imag__ retval = __nan ("") + __nan ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __real__ retval = __nan ("");
+      __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nan ("");
+    }
+
+  return retval;
+}
+/* w e a k _ a l i a s  (__csinh, csinh) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__csinh, __csinhl)
+/* w e a k _ a l i a s  (__csinh, csinhl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csinhf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csinhf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csinhf.c	(revision 2448)
@@ -0,0 +1,125 @@
+/* Complex sine hyperbole function for float.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(csinhf) (__complex__ float x)
+{
+  __complex__ float retval;
+  int negate = signbit (__real__ x);
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  __real__ x = fabsf (__real__ x);
+
+  if (rcls >= FP_ZERO)
+    {
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  float sinh_val = __ieee754_sinhf (__real__ x);
+	  float cosh_val = __ieee754_coshf (__real__ x);
+	  float sinix, cosix;
+
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = sinh_val * cosix;
+	  __imag__ retval = cosh_val * sinix;
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  if (rcls == FP_ZERO)
+	    {
+	      /* Real part is 0.0.  */
+	      __real__ retval = __copysignf (0.0, negate ? -1.0 : 1.0);
+	      __imag__ retval = __nanf ("") + __nanf ("");
+
+#ifdef FE_INVALID
+	      if (icls == FP_INFINITE)
+		feraiseexcept (FE_INVALID);
+#endif
+	    }
+	  else
+	    {
+	      __real__ retval = __nanf ("");
+	      __imag__ retval = __nanf ("");
+
+#ifdef FE_INVALID
+	      feraiseexcept (FE_INVALID);
+#endif
+	    }
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (icls == FP_ZERO)
+	{
+	  /* Imaginary part is 0.0.  */
+	  __real__ retval = negate ? -HUGE_VALF : HUGE_VALF;
+	  __imag__ retval = __imag__ x;
+	}
+      else if (icls > FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  float sinix, cosix;
+
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignf (HUGE_VALF, cosix);
+	  __imag__ retval = __copysignf (HUGE_VALF, sinix);
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = HUGE_VALF;
+	  __imag__ retval = __nanf ("") + __nanf ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __real__ retval = __nanf ("");
+      __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nanf ("");
+    }
+
+  return retval;
+}
+#ifndef __csinhf
+/* w e a k _ a l i a s  (__csinhf, csinhf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csinhl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csinhl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csinhl.c	(revision 2448)
@@ -0,0 +1,123 @@
+/* Complex sine hyperbole function for long double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(csinhl) (__complex__ long double x)
+{
+  __complex__ long double retval;
+  int negate = signbit (__real__ x);
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  __real__ x = fabsl (__real__ x);
+
+  if (rcls >= FP_ZERO)
+    {
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  long double sinh_val = __ieee754_sinhl (__real__ x);
+	  long double cosh_val = __ieee754_coshl (__real__ x);
+	  long double sinix, cosix;
+
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = sinh_val * cosix;
+	  __imag__ retval = cosh_val * sinix;
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  if (rcls == FP_ZERO)
+	    {
+	      /* Real part is 0.0.  */
+	      __real__ retval = __copysignl (0.0, negate ? -1.0 : 1.0);
+	      __imag__ retval = __nanl ("") + __nanl ("");
+
+#ifdef FE_INVALID
+	      if (icls == FP_INFINITE)
+		feraiseexcept (FE_INVALID);
+#endif
+	    }
+	  else
+	    {
+	      __real__ retval = __nanl ("");
+	      __imag__ retval = __nanl ("");
+
+#ifdef FE_INVALID
+	      feraiseexcept (FE_INVALID);
+#endif
+	    }
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (icls == FP_ZERO)
+	{
+	  /* Imaginary part is 0.0.  */
+	  __real__ retval = negate ? -HUGE_VALL : HUGE_VALL;
+	  __imag__ retval = __imag__ x;
+	}
+      else if (icls > FP_ZERO)
+	{
+	  /* Imaginary part is finite.  */
+	  long double sinix, cosix;
+
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignl (HUGE_VALL, cosix);
+	  __imag__ retval = __copysignl (HUGE_VALL, sinix);
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = HUGE_VALL;
+	  __imag__ retval = __nanl ("") + __nanl ("");
+
+#ifdef FE_INVALID
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      __real__ retval = __nanl ("");
+      __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nanl ("");
+    }
+
+  return retval;
+}
+/* w e a k _ a l i a s  (__csinhl, csinhl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csinl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csinl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csinl.c	(revision 2448)
@@ -0,0 +1,128 @@
+/* Complex sine function for long double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(csinl) (__complex__ long double x)
+{
+  __complex__ long double retval;
+  int negate = signbit (__real__ x);
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  __real__ x = fabsl (__real__ x);
+
+  if (icls >= FP_ZERO)
+    {
+      /* Imaginary part is finite.  */
+      if (rcls >= FP_ZERO)
+	{
+	  /* Real part is finite.  */
+	  long double sinh_val = __ieee754_sinhl (__imag__ x);
+	  long double cosh_val = __ieee754_coshl (__imag__ x);
+	  long double sinix, cosix;
+
+	  __sincosl (__real__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * sinix;
+	  __imag__ retval = sinh_val * cosix;
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else
+	{
+	  if (icls == FP_ZERO)
+	    {
+	      /* Imaginary part is 0.0.  */
+	      __real__ retval = __nanl ("");
+	      __imag__ retval = __imag__ x;
+
+#ifdef FE_INVALID
+	      if (rcls == FP_INFINITE)
+		feraiseexcept (FE_INVALID);
+#endif
+	    }
+	  else
+	    {
+	      __real__ retval = __nanl ("");
+	      __imag__ retval = __nanl ("");
+
+#ifdef FE_INVALID
+	      feraiseexcept (FE_INVALID);
+#endif
+	    }
+	}
+    }
+  else if (icls == FP_INFINITE)
+    {
+      /* Imaginary part is infinite.  */
+      if (rcls == FP_ZERO)
+	{
+	  /* Real part is 0.0.  */
+	  __real__ retval = __copysignl (0.0, negate ? -1.0 : 1.0);
+	  __imag__ retval = __imag__ x;
+	}
+      else if (rcls > FP_ZERO)
+	{
+	  /* Real part is finite.  */
+	  long double sinix, cosix;
+
+	  __sincosl (__real__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignl (HUGE_VALL, sinix);
+	  __imag__ retval = __copysignl (HUGE_VALL, cosix);
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	  if (signbit (__imag__ x))
+	    __imag__ retval = -__imag__ retval;
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = __nanl ("");
+	  __imag__ retval = HUGE_VALL;
+
+#ifdef FE_INVALID
+	  if (rcls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      if (rcls == FP_ZERO)
+	__real__ retval = __copysignl (0.0, negate ? -1.0 : 1.0);
+      else
+	__real__ retval = __nanl ("");
+      __imag__ retval = __nanl ("");
+    }
+
+  return retval;
+}
+/* w e a k _ a l i a s  (__csinl, csinl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csqrt.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csqrt.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csqrt.c	(revision 2448)
@@ -0,0 +1,118 @@
+/* Complex square root of double value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on an algorithm by Stephen L. Moshier <moshier@world.std.com>.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#define __nan(x) __builtin_nan(x)
+
+
+#include "math_private.h"
+
+
+__complex__ double
+_STD(csqrt) (__complex__ double x)
+{
+  __complex__ double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VAL;
+	  __imag__ res = __imag__ x;
+	}
+      else if (rcls == FP_INFINITE)
+	{
+	  if (__real__ x < 0.0)
+	    {
+	      __real__ res = icls == FP_NAN ? __nan ("") : 0;
+	      __imag__ res = __copysign (HUGE_VAL, __imag__ x);
+	    }
+	  else
+	    {
+	      __real__ res = __real__ x;
+	      __imag__ res = (icls == FP_NAN
+			      ? __nan ("") : __copysign (0.0, __imag__ x));
+	    }
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+	}
+    }
+  else
+    {
+      if (icls == FP_ZERO)
+	{
+	  if (__real__ x < 0.0)
+	    {
+	      __real__ res = 0.0;
+	      __imag__ res = __copysign (__ieee754_sqrt (-__real__ x),
+					 __imag__ x);
+	    }
+	  else
+	    {
+	      __real__ res = fabs (__ieee754_sqrt (__real__ x));
+	      __imag__ res = __copysign (0.0, __imag__ x);
+	    }
+	}
+      else if (rcls == FP_ZERO)
+	{
+	  double r = __ieee754_sqrt (0.5 * fabs (__imag__ x));
+
+	  __real__ res = __copysign (r, __imag__ x);
+	  __imag__ res = r;
+	}
+      else
+	{
+	  double d, r, s;
+
+	  d = __ieee754_hypot (__real__ x, __imag__ x);
+	  /* Use the identity   2  Re res  Im res = Im x
+	     to avoid cancellation error in  d +/- Re x.  */
+	  if (__real__ x > 0)
+	    {
+	      r = __ieee754_sqrt (0.5 * d + 0.5 * __real__ x);
+	      s = (0.5 * __imag__ x) / r;
+	    }
+	  else
+	    {
+	      s = __ieee754_sqrt (0.5 * d - 0.5 * __real__ x);
+	      r = fabs ((0.5 * __imag__ x) / s);
+	    }
+
+	  __real__ res = r;
+	  __imag__ res = __copysign (s, __imag__ x);
+	}
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__csqrt, csqrt) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__csqrt, __csqrtl)
+/* w e a k _ a l i a s  (__csqrt, csqrtl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csqrtf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csqrtf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csqrtf.c	(revision 2448)
@@ -0,0 +1,113 @@
+/* Complex square root of float value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on an algorithm by Stephen L. Moshier <moshier@world.std.com>.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(csqrtf) (__complex__ float x)
+{
+  __complex__ float res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VALF;
+	  __imag__ res = __imag__ x;
+	}
+      else if (rcls == FP_INFINITE)
+	{
+	  if (__real__ x < 0.0)
+	    {
+	      __real__ res = icls == FP_NAN ? __nanf ("") : 0;
+	      __imag__ res = __copysignf (HUGE_VALF, __imag__ x);
+	    }
+	  else
+	    {
+	      __real__ res = __real__ x;
+	      __imag__ res = (icls == FP_NAN
+			      ? __nanf ("") : __copysignf (0.0, __imag__ x));
+	    }
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+	}
+    }
+  else
+    {
+      if (icls == FP_ZERO)
+	{
+	  if (__real__ x < 0.0)
+	    {
+	      __real__ res = 0.0;
+	      __imag__ res = __copysignf (__ieee754_sqrtf (-__real__ x),
+					  __imag__ x);
+	    }
+	  else
+	    {
+	      __real__ res = fabsf (__ieee754_sqrtf (__real__ x));
+	      __imag__ res = __copysignf (0.0, __imag__ x);
+	    }
+	}
+      else if (rcls == FP_ZERO)
+	{
+	  float r = __ieee754_sqrtf (0.5 * fabsf (__imag__ x));
+
+	  __real__ res = __copysignf (r, __imag__ x);
+	  __imag__ res = r;
+	}
+      else
+	{
+	  float d, r, s;
+
+	  d = __ieee754_hypotf (__real__ x, __imag__ x);
+	  /* Use the identity   2  Re res  Im res = Im x
+	     to avoid cancellation error in  d +/- Re x.  */
+	  if (__real__ x > 0)
+	    {
+	      r = __ieee754_sqrtf (0.5f * d + 0.5f * __real__ x);
+	      s = (0.5f * __imag__ x) / r;
+	    }
+	  else
+	    {
+	      s = __ieee754_sqrtf (0.5f * d - 0.5f * __real__ x);
+	      r = fabsf ((0.5f * __imag__ x) / s);
+	    }
+
+	  __real__ res = r;
+	  __imag__ res = __copysignf (s, __imag__ x);
+	}
+    }
+
+  return res;
+}
+#ifndef __csqrtf
+/* w e a k _ a l i a s  (__csqrtf, csqrtf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_csqrtl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_csqrtl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_csqrtl.c	(revision 2448)
@@ -0,0 +1,111 @@
+/* Complex square root of long double value.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on an algorithm by Stephen L. Moshier <moshier@world.std.com>.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(csqrtl) (__complex__ long double x)
+{
+  __complex__ long double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = HUGE_VALL;
+	  __imag__ res = __imag__ x;
+	}
+      else if (rcls == FP_INFINITE)
+	{
+	  if (__real__ x < 0.0)
+	    {
+	      __real__ res = icls == FP_NAN ? __nanl ("") : 0;
+	      __imag__ res = __copysignl (HUGE_VALL, __imag__ x);
+	    }
+	  else
+	    {
+	      __real__ res = __real__ x;
+	      __imag__ res = (icls == FP_NAN
+			      ? __nanl ("") : __copysignl (0.0, __imag__ x));
+	    }
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+	}
+    }
+  else
+    {
+      if (icls == FP_ZERO)
+	{
+	  if (__real__ x < 0.0)
+	    {
+	      __real__ res = 0.0;
+	      __imag__ res = __copysignl (__ieee754_sqrtl (-__real__ x),
+					  __imag__ x);
+	    }
+	  else
+	    {
+	      __real__ res = fabsl (__ieee754_sqrtl (__real__ x));
+	      __imag__ res = __copysignl (0.0, __imag__ x);
+	    }
+	}
+      else if (rcls == FP_ZERO)
+	{
+	  long double r = __ieee754_sqrtl (0.5 * fabsl (__imag__ x));
+
+	  __real__ res = __copysignl (r, __imag__ x);
+	  __imag__ res = r;
+	}
+      else
+	{
+	  long double d, r, s;
+
+	  d = __ieee754_hypotl (__real__ x, __imag__ x);
+	  /* Use the identity   2  Re res  Im res = Im x
+	     to avoid cancellation error in  d +/- Re x.  */
+	  if (__real__ x > 0)
+	    {
+	      r = __ieee754_sqrtl (0.5L * d + 0.5L * __real__ x);
+	      s = (0.5L * __imag__ x) / r;
+	    }
+	  else
+	    {
+	      s = __ieee754_sqrtl (0.5L * d - 0.5L * __real__ x);
+	      r = fabsl ((0.5L * __imag__ x) / s);
+	    }
+
+	  __real__ res = r;
+	  __imag__ res = __copysignl (s, __imag__ x);
+	}
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__csqrtl, csqrtl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ctan.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ctan.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ctan.c	(revision 2448)
@@ -0,0 +1,75 @@
+/* Complex tangent function for double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+#define __nan __builtin_nan
+
+__complex__ double
+_STD(ctan) (__complex__ double x)
+{
+  __complex__ double res;
+
+  if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      if (__isinf (__imag__ x))
+	{
+	  __real__ res = __copysign (0.0, __real__ x);
+	  __imag__ res = __copysign (1.0, __imag__ x);
+	}
+      else if (__real__ x == 0.0)
+	{
+	  res = x;
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+
+#ifdef FE_INVALID
+	  if (__isinf (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      double sin2rx, cos2rx;
+      double den;
+
+      __sincos (2.0 * __real__ x, &sin2rx, &cos2rx);
+
+      den = cos2rx + __ieee754_cosh (2.0 * __imag__ x);
+
+      __real__ res = sin2rx / den;
+      __imag__ res = __ieee754_sinh (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__ctan, ctan) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__ctan, __ctanl)
+/* w e a k _ a l i a s  (__ctan, ctanl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ctanf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ctanf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ctanf.c	(revision 2448)
@@ -0,0 +1,73 @@
+/* Complex tangent function for float.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(ctanf) (__complex__ float x)
+{
+  __complex__ float res;
+
+  if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      if (__isinff (__imag__ x))
+	{
+	  __real__ res = __copysignf (0.0, __real__ x);
+	  __imag__ res = __copysignf (1.0, __imag__ x);
+	}
+      else if (__real__ x == 0.0)
+	{
+	  res = x;
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+
+#ifdef FE_INVALID
+	  if (__isinff (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      float sin2rx, cos2rx;
+      float den;
+
+      __sincosf (2.0 * __real__ x, &sin2rx, &cos2rx);
+
+      den = cos2rx + __ieee754_coshf (2.0 * __imag__ x);
+
+      __real__ res = sin2rx / den;
+      __imag__ res = __ieee754_sinhf (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+#ifndef __ctanf
+/* w e a k _ a l i a s  (__ctanf, ctanf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ctanh.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ctanh.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ctanh.c	(revision 2448)
@@ -0,0 +1,76 @@
+/* Complex hyperbole tangent for double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+#define __nan __builtin_nan
+
+
+__complex__ double
+_STD(ctanh) (__complex__ double x)
+{
+  __complex__ double res;
+
+  if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      if (__isinf (__real__ x))
+	{
+	  __real__ res = __copysign (1.0, __real__ x);
+	  __imag__ res = __copysign (0.0, __imag__ x);
+	}
+      else if (__imag__ x == 0.0)
+	{
+	  res = x;
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+
+#ifdef FE_INVALID
+	  if (__isinf (__imag__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      double sin2ix, cos2ix;
+      double den;
+
+      __sincos (2.0 * __imag__ x, &sin2ix, &cos2ix);
+
+      den = (__ieee754_cosh (2.0 * __real__ x) + cos2ix);
+
+      __real__ res = __ieee754_sinh (2.0 * __real__ x) / den;
+      __imag__ res = sin2ix / den;
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__ctanh, ctanh) */
+#ifdef NO_LONG_DOUBLE
+strong_alias (__ctanh, __ctanhl)
+/* w e a k _ a l i a s  (__ctanh, ctanhl) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ctanhf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ctanhf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ctanhf.c	(revision 2448)
@@ -0,0 +1,73 @@
+/* Complex hyperbole tangent for float.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ float
+_STD(ctanhf) (__complex__ float x)
+{
+  __complex__ float res;
+
+  if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      if (__isinff (__real__ x))
+	{
+	  __real__ res = __copysignf (1.0, __real__ x);
+	  __imag__ res = __copysignf (0.0, __imag__ x);
+	}
+      else if (__imag__ x == 0.0)
+	{
+	  res = x;
+	}
+      else
+	{
+	  __real__ res = __nanf ("");
+	  __imag__ res = __nanf ("");
+
+#ifdef FE_INVALID
+	  if (__isinff (__imag__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      float sin2ix, cos2ix;
+      float den;
+
+      __sincosf (2.0 * __imag__ x, &sin2ix, &cos2ix);
+
+      den = (__ieee754_coshf (2.0 * __real__ x) + cos2ix);
+
+      __real__ res = __ieee754_sinhf (2.0 * __real__ x) / den;
+      __imag__ res = sin2ix / den;
+    }
+
+  return res;
+}
+#ifndef __ctanhf
+/* w e a k _ a l i a s  (__ctanhf, ctanhf) */
+#endif
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ctanhl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ctanhl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ctanhl.c	(revision 2448)
@@ -0,0 +1,71 @@
+/* Complex hyperbole tangent for long double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(ctanhl) (__complex__ long double x)
+{
+  __complex__ long double res;
+
+  if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      if (__isinfl (__real__ x))
+	{
+	  __real__ res = __copysignl (1.0, __real__ x);
+	  __imag__ res = __copysignl (0.0, __imag__ x);
+	}
+      else if (__imag__ x == 0.0)
+	{
+	  res = x;
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+
+#ifdef FE_INVALID
+	  if (__isinfl (__imag__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      long double sin2ix, cos2ix;
+      long double den;
+
+      __sincosl (2.0 * __imag__ x, &sin2ix, &cos2ix);
+
+      den = (__ieee754_coshl (2.0 * __real__ x) + cos2ix);
+
+      __real__ res = __ieee754_sinhl (2.0 * __real__ x) / den;
+      __imag__ res = sin2ix / den;
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__ctanhl, ctanhl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_ctanl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_ctanl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_ctanl.c	(revision 2448)
@@ -0,0 +1,71 @@
+/* Complex tangent function for long double.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+
+#include "math_private.h"
+
+
+__complex__ long double
+_STD(ctanl) (__complex__ long double x)
+{
+  __complex__ long double res;
+
+  if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+    {
+      if (__isinfl (__imag__ x))
+	{
+	  __real__ res = __copysignl (0.0, __real__ x);
+	  __imag__ res = __copysignl (1.0, __imag__ x);
+	}
+      else if (__real__ x == 0.0)
+	{
+	  res = x;
+	}
+      else
+	{
+	  __real__ res = __nanl ("");
+	  __imag__ res = __nanl ("");
+
+#ifdef FE_INVALID
+	  if (__isinfl (__real__ x))
+	    feraiseexcept (FE_INVALID);
+#endif
+	}
+    }
+  else
+    {
+      long double sin2rx, cos2rx;
+      long double den;
+
+      __sincosl (2.0 * __real__ x, &sin2rx, &cos2rx);
+
+      den = cos2rx + __ieee754_coshl (2.0 * __imag__ x);
+
+      __real__ res = sin2rx / den;
+      __imag__ res = __ieee754_sinhl (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+/* w e a k _ a l i a s  (__ctanl, ctanl) */
Index: /trunk/libc/src/glibc/sysdeps/generic/s_erfl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/s_erfl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/s_erfl.c	(revision 2448)
@@ -0,0 +1,27 @@
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include <stdio.h>
+#include <errno.h>
+
+long double
+_STD(erfl) (long double x)
+{
+  fputs ("__erfl not implemented\n", stderr);
+  errno = ENOSYS;
+  return 0.0;
+}
+/* w e a k _ a l i a s (__erfl, erfl) */
+
+//stub_warning (erfl)
+
+long double
+_STD(erfcl) (long double x)
+{
+  fputs ("__erfcl not implemented\n", stderr);
+  errno = ENOSYS;
+  return 0.0;
+}
+/* w e a k _ a l i a s (__erfcl, erfcl) */
+
+//stub_warning (erfcl)
+//#include <stub-tag.h>
Index: /trunk/libc/src/glibc/sysdeps/generic/symbol-hacks.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/symbol-hacks.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/symbol-hacks.h	(revision 2448)
@@ -0,0 +1,1 @@
+/* Fortunately nothing to do.  */
Index: /trunk/libc/src/glibc/sysdeps/generic/sysdep.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/sysdep.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/sysdep.h	(revision 2448)
@@ -0,0 +1,135 @@
+/* Generic asm macros used on many machines.
+   Copyright (C) 1991,92,93,96,98,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.  */
+
+#ifndef C_LABEL
+
+/* Define a macro we can use to construct the asm name for a C symbol.  */
+#ifdef	NO_UNDERSCORES
+#ifdef	__STDC__
+#define C_LABEL(name)		name##:
+#else
+#define C_LABEL(name)		name/**/:
+#endif
+#else
+#ifdef	__STDC__
+#define C_LABEL(name)		_##name##:
+#else
+#define C_LABEL(name)		_/**/name/**/:
+#endif
+#endif
+
+#endif
+
+#ifdef __ASSEMBLER__
+/* Mark the end of function named SYM.  This is used on some platforms
+   to generate correct debugging information.  */
+#ifndef END
+#define END(sym)
+#endif
+
+#ifndef JUMPTARGET
+#define JUMPTARGET(sym)		sym
+#endif
+
+/* Makros to generate eh_frame unwind information.  */
+# ifdef HAVE_ASM_CFI_DIRECTIVES
+#  define cfi_startproc			.cfi_startproc
+#  define cfi_endproc			.cfi_endproc
+#  define cfi_def_cfa(reg, off)		.cfi_def_cfa reg, off
+#  define cfi_def_cfa_register(reg)	.cfi_def_cfa_register reg
+#  define cfi_def_cfa_offset(off)	.cfi_def_cfa_offset off
+#  define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
+#  define cfi_offset(reg, off)		.cfi_offset reg, off
+#  define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
+#  define cfi_register(r1, r2)		.cfi_register r1, r2
+#  define cfi_return_column(reg)	.cfi_return_column reg
+#  define cfi_restore(reg)		.cfi_restore reg
+#  define cfi_undefined(reg)		.cfi_undefined reg
+#  define cfi_remember_state		.cfi_remember_state
+#  define cfi_restore_state		.cfi_restore_state
+#  define cfi_window_save		.cfi_window_save
+# else
+#  define cfi_startproc
+#  define cfi_endproc
+#  define cfi_def_cfa(reg, off)
+#  define cfi_def_cfa_register(reg)
+#  define cfi_def_cfa_offset(off)
+#  define cfi_adjust_cfa_offset(off)
+#  define cfi_offset(reg, off)
+#  define cfi_rel_offset(reg, off)
+#  define cfi_register(r1, r2)
+#  define cfi_return_column(reg)
+#  define cfi_restore(reg)
+#  define cfi_undefined(reg)
+#  define cfi_remember_state
+#  define cfi_restore_state
+#  define cfi_window_save
+# endif
+
+#else /* ! ASSEMBLER */
+# ifdef HAVE_ASM_CFI_DIRECTIVES
+#  define CFI_STRINGIFY(Name) CFI_STRINGIFY2 (Name)
+#  define CFI_STRINGIFY2(Name) #Name
+#  define CFI_STARTPROC	".cfi_startproc"
+#  define CFI_ENDPROC	".cfi_endproc"
+#  define CFI_DEF_CFA(reg, off)	\
+   ".cfi_def_cfa " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
+#  define CFI_DEF_CFA_REGISTER(reg) \
+   ".cfi_def_cfa_register " CFI_STRINGIFY(reg)
+#  define CFI_DEF_CFA_OFFSET(off) \
+   ".cfi_def_cfa_offset " CFI_STRINGIFY(off)
+#  define CFI_ADJUST_CFA_OFFSET(off) \
+   ".cfi_adjust_cfa_offset " CFI_STRINGIFY(off)
+#  define CFI_OFFSET(reg, off) \
+   ".cfi_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
+#  define CFI_REL_OFFSET(reg, off) \
+   ".cfi_rel_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
+#  define CFI_REGISTER(r1, r2) \
+   ".cfi_register " CFI_STRINGIFY(r1) "," CFI_STRINGIFY(r2)
+#  define CFI_RETURN_COLUMN(reg) \
+   ".cfi_return_column " CFI_STRINGIFY(reg)
+#  define CFI_RESTORE(reg) \
+   ".cfi_restore " CFI_STRINGIFY(reg)
+#  define CFI_UNDEFINED(reg) \
+   ".cfi_undefined " CFI_STRINGIFY(reg)
+#  define CFI_REMEMBER_STATE \
+   ".cfi_remember_state"
+#  define CFI_RESTORE_STATE \
+   ".cfi_restore_state"
+#  define CFI_WINDOW_SAVE \
+   ".cfi_window_save"
+# else
+#  define CFI_STARTPROC
+#  define CFI_ENDPROC
+#  define CFI_DEF_CFA(reg, off)
+#  define CFI_DEF_CFA_REGISTER(reg)
+#  define CFI_DEF_CFA_OFFSET(off)
+#  define CFI_ADJUST_CFA_OFFSET(off)
+#  define CFI_OFFSET(reg, off)
+#  define CFI_REL_OFFSET(reg, off)
+#  define CFI_REGISTER(r1, r2)
+#  define CFI_RETURN_COLUMN(reg)
+#  define CFI_RESTORE(reg)
+#  define CFI_UNDEFINED(reg)
+#  define CFI_REMEMBER_STATE
+#  define CFI_RESTORE_STATE
+#  define CFI_WINDOW_SAVE
+# endif
+
+#endif /* __ASSEMBLER__ */
Index: /trunk/libc/src/glibc/sysdeps/generic/w_lgammal.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/w_lgammal.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/w_lgammal.c	(revision 2448)
@@ -0,0 +1,59 @@
+/* w_lgammal.c -- long double version of w_lgamma.c.
+ * Conversion to long double by Ulrich Drepper,
+ * Cygnus Support, drepper@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "libc-alias-glibc.h"
+#if defined(LIBM_SCCS) && !defined(lint)
+static char rcsid[] = "$NetBSD: $";
+#endif
+
+/* long double lgammal(long double x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_lgammal_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+	long double __lgammal(long double x)
+#else
+	long double __lgammal(x)
+	long double x;
+#endif
+{
+#if defined _IEEE_LIBM || defined __INNOTEK_LIBC__
+	return __ieee754_lgammal_r(x,&signgam);
+#else
+        long double y;
+	int local_signgam = 0;
+        y = __ieee754_lgammal_r(x,&local_signgam);
+	if (_LIB_VERSION != _ISOC_)
+	  /* ISO C99 does not define the global variable.  */
+	  signgam = local_signgam;
+        if(_LIB_VERSION == _IEEE_) return y;
+        if(!__finitel(y)&&__finitel(x)) {
+            if(__floorl(x)==x&&x<=0.0)
+                return __kernel_standard(x,x,215); /* lgamma pole */
+            else
+                return __kernel_standard(x,x,214); /* lgamma overflow */
+        } else
+            return y;
+#endif
+}
+/* w e a k _alias (__lgammal, lgammal) */
+strong_alias (_std_lgammal, _std_gammal)
+/* w e a k _alias (__gammal, gammal) */
Index: /trunk/libc/src/glibc/sysdeps/generic/w_tgammaf.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/w_tgammaf.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/w_tgammaf.c	(revision 2448)
@@ -0,0 +1,55 @@
+/* w_gammaf.c -- float version of w_gamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#if defined(LIBM_SCCS) && !defined(lint)
+static char rcsid[] = "$NetBSD: w_gammaf.c,v 1.4 1995/11/20 22:06:48 jtc Exp $";
+#endif
+
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+	float _STD(tgammaf)(float x)
+#else
+	float _STD(tgammaf)(x)
+	float x;
+#endif
+{
+        float y;
+	int local_signgam;
+	y = __ieee754_gammaf_r(x,&local_signgam);
+	if (local_signgam < 0) y = -y;
+#if defined _IEEE_LIBM || defined __INNOTEK_LIBC__
+	return y;
+#else
+	if(_LIB_VERSION == _IEEE_) return y;
+
+	if(!__finitef(y)&&__finitef(x)) {
+	  if (x == (float)0.0)
+	    /* tgammaf pole */
+	    return (float)__kernel_standard((double)x,(double)x,150);
+	  else if(__floorf(x)==x&&x<(float)0.0)
+	    /* tgammaf domain */
+	    return (float)__kernel_standard((double)x,(double)x,141);
+	  else
+	    /* tgammaf overflow */
+	    return (float)__kernel_standard((double)x,(double)x,140);
+	}
+	return y;
+#endif
+}
+weak_alias (__tgammaf, tgammaf)
Index: /trunk/libc/src/glibc/sysdeps/generic/w_tgammal.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/generic/w_tgammal.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/generic/w_tgammal.c	(revision 2448)
@@ -0,0 +1,57 @@
+/* w_gammal.c -- long double version of w_gamma.c.
+ * Conversion to long double by Ulrich Drepper,
+ * Cygnus Support, drepper@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#if defined(LIBM_SCCS) && !defined(lint)
+static char rcsid[] = "$NetBSD: $";
+#endif
+
+/* long double gammal(double x)
+ * Return the Gamma function of x.
+ */
+
+#include "libc-alias-glibc.h"
+#define __ieee754_gammal_r gammal_r
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+	long double _STD(tgammal)(long double x)
+#else
+	long double _STD(tgammal)(x)
+	long double x;
+#endif
+{
+        long double y;
+	int local_signgam;
+	y = __ieee754_gammal_r(x,&local_signgam);
+	if (local_signgam < 0) y = -y;
+#if defined _IEEE_LIBM || defined __INNOTEK_LIBC__
+	return y;
+#else
+	if(_LIB_VERSION == _IEEE_) return y;
+
+	if(!__finitel(y)&&__finitel(x)) {
+	  if(x==0.0)
+	    return __kernel_standard(x,x,250); /* tgamma pole */
+	  else if(__floorl(x)==x&&x<0.0)
+	    return __kernel_standard(x,x,241); /* tgamma domain */
+	  else
+	    return __kernel_standard(x,x,240); /* tgamma overflow */
+	}
+	return y;
+#endif
+}
+/*  w e a k _ a l i a s (__tgammal, tgammal) */
Index: /trunk/libc/src/glibc/sysdeps/i386/asm-syntax.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/asm-syntax.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/asm-syntax.h	(revision 2448)
@@ -0,0 +1,41 @@
+/* Definitions for x86 syntax variations.
+   Copyright (C) 1992, 1994, 1995, 1997, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.  Its master source is NOT part of
+   the C library, however.  The master source lives in the GNU MP 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 ALIGN
+#if defined NOLOG_ALIGN || defined HAVE_ELF
+# define ALIGN(log) .align 1<<log
+#else
+# define ALIGN(log) .align log
+#endif
+
+#undef L
+#ifdef __ELF__
+# ifdef __STDC__
+#  define L(body) .L##body
+# else
+#  define L(body) .L/**/body
+# endif
+#else
+# ifdef __STDC__
+#  define L(body) L##body
+# else
+#  define L(body) L/**/body
+# endif
+#endif
Index: /trunk/libc/src/glibc/sysdeps/i386/bp-asm.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/bp-asm.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/bp-asm.h	(revision 2448)
@@ -0,0 +1,144 @@
+/* Bounded-pointer definitions for x86 assembler.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Greg McGary <greg@mcgary.org>
+   This file is part of the GNU C Library.  Its master source is NOT part of
+   the C library, however.  The master source lives in the GNU MP 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.  */
+
+#ifndef _bp_asm_h_
+# define _bp_asm_h_ 1
+
+# if __ASSEMBLER__
+
+#  if __BOUNDED_POINTERS__
+
+/* Bounded pointers occupy three words.  */
+#   define PTR_SIZE 12
+/* Bounded pointer return values are passed back through a hidden
+   argument that points to caller-allocate space.  The hidden arg
+   occupies one word on the stack.  */
+#   define RTN_SIZE 4
+/* Although the caller pushes the hidden arg, the callee is
+   responsible for popping it.  */
+#   define RET_PTR ret $RTN_SIZE
+/* Maintain frame pointer chain in leaf assembler functions for the benefit
+   of debugging stack traces when bounds violations occur.  */
+#   define ENTER pushl %ebp; movl %esp, %ebp
+#   define LEAVE movl %ebp, %esp; popl %ebp
+/* Stack space overhead of procedure-call linkage: return address and
+   frame pointer.  */
+#   define LINKAGE 8
+/* Stack offset of return address after calling ENTER.  */
+#   define PCOFF 4
+
+/* Int 5 is the "bound range" exception also raised by the "bound"
+   instruction.  */
+#   define BOUNDS_VIOLATED int $5
+
+#   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)	\
+	cmpl 4+BP_MEM, VAL_REG;			\
+	jae 0f; /* continue if value >= low */	\
+	BOUNDS_VIOLATED;			\
+    0:
+
+#   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)	\
+	cmpl 8+BP_MEM, VAL_REG;				\
+	Jcc 0f; /* continue if value < high */		\
+	BOUNDS_VIOLATED;				\
+    0:
+
+#   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)	\
+	cmpl 4+BP_MEM, VAL_REG;			\
+	jb 1f; /* die if value < low */		\
+    	cmpl 8+BP_MEM, VAL_REG;			\
+	jb 0f; /* continue if value < high */	\
+    1:	BOUNDS_VIOLATED;			\
+    0:
+
+#   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)	\
+	CHECK_BOUNDS_LOW(VAL_REG, BP_MEM);			\
+	addl LENGTH, VAL_REG;					\
+    	cmpl 8+BP_MEM, VAL_REG;					\
+	jbe 0f; /* continue if value <= high */			\
+	BOUNDS_VIOLATED;					\
+    0:	subl LENGTH, VAL_REG /* restore value */
+
+/* Take bounds from BP_MEM and affix them to the pointer
+   value in %eax, stuffing all into memory at RTN(%esp).
+   Use %edx as a scratch register.  */
+
+#   define RETURN_BOUNDED_POINTER(BP_MEM)	\
+	movl RTN(%esp), %edx;			\
+	movl %eax, 0(%edx);			\
+	movl 4+BP_MEM, %eax;			\
+	movl %eax, 4(%edx);			\
+	movl 8+BP_MEM, %eax;			\
+	movl %eax, 8(%edx)
+
+#   define RETURN_NULL_BOUNDED_POINTER		\
+	movl RTN(%esp), %edx;			\
+	movl %eax, 0(%edx);			\
+	movl %eax, 4(%edx);			\
+	movl %eax, 8(%edx)
+
+/* The caller of __errno_location is responsible for allocating space
+   for the three-word BP return-value and passing pushing its address
+   as an implicit first argument.  */
+#   define PUSH_ERRNO_LOCATION_RETURN		\
+	subl $8, %esp;				\
+	subl $4, %esp;				\
+	pushl %esp
+
+/* __errno_location is responsible for popping the implicit first
+   argument, but we must pop the space for the BP itself.  We also
+   dereference the return value in order to dig out the pointer value.  */
+#   define POP_ERRNO_LOCATION_RETURN		\
+	popl %eax;				\
+	addl $8, %esp
+
+#  else /* !__BOUNDED_POINTERS__ */
+
+/* Unbounded pointers occupy one word.  */
+#   define PTR_SIZE 4
+/* Unbounded pointer return values are passed back in the register %eax.  */
+#   define RTN_SIZE 0
+/* Use simple return instruction for unbounded pointer values.  */
+#   define RET_PTR ret
+/* Don't maintain frame pointer chain for leaf assembler functions.  */
+#   define ENTER
+#   define LEAVE
+/* Stack space overhead of procedure-call linkage: return address only.  */
+#   define LINKAGE 4
+/* Stack offset of return address after calling ENTER.  */
+#   define PCOFF 0
+
+#   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)
+#   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)
+#   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)
+#   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)
+#   define RETURN_BOUNDED_POINTER(BP_MEM)
+
+#   define RETURN_NULL_BOUNDED_POINTER
+
+#   define PUSH_ERRNO_LOCATION_RETURN
+#   define POP_ERRNO_LOCATION_RETURN
+
+#  endif /* !__BOUNDED_POINTERS__ */
+
+# endif /* __ASSEMBLER__ */
+
+#endif /* _bp_asm_h_ */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_atan2l.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_atan2l.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_atan2l.c	(revision 2448)
@@ -0,0 +1,20 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include <math_private.h>
+
+long double
+_STD(atan2l) (long double y, long double x)
+{
+  long double res;
+
+  asm ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)");
+
+  return res;
+}
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_atanhl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_atanhl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_atanhl.S	(revision 2448)
@@ -0,0 +1,122 @@
+/* ix87 specific implementation of arctanh function.
+   Copyright (C) 1996, 1999 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.  */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+
+	.align ALIGNARG(4)
+	/* Please note that we use double values for 0.5 and 1.0.  These
+	   numbers have exact representations and so we don't get accuracy
+	   problems.  The advantage is that the code is simpler.  */
+	ASM_TYPE_DIRECTIVE(half,@object)
+half:	.double 0.5
+	ASM_SIZE_DIRECTIVE(half)
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	/* It is not important that this constant is precise.  It is only
+	   a value which is known to be on the safe side for using the
+	   fyl2xp1 instruction.  */
+	ASM_TYPE_DIRECTIVE(limit,@object)
+limit:	.double 0.29
+	ASM_SIZE_DIRECTIVE(limit)
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(ln2_2,@object)
+ln2_2:	.tfloat 0.3465735902799726547086160
+	ASM_SIZE_DIRECTIVE(ln2_2)
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%edx)
+#else
+#define MO(op) op
+#endif
+
+	.text
+ENTRY(_STD(atanhl))
+	movl	12(%esp), %ecx
+
+	movl	%ecx, %eax
+	andl	$0x7fff, %eax
+	cmpl	$0x7fff, %eax
+	je	5f
+7:
+
+#ifdef PIC
+	LOAD_PIC_REG (dx)
+#endif
+
+	andl	$0x8000, %ecx	// ECX == 0 iff X >= 0
+
+	fldt	MO(ln2_2)	// 0.5*ln2
+	xorl	%ecx, 12(%esp)
+	fldt	4(%esp)		// |x| : 0.5*ln2
+	fcoml	MO(half)	// |x| : 0.5*ln2
+	fld	%st(0)		// |x| : |x| : 0.5*ln2
+	fnstsw			// |x| : |x| : 0.5*ln2
+	sahf
+	jae	2f
+	fadd	%st, %st(1)	// |x| : 2*|x| : 0.5*ln2
+	fld	%st		// |x| : |x| : 2*|x| : 0.5*ln2
+	fsubrl	MO(one)		// 1-|x| : |x| : 2*|x| : 0.5*ln2
+	fxch			// |x| : 1-|x| : 2*|x| : 0.5*ln2
+	fmul	%st(2)		// 2*|x|^2 : 1-|x| : 2*|x| : 0.5*ln2
+	fdivp			// (2*|x|^2)/(1-|x|) : 2*|x| : 0.5*ln2
+	faddp			// 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2
+	fcoml	MO(limit)	// 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2
+	fnstsw			// 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2
+	sahf
+	jae	4f
+	fyl2xp1			// 0.5*ln2*ld(1+2*|x|+(2*|x|^2)/(1-|x|))
+	jecxz	3f
+	fchs			// 0.5*ln2*ld(1+2*x+(2*x^2)/(1-x))
+3:	ret
+
+	.align ALIGNARG(4)
+4:	faddl	MO(one)		// 1+2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2
+	fyl2x			// 0.5*ln2*ld(1+2*|x|+(2*|x|^2)/(1-|x|))
+	jecxz	3f
+	fchs			// 0.5*ln2*ld(1+2*x+(2*x^2)/(1-x))
+3:	ret
+
+	.align ALIGNARG(4)
+2:	faddl	MO(one)		// 1+|x| : |x| : 0.5*ln2
+	fxch			// |x| : 1+|x| : 0.5*ln2
+	fsubrl	MO(one)		// 1-|x| : 1+|x| : 0.5*ln2
+	fdivrp			// (1+|x|)/(1-|x|) : 0.5*ln2
+	fyl2x			// 0.5*ln2*ld((1+|x|)/(1-|x|))
+	jecxz	3f
+	fchs			// 0.5*ln2*ld((1+x)/(1-x))
+3:	ret
+
+	// x == NaN or ±Inf
+5:	cmpl	$0x80000000, 8(%esp)
+	ja	6f
+	cmpl	$0, 4(%esp)
+	je	7b
+6:	fldt	4(%esp)
+	ret
+END(_STD(atanhl))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10.S	(revision 2448)
@@ -0,0 +1,40 @@
+/*
+ * Written by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+/* 10^x = 2^(x * log2(10)) */
+ENTRY(_STD(exp10))
+	fldl	4(%esp)
+/* I added the following ugly construct because exp(+-Inf) resulted
+   in NaN.  The ugliness results from the bright minds at Intel.
+   For the i686 the code can be written better.
+   -- drepper@cygnus.com.  */
+	fxam				/* Is NaN or +-Inf?  */
+	fstsw	%ax
+	movb	$0x45, %dh
+	andb	%ah, %dh
+	cmpb	$0x05, %dh
+	je	1f			/* Is +-Inf, jump.  */
+	fldl2t
+	fmulp				/* x * log2(10) */
+	fld	%st
+	frndint				/* int(x * log2(10)) */
+	fsubr	%st,%st(1)		/* fract(x * log2(10)) */
+	fxch
+	f2xm1				/* 2^(fract(x * log2(10))) - 1 */
+	fld1
+	faddp				/* 2^(fract(x * log2(10))) */
+	fscale				/* e^x */
+	fstp	%st(1)
+	ret
+
+1:	testl	$0x200, %eax		/* Test sign.  */
+	jz	2f			/* If positive, jump.  */
+	fstp	%st
+	fldz				/* Set result to 0.  */
+2:	ret
+END (_STD(exp10))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10f.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10f.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10f.S	(revision 2448)
@@ -0,0 +1,41 @@
+/*
+ * Written by Ulrich Drepper.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+
+/* e^x = 2^(x * log2(10)) */
+ENTRY(_STD(exp10f))
+	flds	4(%esp)
+/* I added the following ugly construct because exp(+-Inf) resulted
+   in NaN.  The ugliness results from the bright minds at Intel.
+   For the i686 the code can be written better.
+   -- drepper@cygnus.com.  */
+	fxam				/* Is NaN or +-Inf?  */
+	fstsw	%ax
+	movb	$0x45, %dh
+	andb	%ah, %dh
+	cmpb	$0x05, %dh
+	je	1f			/* Is +-Inf, jump.  */
+	fldl2t
+	fmulp				/* x * log2(10) */
+	fld	%st
+	frndint				/* int(x * log2(10)) */
+	fsubr	%st,%st(1)		/* fract(x * log2(10)) */
+	fxch
+	f2xm1				/* 2^(fract(x * log2(10))) - 1 */
+	fld1
+	faddp				/* 2^(fract(x * log2(10))) */
+	fscale				/* e^x */
+	fstp	%st(1)
+	ret
+
+1:	testl	$0x200, %eax		/* Test sign.  */
+	jz	2f			/* If positive, jump.  */
+	fstp	%st
+	fldz				/* Set result to 0.  */
+2:	ret
+END (_STD(exp10f))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10l.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10l.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp10l.S	(revision 2448)
@@ -0,0 +1,40 @@
+/*
+ * Written by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+/* e^x = 2^(x * log2l(10)) */
+ENTRY(_STD(exp10l))
+	fldt	4(%esp)
+/* I added the following ugly construct because expl(+-Inf) resulted
+   in NaN.  The ugliness results from the bright minds at Intel.
+   For the i686 the code can be written better.
+   -- drepper@cygnus.com.  */
+	fxam				/* Is NaN or +-Inf?  */
+	fstsw	%ax
+	movb	$0x45, %dh
+	andb	%ah, %dh
+	cmpb	$0x05, %dh
+	je	1f			/* Is +-Inf, jump.  */
+	fldl2t
+	fmulp				/* x * log2(10) */
+	fld	%st
+	frndint				/* int(x * log2(10)) */
+	fsubr	%st,%st(1)		/* fract(x * log2(10)) */
+	fxch
+	f2xm1				/* 2^(fract(x * log2(10))) - 1 */
+	fld1
+	faddp				/* 2^(fract(x * log2(10))) */
+	fscale				/* e^x */
+	fstp	%st(1)
+	ret
+
+1:	testl	$0x200, %eax		/* Test sign.  */
+	jz	2f			/* If positive, jump.  */
+	fstp	%st
+	fldz				/* Set result to 0.  */
+2:	ret
+END (_STD(exp10l))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp2l.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp2l.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_exp2l.S	(revision 2448)
@@ -0,0 +1,39 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Adapted for exp2 by Ulrich Drepper <drepper@cygnus.com>.
+ * Public domain.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+ENTRY(_STD(exp2l))
+	fldt	4(%esp)
+/* I added the following ugly construct because exp(+-Inf) resulted
+   in NaN.  The ugliness results from the bright minds at Intel.
+   For the i686 the code can be written better.
+   -- drepper@cygnus.com.  */
+	fxam				/* Is NaN or +-Inf?  */
+	fstsw	%ax
+	movb	$0x45, %dh
+	andb	%ah, %dh
+	cmpb	$0x05, %dh
+	je	1f			/* Is +-Inf, jump.  */
+	fld	%st
+	frndint				/* int(x) */
+	fsubr	%st,%st(1)		/* fract(x) */
+	fxch
+	f2xm1				/* 2^(fract(x)) - 1 */
+	fld1
+	faddp				/* 2^(fract(x)) */
+	fscale				/* e^x */
+	fstp	%st(1)
+	ret
+
+1:	testl	$0x200, %eax		/* Test sign.  */
+	jz	2f			/* If positive, jump.  */
+	fstp	%st
+	fldz				/* Set result to 0.  */
+2:	ret
+END (_STD(exp2l))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_fmodl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_fmodl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_fmodl.c	(revision 2448)
@@ -0,0 +1,24 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include <math_private.h>
+
+long double
+_STD(fmodl) (long double x, long double y)
+{
+  long double res;
+
+  asm ("1:\tfprem\n"
+       "fstsw   %%ax\n"
+       "sahf\n"
+       "jp      1b\n"
+       "fstp    %%st(1)"
+       : "=t" (res) : "0" (x), "u" (y) : "ax", "st(1)");
+  return res;
+}
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log10l.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log10l.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log10l.S	(revision 2448)
@@ -0,0 +1,70 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ *
+ * Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+//RCSID("$NetBSD: $")
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	/* It is not important that this constant is precise.  It is only
+	   a value which is known to be on the safe side for using the
+	   fyl2xp1 instruction.  */
+	ASM_TYPE_DIRECTIVE(limit,@object)
+limit:	.double 0.29
+	ASM_SIZE_DIRECTIVE(limit)
+
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%edx)
+#else
+#define MO(op) op
+#endif
+
+	.text
+ENTRY(_STD(log10l))
+	fldlg2			// log10(2)
+	fldt	4(%esp)		// x : log10(2)
+#ifdef PIC
+	LOAD_PIC_REG (dx)
+#endif
+	fxam
+	fnstsw
+	fld	%st		// x : x : log10(2)
+	sahf
+	jc	3f		// in case x is NaN or ±Inf
+4:	fsubl	MO(one)		// x-1 : x : log10(2)
+	fld	%st		// x-1 : x-1 : x : log10(2)
+	fabs			// |x-1| : x-1 : x : log10(2)
+	fcompl	MO(limit)	// x-1 : x : log10(2)
+	fnstsw			// x-1 : x : log10(2)
+	andb	$0x45, %ah
+	jz	2f
+	fstp	%st(1)		// x-1 : log10(2)
+	fyl2xp1			// log10(x)
+	ret
+
+2:	fstp	%st(0)		// x : log10(2)
+	fyl2x			// log10(x)
+	ret
+
+3:	jp	4b		// in case x is ±Inf
+	fstp	%st(1)
+	fstp	%st(1)
+	ret
+END(_STD(log10l))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2.S	(revision 2448)
@@ -0,0 +1,67 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Adapted for use as log2 by Ulrich Drepper <drepper@cygnus.com>.
+ * Public domain.
+ *
+ * Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	/* It is not important that this constant is precise.  It is only
+	   a value which is known to be on the safe side for using the
+	   fyl2xp1 instruction.  */
+	ASM_TYPE_DIRECTIVE(limit,@object)
+limit:	.double 0.29
+	ASM_SIZE_DIRECTIVE(limit)
+
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%edx)
+#else
+#define MO(op) op
+#endif
+
+	.text
+ENTRY(_STD(log2))
+#ifdef PIC
+	LOAD_PIC_REG (dx)
+#endif
+	fldl	MO(one)
+	fldl	4(%esp)		// x : 1
+	fxam
+	fnstsw
+	fld	%st		// x : x : 1
+	sahf
+	jc	3f		// in case x is NaN or ±Inf
+4:	fsub	%st(2), %st	// x-1 : x : 1
+	fld	%st		// x-1 : x-1 : x : 1
+	fabs			// |x-1| : x-1 : x : 1
+	fcompl	MO(limit)	// x-1 : x : 1
+	fnstsw			// x-1 : x : 1
+	andb	$0x45, %ah
+	jz	2f
+	fstp	%st(1)		// x-1 : 1
+	fyl2xp1			// log(x)
+	ret
+
+2:	fstp	%st(0)		// x : 1
+	fyl2x			// log(x)
+	ret
+
+3:	jp	4b		// in case x is ±Inf
+	fstp	%st(1)
+	fstp	%st(1)
+	ret
+END (_STD(log2))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2f.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2f.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2f.S	(revision 2448)
@@ -0,0 +1,67 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Adapted for use as log2 by Ulrich Drepper <drepper@cygnus.com>.
+ * Public domain.
+ *
+ * Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	/* It is not important that this constant is precise.  It is only
+	   a value which is known to be on the safe side for using the
+	   fyl2xp1 instruction.  */
+	ASM_TYPE_DIRECTIVE(limit,@object)
+limit:	.double 0.29
+	ASM_SIZE_DIRECTIVE(limit)
+
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%edx)
+#else
+#define MO(op) op
+#endif
+
+	.text
+ENTRY(_STD(log2f))
+#ifdef PIC
+	LOAD_PIC_REG (dx)
+#endif
+	fldl	MO(one)
+	flds	4(%esp)		// x : 1
+	fxam
+	fnstsw
+	fld	%st		// x : x : 1
+	sahf
+	jc	3f		// in case x is NaN or ±Inf
+4:	fsub	%st(2), %st	// x-1 : x : 1
+	fld	%st		// x-1 : x-1 : x : 1
+	fabs			// |x-1| : x-1 : x : 1
+	fcompl	MO(limit)	// x-1 : x : 1
+	fnstsw			// x-1 : x : 1
+	andb	$0x45, %ah
+	jz	2f
+	fstp	%st(1)		// x-1 : 1
+	fyl2xp1			// log(x)
+	ret
+
+2:	fstp	%st(0)		// x : 1
+	fyl2x			// log(x)
+	ret
+
+3:	jp	4b		// in case x is ±Inf
+	fstp	%st(1)
+	fstp	%st(1)
+	ret
+END (_STD(log2f))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2l.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2l.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_log2l.S	(revision 2448)
@@ -0,0 +1,67 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Adapted for use as log2 by Ulrich Drepper <drepper@cygnus.com>.
+ * Public domain.
+ *
+ * Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	/* It is not important that this constant is precise.  It is only
+	   a value which is known to be on the safe side for using the
+	   fyl2xp1 instruction.  */
+	ASM_TYPE_DIRECTIVE(limit,@object)
+limit:	.double 0.29
+	ASM_SIZE_DIRECTIVE(limit)
+
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%edx)
+#else
+#define MO(op) op
+#endif
+
+	.text
+ENTRY(_STD(log2l))
+#ifdef PIC
+	LOAD_PIC_REG (dx)
+#endif
+	fldl	MO(one)
+	fldt	4(%esp)		// x : 1
+	fxam
+	fnstsw
+	fld	%st		// x : x : 1
+	sahf
+	jc	3f		// in case x is NaN or ±Inf
+4:	fsub	%st(2), %st	// x-1 : x : 1
+	fld	%st		// x-1 : x-1 : x : 1
+	fabs			// |x-1| : x-1 : x : 1
+	fcompl	MO(limit)	// x-1 : x : 1
+	fnstsw			// x-1 : x : 1
+	andb	$0x45, %ah
+	jz	2f
+	fstp	%st(1)		// x-1 : 1
+	fyl2xp1			// log(x)
+	ret
+
+2:	fstp	%st(0)		// x : 1
+	fyl2x			// log(x)
+	ret
+
+3:	jp	4b		// in case x is ±Inf
+	fstp	%st(1)
+	fstp	%st(1)
+	ret
+END (_STD(log2l))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_logl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_logl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_logl.S	(revision 2448)
@@ -0,0 +1,60 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+//RCSID("$NetBSD: $")
+
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	/* It is not important that this constant is precise.  It is only
+	   a value which is known to be on the safe side for using the
+	   fyl2xp1 instruction.  */
+	ASM_TYPE_DIRECTIVE(limit,@object)
+limit:	.double 0.29
+	ASM_SIZE_DIRECTIVE(limit)
+
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%edx)
+#else
+#define MO(op) op
+#endif
+
+	.text
+ENTRY(_STD(logl))
+	fldln2			// log(2)
+	fldt	4(%esp)		// x : log(2)
+#ifdef PIC
+	LOAD_PIC_REG (dx)
+#endif
+	fld	%st		// x : x : log(2)
+	fsubl	MO(one)		// x-1 : x : log(2)
+	fld	%st		// x-1 : x-1 : x : log(2)
+	fabs			// |x-1| : x-1 : x : log(2)
+	fcompl	MO(limit)	// x-1 : x : log(2)
+	fnstsw			// x-1 : x : log(2)
+	andb	$0x45, %ah
+	jz	2f
+	fstp	%st(1)		// x-1 : log(2)
+	fyl2xp1			// log(x)
+	ret
+
+2:	fstp	%st(0)		// x : log(2)
+	fyl2x			// log(x)
+	ret
+END (_STD(logl))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_powl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_powl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_powl.S	(revision 2448)
@@ -0,0 +1,362 @@
+/* ix87 specific implementation of pow function.
+   Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2005
+   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.  */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(infinity,@object)
+inf_zero:
+infinity:
+	.byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
+	ASM_SIZE_DIRECTIVE(infinity)
+	ASM_TYPE_DIRECTIVE(zero,@object)
+zero:	.double 0.0
+	ASM_SIZE_DIRECTIVE(zero)
+	ASM_TYPE_DIRECTIVE(minf_mzero,@object)
+minf_mzero:
+minfinity:
+	.byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
+mzero:
+	.byte 0, 0, 0, 0, 0, 0, 0, 0x80
+	ASM_SIZE_DIRECTIVE(minf_mzero)
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	ASM_TYPE_DIRECTIVE(limit,@object)
+limit:	.double 0.29
+	ASM_SIZE_DIRECTIVE(limit)
+	ASM_TYPE_DIRECTIVE(p63,@object)
+p63:	.byte 0, 0, 0, 0, 0, 0, 0xe0, 0x43
+	ASM_SIZE_DIRECTIVE(p63)
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%ecx)
+#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
+#else
+#define MO(op) op
+#define MOX(op,x,f) op(,x,f)
+#endif
+
+	.text
+ENTRY(_STD(powl))
+	fldt	16(%esp)	// y
+	fxam
+
+#ifdef	PIC
+	LOAD_PIC_REG (cx)
+#endif
+
+	fnstsw
+	movb	%ah, %dl
+	andb	$0x45, %ah
+	cmpb	$0x40, %ah	// is y == 0 ?
+	je	11f
+
+	cmpb	$0x05, %ah	// is y == ±inf ?
+	je	12f
+
+	cmpb	$0x01, %ah	// is y == NaN ?
+	je	30f
+
+	fldt	4(%esp)		// x : y
+
+	subl	$8,%esp
+	cfi_adjust_cfa_offset (8)
+
+	fxam
+	fnstsw
+	movb	%ah, %dh
+	andb	$0x45, %ah
+	cmpb	$0x40, %ah
+	je	20f		// x is ±0
+
+	cmpb	$0x05, %ah
+	je	15f		// x is ±inf
+
+	fxch			// y : x
+
+	/* fistpll raises invalid exception for |y| >= 1L<<63.  */
+	fld	%st		// y : y : x
+	fabs			// |y| : y : x
+	fcompl	MO(p63)		// y : x
+	fnstsw
+	sahf
+	jnc	2f
+
+	/* First see whether `y' is a natural number.  In this case we
+	   can use a more precise algorithm.  */
+	fld	%st		// y : y : x
+	fistpll	(%esp)		// y : x
+	fildll	(%esp)		// int(y) : y : x
+	fucomp	%st(1)		// y : x
+	fnstsw
+	sahf
+	jne	2f
+
+	/* OK, we have an integer value for y.  */
+	popl	%eax
+	cfi_adjust_cfa_offset (-4)
+	popl	%edx
+	cfi_adjust_cfa_offset (-4)
+	orl	$0, %edx
+	fstp	%st(0)		// x
+	jns	4f		// y >= 0, jump
+	fdivrl	MO(one)		// 1/x		(now referred to as x)
+	negl	%eax
+	adcl	$0, %edx
+	negl	%edx
+4:	fldl	MO(one)		// 1 : x
+	fxch
+
+6:	shrdl	$1, %edx, %eax
+	jnc	5f
+	fxch
+	fmul	%st(1)		// x : ST*x
+	fxch
+5:	fmul	%st(0), %st	// x*x : ST*x
+	shrl	$1, %edx
+	movl	%eax, %ecx
+	orl	%edx, %ecx
+	jnz	6b
+	fstp	%st(0)		// ST*x
+	ret
+
+	/* y is ±NAN */
+30:	fldt	4(%esp)		// x : y
+	fldl	MO(one)		// 1.0 : x : y
+	fucomp	%st(1)		// x : y
+	fnstsw
+	sahf
+	je	31f
+	fxch			// y : x
+31:	fstp	%st(1)
+	ret
+
+	cfi_adjust_cfa_offset (8)
+	.align ALIGNARG(4)
+2:	/* y is a real number.  */
+	fxch			// x : y
+	fldl	MO(one)		// 1.0 : x : y
+	fld	%st(1)		// x : 1.0 : x : y
+	fsub	%st(1)		// x-1 : 1.0 : x : y
+	fabs			// |x-1| : 1.0 : x : y
+	fcompl	MO(limit)	// 1.0 : x : y
+	fnstsw
+	fxch			// x : 1.0 : y
+	sahf
+	ja	7f
+	fsub	%st(1)		// x-1 : 1.0 : y
+	fyl2xp1			// log2(x) : y
+	jmp	8f
+
+7:	fyl2x			// log2(x) : y
+8:	fmul	%st(1)		// y*log2(x) : y
+	fxam
+	fnstsw
+	andb	$0x45, %ah
+	cmpb	$0x05, %ah	// is y*log2(x) == ±inf ?
+	je	28f
+	fst	%st(1)		// y*log2(x) : y*log2(x)
+	frndint			// int(y*log2(x)) : y*log2(x)
+	fsubr	%st, %st(1)	// int(y*log2(x)) : fract(y*log2(x))
+	fxch			// fract(y*log2(x)) : int(y*log2(x))
+	f2xm1			// 2^fract(y*log2(x))-1 : int(y*log2(x))
+	faddl	MO(one)		// 2^fract(y*log2(x)) : int(y*log2(x))
+	fscale			// 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x))
+	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
+	fstp	%st(1)		// 2^fract(y*log2(x))*2^int(y*log2(x))
+	ret
+
+	cfi_adjust_cfa_offset (8)
+28:	fstp	%st(1)		// y*log2(x)
+	fldl	MO(one)		// 1 : y*log2(x)
+	fscale			// 2^(y*log2(x)) : y*log2(x)
+	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
+	fstp	%st(1)		// 2^(y*log2(x))
+	ret
+
+	// pow(x,±0) = 1
+	.align ALIGNARG(4)
+11:	fstp	%st(0)		// pop y
+	fldl	MO(one)
+	ret
+
+	// y == ±inf
+	.align ALIGNARG(4)
+12:	fstp	%st(0)		// pop y
+	fldt	4(%esp)		// x
+	fabs
+	fcompl	MO(one)		// < 1, == 1, or > 1
+	fnstsw
+	andb	$0x45, %ah
+	cmpb	$0x45, %ah
+	je	13f		// jump if x is NaN
+
+	cmpb	$0x40, %ah
+	je	14f		// jump if |x| == 1
+
+	shlb	$1, %ah
+	xorb	%ah, %dl
+	andl	$2, %edx
+	fldl	MOX(inf_zero, %edx, 4)
+	ret
+
+	.align ALIGNARG(4)
+14:	fldl	MO(one)
+	ret
+
+	.align ALIGNARG(4)
+13:	fldt	4(%esp)		// load x == NaN
+	ret
+
+	cfi_adjust_cfa_offset (8)
+	.align ALIGNARG(4)
+	// x is ±inf
+15:	fstp	%st(0)		// y
+	testb	$2, %dh
+	jz	16f		// jump if x == +inf
+
+	// We must find out whether y is an odd integer.
+	fld	%st		// y : y
+	fistpll	(%esp)		// y
+	fildll	(%esp)		// int(y) : y
+	fucompp			// <empty>
+	fnstsw
+	sahf
+	jne	17f
+
+	// OK, the value is an integer, but is it odd?
+	popl	%eax
+	cfi_adjust_cfa_offset (-4)
+	popl	%edx
+	cfi_adjust_cfa_offset (-4)
+	andb	$1, %al
+	jz	18f		// jump if not odd
+	// It's an odd integer.
+	shrl	$31, %edx
+	fldl	MOX(minf_mzero, %edx, 8)
+	ret
+
+	cfi_adjust_cfa_offset (8)
+	.align ALIGNARG(4)
+16:	fcompl	MO(zero)
+	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
+	fnstsw
+	shrl	$5, %eax
+	andl	$8, %eax
+	fldl	MOX(inf_zero, %eax, 1)
+	ret
+
+	cfi_adjust_cfa_offset (8)
+	.align ALIGNARG(4)
+17:	shll	$30, %edx	// sign bit for y in right position
+	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
+18:	shrl	$31, %edx
+	fldl	MOX(inf_zero, %edx, 8)
+	ret
+
+	cfi_adjust_cfa_offset (8)
+	.align ALIGNARG(4)
+	// x is ±0
+20:	fstp	%st(0)		// y
+	testb	$2, %dl
+	jz	21f		// y > 0
+
+	// x is ±0 and y is < 0.  We must find out whether y is an odd integer.
+	testb	$2, %dh
+	jz	25f
+
+	fld	%st		// y : y
+	fistpll	(%esp)		// y
+	fildll	(%esp)		// int(y) : y
+	fucompp			// <empty>
+	fnstsw
+	sahf
+	jne	26f
+
+	// OK, the value is an integer, but is it odd?
+	popl	%eax
+	cfi_adjust_cfa_offset (-4)
+	popl	%edx
+	cfi_adjust_cfa_offset (-4)
+	andb	$1, %al
+	jz	27f		// jump if not odd
+	// It's an odd integer.
+	// Raise divide-by-zero exception and get minus infinity value.
+	fldl	MO(one)
+	fdivl	MO(zero)
+	fchs
+	ret
+
+	cfi_adjust_cfa_offset (8)
+25:	fstp	%st(0)
+26:	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
+27:	// Raise divide-by-zero exception and get infinity value.
+	fldl	MO(one)
+	fdivl	MO(zero)
+	ret
+
+	cfi_adjust_cfa_offset (8)
+	.align ALIGNARG(4)
+	// x is ±0 and y is > 0.  We must find out whether y is an odd integer.
+21:	testb	$2, %dh
+	jz	22f
+
+	fld	%st		// y : y
+	fistpll	(%esp)		// y
+	fildll	(%esp)		// int(y) : y
+	fucompp			// <empty>
+	fnstsw
+	sahf
+	jne	23f
+
+	// OK, the value is an integer, but is it odd?
+	popl	%eax
+	cfi_adjust_cfa_offset (-4)
+	popl	%edx
+	cfi_adjust_cfa_offset (-4)
+	andb	$1, %al
+	jz	24f		// jump if not odd
+	// It's an odd integer.
+	fldl	MO(mzero)
+	ret
+
+	cfi_adjust_cfa_offset (8)
+22:	fstp	%st(0)
+23:	addl	$8, %esp	// Don't use 2 x pop
+	cfi_adjust_cfa_offset (-8)
+24:	fldl	MO(zero)
+	ret
+
+END(_STD(powl))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_remainderl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_remainderl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_remainderl.S	(revision 2448)
@@ -0,0 +1,23 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+//RCSID("$NetBSD: $")
+
+ENTRY(_STD(remainderl))
+	fldt	16(%esp)
+	fldt	4(%esp)
+1:	fprem1
+	fstsw	%ax
+	sahf
+	jp	1b
+	fstp	%st(1)
+	ret
+END (_STD(remainderl))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_scalbl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_scalbl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_scalbl.S	(revision 2448)
@@ -0,0 +1,106 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ *
+ * Correct handling of y==-inf <drepper@gnu>
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+//RCSID("$NetBSD: $")
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(zero_nan,@object)
+zero_nan:
+	.double 0.0
+nan:	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
+minus_zero:
+	.byte 0, 0, 0, 0, 0, 0, 0, 0x80
+	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
+	ASM_SIZE_DIRECTIVE(zero_nan)
+
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%ecx)
+#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
+#else
+#define MO(op) op
+#define MOX(op,x,f) op(,x,f)
+#endif
+
+	.text
+ENTRY(_STD(scalbl))
+	fldt	16(%esp)
+	fxam
+	fnstsw
+	fldt	4(%esp)
+	andl	$0x4700, %eax
+	cmpl	$0x0700, %eax
+	je	1f
+	andl	$0x4500, %eax
+	cmpl	$0x0100, %eax
+	je	2f
+	fxam
+	fnstsw
+	andl	$0x4500, %eax
+	cmpl	$0x0100, %eax
+	je	3f
+	fld	%st(1)
+	frndint
+	fcomp	%st(2)
+	fnstsw
+	sahf
+	jne	4f
+	fscale
+	fstp	%st(1)
+	ret
+
+	/* y is -inf */
+1:	fxam
+#ifdef  PIC
+	LOAD_PIC_REG (cx)
+#endif
+	fnstsw
+	movl	12(%esp), %edx
+	shrl	$5, %eax
+	fstp	%st
+	fstp	%st
+	andl	$0x8000, %edx
+	andl	$8, %eax
+	jnz	4f
+	shrl	$11, %edx
+	addl	%edx, %eax
+	fldl	MOX(zero_nan, %eax, 1)
+	ret
+
+	/* The result is NaN, but we must not raise an exception.
+	   So use a variable.  */
+2:	fstp	%st
+	fstp	%st
+#ifdef  PIC
+	LOAD_PIC_REG (cx)
+#endif
+	fldl	MO(nan)
+	ret
+
+	/* The first parameter is a NaN.  Return it.  */
+3:	fstp	%st(1)
+	ret
+
+	/* Return NaN and raise the invalid exception.  */
+4:	fstp	%st
+	fstp	%st
+	fldz
+	fdiv	%st
+	ret
+END(_STD(scalbl))
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/e_sqrtl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/e_sqrtl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/e_sqrtl.c	(revision 2448)
@@ -0,0 +1,20 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include <math_private.h>
+
+long double
+_STD(sqrtl) (long double x)
+{
+  long double res;
+
+  asm ("fsqrt" : "=t" (res) : "0" (x));
+
+  return res;
+}
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_asinhl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_asinhl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_asinhl.S	(revision 2448)
@@ -0,0 +1,145 @@
+/* ix87 specific implementation of arcsinh.
+   Copyright (C) 1996, 1997, 2005 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.  */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(huge,@object)
+huge:	.tfloat 1e+4930
+	ASM_SIZE_DIRECTIVE(huge)
+	.align ALIGNARG(4)
+	/* Please note that we use double value for 1.0.  This number
+	   has an exact representation and so we don't get accuracy
+	   problems.  The advantage is that the code is simpler.  */
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	/* It is not important that this constant is precise.  It is only
+	   a value which is known to be on the safe side for using the
+	   fyl2xp1 instruction.  */
+	ASM_TYPE_DIRECTIVE(limit,@object)
+limit:	.double 0.29
+	ASM_SIZE_DIRECTIVE(limit)
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%edx)
+#else
+#define MO(op) op
+#endif
+
+	.text
+ENTRY(_STD(asinhl))
+	movl	12(%esp), %ecx
+	movl	$0x7fff, %eax
+	andl	%ecx, %eax
+	andl	$0x8000, %ecx
+	movl	%eax, %edx
+	orl	$0xffff8000, %edx
+	incl	%edx
+	jz	7f			// x in ±Inf or NaN
+	xorl	%ecx, 12(%esp)
+	fldt	4(%esp)			// |x|
+	cmpl	$0x3fde, %eax
+	jb	2f			// |x| < 2^-34
+	fldln2				// log(2) : |x|
+	cmpl	$0x4020, %eax
+	fxch				// |x| : log(2)
+	ja	3f			// |x| > 2^34
+#ifdef	PIC
+	LOAD_PIC_REG (dx)
+#endif
+	cmpl	$0x4000, %eax
+	ja	5f			// |x| > 2
+
+	// 2^-34 <= |x| <= 2 => y = sign(x)*log1p(|x|+|x|^2/(1+sqrt(1+|x|^2)))
+	fld	%st			// |x| : |x| : log(2)
+	fmul	%st(1)			// |x|^2 : |x| : log(2)
+	fld	%st			// |x|^2 : |x|^2 : |x| : log(2)
+	faddl	MO(one)			// 1+|x|^2 : |x|^2 : |x| : log(2)
+	fsqrt				// sqrt(1+|x|^2) : |x|^2 : |x| : log(2)
+	faddl	MO(one)			// 1+sqrt(1+|x|^2) : |x|^2 : |x| : log(2)
+	fdivrp				// |x|^2/(1+sqrt(1+|x|^2)) : |x| : log(2)
+	faddp				// |x|+|x|^2/(1+sqrt(1+|x|^2)) : log(2)
+	fcoml	MO(limit)
+	fnstsw
+	sahf
+	ja	6f
+	fyl2xp1
+	jecxz	4f
+	fchs
+4:	ret
+
+7:	fldt	4(%esp)
+	ret
+
+6:	faddl	MO(one)
+	fyl2x
+	jecxz	4f
+	fchs
+4:	ret
+
+	// |x| < 2^-34 => y = x (inexact iff |x| != 0.0)
+	.align ALIGNARG(4)
+2:
+#ifdef	PIC
+	LOAD_PIC_REG (dx)
+#endif
+	jecxz	4f
+	fchs				// x
+4:	fld	%st			// x : x
+	fldt	MO(huge)		// huge : x : x
+	faddp				// huge+x : x
+	fstp	%st(0)			// x
+	ret
+
+	// |x| > 2^34 => y = sign(x) * (log(|x|) + log(2))
+	.align ALIGNARG(4)
+3:	fyl2x				// log(|x|)
+	fldln2				// log(2) : log(|x|)
+	faddp				// log(|x|)+log(2)
+	jecxz	4f
+	fchs
+4:	ret
+
+	// |x| > 2 => y = sign(x) * log(2*|x| + 1/(|x|+sqrt(x*x+1)))
+	.align ALIGNARG(4)
+5:	fld	%st			// |x| : |x| : log(2)
+	fadd	%st, %st(1)		// |x| : 2*|x| : log(2)
+	fld	%st			// |x| : |x| : 2*|x| : log(2)
+	fmul	%st(1)			// |x|^2 : |x| : 2*|x| : log(2)
+	faddl	MO(one)			// 1+|x|^2 : |x| : 2*|x| : log(2)
+	fsqrt				// sqrt(1+|x|^2) : |x| : 2*|x| : log(2)
+	faddp				// |x|+sqrt(1+|x|^2) : 2*|x| : log(2)
+	fdivrl	MO(one)			// 1/(|x|+sqrt(1+|x|^2)) : 2*|x| : log(2)
+	faddp				// 2*|x|+1/(|x|+sqrt(1+|x|^2)) : log(2)
+	fyl2x				// log(2*|x|+1/(|x|+sqrt(1+|x|^2)))
+	jecxz	4f
+	fchs
+4:	ret
+END(_STD(asinhl))
+/* w e a k _ a l i a s  (__asinhl, asinhl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_atanl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_atanl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_atanl.c	(revision 2448)
@@ -0,0 +1,24 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include <math_private.h>
+
+long double
+_STD(atanl) (long double x)
+{
+  long double res;
+
+  asm ("fld1\n"
+       "fpatan"
+       : "=t" (res) : "0" (x));
+
+  return res;
+}
+
+/*  w e a k _ a l i a s (__atanl, atanl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_cexp.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_cexp.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_cexp.S	(revision 2448)
@@ -0,0 +1,257 @@
+/* ix87 specific implementation of complex exponential function for double.
+   Copyright (C) 1997, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <sysdep.h>
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(huge_nan_null_null,@object)
+huge_nan_null_null:
+	.byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
+	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
+	.double	0.0
+zero:	.double	0.0
+infinity:
+	.byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
+	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
+	.double 0.0
+	.byte 0, 0, 0, 0, 0, 0, 0, 0x80
+	ASM_SIZE_DIRECTIVE(huge_nan_null_null)
+
+	ASM_TYPE_DIRECTIVE(twopi,@object)
+twopi:
+	.byte 0x35, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0xf, 0xc9, 0x1, 0x40
+	.byte 0, 0, 0, 0, 0, 0
+	ASM_SIZE_DIRECTIVE(twopi)
+
+	ASM_TYPE_DIRECTIVE(l2e,@object)
+l2e:
+	.byte 0xbc, 0xf0, 0x17, 0x5c, 0x29, 0x3b, 0xaa, 0xb8, 0xff, 0x3f
+	.byte 0, 0, 0, 0, 0, 0
+	ASM_SIZE_DIRECTIVE(l2e)
+
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%ecx)
+#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
+#else
+#define MO(op) op
+#define MOX(op,x,f) op(,x,f)
+#endif
+
+	.text
+ENTRY(_STD(cexp))
+	fldl	8(%esp)			/* x */
+	fxam
+	fnstsw
+	fldl	16(%esp)		/* y : x */
+#ifdef  PIC
+	LOAD_PIC_REG (cx)
+#endif
+	movb	%ah, %dh
+	andb	$0x45, %ah
+	cmpb	$0x05, %ah
+	je	1f			/* Jump if real part is +-Inf */
+	cmpb	$0x01, %ah
+	je	2f			/* Jump if real part is NaN */
+
+	fxam				/* y : x */
+	fnstsw
+	/* If the imaginary part is not finite we return NaN+i NaN, as
+	   for the case when the real part is NaN.  A test for +-Inf and
+	   NaN would be necessary.  But since we know the stack register
+	   we applied `fxam' to is not empty we can simply use one test.
+	   Check your FPU manual for more information.  */
+	andb	$0x01, %ah
+	cmpb	$0x01, %ah
+	je	20f
+
+	/* We have finite numbers in the real and imaginary part.  Do
+	   the real work now.  */
+	fxch			/* x : y */
+	fldt	MO(l2e)		/* log2(e) : x : y */
+	fmulp			/* x * log2(e) : y */
+	fld	%st		/* x * log2(e) : x * log2(e) : y */
+	frndint			/* int(x * log2(e)) : x * log2(e) : y */
+	fsubr	%st, %st(1)	/* int(x * log2(e)) : frac(x * log2(e)) : y */
+	fxch			/* frac(x * log2(e)) : int(x * log2(e)) : y */
+	f2xm1			/* 2^frac(x * log2(e))-1 : int(x * log2(e)) : y */
+	faddl	MO(one)		/* 2^frac(x * log2(e)) : int(x * log2(e)) : y */
+	fscale			/* e^x : int(x * log2(e)) : y */
+	fst	%st(1)		/* e^x : e^x : y */
+	fxch	%st(2)		/* y : e^x : e^x */
+	fsincos			/* cos(y) : sin(y) : e^x : e^x */
+	fnstsw
+	testl	$0x400, %eax
+	jnz	7f
+	fmulp	%st, %st(3)	/* sin(y) : e^x : e^x * cos(y) */
+	fmulp	%st, %st(1)	/* e^x * sin(y) : e^x * cos(y) */
+	movl	4(%esp), %eax		/* Pointer to memory for result.  */
+	fstpl	8(%eax)
+	fstpl	(%eax)
+	ret	$4
+
+	/* We have to reduce the argument to fsincos.  */
+	.align ALIGNARG(4)
+7:	fldt	MO(twopi)	/* 2*pi : y : e^x : e^x */
+	fxch			/* y : 2*pi : e^x : e^x */
+8:	fprem1			/* y%(2*pi) : 2*pi : e^x : e^x */
+	fnstsw
+	testl	$0x400, %eax
+	jnz	8b
+	fstp	%st(1)		/* y%(2*pi) : e^x : e^x */
+	fsincos			/* cos(y) : sin(y) : e^x : e^x */
+	fmulp	%st, %st(3)
+	fmulp	%st, %st(1)
+	movl	4(%esp), %eax		/* Pointer to memory for result.  */
+	fstpl	8(%eax)
+	fstpl	(%eax)
+	ret	$4
+
+	/* The real part is +-inf.  We must make further differences.  */
+	.align ALIGNARG(4)
+1:	fxam			/* y : x */
+	fnstsw
+	movb	%ah, %dl
+	testb	$0x01, %ah	/* See above why 0x01 is usable here.  */
+	jne	3f
+
+
+	/* The real part is +-Inf and the imaginary part is finite.  */
+	andl	$0x245, %edx
+	cmpb	$0x40, %dl	/* Imaginary part == 0?  */
+	je	4f		/* Yes ->  */
+
+	fxch			/* x : y */
+	shrl	$5, %edx
+	fstp	%st(0)		/* y */ /* Drop the real part.  */
+	andl	$16, %edx	/* This puts the sign bit of the real part
+				   in bit 4.  So we can use it to index a
+				   small array to select 0 or Inf.  */
+	fsincos			/* cos(y) : sin(y) */
+	fnstsw
+	testl	$0x0400, %eax
+	jnz	5f
+	fldl	MOX(huge_nan_null_null,%edx,1)
+	movl	4(%esp), %edx		/* Pointer to memory for result.  */
+	fstl	8(%edx)
+	fstpl	(%edx)
+	ftst
+	fnstsw
+	shll	$23, %eax
+	andl	$0x80000000, %eax
+	orl	%eax, 4(%edx)
+	fstp	%st(0)
+	ftst
+	fnstsw
+	shll	$23, %eax
+	andl	$0x80000000, %eax
+	orl	%eax, 12(%edx)
+	fstp	%st(0)
+	ret	$4
+	/* We must reduce the argument to fsincos.  */
+	.align ALIGNARG(4)
+5:	fldt	MO(twopi)
+	fxch
+6:	fprem1
+	fnstsw
+	testl	$0x400, %eax
+	jnz	6b
+	fstp	%st(1)
+	fsincos
+	fldl	MOX(huge_nan_null_null,%edx,1)
+	movl	4(%esp), %edx		/* Pointer to memory for result.  */
+	fstl	8(%edx)
+	fstpl	(%edx)
+	ftst
+	fnstsw
+	shll	$23, %eax
+	andl	$0x80000000, %eax
+	orl	%eax, 4(%edx)
+	fstp	%st(0)
+	ftst
+	fnstsw
+	shll	$23, %eax
+	andl	$0x80000000, %eax
+	orl	%eax, 12(%edx)
+	fstp	%st(0)
+	ret	$4
+
+	/* The real part is +-Inf and the imaginary part is +-0.  So return
+	   +-Inf+-0i.  */
+	.align ALIGNARG(4)
+4:	movl	4(%esp), %eax		/* Pointer to memory for result.  */
+	fstpl	8(%eax)
+	shrl	$5, %edx
+	fstp	%st(0)
+	andl	$16, %edx
+	fldl	MOX(huge_nan_null_null,%edx,1)
+	fstpl	(%eax)
+	ret	$4
+
+	/* The real part is +-Inf, the imaginary is also is not finite.  */
+	.align ALIGNARG(4)
+3:	fstp	%st(0)
+	fstp	%st(0)		/* <empty> */
+	andb	$0x45, %ah
+	andb	$0x47, %dh
+	xorb	%dh, %ah
+	jnz	30f
+	fldl	MO(infinity)	/* Raise invalid exception.  */
+	fmull	MO(zero)
+	fstp	%st(0)
+30:	movl	%edx, %eax
+	shrl	$5, %edx
+	shll	$4, %eax
+	andl	$16, %edx
+	andl	$32, %eax
+	orl	%eax, %edx
+	movl	4(%esp), %eax		/* Pointer to memory for result.  */
+
+	fldl	MOX(huge_nan_null_null,%edx,1)
+	fldl	MOX(huge_nan_null_null+8,%edx,1)
+	fxch
+	fstpl	(%eax)
+	fstpl	8(%eax)
+	ret	$4
+
+	/* The real part is NaN.  */
+	.align ALIGNARG(4)
+20:	fldl	MO(infinity)		/* Raise invalid exception.  */
+	fmull	MO(zero)
+	fstp	%st(0)
+2:	fstp	%st(0)
+	fstp	%st(0)
+	movl	4(%esp), %eax		/* Pointer to memory for result.  */
+	fldl	MO(huge_nan_null_null+8)
+	fstl	(%eax)
+	fstpl	8(%eax)
+	ret	$4
+
+END(_STD(cexp))
+/* w e a k _ a l i a s (__cexp, cexp) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_expm1l.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_expm1l.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_expm1l.S	(revision 2448)
@@ -0,0 +1,89 @@
+/* ix87 specific implementation of exp(x)-1.
+   Copyright (C) 1996, 1997, 2002, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   Based on code by John C. Bowman <bowman@ipp-garching.mpg.de>.
+   Corrections by H.J. Lu (hjl@gnu.ai.mit.edu), 1997.
+
+   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.  */
+
+	/* Using: e^x - 1 = 2^(x * log2(e)) - 1 */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+	.align ALIGNARG(4)
+	ASM_TYPE_DIRECTIVE(minus1,@object)
+minus1:	.double -1.0
+	ASM_SIZE_DIRECTIVE(minus1)
+	ASM_TYPE_DIRECTIVE(one,@object)
+one:	.double 1.0
+	ASM_SIZE_DIRECTIVE(one)
+	ASM_TYPE_DIRECTIVE(l2e,@object)
+l2e:	.tfloat 1.442695040888963407359924681002
+	ASM_SIZE_DIRECTIVE(l2e)
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%edx)
+#else
+#define MO(op) op
+#endif
+
+	.text
+ENTRY(_STD(expm1l))
+	fldt	4(%esp)		// x
+	fxam			// Is NaN or +-Inf?
+	fstsw	%ax
+	movb	$0x45, %ch
+	andb	%ah, %ch
+	cmpb	$0x40, %ch
+	je	3f		// If +-0, jump.
+#ifdef	PIC
+	LOAD_PIC_REG (dx)
+#endif
+	cmpb	$0x05, %ch
+	je	2f		// If +-Inf, jump.
+
+	fldt	MO(l2e)		// log2(e) : x
+	fmulp			// log2(e)*x
+	fld	%st		// log2(e)*x : log2(e)*x
+	frndint			// int(log2(e)*x) : log2(e)*x
+	fsubr	%st, %st(1)	// int(log2(e)*x) : fract(log2(e)*x)
+	fxch			// fract(log2(e)*x) : int(log2(e)*x)
+	f2xm1			// 2^fract(log2(e)*x)-1 : int(log2(e)*x)
+	fscale			// 2^(log2(e)*x)-2^int(log2(e)*x) : int(log2(e)*x)
+	fxch			// int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
+	fldl	MO(one)		// 1 : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
+	fscale			// 2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
+	fsubrl	MO(one)		// 1-2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
+	fstp	%st(1)		// 1-2^int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
+	fsubrp	%st, %st(1)	// 2^(log2(e)*x)
+	ret
+
+2:	testl	$0x200, %eax	// Test sign.
+	jz	3f		// If positive, jump.
+	fstp	%st
+	fldl	MO(minus1)	// Set result to -1.0.
+3:	ret
+END(_STD(expm1l))
+/*libm_hidden_def(__expm1l) */
+/* w  e a k _ a l i a s  (__expm1l, expm1l) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_llrintl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_llrintl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_llrintl.S	(revision 2448)
@@ -0,0 +1,37 @@
+/* Round argument to nearest integral value according to current rounding
+   direction.
+   Copyright (C) 1997, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <sysdep.h>
+
+	.text
+ENTRY(_STD(llrintl))
+	fldt	4(%esp)
+	subl	$8, %esp
+	cfi_adjust_cfa_offset (8)
+	fistpll	(%esp)
+	fwait
+	popl	%eax
+	cfi_adjust_cfa_offset (-4)
+	popl	%edx
+	cfi_adjust_cfa_offset (-4)
+	ret
+END(_STD(llrintl))
+/* w e a k _ a l i a s  (__llrintl, llrintl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_log1pl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_log1pl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_log1pl.S	(revision 2448)
@@ -0,0 +1,78 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ *
+ * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+//RCSID("$NetBSD: s_log1p.S,v 1.7 1995/05/09 00:10:58 jtc Exp $")
+
+#ifdef __ELF__
+	.section .rodata
+#else
+	.text
+#endif
+	.align ALIGNARG(4)
+	/* The fyl2xp1 can only be used for values in
+		-1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2
+	   0.29 is a safe value.
+	*/
+limit:	.tfloat 0.29
+	/* Please note:	 we use a double value here.  Since 1.0 has
+	   an exact representation this does not effect the accuracy
+	   but it helps to optimize the code.  */
+one:	.double 1.0
+
+/*
+ * Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29,
+ * otherwise fyl2x with the needed extra computation.
+ */
+	.text
+ENTRY(_STD(log1pl))
+	fldln2
+
+	fldt	4(%esp)
+
+#ifdef PIC
+	LOAD_PIC_REG (dx)
+#endif
+
+	fxam
+	fnstsw
+	fld	%st
+	sahf
+	jc	3f		// in case x is NaN or ±Inf
+4:
+	fabs
+#ifdef PIC
+	fldt	limit@GOTOFF(%edx)
+#else
+	fldt	limit
+#endif
+	fcompp
+	fnstsw
+	sahf
+	jnc	2f
+
+#ifdef PIC
+	faddl	one@GOTOFF(%edx)
+#else
+	faddl	one
+#endif
+	fyl2x
+	ret
+
+2:	fyl2xp1
+	ret
+
+3:	jp	4b		// in case x is ±Inf
+	fstp	%st(1)
+	fstp	%st(1)
+	ret
+
+END (_STD(log1pl))
+/* w e a k _ a l i a s (__log1pl, log1pl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_logbl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_logbl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_logbl.c	(revision 2448)
@@ -0,0 +1,21 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Changes for long double by Ulrich Drepper <drepper@cygnus.com>
+ * Public domain.
+ */
+
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include <math_private.h>
+
+long double
+_STD(logbl) (long double x)
+{
+  long double res;
+
+  asm ("fxtract\n"
+       "fstp	%%st" : "=t" (res) : "0" (x));
+  return res;
+}
+
+/*  w e a k _ a l i a s (__logbl, logbl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_lrintl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_lrintl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_lrintl.S	(revision 2448)
@@ -0,0 +1,35 @@
+/* Round argument to nearest integral value according to current rounding
+   direction.
+   Copyright (C) 1997, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <sysdep.h>
+
+	.text
+ENTRY(_STD(lrintl))
+	fldt	4(%esp)
+	subl	$4, %esp
+	cfi_adjust_cfa_offset (4)
+	fistpl	(%esp)
+	fwait
+	popl	%eax
+	cfi_adjust_cfa_offset (-4)
+	ret
+END(_STD(lrintl))
+/* w e a k _ a l i a s  (__lrintl, lrintl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_nearbyintl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_nearbyintl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_nearbyintl.S	(revision 2448)
@@ -0,0 +1,31 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+/* Adapted for use as nearbyint by Ulrich Drepper <drepper@cygnus.com>.  */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+
+ENTRY(_STD(nearbyintl))
+	fldt	4(%esp)
+	pushl	%eax
+	cfi_adjust_cfa_offset (4)
+	pushl	%ecx
+	cfi_adjust_cfa_offset (4)
+	fnstcw	(%esp)
+	movl	(%esp), %eax
+	orl	$0x20, %eax
+	movl	%eax, 4(%esp)
+	fldcw	4(%esp)
+	frndint
+	fclex
+	fldcw	(%esp)
+	popl	%ecx
+	cfi_adjust_cfa_offset (-4)
+	popl	%eax
+	cfi_adjust_cfa_offset (-4)
+	ret
+END (_STD(nearbyintl))
+/*  w e a k _ a l i a s (__nearbyintl, nearbyintl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_remquol.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_remquol.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_remquol.S	(revision 2448)
@@ -0,0 +1,52 @@
+/*
+ * Written by Ulrich Drepper <drepper@cygnus.com>.
+ * Based on e_remainder by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+//#include <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+#define PARMS	LINKAGE		/* no space for saved regs */
+#define DVDND	PARMS
+#define DVSOR	DVDND+12
+#define QUOP	DVSOR+12
+
+	.text
+ENTRY (BP_SYM (_STD(remquol)))
+	ENTER
+
+	fldt	DVSOR(%esp)
+	fldt	DVDND(%esp)
+1:	fprem1
+	fstsw	%ax
+	sahf
+	jp	1b
+	fstp	%st(1)
+	/* Compute the congruent of the quotient.  */
+	movl	%eax, %ecx
+	shrl	$8, %eax
+	shrl	$12, %ecx
+	andl	$4, %ecx
+	andl	$3, %eax
+	orl	%eax, %ecx
+	leal	(%ecx,%ecx,2),%ecx
+	movl	$0xef2a60, %eax
+	shrl	%cl, %eax
+	andl	$7, %eax
+	movl	QUOP(%esp), %ecx
+	CHECK_BOUNDS_BOTH_WIDE (%ecx, QUOP(%esp), $4)
+	movl	DVDND+8(%esp), %edx
+	xorl	DVSOR+8(%esp), %edx
+	testl	$0x8000, %edx
+	jz	1f
+	negl	%eax
+1:	movl	%eax, (%ecx)
+
+	LEAVE
+	ret
+END (BP_SYM (_STD(remquol)))
+/*  w e a k _ a l i a s (BP_SYM (__remquol), BP_SYM (remquol)) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_rintl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_rintl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_rintl.c	(revision 2448)
@@ -0,0 +1,20 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Changes for long double by Ulrich Drepper <drepper@cygnus.com>
+ * Public domain.
+ */
+
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include <math_private.h>
+
+long double
+_STD(rintl) (long double x)
+{
+  long double res;
+
+  asm ("frndint" : "=t" (res) : "0" (x));
+  return res;
+}
+
+/*  w e a k _ a l i a s (__rintl, rintl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_significandl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_significandl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_significandl.c	(revision 2448)
@@ -0,0 +1,21 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Changes for long double by Ulrich Drepper <drepper@cygnus.com>
+ * Public domain.
+ */
+
+#include "libc-alias-glibc.h"
+#include <math.h>
+#include <math_private.h>
+
+long double
+_STD(significandl) (long double x)
+{
+  long double res;
+
+  asm ("fxtract\n"
+       "fstp	%%st(1)" : "=t" (res) : "0" (x));
+  return res;
+}
+
+/*  w e a k _alias (__significandl, significandl) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincos.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincos.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincos.S	(revision 2448)
@@ -0,0 +1,67 @@
+/* Compute sine and cosine of argument.
+   Copyright (C) 1997, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+#define PARMS	LINKAGE		/* no space for saved regs */
+#define ANGLE	PARMS
+#define SINP	ANGLE+8
+#define COSP	SINP+PTR_SIZE
+
+	.text
+ENTRY (BP_SYM (_STD(sincos)))
+	ENTER
+
+	fldl	ANGLE(%esp)
+	fsincos
+	movl	SINP(%esp), %ecx
+	CHECK_BOUNDS_BOTH_WIDE (%ecx, SINP(%esp), $8)
+	movl	COSP(%esp), %edx
+	CHECK_BOUNDS_BOTH_WIDE (%edx, COSP(%esp), $8)
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	1f
+	fstpl	(%edx)
+	fstpl	(%ecx)
+
+	LEAVE
+	ret
+
+	.align ALIGNARG(4)
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	2b
+	fstp	%st(1)
+	fsincos
+	fstpl	(%edx)
+	fstpl	(%ecx)
+
+	LEAVE
+	ret
+END (BP_SYM (_STD(sincos)))
+/*  w e a k _ a l i a s  (BP_SYM (__sincos), BP_SYM (sincos)) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincosf.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincosf.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincosf.S	(revision 2448)
@@ -0,0 +1,67 @@
+/* Compute sine and cosine of argument.
+   Copyright (C) 1997, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+#define PARMS	LINKAGE		/* no space for saved regs */
+#define ANGLE	PARMS
+#define SINP	ANGLE+4
+#define COSP	SINP+PTR_SIZE
+
+	.text
+ENTRY (BP_SYM (_STD(sincosf)))
+	ENTER
+
+	flds	ANGLE(%esp)
+	fsincos
+	movl	SINP(%esp), %ecx
+	CHECK_BOUNDS_BOTH_WIDE (%ecx, SINP(%esp), $4)
+	movl	COSP(%esp), %edx
+	CHECK_BOUNDS_BOTH_WIDE (%edx, COSP(%esp), $4)
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	1f
+	fstps	(%edx)
+	fstps	(%ecx)
+
+	LEAVE
+	ret
+
+	.align ALIGNARG(4)
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	2b
+	fstp	%st(1)
+	fsincos
+	fstps	(%edx)
+	fstps	(%ecx)
+
+	LEAVE
+	ret
+END (BP_SYM (_STD(sincosf)))
+/* w e a k _ a l i a s (BP_SYM (__sincosf), BP_SYM (sincosf)) */
Index: /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincosl.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincosl.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/fpu/s_sincosl.S	(revision 2448)
@@ -0,0 +1,67 @@
+/* Compute sine and cosine of argument.
+   Copyright (C) 1997, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <machine/asm.h>
+#include <sysdep.h>
+#include <asm-syntax.h>
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+#define PARMS	LINKAGE		/* no space for saved regs */
+#define ANGLE	PARMS
+#define SINP	ANGLE+12
+#define COSP	SINP+PTR_SIZE
+
+	.text
+ENTRY (BP_SYM (_STD(sincosl)))
+	ENTER
+
+	fldt	ANGLE(%esp)
+	fsincos
+	movl	SINP(%esp), %ecx
+	CHECK_BOUNDS_BOTH_WIDE (%ecx, SINP(%esp), $12)
+	movl	COSP(%esp), %edx
+	CHECK_BOUNDS_BOTH_WIDE (%edx, COSP(%esp), $12)
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	1f
+	fstpt	(%edx)
+	fstpt	(%ecx)
+
+	LEAVE
+	ret
+
+	.align ALIGNARG(4)
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	2b
+	fstp	%st(1)
+	fsincos
+	fstpt	(%edx)
+	fstpt	(%ecx)
+
+	LEAVE
+	ret
+END (BP_SYM (_STD(sincosl)))
+/* w e a k _ a l i a s  (BP_SYM (__sincosl), BP_SYM (sincosl)) */
Index: /trunk/libc/src/glibc/sysdeps/i386/rawmemchr.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/rawmemchr.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/rawmemchr.S	(revision 2448)
@@ -0,0 +1,231 @@
+/* rawmemchr (str, ch) -- Return pointer to first occurrence of CH in STR.
+   For Intel 80x86, x>=3.
+   Copyright (C) 1994-2000,2002,2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+   Optimised a little by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
+   This version is developed using the same algorithm as the fast C
+   version which carries the following introduction:
+   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se) and
+   commentary by Jim Blandy (jimb@ai.mit.edu);
+   adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+   and implemented by Roland McGrath (roland@ai.mit.edu).
+
+   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 <sysdep.h>
+#include "asm-syntax.h"
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+#define PARMS	LINKAGE+4	/* space for 1 saved reg */
+#define RTN	PARMS
+#define STR	RTN+RTN_SIZE
+#define CHR	STR+PTR_SIZE
+
+	.text
+ENTRY (BP_SYM (__rawmemchr))
+	ENTER
+
+	/* Save callee-safe register used in this function.  */
+	pushl %edi
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (edi, 0)
+
+	/* Load parameters into registers.  */
+	movl STR(%esp), %eax
+	movl CHR(%esp), %edx
+	CHECK_BOUNDS_LOW (%eax, STR(%esp))
+
+	/* At the moment %edx contains C.  What we need for the
+	   algorithm is C in all bytes of the dword.  Avoid
+	   operations on 16 bit words because these require an
+	   prefix byte (and one more cycle).  */
+	movb %dl, %dh		/* Now it is 0|0|c|c */
+	movl %edx, %ecx
+	shll $16, %edx		/* Now c|c|0|0 */
+	movw %cx, %dx		/* And finally c|c|c|c */
+
+	/* Better performance can be achieved if the word (32
+	   bit) memory access is aligned on a four-byte-boundary.
+	   So process first bytes one by one until boundary is
+	   reached. Don't use a loop for better performance.  */
+
+	testb $3, %al		/* correctly aligned ? */
+	je L(1)			/* yes => begin loop */
+	cmpb %dl, (%eax)	/* compare byte */
+	je L(9)			/* target found => return */
+	incl %eax		/* increment source pointer */
+
+	testb $3, %al		/* correctly aligned ? */
+	je L(1)			/* yes => begin loop */
+	cmpb %dl, (%eax)	/* compare byte */
+	je L(9)			/* target found => return */
+	incl %eax		/* increment source pointer */
+
+	testb $3, %al		/* correctly aligned ? */
+	je L(1)			/* yes => begin loop */
+	cmpb %dl, (%eax)	/* compare byte */
+	je L(9)			/* target found => return */
+	incl %eax		/* increment source pointer */
+
+      /* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
+	 change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.	If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-31 is set, there will be a carry
+	 into bit 32 (=carry flag), so all of the hole bits will
+	 be changed.
+
+	 3) But wait!  Aren't we looking for C, not zero?
+	 Good point.  So what we do is XOR LONGWORD with a longword,
+	 each of whose bytes is C.  This turns each byte that is C
+	 into a zero.  */
+
+
+	/* Each round the main loop processes 16 bytes.  */
+	ALIGN (4)
+
+L(1):	movl (%eax), %ecx	/* get word (= 4 bytes) in question */
+	movl $0xfefefeff, %edi	/* magic value */
+	xorl %edx, %ecx		/* XOR with word c|c|c|c => bytes of str == c
+				   are now 0 */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* 0 */
+
+	/* According to the algorithm we had to reverse the effect of the
+	   XOR first and then test the overflow bits.  But because the
+	   following XOR would destroy the carry flag and it would (in a
+	   representation with more than 32 bits) not alter then last
+	   overflow, we can now test this condition.  If no carry is signaled
+	   no overflow must have occurred in the last byte => it was 0.	*/
+	jnc L(8)
+
+	/* We are only interested in carry bits that change due to the
+	   previous add, so remove original bits */
+	xorl %ecx, %edi		/* ((word^charmask)+magic)^(word^charmask) */
+
+	/* Now test for the other three overflow bits.  */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+
+	/* If at least one byte of the word is C we don't get 0 in %edi.  */
+	jnz L(8)		/* found it => return pointer */
+
+	/* This process is unfolded four times for better performance.
+	   we don't increment the source pointer each time.  Instead we
+	   use offsets and increment by 16 in each run of the loop.  But
+	   before probing for the matching byte we need some extra code
+	   (following LL(13) below).  Even the len can be compared with
+	   constants instead of decrementing each time.  */
+
+	movl 4(%eax), %ecx	/* get word (= 4 bytes) in question */
+	movl $0xfefefeff, %edi	/* magic value */
+	xorl %edx, %ecx		/* XOR with word c|c|c|c => bytes of str == c
+				   are now 0 */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* 0 */
+	jnc L(7)		/* highest byte is C => return pointer */
+	xorl %ecx, %edi		/* ((word^charmask)+magic)^(word^charmask) */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(7)		/* found it => return pointer */
+
+	movl 8(%eax), %ecx	/* get word (= 4 bytes) in question */
+	movl $0xfefefeff, %edi	/* magic value */
+	xorl %edx, %ecx		/* XOR with word c|c|c|c => bytes of str == c
+				   are now 0 */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* 0 */
+	jnc L(6)		/* highest byte is C => return pointer */
+	xorl %ecx, %edi		/* ((word^charmask)+magic)^(word^charmask) */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(6)		/* found it => return pointer */
+
+	movl 12(%eax), %ecx	/* get word (= 4 bytes) in question */
+	movl $0xfefefeff, %edi	/* magic value */
+	xorl %edx, %ecx		/* XOR with word c|c|c|c => bytes of str == c
+				   are now 0 */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* 0 */
+	jnc L(5)		/* highest byte is C => return pointer */
+	xorl %ecx, %edi		/* ((word^charmask)+magic)^(word^charmask) */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(5)		/* found it => return pointer */
+
+	/* Adjust both counters for a full round, i.e. 16 bytes.  */
+	addl $16, %eax
+	jmp L(1)
+	/* add missing source pointer increments */
+L(5):	addl $4, %eax
+L(6):	addl $4, %eax
+L(7):	addl $4, %eax
+
+	/* Test for the matching byte in the word.  %ecx contains a NUL
+	   char in the byte which originally was the byte we are looking
+	   at.  */
+L(8):	testb %cl, %cl		/* test first byte in dword */
+	jz L(9)			/* if zero => return pointer */
+	incl %eax		/* increment source pointer */
+
+	testb %ch, %ch		/* test second byte in dword */
+	jz L(9)			/* if zero => return pointer */
+	incl %eax		/* increment source pointer */
+
+	testl $0xff0000, %ecx	/* test third byte in dword */
+	jz L(9)			/* if zero => return pointer */
+	incl %eax		/* increment source pointer */
+
+	/* No further test needed we we know it is one of the four bytes.  */
+
+L(9):
+	CHECK_BOUNDS_HIGH (%eax, STR(%esp), jb)
+	RETURN_BOUNDED_POINTER (STR(%esp))
+	popl %edi		/* pop saved register */
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (edi)
+
+	LEAVE
+	RET_PTR
+END (BP_SYM (__rawmemchr))
+
+/*libc_hidden_def (BP_SYM (__rawmemchr)) */
+/*w e a k _ a l i a s (BP_SYM (__rawmemchr), BP_SYM (rawmemchr)) */
+weak_alias(__rawmemchr, rawmemchr)
Index: /trunk/libc/src/glibc/sysdeps/i386/stpncpy.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/stpncpy.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/stpncpy.S	(revision 2448)
@@ -0,0 +1,162 @@
+/* copy no more then N bytes from SRC to DEST, returning the address of
+   the terminating '\0' in DEST.
+   For Intel 80x86, x>=3.
+   Copyright (C) 1994-1997,2000,2002,2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+   Some bug fixes by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
+     - original wrote n+1 chars in some cases.
+     - stpncpy() ought to behave like strncpy() ie. not null-terminate
+       if limited by n.  glibc-1.09 stpncpy() does this.
+
+   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 <sysdep.h>
+#include "asm-syntax.h"
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+#define PARMS	LINKAGE+4	/* space for 1 saved reg */
+#define RTN	PARMS
+#define DEST	RTN+RTN_SIZE
+#define SRC	DEST+PTR_SIZE
+#define LEN	SRC+PTR_SIZE
+
+	.text
+ENTRY (BP_SYM (__stpncpy))
+	ENTER
+
+	pushl %esi
+	cfi_adjust_cfa_offset (4)
+
+	movl DEST(%esp), %eax
+	movl SRC(%esp), %esi
+	cfi_rel_offset (esi, 0)
+	movl LEN(%esp), %ecx
+	CHECK_BOUNDS_LOW (%eax, DEST(%esp))
+	CHECK_BOUNDS_LOW (%esi, SRC(%esp))
+
+	subl %eax, %esi		/* magic: reduce number of loop variants
+				   to one using addressing mode */
+	jmp L(1)		/* jump to loop "head" */
+
+	ALIGN(4)
+
+	/* Four times unfolded loop with two loop counters.  We get the
+	   the third value (the source address) by using the index+base
+	   addressing mode.  */
+L(2):	movb (%eax,%esi), %dl	/* load current char */
+	movb %dl, (%eax)	/* and store it */
+	testb %dl, %dl		/* was it NUL? */
+	jz L(7)			/* yes, then exit */
+
+	movb 1(%eax,%esi), %dl	/* load current char */
+	movb %dl, 1(%eax)	/* and store it */
+	testb %dl, %dl		/* was it NUL? */
+	jz L(6)			/* yes, then exit */
+
+	movb 2(%eax,%esi), %dl	/* load current char */
+	movb %dl, 2(%eax)	/* and store it */
+	testb %dl, %dl		/* was it NUL? */
+	jz L(5)			/* yes, then exit */
+
+	movb 3(%eax,%esi), %dl	/* load current char */
+	movb %dl, 3(%eax)	/* and store it */
+	testb %dl, %dl		/* was it NUL? */
+	jz L(4)			/* yes, then exit */
+
+	addl $4, %eax		/* increment loop counter for full round */
+
+L(1):	subl $4, %ecx		/* still more than 4 bytes allowed? */
+	jae L(2)		/* yes, then go to start of loop */
+
+	/* The maximal remaining 15 bytes are not processed in a loop.  */
+
+	addl $4, %ecx		/* correct above subtraction */
+	jz L(9)			/* maximal allowed char reached => go to end */
+
+	movb (%eax,%esi), %dl	/* load current char */
+	movb %dl, (%eax)	/* and store it */
+	testb %dl, %dl		/* was it NUL? */
+	jz L(3)			/* yes, then exit */
+
+	incl %eax		/* increment pointer */
+	decl %ecx		/* decrement length counter */
+	jz L(9)			/* no more allowed => exit */
+
+	movb (%eax,%esi), %dl	/* load current char */
+	movb %dl, (%eax)	/* and store it */
+	testb %dl, %dl		/* was it NUL? */
+	jz L(3)			/* yes, then exit */
+
+	incl %eax		/* increment pointer */
+	decl %ecx		/* decrement length counter */
+	jz L(9)			/* no more allowed => exit */
+
+	movb (%eax,%esi), %dl	/* load current char */
+	movb %dl, (%eax)	/* and store it */
+	testb %dl, %dl		/* was it NUL? */
+	jz L(3)			/* yes, then exit */
+
+	incl %eax		/* increment pointer */
+	jmp L(9)		/* we don't have to test for counter underflow
+				   because we know we had a most 3 bytes
+				   remaining => exit */
+
+	/* When coming from the main loop we have to adjust the pointer.  */
+L(4):	decl %ecx		/* decrement counter */
+	incl %eax		/* increment pointer */
+
+L(5):	decl %ecx		/* increment pointer */
+	incl %eax		/* increment pointer */
+
+L(6):	decl %ecx		/* increment pointer */
+	incl %eax		/* increment pointer */
+L(7):
+
+	addl $3, %ecx		/* correct pre-decrementation of counter
+				   at the beginning of the loop; but why 3
+				   and not 4?  Very simple, we have to count
+				   the NUL char we already wrote.  */
+	jz L(9)			/* counter is also 0 => exit */
+
+	/* We now have to fill the rest of the buffer with NUL.  This
+	   is done in a tricky way.  Please note that the addressing mode
+	   used below is not the same we used above.  Here we use the
+	   %ecx register.  */
+L(8):
+	movb $0, (%ecx,%eax)	/* store NUL char */
+L(3):	decl %ecx		/* all bytes written? */
+	jnz L(8)		/* no, then again */
+
+L(9):
+#if __BOUNDED_POINTERS__
+	addl %eax, %esi		/* undo magic: %esi now points beyond end of SRC */
+	CHECK_BOUNDS_HIGH (%esi, SRC(%esp), jbe)
+	CHECK_BOUNDS_HIGH (%eax, DEST(%esp), jbe)
+	RETURN_BOUNDED_POINTER (DEST(%esp))
+#endif
+	popl %esi		/* restore saved register content */
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (esi)
+
+	LEAVE
+	RET_PTR
+END (BP_SYM (__stpncpy))
+
+/*  l i b c _hidden_def (BP_SYM (__stpncpy)) */
+/* w e a k _ a l i a s (BP_SYM (__stpncpy), BP_SYM (stpncpy)) */
+weak_alias(__stpncpy, stpncpy)
Index: /trunk/libc/src/glibc/sysdeps/i386/strchrnul.S
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/strchrnul.S	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/strchrnul.S	(revision 2448)
@@ -0,0 +1,290 @@
+/* strchrnul (str, chr) -- Return pointer to first occurrence of CHR in STR
+   or the final NUL byte.
+   For Intel 80x86, x>=3.
+   Copyright (C) 1994-1997, 1999, 2000, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.org>
+   Some optimisations by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
+
+   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 <sysdep.h>
+#include "asm-syntax.h"
+#include "bp-sym.h"
+#include "bp-asm.h"
+#ifndef _LIBC_SYMBOLS_H
+#error
+#endif
+
+#define PARMS	LINKAGE+4	/* space for 1 saved reg */
+#define RTN	PARMS
+#define STR	RTN+RTN_SIZE
+#define CHR	STR+PTR_SIZE
+
+	.text
+ENTRY (BP_SYM (__strchrnul))
+	ENTER
+
+	pushl %edi		/* Save callee-safe registers used here.  */
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (edi, 0)
+
+	movl STR(%esp), %eax
+	movl CHR(%esp), %edx
+	CHECK_BOUNDS_LOW (%eax, STR(%esp))
+
+	/* At the moment %edx contains CHR.  What we need for the
+	   algorithm is CHR in all bytes of the dword.  Avoid
+	   operations on 16 bit words because these require an
+	   prefix byte (and one more cycle).  */
+	movb %dl, %dh		/* now it is 0|0|c|c */
+	movl %edx, %ecx
+	shll $16, %edx		/* now it is c|c|0|0 */
+	movw %cx, %dx		/* and finally c|c|c|c */
+
+	/* Before we start with the main loop we process single bytes
+	   until the source pointer is aligned.  This has two reasons:
+	   1. aligned 32-bit memory access is faster
+	   and (more important)
+	   2. we process in the main loop 32 bit in one step although
+	      we don't know the end of the string.  But accessing at
+	      4-byte alignment guarantees that we never access illegal
+	      memory if this would not also be done by the trivial
+	      implementation (this is because all processor inherent
+	      boundaries are multiples of 4.  */
+
+	testb $3, %al		/* correctly aligned ? */
+	jz L(11)		/* yes => begin loop */
+	movb (%eax), %cl	/* load byte in question (we need it twice) */
+	cmpb %cl, %dl		/* compare byte */
+	je L(6)			/* target found => return */
+	testb %cl, %cl		/* is NUL? */
+	jz L(6)			/* yes => return NULL */
+	incl %eax		/* increment pointer */
+
+	testb $3, %al		/* correctly aligned ? */
+	jz L(11)		/* yes => begin loop */
+	movb (%eax), %cl	/* load byte in question (we need it twice) */
+	cmpb %cl, %dl		/* compare byte */
+	je L(6)			/* target found => return */
+	testb %cl, %cl		/* is NUL? */
+	jz L(6)			/* yes => return NULL */
+	incl %eax		/* increment pointer */
+
+	testb $3, %al		/* correctly aligned ? */
+	jz L(11)		/* yes => begin loop */
+	movb (%eax), %cl	/* load byte in question (we need it twice) */
+	cmpb %cl, %dl		/* compare byte */
+	je L(6)			/* target found => return */
+	testb %cl, %cl		/* is NUL? */
+	jz L(6)			/* yes => return NULL */
+	incl %eax		/* increment pointer */
+
+	/* No we have reached alignment.  */
+	jmp L(11)		/* begin loop */
+
+      /* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
+	 change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.	If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-31 is set, there will be a carry
+	 into bit 32 (=carry flag), so all of the hole bits will
+	 be changed.
+
+	 3) But wait!  Aren't we looking for CHR, not zero?
+	 Good point.  So what we do is XOR LONGWORD with a longword,
+	 each of whose bytes is CHR.  This turns each byte that is CHR
+	 into a zero.  */
+
+	/* Each round the main loop processes 16 bytes.  */
+
+	ALIGN(4)
+
+L(1):	addl $16, %eax		/* adjust pointer for whole round */
+
+L(11):	movl (%eax), %ecx	/* get word (= 4 bytes) in question */
+	xorl %edx, %ecx		/* XOR with word c|c|c|c => bytes of str == c
+				   are now 0 */
+	movl $0xfefefeff, %edi	/* magic value */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* CHR */
+
+	/* According to the algorithm we had to reverse the effect of the
+	   XOR first and then test the overflow bits.  But because the
+	   following XOR would destroy the carry flag and it would (in a
+	   representation with more than 32 bits) not alter then last
+	   overflow, we can now test this condition.  If no carry is signaled
+	   no overflow must have occurred in the last byte => it was 0.	*/
+	jnc L(7)
+
+	/* We are only interested in carry bits that change due to the
+	   previous add, so remove original bits */
+	xorl %ecx, %edi		/* ((word^charmask)+magic)^(word^charmask) */
+
+	/* Now test for the other three overflow bits.  */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+
+	/* If at least one byte of the word is CHR we don't get 0 in %edi.  */
+	jnz L(7)		/* found it => return pointer */
+
+	/* Now we made sure the dword does not contain the character we are
+	   looking for.  But because we deal with strings we have to check
+	   for the end of string before testing the next dword.  */
+
+	xorl %edx, %ecx		/* restore original dword without reload */
+	movl $0xfefefeff, %edi	/* magic value */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* 0 */
+	jnc L(7)		/* highest byte is NUL => return NULL */
+	xorl %ecx, %edi		/* (word+magic)^word */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(7)		/* found NUL => return NULL */
+
+	movl 4(%eax), %ecx	/* get word (= 4 bytes) in question */
+	xorl %edx, %ecx		/* XOR with word c|c|c|c => bytes of str == c
+				   are now 0 */
+	movl $0xfefefeff, %edi	/* magic value */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* CHR */
+	jnc L(71)		/* highest byte is CHR => return pointer */
+	xorl %ecx, %edi		/* ((word^charmask)+magic)^(word^charmask) */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(71)		/* found it => return pointer */
+	xorl %edx, %ecx		/* restore original dword without reload */
+	movl $0xfefefeff, %edi	/* magic value */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* 0 */
+	jnc L(71)		/* highest byte is NUL => return NULL */
+	xorl %ecx, %edi		/* (word+magic)^word */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(71)		/* found NUL => return NULL */
+
+	movl 8(%eax), %ecx	/* get word (= 4 bytes) in question */
+	xorl %edx, %ecx		/* XOR with word c|c|c|c => bytes of str == c
+				   are now 0 */
+	movl $0xfefefeff, %edi	/* magic value */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* CHR */
+	jnc L(72)		/* highest byte is CHR => return pointer */
+	xorl %ecx, %edi		/* ((word^charmask)+magic)^(word^charmask) */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(72)		/* found it => return pointer */
+	xorl %edx, %ecx		/* restore original dword without reload */
+	movl $0xfefefeff, %edi	/* magic value */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* 0 */
+	jnc L(72)		/* highest byte is NUL => return NULL */
+	xorl %ecx, %edi		/* (word+magic)^word */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(72)		/* found NUL => return NULL */
+
+	movl 12(%eax), %ecx	/* get word (= 4 bytes) in question */
+	xorl %edx, %ecx		/* XOR with word c|c|c|c => bytes of str == c
+				   are now 0 */
+	movl $0xfefefeff, %edi	/* magic value */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* CHR */
+	jnc L(73)		/* highest byte is CHR => return pointer */
+	xorl %ecx, %edi		/* ((word^charmask)+magic)^(word^charmask) */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jnz L(73)		/* found it => return pointer */
+	xorl %edx, %ecx		/* restore original dword without reload */
+	movl $0xfefefeff, %edi	/* magic value */
+	addl %ecx, %edi		/* add the magic value to the word.  We get
+				   carry bits reported for each byte which
+				   is *not* 0 */
+	jnc L(73)		/* highest byte is NUL => return NULL */
+	xorl %ecx, %edi		/* (word+magic)^word */
+	orl $0xfefefeff, %edi	/* set all non-carry bits */
+	incl %edi		/* add 1: if one carry bit was *not* set
+				   the addition will not result in 0.  */
+	jz L(1)			/* no NUL found => restart loop */
+
+L(73):	addl $4, %eax		/* adjust pointer */
+L(72):	addl $4, %eax
+L(71):	addl $4, %eax
+
+	/* We now scan for the byte in which the character was matched.
+	   But we have to take care of the case that a NUL char is
+	   found before this in the dword.  */
+
+L(7):	testb %cl, %cl		/* is first byte CHR? */
+	jz L(6)			/* yes => return pointer */
+	cmpb %dl, %cl		/* is first byte NUL? */
+	je L(6)			/* yes => return NULL */
+	incl %eax		/* it's not in the first byte */
+
+	testb %ch, %ch		/* is second byte CHR? */
+	jz L(6)			/* yes => return pointer */
+	cmpb %dl, %ch		/* is second byte NUL? */
+	je L(6)			/* yes => return NULL? */
+	incl %eax		/* it's not in the second byte */
+
+	shrl $16, %ecx		/* make upper byte accessible */
+	testb %cl, %cl		/* is third byte CHR? */
+	jz L(6)			/* yes => return pointer */
+	cmpb %dl, %cl		/* is third byte NUL? */
+	je L(6)			/* yes => return NULL */
+
+	/* It must be in the fourth byte and it cannot be NUL.  */
+	incl %eax
+
+L(6):	CHECK_BOUNDS_HIGH (%eax, STR(%esp), jb)
+	RETURN_BOUNDED_POINTER (STR(%esp))
+	popl %edi		/* restore saved register content */
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (edi)
+
+	LEAVE
+	RET_PTR
+END (BP_SYM (__strchrnul))
+
+/*w e a k _ a l i a s (BP_SYM (__strchrnul), BP_SYM (strchrnul)) */
+weak_alias(__strchrnul, strchrnul)
Index: /trunk/libc/src/glibc/sysdeps/i386/sysdep.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/i386/sysdep.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/i386/sysdep.h	(revision 2448)
@@ -0,0 +1,180 @@
+/* Assembler macros for i386.
+   Copyright (C) 1991-93,95,96,98,2002,2003,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.  */
+
+#include <sysdeps/generic/sysdep.h>
+
+#ifdef	__ASSEMBLER__
+#undef _STD
+#define _STD(x) _std_ ## x
+
+/* Syntactic details of assembler.  */
+
+#ifdef HAVE_ELF
+
+/* ELF uses byte-counts for .align, most others use log2 of count of bytes.  */
+#define ALIGNARG(log2) 1<<log2
+/* For ELF we need the `.type' directive to make shared libs work right.  */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
+
+/* In ELF C symbols are asm symbols.  */
+#undef	NO_UNDERSCORES
+#define NO_UNDERSCORES
+
+#else
+
+#define ALIGNARG(log2) log2
+#define ASM_TYPE_DIRECTIVE(name,type)	/* Nothing is specified.  */
+#define ASM_SIZE_DIRECTIVE(name)	/* Nothing is specified.  */
+
+#endif
+
+
+/* Define an entry point visible from C.
+
+   There is currently a bug in gdb which prevents us from specifying
+   incomplete stabs information.  Fake some entries here which specify
+   the current source file.  */
+#define	ENTRY(name)							      \
+  STABS_CURRENT_FILE1("")						      \
+  STABS_CURRENT_FILE(name)						      \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);				      \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)			      \
+  .align ALIGNARG(4);							      \
+  STABS_FUN(name)							      \
+  C_LABEL(name)								      \
+  cfi_startproc;							      \
+  CALL_MCOUNT
+
+#undef	END
+#define END(name)							      \
+  cfi_endproc;								      \
+  ASM_SIZE_DIRECTIVE(name)						      \
+  STABS_FUN_END(name)
+
+#ifdef HAVE_CPP_ASM_DEBUGINFO
+/* Disable that goop, because we just pass -g through to the assembler
+   and it generates proper line number information directly.  */
+# define STABS_CURRENT_FILE1(name)
+# define STABS_CURRENT_FILE(name)
+# define STABS_FUN(name)
+# define STABS_FUN_END(name)
+#else
+/* Remove the following two lines once the gdb bug is fixed.  */
+#define STABS_CURRENT_FILE(name)					      \
+  STABS_CURRENT_FILE1 (#name)
+#define STABS_CURRENT_FILE1(name)					      \
+  1: .stabs name,100,0,0,1b;
+/* Emit stabs definition lines.  We use F(0,1) and define t(0,1) as `int',
+   the same way gcc does it.  */
+#define STABS_FUN(name) STABS_FUN2(name, name##:F(0,1))
+#define STABS_FUN2(name, namestr)					      \
+  .stabs "int:t(0,1)=r(0,1);-2147483648;2147483647;",128,0,0,0;		      \
+  .stabs #namestr,36,0,0,name;
+#define STABS_FUN_END(name)						      \
+  1: .stabs "",36,0,0,1b-name;
+#endif
+
+/* If compiled for profiling, call `mcount' at the start of each function.  */
+#ifdef	PROF
+/* The mcount code relies on a normal frame pointer being on the stack
+   to locate our caller, so push one just for its benefit.  */
+#define CALL_MCOUNT \
+  pushl %ebp; cfi_adjust_cfa_offset (4); movl %esp, %ebp; \
+  cfi_def_cfa_register (ebp); call JUMPTARGET(mcount); \
+  popl %ebp; cfi_def_cfa (esp, 4);
+#else
+#define CALL_MCOUNT		/* Do nothing.  */
+#endif
+
+#ifdef	NO_UNDERSCORES
+/* Since C identifiers are not normally prefixed with an underscore
+   on this system, the asm identifier `syscall_error' intrudes on the
+   C name space.  Make sure we use an innocuous name.  */
+#define	syscall_error	__syscall_error
+#define mcount		_mcount
+#endif
+#ifdef __EMX__
+#define mcount __mcount
+#endif
+
+#define	PSEUDO(name, syscall_name, args)				      \
+  .globl syscall_error;							      \
+lose: SYSCALL_PIC_SETUP							      \
+  jmp JUMPTARGET(syscall_error);					      \
+  ENTRY (name)								      \
+  DO_CALL (syscall_name, args);						      \
+  jb lose
+
+#undef	PSEUDO_END
+#define	PSEUDO_END(name)						      \
+  END (name)
+
+#undef JUMPTARGET
+#ifdef PIC
+#define JUMPTARGET(name)	name##@PLT
+#define SYSCALL_PIC_SETUP \
+    pushl %ebx;								      \
+    cfi_adjust_cfa_offset (4);						      \
+    call 0f;								      \
+0:  popl %ebx;								      \
+    cfi_adjust_cfa_offset (-4);						      \
+    addl $_GLOBAL_OFFSET_TABLE+[.-0b], %ebx;
+
+# ifndef HAVE_HIDDEN
+#  define SETUP_PIC_REG(reg) \
+  call 1f;								      \
+  .subsection 1;							      \
+1:movl (%esp), %e##reg;							      \
+  ret;									      \
+  .previous
+# else
+#  define SETUP_PIC_REG(reg) \
+  .ifndef __i686.get_pc_thunk.reg;					      \
+  .section .gnu.linkonce.t.__i686.get_pc_thunk.reg,"ax",@progbits;	      \
+  .globl __i686.get_pc_thunk.reg;					      \
+  .hidden __i686.get_pc_thunk.reg;					      \
+  .type __i686.get_pc_thunk.reg,@function;				      \
+__i686.get_pc_thunk.reg:						      \
+  movl (%esp), %e##reg;							      \
+  ret;									      \
+  .size __i686.get_pc_thunk.reg, . - __i686.get_pc_thunk.reg;		      \
+  .previous;								      \
+  .endif;								      \
+  call __i686.get_pc_thunk.reg
+# endif
+
+# define LOAD_PIC_REG(reg) \
+  SETUP_PIC_REG(reg); addl $_GLOBAL_OFFSET_TABLE_, %e##reg
+
+#else
+#define JUMPTARGET(name)	name
+#define SYSCALL_PIC_SETUP	/* Nothing.  */
+#endif
+
+/* Local label name for asm code. */
+#ifndef L
+#ifdef HAVE_ELF
+#define L(name)		.L##name
+#else
+#define L(name)		name
+#endif
+#endif
+
+#endif	/* __ASSEMBLER__ */
Index: /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_acoshl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_acoshl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_acoshl.c	(revision 2448)
@@ -0,0 +1,73 @@
+/* e_acoshl.c -- long double version of e_acosh.c.
+ * Conversion to long double by Ulrich Drepper,
+ * Cygnus Support, drepper@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "libc-alias-glibc.h"
+#if defined(LIBM_SCCS) && !defined(lint)
+static char rcsid[] = "$NetBSD: $";
+#endif
+
+/* __ieee754_acoshl(x)
+ * Method :
+ *	Based on
+ *		acoshl(x) = logl [ x + sqrtl(x*x-1) ]
+ *	we have
+ *		acoshl(x) := logl(x)+ln2,	if x is large; else
+ *		acoshl(x) := logl(2x-1/(sqrtl(x*x-1)+x)) if x>2; else
+ *		acoshl(x) := log1pl(t+sqrtl(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ *	acoshl(x) is NaN with signal if x<1.
+ *	acoshl(NaN) is NaN without signal.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const long double
+#else
+static long double
+#endif
+one	= 1.0,
+ln2	= 6.931471805599453094287e-01L; /* 0x3FFE, 0xB17217F7, 0xD1CF79AC */
+
+#ifdef __STDC__
+	long double __ieee754_acoshl(long double x)
+#else
+	long double __ieee754_acoshl(x)
+	long double x;
+#endif
+{
+	long double t;
+	u_int32_t se,i0,i1;
+	GET_LDOUBLE_WORDS(se,i0,i1,x);
+	if(se<0x3fff || se & 0x8000) {	/* x < 1 */
+	    return (x-x)/(x-x);
+	} else if(se >=0x401d) {	/* x > 2**30 */
+	    if(se >=0x7fff) {		/* x is inf of NaN */
+	        return x+x;
+	    } else
+		return __ieee754_logl(x)+ln2;	/* acoshl(huge)=logl(2x) */
+	} else if(((se-0x3fff)|i0|i1)==0) {
+	    return 0.0;			/* acosh(1) = 0 */
+	} else if (se > 0x4000) {	/* 2**28 > x > 2 */
+	    t=x*x;
+	    return __ieee754_logl(2.0*x-one/(x+__ieee754_sqrtl(t-one)));
+	} else {			/* 1<x<2 */
+	    t = x-one;
+	    return __log1pl(t+__sqrtl(2.0*t+t*t));
+	}
+}
Index: /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_gammal_r.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_gammal_r.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_gammal_r.c	(revision 2448)
@@ -0,0 +1,63 @@
+/* Implementation of gamma function according to ISO C.
+   Copyright (C) 1997, 1999, 2001, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 "libc-alias-glibc.h"
+#include <math.h>
+#include "math_private.h"
+
+
+long double
+__ieee754_gammal_r (long double x, int *signgamp)
+{
+  /* We don't have a real gamma implementation now.  We'll use lgamma
+     and the exp function.  But due to the required boundary
+     conditions we must check some values separately.  */
+  u_int32_t es, hx, lx;
+
+  GET_LDOUBLE_WORDS (es, hx, lx, x);
+
+  if (((es & 0x7fff) | hx | lx) == 0)
+    {
+      /* Return value for x == 0 is Inf with divide by zero exception.  */
+      *signgamp = 0;
+      return 1.0 / x;
+    }
+  if (es == 0xffffffff && ((hx & 0x7fffffff) | lx) == 0)
+    {
+      /* x == -Inf.  According to ISO this is NaN.  */
+      *signgamp = 0;
+      return x - x;
+    }
+  if ((es & 0x7fff) == 0x7fff && ((hx & 0x7fffffff) | lx) != 0)
+    {
+      /* NaN, return it.  */
+      *signgamp = 0;
+      return x;
+    }
+  if ((es & 0x8000) != 0 && x < 0xffffffff && __rintl (x) == x)
+    {
+      /* Return value for integer x < 0 is NaN with invalid exception.  */
+      *signgamp = 0;
+      return (x - x) / (x - x);
+    }
+
+  /* XXX FIXME.  */
+  return __ieee754_expl (__ieee754_lgammal_r (x, signgamp));
+}
Index: /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_j0l.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_j0l.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_j0l.c	(revision 2448)
@@ -0,0 +1,645 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Long double expansions are
+  Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
+  and are incorporated herein by permission of the author.  The author
+  reserves the right to distribute this material elsewhere under different
+  copying permissions.  These modifications are distributed here under
+  the following terms:
+
+    This 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.
+
+    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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA */
+
+/* __ieee754_j0(x), __ieee754_y0(x)
+ * Bessel function of the first and second kinds of order zero.
+ * Method -- j0(x):
+ *	1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ...
+ *	2. Reduce x to |x| since j0(x)=j0(-x),  and
+ *	   for x in (0,2)
+ *		j0(x) = 1 - z/4 + z^2*R0/S0,  where z = x*x;
+ *	   for x in (2,inf)
+ *		j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0))
+ *	   where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+ *	   as follow:
+ *		cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+ *			= 1/sqrt(2) * (cos(x) + sin(x))
+ *		sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4)
+ *			= 1/sqrt(2) * (sin(x) - cos(x))
+ *	   (To avoid cancellation, use
+ *		sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ *	    to compute the worse one.)
+ *
+ *	3 Special cases
+ *		j0(nan)= nan
+ *		j0(0) = 1
+ *		j0(inf) = 0
+ *
+ * Method -- y0(x):
+ *	1. For x<2.
+ *	   Since
+ *		y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...)
+ *	   therefore y0(x)-2/pi*j0(x)*ln(x) is an even function.
+ *	   We use the following function to approximate y0,
+ *		y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2
+ *
+ *	   Note: For tiny x, U/V = u0 and j0(x)~1, hence
+ *		y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27)
+ *	2. For x>=2.
+ *		y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0))
+ *	   where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+ *	   by the method mentioned above.
+ *	3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0.
+ */
+
+#include "libc-alias-glibc.h"
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static long double pzero (long double), qzero (long double);
+#else
+static long double pzero (), qzero ();
+#endif
+
+#ifdef __STDC__
+static const long double
+#else
+static long double
+#endif
+  huge = 1e4930L,
+  one = 1.0L,
+  invsqrtpi = 5.6418958354775628694807945156077258584405e-1L,
+  tpi = 6.3661977236758134307553505349005744813784e-1L,
+
+  /* J0(x) = 1 - x^2 / 4 + x^4 R0(x^2) / S0(x^2)
+     0 <= x <= 2
+     peak relative error 1.41e-22 */
+  R[5] = {
+  4.287176872744686992880841716723478740566E7L,
+  -6.652058897474241627570911531740907185772E5L,
+  7.011848381719789863458364584613651091175E3L,
+  -3.168040850193372408702135490809516253693E1L,
+  6.030778552661102450545394348845599300939E-2L,
+},
+
+ S[4] = {
+   2.743793198556599677955266341699130654342E9L,
+   3.364330079384816249840086842058954076201E7L,
+   1.924119649412510777584684927494642526573E5L,
+   6.239282256012734914211715620088714856494E2L,
+   /*   1.000000000000000000000000000000000000000E0L,*/
+};
+
+#ifdef __STDC__
+static const long double zero = 0.0;
+#else
+static long double zero = 0.0;
+#endif
+
+#ifdef __STDC__
+long double
+__ieee754_j0l (long double x)
+#else
+long double
+__ieee754_j0l (x)
+     long double x;
+#endif
+{
+  long double z, s, c, ss, cc, r, u, v;
+  int32_t ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  if (ix >= 0x7fff)
+    return one / (x * x);
+  x = fabsl (x);
+  if (ix >= 0x4000)		/* |x| >= 2.0 */
+    {
+      __sincosl (x, &s, &c);
+      ss = s - c;
+      cc = s + c;
+      if (ix < 0x7ffe)
+	{			/* make sure x+x not overflow */
+	  z = -__cosl (x + x);
+	  if ((s * c) < zero)
+	    cc = z / ss;
+	  else
+	    ss = z / cc;
+	}
+      /*
+       * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+       * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+       */
+      if (ix > 0x4080)	/* 2^129 */
+	z = (invsqrtpi * cc) / __ieee754_sqrtl (x);
+      else
+	{
+	  u = pzero (x);
+	  v = qzero (x);
+	  z = invsqrtpi * (u * cc - v * ss) / __ieee754_sqrtl (x);
+	}
+      return z;
+    }
+  if (ix < 0x3fef) /* |x| < 2**-16 */
+    {
+      if (huge + x > one)
+	{			/* raise inexact if x != 0 */
+	  if (ix < 0x3fde) /* |x| < 2^-33 */
+	    return one;
+	  else
+	    return one - 0.25 * x * x;
+	}
+    }
+  z = x * x;
+  r = z * (R[0] + z * (R[1] + z * (R[2] + z * (R[3] + z * R[4]))));
+  s = S[0] + z * (S[1] + z * (S[2] + z * (S[3] + z)));
+  if (ix < 0x3fff)
+    {				/* |x| < 1.00 */
+      return (one - 0.25 * z + z * (r / s));
+    }
+  else
+    {
+      u = 0.5 * x;
+      return ((one + u) * (one - u) + z * (r / s));
+    }
+}
+
+
+/* y0(x) = 2/pi ln(x) J0(x) + U(x^2)/V(x^2)
+   0 < x <= 2
+   peak relative error 1.7e-21 */
+#ifdef __STDC__
+static const long double
+#else
+static long double
+#endif
+U[6] = {
+  -1.054912306975785573710813351985351350861E10L,
+  2.520192609749295139432773849576523636127E10L,
+  -1.856426071075602001239955451329519093395E9L,
+  4.079209129698891442683267466276785956784E7L,
+  -3.440684087134286610316661166492641011539E5L,
+  1.005524356159130626192144663414848383774E3L,
+};
+#ifdef __STDC__
+static const long double
+#else
+static long double
+#endif
+V[5] = {
+  1.429337283720789610137291929228082613676E11L,
+  2.492593075325119157558811370165695013002E9L,
+  2.186077620785925464237324417623665138376E7L,
+  1.238407896366385175196515057064384929222E5L,
+  4.693924035211032457494368947123233101664E2L,
+  /*  1.000000000000000000000000000000000000000E0L */
+};
+
+#ifdef __STDC__
+long double
+__ieee754_y0l (long double x)
+#else
+long double
+__ieee754_y0l (x)
+     long double x;
+#endif
+{
+  long double z, s, c, ss, cc, u, v;
+  int32_t ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0  */
+  if (se & 0x8000)
+    return zero / (zero * x);
+  if (ix >= 0x7fff)
+    return one / (x + x * x);
+  if ((i0 | i1) == 0)
+    return -HUGE_VALL + x;  /* -inf and overflow exception.  */
+  if (ix >= 0x4000)
+    {				/* |x| >= 2.0 */
+
+      /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
+       * where x0 = x-pi/4
+       *      Better formula:
+       *              cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+       *                      =  1/sqrt(2) * (sin(x) + cos(x))
+       *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+       *                      =  1/sqrt(2) * (sin(x) - cos(x))
+       * To avoid cancellation, use
+       *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+       * to compute the worse one.
+       */
+      __sincosl (x, &s, &c);
+      ss = s - c;
+      cc = s + c;
+      /*
+       * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+       * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+       */
+      if (ix < 0x7ffe)
+	{			/* make sure x+x not overflow */
+	  z = -__cosl (x + x);
+	  if ((s * c) < zero)
+	    cc = z / ss;
+	  else
+	    ss = z / cc;
+	}
+      if (ix > 0x4080)	/* 1e39 */
+	z = (invsqrtpi * ss) / __ieee754_sqrtl (x);
+      else
+	{
+	  u = pzero (x);
+	  v = qzero (x);
+	  z = invsqrtpi * (u * ss + v * cc) / __ieee754_sqrtl (x);
+	}
+      return z;
+    }
+  if (ix <= 0x3fde) /* x < 2^-33 */
+    {
+      z = -7.380429510868722527629822444004602747322E-2L
+	+ tpi * __ieee754_logl (x);
+      return z;
+    }
+  z = x * x;
+  u = U[0] + z * (U[1] + z * (U[2] + z * (U[3] + z * (U[4] + z * U[5]))));
+  v = V[0] + z * (V[1] + z * (V[2] + z * (V[3] + z * (V[4] + z))));
+  return (u / v + tpi * (__ieee754_j0l (x) * __ieee754_logl (x)));
+}
+
+/* The asymptotic expansions of pzero is
+ *	1 - 9/128 s^2 + 11025/98304 s^4 - ...,	where s = 1/x.
+ * For x >= 2, We approximate pzero by
+ *	pzero(x) = 1 + s^2 R(s^2) / S(s^2)
+ */
+#ifdef __STDC__
+static const long double pR8[7] = {
+#else
+static long double pR8[7] = {
+#endif
+  /* 8 <= x <= inf
+     Peak relative error 4.62 */
+  -4.094398895124198016684337960227780260127E-9L,
+  -8.929643669432412640061946338524096893089E-7L,
+  -6.281267456906136703868258380673108109256E-5L,
+  -1.736902783620362966354814353559382399665E-3L,
+  -1.831506216290984960532230842266070146847E-2L,
+  -5.827178869301452892963280214772398135283E-2L,
+  -2.087563267939546435460286895807046616992E-2L,
+};
+#ifdef __STDC__
+static const long double pS8[6] = {
+#else
+static long double pS8[6] = {
+#endif
+  5.823145095287749230197031108839653988393E-8L,
+  1.279281986035060320477759999428992730280E-5L,
+  9.132668954726626677174825517150228961304E-4L,
+  2.606019379433060585351880541545146252534E-2L,
+  2.956262215119520464228467583516287175244E-1L,
+  1.149498145388256448535563278632697465675E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+#ifdef __STDC__
+static const long double pR5[7] = {
+#else
+static long double pR5[7] = {
+#endif
+  /* 4.54541015625 <= x <= 8
+     Peak relative error 6.51E-22 */
+  -2.041226787870240954326915847282179737987E-7L,
+  -2.255373879859413325570636768224534428156E-5L,
+  -7.957485746440825353553537274569102059990E-4L,
+  -1.093205102486816696940149222095559439425E-2L,
+  -5.657957849316537477657603125260701114646E-2L,
+  -8.641175552716402616180994954177818461588E-2L,
+  -1.354654710097134007437166939230619726157E-2L,
+};
+#ifdef __STDC__
+static const long double pS5[6] = {
+#else
+static long double pS5[6] = {
+#endif
+  2.903078099681108697057258628212823545290E-6L,
+  3.253948449946735405975737677123673867321E-4L,
+  1.181269751723085006534147920481582279979E-2L,
+  1.719212057790143888884745200257619469363E-1L,
+  1.006306498779212467670654535430694221924E0L,
+  2.069568808688074324555596301126375951502E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+#ifdef __STDC__
+static const long double pR3[7] = {
+#else
+static long double pR3[7] = {
+#endif
+  /* 2.85711669921875 <= x <= 4.54541015625
+     peak relative error 5.25e-21 */
+  -5.755732156848468345557663552240816066802E-6L,
+  -3.703675625855715998827966962258113034767E-4L,
+  -7.390893350679637611641350096842846433236E-3L,
+  -5.571922144490038765024591058478043873253E-2L,
+  -1.531290690378157869291151002472627396088E-1L,
+  -1.193350853469302941921647487062620011042E-1L,
+  -8.567802507331578894302991505331963782905E-3L,
+};
+#ifdef __STDC__
+static const long double pS3[6] = {
+#else
+static long double pS3[6] = {
+#endif
+  8.185931139070086158103309281525036712419E-5L,
+  5.398016943778891093520574483111255476787E-3L,
+  1.130589193590489566669164765853409621081E-1L,
+  9.358652328786413274673192987670237145071E-1L,
+  3.091711512598349056276917907005098085273E0L,
+  3.594602474737921977972586821673124231111E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+#ifdef __STDC__
+static const long double pR2[7] = {
+#else
+static long double pR2[7] = {
+#endif
+  /* 2 <= x <= 2.85711669921875
+     peak relative error 2.64e-21 */
+  -1.219525235804532014243621104365384992623E-4L,
+  -4.838597135805578919601088680065298763049E-3L,
+  -5.732223181683569266223306197751407418301E-2L,
+  -2.472947430526425064982909699406646503758E-1L,
+  -3.753373645974077960207588073975976327695E-1L,
+  -1.556241316844728872406672349347137975495E-1L,
+  -5.355423239526452209595316733635519506958E-3L,
+};
+#ifdef __STDC__
+static const long double pS2[6] = {
+#else
+static long double pS2[6] = {
+#endif
+  1.734442793664291412489066256138894953823E-3L,
+  7.158111826468626405416300895617986926008E-2L,
+  9.153839713992138340197264669867993552641E-1L,
+  4.539209519433011393525841956702487797582E0L,
+  8.868932430625331650266067101752626253644E0L,
+  6.067161890196324146320763844772857713502E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+#ifdef __STDC__
+static long double
+pzero (long double x)
+#else
+static long double
+pzero (x)
+     long double x;
+#endif
+{
+#ifdef __STDC__
+  const long double *p, *q;
+#else
+  long double *p, *q;
+#endif
+  long double z, r, s;
+  int32_t ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  if (ix >= 0x4002)
+    {
+      p = pR8;
+      q = pS8;
+    }				/* x >= 8 */
+  else
+    {
+      i1 = (ix << 16) | (i0 >> 16);
+      if (i1 >= 0x40019174)	/* x >= 4.54541015625 */
+	{
+	  p = pR5;
+	  q = pS5;
+	}
+      else if (i1 >= 0x4000b6db)	/* x >= 2.85711669921875 */
+	{
+	  p = pR3;
+	  q = pS3;
+	}
+      else if (ix >= 0x4000)	/* x better be >= 2 */
+	{
+	  p = pR2;
+	  q = pS2;
+	}
+    }
+  z = one / (x * x);
+  r =
+    p[0] + z * (p[1] +
+		z * (p[2] + z * (p[3] + z * (p[4] + z * (p[5] + z * p[6])))));
+  s =
+    q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * (q[5] + z)))));
+  return (one + z * r / s);
+}
+
+
+/* For x >= 8, the asymptotic expansions of qzero is
+ *	-1/8 s + 75/1024 s^3 - ..., where s = 1/x.
+ * We approximate qzero by
+ *	qzero(x) = s*(-.125 + R(s^2) / S(s^2))
+ */
+#ifdef __STDC__
+static const long double qR8[7] = {
+#else
+static long double qR8[7] = {
+#endif
+  /* 8 <= x <= inf
+     peak relative error 2.23e-21 */
+  3.001267180483191397885272640777189348008E-10L,
+  8.693186311430836495238494289942413810121E-8L,
+  8.496875536711266039522937037850596580686E-6L,
+  3.482702869915288984296602449543513958409E-4L,
+  6.036378380706107692863811938221290851352E-3L,
+  3.881970028476167836382607922840452192636E-2L,
+  6.132191514516237371140841765561219149638E-2L,
+};
+#ifdef __STDC__
+static const long double qS8[7] = {
+#else
+static long double qS8[7] = {
+#endif
+  4.097730123753051126914971174076227600212E-9L,
+  1.199615869122646109596153392152131139306E-6L,
+  1.196337580514532207793107149088168946451E-4L,
+  5.099074440112045094341500497767181211104E-3L,
+  9.577420799632372483249761659674764460583E-2L,
+  7.385243015344292267061953461563695918646E-1L,
+  1.917266424391428937962682301561699055943E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+#ifdef __STDC__
+static const long double qR5[7] = {
+#else
+static long double qR5[7] = {
+#endif
+  /* 4.54541015625 <= x <= 8
+     peak relative error 1.03e-21 */
+  3.406256556438974327309660241748106352137E-8L,
+  4.855492710552705436943630087976121021980E-6L,
+  2.301011739663737780613356017352912281980E-4L,
+  4.500470249273129953870234803596619899226E-3L,
+  3.651376459725695502726921248173637054828E-2L,
+  1.071578819056574524416060138514508609805E-1L,
+  7.458950172851611673015774675225656063757E-2L,
+};
+#ifdef __STDC__
+static const long double qS5[7] = {
+#else
+static long double qS5[7] = {
+#endif
+  4.650675622764245276538207123618745150785E-7L,
+  6.773573292521412265840260065635377164455E-5L,
+  3.340711249876192721980146877577806687714E-3L,
+  7.036218046856839214741678375536970613501E-2L,
+  6.569599559163872573895171876511377891143E-1L,
+  2.557525022583599204591036677199171155186E0L,
+  3.457237396120935674982927714210361269133E0L,
+  /* 1.000000000000000000000000000000000000000E0L,*/
+};
+
+#ifdef __STDC__
+static const long double qR3[7] = {
+#else
+static long double qR3[7] = {
+#endif
+  /* 2.85711669921875 <= x <= 4.54541015625
+     peak relative error 5.24e-21 */
+  1.749459596550816915639829017724249805242E-6L,
+  1.446252487543383683621692672078376929437E-4L,
+  3.842084087362410664036704812125005761859E-3L,
+  4.066369994699462547896426554180954233581E-2L,
+  1.721093619117980251295234795188992722447E-1L,
+  2.538595333972857367655146949093055405072E-1L,
+  8.560591367256769038905328596020118877936E-2L,
+};
+#ifdef __STDC__
+static const long double qS3[7] = {
+#else
+static long double qS3[7] = {
+#endif
+  2.388596091707517488372313710647510488042E-5L,
+  2.048679968058758616370095132104333998147E-3L,
+  5.824663198201417760864458765259945181513E-2L,
+  6.953906394693328750931617748038994763958E-1L,
+  3.638186936390881159685868764832961092476E0L,
+  7.900169524705757837298990558459547842607E0L,
+  5.992718532451026507552820701127504582907E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+#ifdef __STDC__
+static const long double qR2[7] = {
+#else
+static long double qR2[7] = {
+#endif
+  /* 2 <= x <= 2.85711669921875
+     peak relative error 1.58e-21  */
+  6.306524405520048545426928892276696949540E-5L,
+  3.209606155709930950935893996591576624054E-3L,
+  5.027828775702022732912321378866797059604E-2L,
+  3.012705561838718956481911477587757845163E-1L,
+  6.960544893905752937420734884995688523815E-1L,
+  5.431871999743531634887107835372232030655E-1L,
+  9.447736151202905471899259026430157211949E-2L,
+};
+#ifdef __STDC__
+static const long double qS2[7] = {
+#else
+static long double qS2[7] = {
+#endif
+  8.610579901936193494609755345106129102676E-4L,
+  4.649054352710496997203474853066665869047E-2L,
+  8.104282924459837407218042945106320388339E-1L,
+  5.807730930825886427048038146088828206852E0L,
+  1.795310145936848873627710102199881642939E1L,
+  2.281313316875375733663657188888110605044E1L,
+  1.011242067883822301487154844458322200143E1L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+#ifdef __STDC__
+static long double
+qzero (long double x)
+#else
+static long double
+qzero (x)
+     long double x;
+#endif
+{
+#ifdef __STDC__
+  const long double *p, *q;
+#else
+  long double *p, *q;
+#endif
+  long double s, r, z;
+  int32_t ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  if (ix >= 0x4002)		/* x >= 8 */
+    {
+      p = qR8;
+      q = qS8;
+    }
+  else
+    {
+      i1 = (ix << 16) | (i0 >> 16);
+      if (i1 >= 0x40019174)	/* x >= 4.54541015625 */
+	{
+	  p = qR5;
+	  q = qS5;
+	}
+      else if (i1 >= 0x4000b6db)	/* x >= 2.85711669921875 */
+	{
+	  p = qR3;
+	  q = qS3;
+	}
+      else if (ix >= 0x4000)	/* x better be >= 2 */
+	{
+	  p = qR2;
+	  q = qS2;
+	}
+    }
+  z = one / (x * x);
+  r =
+    p[0] + z * (p[1] +
+		z * (p[2] + z * (p[3] + z * (p[4] + z * (p[5] + z * p[6])))));
+  s =
+    q[0] + z * (q[1] +
+		z * (q[2] +
+		     z * (q[3] + z * (q[4] + z * (q[5] + z * (q[6] + z))))));
+  return (-.125 + z * r / s) / x;
+}
Index: /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_j1l.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_j1l.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_j1l.c	(revision 2448)
@@ -0,0 +1,652 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Long double expansions are
+  Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
+  and are incorporated herein by permission of the author.  The author
+  reserves the right to distribute this material elsewhere under different
+  copying permissions.  These modifications are distributed here under
+  the following terms:
+
+    This 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.
+
+    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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA */
+
+/* __ieee754_j1(x), __ieee754_y1(x)
+ * Bessel function of the first and second kinds of order zero.
+ * Method -- j1(x):
+ *	1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ...
+ *	2. Reduce x to |x| since j1(x)=-j1(-x),  and
+ *	   for x in (0,2)
+ *		j1(x) = x/2 + x*z*R0/S0,  where z = x*x;
+ *	   for x in (2,inf)
+ * 		j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1))
+ * 		y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+ * 	   where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+ *	   as follow:
+ *		cos(x1) =  cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+ *			=  1/sqrt(2) * (sin(x) - cos(x))
+ *		sin(x1) =  sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ *			= -1/sqrt(2) * (sin(x) + cos(x))
+ * 	   (To avoid cancellation, use
+ *		sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * 	    to compute the worse one.)
+ *
+ *	3 Special cases
+ *		j1(nan)= nan
+ *		j1(0) = 0
+ *		j1(inf) = 0
+ *
+ * Method -- y1(x):
+ *	1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN
+ *	2. For x<2.
+ *	   Since
+ *		y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...)
+ *	   therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function.
+ *	   We use the following function to approximate y1,
+ *		y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2
+ *	   Note: For tiny x, 1/x dominate y1 and hence
+ *		y1(tiny) = -2/pi/tiny
+ *	3. For x>=2.
+ * 		y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+ * 	   where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+ *	   by method mentioned above.
+ */
+
+#include "libc-alias-glibc.h"
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static long double pone (long double), qone (long double);
+#else
+static long double pone (), qone ();
+#endif
+
+#ifdef __STDC__
+static const long double
+#else
+static long double
+#endif
+  huge = 1e4930L,
+ one = 1.0L,
+ invsqrtpi = 5.6418958354775628694807945156077258584405e-1L,
+  tpi =  6.3661977236758134307553505349005744813784e-1L,
+
+  /* J1(x) = .5 x + x x^2 R(x^2) / S(x^2)
+     0 <= x <= 2
+     Peak relative error 4.5e-21 */
+R[5] = {
+    -9.647406112428107954753770469290757756814E7L,
+    2.686288565865230690166454005558203955564E6L,
+    -3.689682683905671185891885948692283776081E4L,
+    2.195031194229176602851429567792676658146E2L,
+    -5.124499848728030297902028238597308971319E-1L,
+},
+
+  S[4] =
+{
+  1.543584977988497274437410333029029035089E9L,
+  2.133542369567701244002565983150952549520E7L,
+  1.394077011298227346483732156167414670520E5L,
+  5.252401789085732428842871556112108446506E2L,
+  /*  1.000000000000000000000000000000000000000E0L, */
+};
+
+#ifdef __STDC__
+static const long double zero = 0.0;
+#else
+static long double zero = 0.0;
+#endif
+
+
+#ifdef __STDC__
+long double
+__ieee754_j1l (long double x)
+#else
+long double
+__ieee754_j1l (x)
+     long double x;
+#endif
+{
+  long double z, c, r, s, ss, cc, u, v, y;
+  int32_t ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  if (ix >= 0x7fff)
+    return one / x;
+  y = fabsl (x);
+  if (ix >= 0x4000)
+    {				/* |x| >= 2.0 */
+      __sincosl (y, &s, &c);
+      ss = -s - c;
+      cc = s - c;
+      if (ix < 0x7ffe)
+	{			/* make sure y+y not overflow */
+	  z = __cosl (y + y);
+	  if ((s * c) > zero)
+	    cc = z / ss;
+	  else
+	    ss = z / cc;
+	}
+      /*
+       * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
+       * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
+       */
+      if (ix > 0x4080)
+	z = (invsqrtpi * cc) / __ieee754_sqrtl (y);
+      else
+	{
+	  u = pone (y);
+	  v = qone (y);
+	  z = invsqrtpi * (u * cc - v * ss) / __ieee754_sqrtl (y);
+	}
+      if (se & 0x8000)
+	return -z;
+      else
+	return z;
+    }
+  if (ix < 0x3fde) /* |x| < 2^-33 */
+    {
+      if (huge + x > one)
+	return 0.5 * x;		/* inexact if x!=0 necessary */
+    }
+  z = x * x;
+  r = z * (R[0] + z * (R[1]+ z * (R[2] + z * (R[3] + z * R[4]))));
+  s = S[0] + z * (S[1] + z * (S[2] + z * (S[3] + z)));
+  r *= x;
+  return (x * 0.5 + r / s);
+}
+
+
+/* Y1(x) = 2/pi * (log(x) * j1(x) - 1/x) + x R(x^2)
+   0 <= x <= 2
+   Peak relative error 2.3e-23 */
+#ifdef __STDC__
+static const long double U0[6] = {
+#else
+static long double U0[6] = {
+#endif
+  -5.908077186259914699178903164682444848615E10L,
+  1.546219327181478013495975514375773435962E10L,
+  -6.438303331169223128870035584107053228235E8L,
+  9.708540045657182600665968063824819371216E6L,
+  -6.138043997084355564619377183564196265471E4L,
+  1.418503228220927321096904291501161800215E2L,
+};
+#ifdef __STDC__
+static const long double V0[5] = {
+#else
+static long double V0[5] = {
+#endif
+  3.013447341682896694781964795373783679861E11L,
+  4.669546565705981649470005402243136124523E9L,
+  3.595056091631351184676890179233695857260E7L,
+  1.761554028569108722903944659933744317994E5L,
+  5.668480419646516568875555062047234534863E2L,
+  /*  1.000000000000000000000000000000000000000E0L, */
+};
+
+
+#ifdef __STDC__
+long double
+__ieee754_y1l (long double x)
+#else
+long double
+__ieee754_y1l (x)
+     long double x;
+#endif
+{
+  long double z, s, c, ss, cc, u, v;
+  int32_t ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
+  if (se & 0x8000)
+    return zero / (zero * x);
+  if (ix >= 0x7fff)
+    return one / (x + x * x);
+  if ((i0 | i1) == 0)
+    return -HUGE_VALL + x;  /* -inf and overflow exception.  */
+  if (ix >= 0x4000)
+    {				/* |x| >= 2.0 */
+      __sincosl (x, &s, &c);
+      ss = -s - c;
+      cc = s - c;
+      if (ix < 0x7fe00000)
+	{			/* make sure x+x not overflow */
+	  z = __cosl (x + x);
+	  if ((s * c) > zero)
+	    cc = z / ss;
+	  else
+	    ss = z / cc;
+	}
+      /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
+       * where x0 = x-3pi/4
+       *      Better formula:
+       *              cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+       *                      =  1/sqrt(2) * (sin(x) - cos(x))
+       *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+       *                      = -1/sqrt(2) * (cos(x) + sin(x))
+       * To avoid cancellation, use
+       *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+       * to compute the worse one.
+       */
+      if (ix > 0x4080)
+	z = (invsqrtpi * ss) / __ieee754_sqrtl (x);
+      else
+	{
+	  u = pone (x);
+	  v = qone (x);
+	  z = invsqrtpi * (u * ss + v * cc) / __ieee754_sqrtl (x);
+	}
+      return z;
+    }
+  if (ix <= 0x3fbe)
+    {				/* x < 2**-65 */
+      return (-tpi / x);
+    }
+  z = x * x;
+ u = U0[0] + z * (U0[1] + z * (U0[2] + z * (U0[3] + z * (U0[4] + z * U0[5]))));
+ v = V0[0] + z * (V0[1] + z * (V0[2] + z * (V0[3] + z * (V0[4] + z))));
+  return (x * (u / v) +
+	  tpi * (__ieee754_j1l (x) * __ieee754_logl (x) - one / x));
+}
+
+
+/* For x >= 8, the asymptotic expansions of pone is
+ *	1 + 15/128 s^2 - 4725/2^15 s^4 - ...,	where s = 1/x.
+ * We approximate pone by
+ * 	pone(x) = 1 + (R/S)
+ */
+
+/* J1(x) cosX + Y1(x) sinX  =  sqrt( 2/(pi x)) P1(x)
+   P1(x) = 1 + z^2 R(z^2), z=1/x
+   8 <= x <= inf  (0 <= z <= 0.125)
+   Peak relative error 5.2e-22  */
+
+#ifdef __STDC__
+static const long double pr8[7] = {
+#else
+static long double pr8[7] = {
+#endif
+  8.402048819032978959298664869941375143163E-9L,
+  1.813743245316438056192649247507255996036E-6L,
+  1.260704554112906152344932388588243836276E-4L,
+  3.439294839869103014614229832700986965110E-3L,
+  3.576910849712074184504430254290179501209E-2L,
+  1.131111483254318243139953003461511308672E-1L,
+  4.480715825681029711521286449131671880953E-2L,
+};
+#ifdef __STDC__
+static const long double ps8[6] = {
+#else
+static long double ps8[6] = {
+#endif
+  7.169748325574809484893888315707824924354E-8L,
+  1.556549720596672576431813934184403614817E-5L,
+  1.094540125521337139209062035774174565882E-3L,
+  3.060978962596642798560894375281428805840E-2L,
+  3.374146536087205506032643098619414507024E-1L,
+  1.253830208588979001991901126393231302559E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* J1(x) cosX + Y1(x) sinX  =  sqrt( 2/(pi x)) P1(x)
+   P1(x) = 1 + z^2 R(z^2), z=1/x
+   4.54541015625 <= x <= 8
+   Peak relative error 7.7e-22  */
+#ifdef __STDC__
+static const long double pr5[7] = {
+#else
+static long double pr5[7] = {
+#endif
+  4.318486887948814529950980396300969247900E-7L,
+  4.715341880798817230333360497524173929315E-5L,
+  1.642719430496086618401091544113220340094E-3L,
+  2.228688005300803935928733750456396149104E-2L,
+  1.142773760804150921573259605730018327162E-1L,
+  1.755576530055079253910829652698703791957E-1L,
+  3.218803858282095929559165965353784980613E-2L,
+};
+#ifdef __STDC__
+static const long double ps5[6] = {
+#else
+static long double ps5[6] = {
+#endif
+  3.685108812227721334719884358034713967557E-6L,
+  4.069102509511177498808856515005792027639E-4L,
+  1.449728676496155025507893322405597039816E-2L,
+  2.058869213229520086582695850441194363103E-1L,
+  1.164890985918737148968424972072751066553E0L,
+  2.274776933457009446573027260373361586841E0L,
+  /*  1.000000000000000000000000000000000000000E0L,*/
+};
+
+/* J1(x) cosX + Y1(x) sinX  =  sqrt( 2/(pi x)) P1(x)
+   P1(x) = 1 + z^2 R(z^2), z=1/x
+   2.85711669921875 <= x <= 4.54541015625
+   Peak relative error 6.5e-21  */
+#ifdef __STDC__
+static const long double pr3[7] = {
+#else
+static long double pr3[7] = {
+#endif
+  1.265251153957366716825382654273326407972E-5L,
+  8.031057269201324914127680782288352574567E-4L,
+  1.581648121115028333661412169396282881035E-2L,
+  1.179534658087796321928362981518645033967E-1L,
+  3.227936912780465219246440724502790727866E-1L,
+  2.559223765418386621748404398017602935764E-1L,
+  2.277136933287817911091370397134882441046E-2L,
+};
+#ifdef __STDC__
+static const long double ps3[6] = {
+#else
+static long double ps3[6] = {
+#endif
+  1.079681071833391818661952793568345057548E-4L,
+  6.986017817100477138417481463810841529026E-3L,
+  1.429403701146942509913198539100230540503E-1L,
+  1.148392024337075609460312658938700765074E0L,
+  3.643663015091248720208251490291968840882E0L,
+  3.990702269032018282145100741746633960737E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* J1(x) cosX + Y1(x) sinX  =  sqrt( 2/(pi x)) P1(x)
+   P1(x) = 1 + z^2 R(z^2), z=1/x
+   2 <= x <= 2.85711669921875
+   Peak relative error 3.5e-21  */
+#ifdef __STDC__
+static const long double pr2[7] = {
+#else
+static long double pr2[7] = {
+#endif
+  2.795623248568412225239401141338714516445E-4L,
+  1.092578168441856711925254839815430061135E-2L,
+  1.278024620468953761154963591853679640560E-1L,
+  5.469680473691500673112904286228351988583E-1L,
+  8.313769490922351300461498619045639016059E-1L,
+  3.544176317308370086415403567097130611468E-1L,
+  1.604142674802373041247957048801599740644E-2L,
+};
+#ifdef __STDC__
+static const long double ps2[6] = {
+#else
+static long double ps2[6] = {
+#endif
+  2.385605161555183386205027000675875235980E-3L,
+  9.616778294482695283928617708206967248579E-2L,
+  1.195215570959693572089824415393951258510E0L,
+  5.718412857897054829999458736064922974662E0L,
+  1.065626298505499086386584642761602177568E1L,
+  6.809140730053382188468983548092322151791E0L,
+ /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+
+#ifdef __STDC__
+static long double
+pone (long double x)
+#else
+static long double
+pone (x)
+     long double x;
+#endif
+{
+#ifdef __STDC__
+  const long double *p, *q;
+#else
+  long double *p, *q;
+#endif
+  long double z, r, s;
+  int32_t ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  if (ix >= 0x4002) /* x >= 8 */
+    {
+      p = pr8;
+      q = ps8;
+    }
+  else
+    {
+      i1 = (ix << 16) | (i0 >> 16);
+      if (i1 >= 0x40019174)	/* x >= 4.54541015625 */
+	{
+	  p = pr5;
+	  q = ps5;
+	}
+      else if (i1 >= 0x4000b6db)	/* x >= 2.85711669921875 */
+	{
+	  p = pr3;
+	  q = ps3;
+	}
+      else if (ix >= 0x4000)	/* x better be >= 2 */
+	{
+	  p = pr2;
+	  q = ps2;
+	}
+    }
+  z = one / (x * x);
+ r = p[0] + z * (p[1] +
+		 z * (p[2] + z * (p[3] + z * (p[4] + z * (p[5] + z * p[6])))));
+ s = q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * (q[5] + z)))));
+  return one + z * r / s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qone is
+ *	3/8 s - 105/1024 s^3 - ..., where s = 1/x.
+ * We approximate pone by
+ * 	qone(x) = s*(0.375 + (R/S))
+ */
+
+/* Y1(x)cosX - J1(x)sinX = sqrt( 2/(pi x)) Q1(x),
+   Q1(x) = z(.375 + z^2 R(z^2)), z=1/x
+   8 <= x <= inf
+   Peak relative error 8.3e-22 */
+
+#ifdef __STDC__
+static const long double qr8[7] = {
+#else
+static long double qr8[7] = {
+#endif
+  -5.691925079044209246015366919809404457380E-10L,
+  -1.632587664706999307871963065396218379137E-7L,
+  -1.577424682764651970003637263552027114600E-5L,
+  -6.377627959241053914770158336842725291713E-4L,
+  -1.087408516779972735197277149494929568768E-2L,
+  -6.854943629378084419631926076882330494217E-2L,
+  -1.055448290469180032312893377152490183203E-1L,
+};
+#ifdef __STDC__
+static const long double qs8[7] = {
+#else
+static long double qs8[7] = {
+#endif
+  5.550982172325019811119223916998393907513E-9L,
+  1.607188366646736068460131091130644192244E-6L,
+  1.580792530091386496626494138334505893599E-4L,
+  6.617859900815747303032860443855006056595E-3L,
+  1.212840547336984859952597488863037659161E-1L,
+  9.017885953937234900458186716154005541075E-1L,
+  2.201114489712243262000939120146436167178E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* Y1(x)cosX - J1(x)sinX = sqrt( 2/(pi x)) Q1(x),
+   Q1(x) = z(.375 + z^2 R(z^2)), z=1/x
+   4.54541015625 <= x <= 8
+   Peak relative error 4.1e-22 */
+#ifdef __STDC__
+static const long double qr5[7] = {
+#else
+static long double qr5[7] = {
+#endif
+  -6.719134139179190546324213696633564965983E-8L,
+  -9.467871458774950479909851595678622044140E-6L,
+  -4.429341875348286176950914275723051452838E-4L,
+  -8.539898021757342531563866270278505014487E-3L,
+  -6.818691805848737010422337101409276287170E-2L,
+  -1.964432669771684034858848142418228214855E-1L,
+  -1.333896496989238600119596538299938520726E-1L,
+};
+#ifdef __STDC__
+static const long double qs5[7] = {
+#else
+static long double qs5[7] = {
+#endif
+  6.552755584474634766937589285426911075101E-7L,
+  9.410814032118155978663509073200494000589E-5L,
+  4.561677087286518359461609153655021253238E-3L,
+  9.397742096177905170800336715661091535805E-2L,
+  8.518538116671013902180962914473967738771E-1L,
+  3.177729183645800174212539541058292579009E0L,
+  4.006745668510308096259753538973038902990E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* Y1(x)cosX - J1(x)sinX = sqrt( 2/(pi x)) Q1(x),
+   Q1(x) = z(.375 + z^2 R(z^2)), z=1/x
+   2.85711669921875 <= x <= 4.54541015625
+   Peak relative error 2.2e-21 */
+#ifdef __STDC__
+static const long double qr3[7] = {
+#else
+static long double qr3[7] = {
+#endif
+  -3.618746299358445926506719188614570588404E-6L,
+  -2.951146018465419674063882650970344502798E-4L,
+  -7.728518171262562194043409753656506795258E-3L,
+  -8.058010968753999435006488158237984014883E-2L,
+  -3.356232856677966691703904770937143483472E-1L,
+  -4.858192581793118040782557808823460276452E-1L,
+  -1.592399251246473643510898335746432479373E-1L,
+};
+#ifdef __STDC__
+static const long double qs3[7] = {
+#else
+static long double qs3[7] = {
+#endif
+  3.529139957987837084554591421329876744262E-5L,
+  2.973602667215766676998703687065066180115E-3L,
+  8.273534546240864308494062287908662592100E-2L,
+  9.613359842126507198241321110649974032726E-1L,
+  4.853923697093974370118387947065402707519E0L,
+  1.002671608961669247462020977417828796933E1L,
+  7.028927383922483728931327850683151410267E0L,
+  /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* Y1(x)cosX - J1(x)sinX = sqrt( 2/(pi x)) Q1(x),
+   Q1(x) = z(.375 + z^2 R(z^2)), z=1/x
+   2 <= x <= 2.85711669921875
+   Peak relative error 6.9e-22 */
+#ifdef __STDC__
+static const long double qr2[7] = {
+#else
+static long double qr2[7] = {
+#endif
+  -1.372751603025230017220666013816502528318E-4L,
+  -6.879190253347766576229143006767218972834E-3L,
+  -1.061253572090925414598304855316280077828E-1L,
+  -6.262164224345471241219408329354943337214E-1L,
+  -1.423149636514768476376254324731437473915E0L,
+  -1.087955310491078933531734062917489870754E0L,
+  -1.826821119773182847861406108689273719137E-1L,
+};
+#ifdef __STDC__
+static const long double qs2[7] = {
+#else
+static long double qs2[7] = {
+#endif
+  1.338768933634451601814048220627185324007E-3L,
+  7.071099998918497559736318523932241901810E-2L,
+  1.200511429784048632105295629933382142221E0L,
+  8.327301713640367079030141077172031825276E0L,
+  2.468479301872299311658145549931764426840E1L,
+  2.961179686096262083509383820557051621644E1L,
+  1.201402313144305153005639494661767354977E1L,
+ /* 1.000000000000000000000000000000000000000E0L, */
+};
+
+
+#ifdef __STDC__
+static long double
+qone (long double x)
+#else
+static long double
+qone (x)
+     long double x;
+#endif
+{
+#ifdef __STDC__
+  const long double *p, *q;
+#else
+  long double *p, *q;
+#endif
+  static long double s, r, z;
+  int32_t ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  if (ix >= 0x4002)		/* x >= 8 */
+    {
+      p = qr8;
+      q = qs8;
+    }
+  else
+    {
+      i1 = (ix << 16) | (i0 >> 16);
+      if (i1 >= 0x40019174)	/* x >= 4.54541015625 */
+	{
+	  p = qr5;
+	  q = qs5;
+	}
+      else if (i1 >= 0x4000b6db)	/* x >= 2.85711669921875 */
+	{
+	  p = qr3;
+	  q = qs3;
+	}
+      else if (ix >= 0x4000)	/* x better be >= 2 */
+	{
+	  p = qr2;
+	  q = qs2;
+	}
+    }
+  z = one / (x * x);
+  r =
+    p[0] + z * (p[1] +
+		z * (p[2] + z * (p[3] + z * (p[4] + z * (p[5] + z * p[6])))));
+  s =
+    q[0] + z * (q[1] +
+		z * (q[2] +
+		     z * (q[3] + z * (q[4] + z * (q[5] + z * (q[6] + z))))));
+  return (.375 + z * r / s) / x;
+}
Index: /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_jnl.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_jnl.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_jnl.c	(revision 2448)
@@ -0,0 +1,387 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modifications for long double are
+  Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
+  and are incorporated herein by permission of the author.  The author
+  reserves the right to distribute this material elsewhere under different
+  copying permissions.  These modifications are distributed here under
+  the following terms:
+
+    This 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.
+
+    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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA */
+
+/*
+ * __ieee754_jn(n, x), __ieee754_yn(n, x)
+ * floating point Bessel's function of the 1st and 2nd kind
+ * of order n
+ *
+ * Special cases:
+ *	y0(0)=y1(0)=yn(n,0) = -inf with overflow signal;
+ *	y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
+ * Note 2. About jn(n,x), yn(n,x)
+ *	For n=0, j0(x) is called,
+ *	for n=1, j1(x) is called,
+ *	for n<x, forward recursion us used starting
+ *	from values of j0(x) and j1(x).
+ *	for n>x, a continued fraction approximation to
+ *	j(n,x)/j(n-1,x) is evaluated and then backward
+ *	recursion is used starting from a supposed value
+ *	for j(n,x). The resulting value of j(0,x) is
+ *	compared with the actual value to correct the
+ *	supposed value of j(n,x).
+ *
+ *	yn(n,x) is similar in all respects, except
+ *	that forward recursion is used for all
+ *	values of n>1.
+ *
+ */
+
+#include "libc-alias-glibc.h"
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const long double
+#else
+static long double
+#endif
+  invsqrtpi = 5.64189583547756286948079e-1L, two = 2.0e0L, one = 1.0e0L;
+
+#ifdef __STDC__
+static const long double zero = 0.0L;
+#else
+static long double zero = 0.0L;
+#endif
+
+#ifdef __STDC__
+long double
+__ieee754_jnl (int n, long double x)
+#else
+long double
+__ieee754_jnl (n, x)
+     int n;
+     long double x;
+#endif
+{
+  u_int32_t se, i0, i1;
+  int32_t i, ix, sgn;
+  long double a, b, temp, di;
+  long double z, w;
+
+  /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
+   * Thus, J(-n,x) = J(n,-x)
+   */
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+
+  /* if J(n,NaN) is NaN */
+  if ((ix == 0x7fff) && ((i0 & 0x7fffffff) != 0))
+    return x + x;
+  if (n < 0)
+    {
+      n = -n;
+      x = -x;
+      se ^= 0x8000;
+    }
+  if (n == 0)
+    return (__ieee754_j0l (x));
+  if (n == 1)
+    return (__ieee754_j1l (x));
+  sgn = (n & 1) & (se >> 15);	/* even n -- 0, odd n -- sign(x) */
+  x = fabsl (x);
+  if ((ix | i0 | i1) == 0 || ix >= 0x7fff)	/* if x is 0 or inf */
+    b = zero;
+  else if ((long double) n <= x)
+    {
+      /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
+      if (ix >= 0x412D)
+	{			/* x > 2**302 */
+
+	  /* ??? This might be a futile gesture.
+	     If x exceeds X_TLOSS anyway, the wrapper function
+	     will set the result to zero. */
+
+	  /* (x >> n**2)
+	   *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+	   *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+	   *      Let s=sin(x), c=cos(x),
+	   *          xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+	   *
+	   *             n    sin(xn)*sqt2    cos(xn)*sqt2
+	   *          ----------------------------------
+	   *             0     s-c             c+s
+	   *             1    -s-c            -c+s
+	   *             2    -s+c            -c-s
+	   *             3     s+c             c-s
+	   */
+	  long double s;
+	  long double c;
+	  __sincosl (x, &s, &c);
+	  switch (n & 3)
+	    {
+	    case 0:
+	      temp = c + s;
+	      break;
+	    case 1:
+	      temp = -c + s;
+	      break;
+	    case 2:
+	      temp = -c - s;
+	      break;
+	    case 3:
+	      temp = c - s;
+	      break;
+	    }
+	  b = invsqrtpi * temp / __ieee754_sqrtl (x);
+	}
+      else
+	{
+	  a = __ieee754_j0l (x);
+	  b = __ieee754_j1l (x);
+	  for (i = 1; i < n; i++)
+	    {
+	      temp = b;
+	      b = b * ((long double) (i + i) / x) - a;	/* avoid underflow */
+	      a = temp;
+	    }
+	}
+    }
+  else
+    {
+      if (ix < 0x3fde)
+	{			/* x < 2**-33 */
+	  /* x is tiny, return the first Taylor expansion of J(n,x)
+	   * J(n,x) = 1/n!*(x/2)^n  - ...
+	   */
+	  if (n >= 400)		/* underflow, result < 10^-4952 */
+	    b = zero;
+	  else
+	    {
+	      temp = x * 0.5;
+	      b = temp;
+	      for (a = one, i = 2; i <= n; i++)
+		{
+		  a *= (long double) i;	/* a = n! */
+		  b *= temp;	/* b = (x/2)^n */
+		}
+	      b = b / a;
+	    }
+	}
+      else
+	{
+	  /* use backward recurrence */
+	  /*                      x      x^2      x^2
+	   *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
+	   *                      2n  - 2(n+1) - 2(n+2)
+	   *
+	   *                      1      1        1
+	   *  (for large x)   =  ----  ------   ------   .....
+	   *                      2n   2(n+1)   2(n+2)
+	   *                      -- - ------ - ------ -
+	   *                       x     x         x
+	   *
+	   * Let w = 2n/x and h=2/x, then the above quotient
+	   * is equal to the continued fraction:
+	   *                  1
+	   *      = -----------------------
+	   *                     1
+	   *         w - -----------------
+	   *                        1
+	   *              w+h - ---------
+	   *                     w+2h - ...
+	   *
+	   * To determine how many terms needed, let
+	   * Q(0) = w, Q(1) = w(w+h) - 1,
+	   * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+	   * When Q(k) > 1e4      good for single
+	   * When Q(k) > 1e9      good for double
+	   * When Q(k) > 1e17     good for quadruple
+	   */
+	  /* determine k */
+	  long double t, v;
+	  long double q0, q1, h, tmp;
+	  int32_t k, m;
+	  w = (n + n) / (long double) x;
+	  h = 2.0L / (long double) x;
+	  q0 = w;
+	  z = w + h;
+	  q1 = w * z - 1.0L;
+	  k = 1;
+	  while (q1 < 1.0e11L)
+	    {
+	      k += 1;
+	      z += h;
+	      tmp = z * q1 - q0;
+	      q0 = q1;
+	      q1 = tmp;
+	    }
+	  m = n + n;
+	  for (t = zero, i = 2 * (n + k); i >= m; i -= 2)
+	    t = one / (i / x - t);
+	  a = t;
+	  b = one;
+	  /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+	   *  Hence, if n*(log(2n/x)) > ...
+	   *  single 8.8722839355e+01
+	   *  double 7.09782712893383973096e+02
+	   *  long double 1.1356523406294143949491931077970765006170e+04
+	   *  then recurrent value may overflow and the result is
+	   *  likely underflow to zero
+	   */
+	  tmp = n;
+	  v = two / x;
+	  tmp = tmp * __ieee754_logl (fabsl (v * tmp));
+
+	  if (tmp < 1.1356523406294143949491931077970765006170e+04L)
+	    {
+	      for (i = n - 1, di = (long double) (i + i); i > 0; i--)
+		{
+		  temp = b;
+		  b *= di;
+		  b = b / x - a;
+		  a = temp;
+		  di -= two;
+		}
+	    }
+	  else
+	    {
+	      for (i = n - 1, di = (long double) (i + i); i > 0; i--)
+		{
+		  temp = b;
+		  b *= di;
+		  b = b / x - a;
+		  a = temp;
+		  di -= two;
+		  /* scale b to avoid spurious overflow */
+		  if (b > 1e100L)
+		    {
+		      a /= b;
+		      t /= b;
+		      b = one;
+		    }
+		}
+	    }
+	  b = (t * __ieee754_j0l (x) / b);
+	}
+    }
+  if (sgn == 1)
+    return -b;
+  else
+    return b;
+}
+
+#ifdef __STDC__
+long double
+__ieee754_ynl (int n, long double x)
+#else
+long double
+__ieee754_ynl (n, x)
+     int n;
+     long double x;
+#endif
+{
+  u_int32_t se, i0, i1;
+  int32_t i, ix;
+  int32_t sign;
+  long double a, b, temp;
+
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  /* if Y(n,NaN) is NaN */
+  if ((ix == 0x7fff) && ((i0 & 0x7fffffff) != 0))
+    return x + x;
+  if ((ix | i0 | i1) == 0)
+    return -HUGE_VALL + x;  /* -inf and overflow exception.  */
+  if (se & 0x8000)
+    return zero / (zero * x);
+  sign = 1;
+  if (n < 0)
+    {
+      n = -n;
+      sign = 1 - ((n & 1) << 1);
+    }
+  if (n == 0)
+    return (__ieee754_y0l (x));
+  if (n == 1)
+    return (sign * __ieee754_y1l (x));
+  if (ix == 0x7fff)
+    return zero;
+  if (ix >= 0x412D)
+    {				/* x > 2**302 */
+
+      /* ??? See comment above on the possible futility of this.  */
+
+      /* (x >> n**2)
+       *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+       *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+       *      Let s=sin(x), c=cos(x),
+       *          xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+       *
+       *             n    sin(xn)*sqt2    cos(xn)*sqt2
+       *          ----------------------------------
+       *             0     s-c             c+s
+       *             1    -s-c            -c+s
+       *             2    -s+c            -c-s
+       *             3     s+c             c-s
+       */
+      long double s;
+      long double c;
+      __sincosl (x, &s, &c);
+      switch (n & 3)
+	{
+	case 0:
+	  temp = s - c;
+	  break;
+	case 1:
+	  temp = -s - c;
+	  break;
+	case 2:
+	  temp = -s + c;
+	  break;
+	case 3:
+	  temp = s + c;
+	  break;
+	}
+      b = invsqrtpi * temp / __ieee754_sqrtl (x);
+    }
+  else
+    {
+      a = __ieee754_y0l (x);
+      b = __ieee754_y1l (x);
+      /* quit if b is -inf */
+      GET_LDOUBLE_WORDS (se, i0, i1, b);
+      for (i = 1; i < n && se != 0xffff; i++)
+	{
+	  temp = b;
+	  b = ((long double) (i + i) / x) * b - a;
+	  GET_LDOUBLE_WORDS (se, i0, i1, b);
+	  a = temp;
+	}
+    }
+  if (sign > 0)
+    return b;
+  else
+    return -b;
+}
Index: /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_lgammal_r.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_lgammal_r.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/e_lgammal_r.c	(revision 2448)
@@ -0,0 +1,447 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Long double expansions are
+  Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
+  and are incorporated herein by permission of the author.  The author
+  reserves the right to distribute this material elsewhere under different
+  copying permissions.  These modifications are distributed here under
+  the following terms:
+
+    This 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.
+
+    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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA */
+
+/* __ieee754_lgammal_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method:
+ *   1. Argument Reduction for 0 < x <= 8
+ *	Since gamma(1+s)=s*gamma(s), for x in [0,8], we may
+ *	reduce x to a number in [1.5,2.5] by
+ *		lgamma(1+s) = log(s) + lgamma(s)
+ *	for example,
+ *		lgamma(7.3) = log(6.3) + lgamma(6.3)
+ *			    = log(6.3*5.3) + lgamma(5.3)
+ *			    = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)
+ *   2. Polynomial approximation of lgamma around its
+ *	minimun ymin=1.461632144968362245 to maintain monotonicity.
+ *	On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use
+ *		Let z = x-ymin;
+ *		lgamma(x) = -1.214862905358496078218 + z^2*poly(z)
+ *   2. Rational approximation in the primary interval [2,3]
+ *	We use the following approximation:
+ *		s = x-2.0;
+ *		lgamma(x) = 0.5*s + s*P(s)/Q(s)
+ *	Our algorithms are based on the following observation
+ *
+ *                             zeta(2)-1    2    zeta(3)-1    3
+ * lgamma(2+s) = s*(1-Euler) + --------- * s  -  --------- * s  + ...
+ *                                 2                 3
+ *
+ *	where Euler = 0.5771... is the Euler constant, which is very
+ *	close to 0.5.
+ *
+ *   3. For x>=8, we have
+ *	lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+....
+ *	(better formula:
+ *	   lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...)
+ *	Let z = 1/x, then we approximation
+ *		f(z) = lgamma(x) - (x-0.5)(log(x)-1)
+ *	by
+ *				    3       5             11
+ *		w = w0 + w1*z + w2*z  + w3*z  + ... + w6*z
+ *
+ *   4. For negative x, since (G is gamma function)
+ *		-x*G(-x)*G(x) = pi/sin(pi*x),
+ *	we have
+ *		G(x) = pi/(sin(pi*x)*(-x)*G(-x))
+ *	since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0
+ *	Hence, for x<0, signgam = sign(sin(pi*x)) and
+ *		lgamma(x) = log(|Gamma(x)|)
+ *			  = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);
+ *	Note: one should avoid compute pi*(-x) directly in the
+ *	      computation of sin(pi*(-x)).
+ *
+ *   5. Special Cases
+ *		lgamma(2+s) ~ s*(1-Euler) for tiny s
+ *		lgamma(1)=lgamma(2)=0
+ *		lgamma(x) ~ -log(x) for tiny x
+ *		lgamma(0) = lgamma(inf) = inf
+ *		lgamma(-integer) = +-inf
+ *
+ */
+
+#include "libc-alias-glibc.h"
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const long double
+#else
+static long double
+#endif
+  half = 0.5L,
+  one = 1.0L,
+  pi = 3.14159265358979323846264L,
+  two63 = 9.223372036854775808e18L,
+
+  /* lgam(1+x) = 0.5 x + x a(x)/b(x)
+     -0.268402099609375 <= x <= 0
+     peak relative error 6.6e-22 */
+  a0 = -6.343246574721079391729402781192128239938E2L,
+  a1 =  1.856560238672465796768677717168371401378E3L,
+  a2 =  2.404733102163746263689288466865843408429E3L,
+  a3 =  8.804188795790383497379532868917517596322E2L,
+  a4 =  1.135361354097447729740103745999661157426E2L,
+  a5 =  3.766956539107615557608581581190400021285E0L,
+
+  b0 =  8.214973713960928795704317259806842490498E3L,
+  b1 =  1.026343508841367384879065363925870888012E4L,
+  b2 =  4.553337477045763320522762343132210919277E3L,
+  b3 =  8.506975785032585797446253359230031874803E2L,
+  b4 =  6.042447899703295436820744186992189445813E1L,
+  /* b5 =  1.000000000000000000000000000000000000000E0 */
+
+
+  tc =  1.4616321449683623412626595423257213284682E0L,
+  tf = -1.2148629053584961146050602565082954242826E-1,/* double precision */
+/* tt = (tail of tf), i.e. tf + tt has extended precision. */
+  tt = 3.3649914684731379602768989080467587736363E-18L,
+  /* lgam ( 1.4616321449683623412626595423257213284682E0 ) =
+-1.2148629053584960809551455717769158215135617312999903886372437313313530E-1 */
+
+  /* lgam (x + tc) = tf + tt + x g(x)/h(x)
+     - 0.230003726999612341262659542325721328468 <= x
+     <= 0.2699962730003876587373404576742786715318
+     peak relative error 2.1e-21 */
+  g0 = 3.645529916721223331888305293534095553827E-18L,
+  g1 = 5.126654642791082497002594216163574795690E3L,
+  g2 = 8.828603575854624811911631336122070070327E3L,
+  g3 = 5.464186426932117031234820886525701595203E3L,
+  g4 = 1.455427403530884193180776558102868592293E3L,
+  g5 = 1.541735456969245924860307497029155838446E2L,
+  g6 = 4.335498275274822298341872707453445815118E0L,
+
+  h0 = 1.059584930106085509696730443974495979641E4L,
+  h1 =  2.147921653490043010629481226937850618860E4L,
+  h2 = 1.643014770044524804175197151958100656728E4L,
+  h3 =  5.869021995186925517228323497501767586078E3L,
+  h4 =  9.764244777714344488787381271643502742293E2L,
+  h5 =  6.442485441570592541741092969581997002349E1L,
+  /* h6 = 1.000000000000000000000000000000000000000E0 */
+
+
+  /* lgam (x+1) = -0.5 x + x u(x)/v(x)
+     -0.100006103515625 <= x <= 0.231639862060546875
+     peak relative error 1.3e-21 */
+  u0 = -8.886217500092090678492242071879342025627E1L,
+  u1 =  6.840109978129177639438792958320783599310E2L,
+  u2 =  2.042626104514127267855588786511809932433E3L,
+  u3 =  1.911723903442667422201651063009856064275E3L,
+  u4 =  7.447065275665887457628865263491667767695E2L,
+  u5 =  1.132256494121790736268471016493103952637E2L,
+  u6 =  4.484398885516614191003094714505960972894E0L,
+
+  v0 =  1.150830924194461522996462401210374632929E3L,
+  v1 =  3.399692260848747447377972081399737098610E3L,
+  v2 =  3.786631705644460255229513563657226008015E3L,
+  v3 =  1.966450123004478374557778781564114347876E3L,
+  v4 =  4.741359068914069299837355438370682773122E2L,
+  v5 =  4.508989649747184050907206782117647852364E1L,
+  /* v6 =  1.000000000000000000000000000000000000000E0 */
+
+
+  /* lgam (x+2) = .5 x + x s(x)/r(x)
+     0 <= x <= 1
+     peak relative error 7.2e-22 */
+  s0 =  1.454726263410661942989109455292824853344E6L,
+  s1 = -3.901428390086348447890408306153378922752E6L,
+  s2 = -6.573568698209374121847873064292963089438E6L,
+  s3 = -3.319055881485044417245964508099095984643E6L,
+  s4 = -7.094891568758439227560184618114707107977E5L,
+  s5 = -6.263426646464505837422314539808112478303E4L,
+  s6 = -1.684926520999477529949915657519454051529E3L,
+
+  r0 = -1.883978160734303518163008696712983134698E7L,
+  r1 = -2.815206082812062064902202753264922306830E7L,
+  r2 = -1.600245495251915899081846093343626358398E7L,
+  r3 = -4.310526301881305003489257052083370058799E6L,
+  r4 = -5.563807682263923279438235987186184968542E5L,
+  r5 = -3.027734654434169996032905158145259713083E4L,
+  r6 = -4.501995652861105629217250715790764371267E2L,
+  /* r6 =  1.000000000000000000000000000000000000000E0 */
+
+
+/* lgam(x) = ( x - 0.5 ) * log(x) - x + LS2PI + 1/x w(1/x^2)
+   x >= 8
+   Peak relative error 1.51e-21
+   w0 = LS2PI - 0.5 */
+  w0 =  4.189385332046727417803e-1L,
+  w1 =  8.333333333333331447505E-2L,
+  w2 = -2.777777777750349603440E-3L,
+  w3 =  7.936507795855070755671E-4L,
+  w4 = -5.952345851765688514613E-4L,
+  w5 =  8.412723297322498080632E-4L,
+  w6 = -1.880801938119376907179E-3L,
+  w7 =  4.885026142432270781165E-3L;
+
+#ifdef __STDC__
+static const long double zero = 0.0L;
+#else
+static long double zero = 0.0L;
+#endif
+
+#ifdef __STDC__
+static long double
+sin_pi (long double x)
+#else
+static long double
+sin_pi (x)
+     long double x;
+#endif
+{
+  long double y, z;
+  int n, ix;
+  u_int32_t se, i0, i1;
+
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+  ix = (ix << 16) | (i0 >> 16);
+  if (ix < 0x3ffd8000) /* 0.25 */
+    return __sinl (pi * x);
+  y = -x;			/* x is assume negative */
+
+  /*
+   * argument reduction, make sure inexact flag not raised if input
+   * is an integer
+   */
+  z = __floorl (y);
+  if (z != y)
+    {				/* inexact anyway */
+      y  *= 0.5;
+      y = 2.0*(y - __floorl(y));		/* y = |x| mod 2.0 */
+      n = (int) (y*4.0);
+    }
+  else
+    {
+      if (ix >= 0x403f8000)  /* 2^64 */
+	{
+	  y = zero; n = 0;                 /* y must be even */
+	}
+      else
+	{
+	if (ix < 0x403e8000)  /* 2^63 */
+	  z = y + two63;	/* exact */
+	GET_LDOUBLE_WORDS (se, i0, i1, z);
+	n = i1 & 1;
+	y  = n;
+	n <<= 2;
+      }
+    }
+
+  switch (n)
+    {
+    case 0:
+      y = __sinl (pi * y);
+      break;
+    case 1:
+    case 2:
+      y = __cosl (pi * (half - y));
+      break;
+    case 3:
+    case 4:
+      y = __sinl (pi * (one - y));
+      break;
+    case 5:
+    case 6:
+      y = -__cosl (pi * (y - 1.5));
+      break;
+    default:
+      y = __sinl (pi * (y - 2.0));
+      break;
+    }
+  return -y;
+}
+
+
+#ifdef __STDC__
+long double
+__ieee754_lgammal_r (long double x, int *signgamp)
+#else
+long double
+__ieee754_lgammal_r (x, signgamp)
+     long double x;
+     int *signgamp;
+#endif
+{
+  long double t, y, z, nadj, p, p1, p2, q, r, w;
+  int i, ix;
+  u_int32_t se, i0, i1;
+
+  *signgamp = 1;
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+  ix = se & 0x7fff;
+
+  if ((ix | i0 | i1) == 0)
+    return one / fabsl (x);
+
+  ix = (ix << 16) | (i0 >> 16);
+
+  /* purge off +-inf, NaN, +-0, and negative arguments */
+  if (ix >= 0x7fff0000)
+    return x * x;
+
+  if (ix < 0x3fc08000) /* 2^-63 */
+    {				/* |x|<2**-63, return -log(|x|) */
+      if (se & 0x8000)
+	{
+	  *signgamp = -1;
+	  return -__ieee754_logl (-x);
+	}
+      else
+	return -__ieee754_logl (x);
+    }
+  if (se & 0x8000)
+    {
+      t = sin_pi (x);
+      if (t == zero)
+	return one / fabsl (t);	/* -integer */
+      nadj = __ieee754_logl (pi / fabsl (t * x));
+      if (t < zero)
+	*signgamp = -1;
+      x = -x;
+    }
+
+  /* purge off 1 and 2 */
+  if ((((ix - 0x3fff8000) | i0 | i1) == 0)
+      || (((ix - 0x40008000) | i0 | i1) == 0))
+    r = 0;
+  else if (ix < 0x40008000) /* 2.0 */
+    {
+      /* x < 2.0 */
+      if (ix <= 0x3ffee666) /* 8.99993896484375e-1 */
+	{
+	  /* lgamma(x) = lgamma(x+1) - log(x) */
+	  r = -__ieee754_logl (x);
+	  if (ix >= 0x3ffebb4a) /* 7.31597900390625e-1 */
+	    {
+	      y = x - one;
+	      i = 0;
+	    }
+	  else if (ix >= 0x3ffced33)/* 2.31639862060546875e-1 */
+	    {
+	      y = x - (tc - one);
+	      i = 1;
+	    }
+	  else
+	    {
+	      /* x < 0.23 */
+	      y = x;
+	      i = 2;
+	    }
+	}
+      else
+	{
+	  r = zero;
+	  if (ix >= 0x3fffdda6) /* 1.73162841796875 */
+	    {
+	      /* [1.7316,2] */
+	      y = x - 2.0;
+	      i = 0;
+	    }
+	  else if (ix >= 0x3fff9da6)/* 1.23162841796875 */
+	    {
+	      /* [1.23,1.73] */
+	      y = x - tc;
+	      i = 1;
+	    }
+	  else
+	    {
+	      /* [0.9, 1.23] */
+	      y = x - one;
+	      i = 2;
+	    }
+	}
+      switch (i)
+	{
+	case 0:
+	  p1 = a0 + y * (a1 + y * (a2 + y * (a3 + y * (a4 + y * a5))));
+	  p2 = b0 + y * (b1 + y * (b2 + y * (b3 + y * (b4 + y))));
+	  r += half * y + y * p1/p2;
+	  break;
+	case 1:
+    p1 = g0 + y * (g1 + y * (g2 + y * (g3 + y * (g4 + y * (g5 + y * g6)))));
+    p2 = h0 + y * (h1 + y * (h2 + y * (h3 + y * (h4 + y * (h5 + y)))));
+    p = tt + y * p1/p2;
+	  r += (tf + p);
+	  break;
+	case 2:
+ p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * (u5 + y * u6))))));
+      p2 = v0 + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * (v5 + y)))));
+	  r += (-half * y + p1 / p2);
+	}
+    }
+  else if (ix < 0x40028000) /* 8.0 */
+    {
+      /* x < 8.0 */
+      i = (int) x;
+      t = zero;
+      y = x - (double) i;
+  p = y *
+     (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6))))));
+  q = r0 + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * (r6 + y))))));
+      r = half * y + p / q;
+      z = one;			/* lgamma(1+s) = log(s) + lgamma(s) */
+      switch (i)
+	{
+	case 7:
+	  z *= (y + 6.0);	/* FALLTHRU */
+	case 6:
+	  z *= (y + 5.0);	/* FALLTHRU */
+	case 5:
+	  z *= (y + 4.0);	/* FALLTHRU */
+	case 4:
+	  z *= (y + 3.0);	/* FALLTHRU */
+	case 3:
+	  z *= (y + 2.0);	/* FALLTHRU */
+	  r += __ieee754_logl (z);
+	  break;
+	}
+    }
+  else if (ix < 0x40418000) /* 2^66 */
+    {
+      /* 8.0 <= x < 2**66 */
+      t = __ieee754_logl (x);
+      z = one / x;
+      y = z * z;
+      w = w0 + z * (w1
+          + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * (w6 + y * w7))))));
+      r = (x - half) * (t - one) + w;
+    }
+  else
+    /* 2**66 <= x <= inf */
+    r = x * (__ieee754_logl (x) - one);
+  if (se & 0x8000)
+    r = nadj - r;
+  return r;
+}
Index: /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/math_ldbl.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/math_ldbl.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/math_ldbl.h	(revision 2448)
@@ -0,0 +1,98 @@
+#ifndef _MATH_PRIVATE_H_
+#error "Never use <math_ldbl.h> directly; include <math_private.h> instead."
+#endif
+
+/* A union which permits us to convert between a long double and
+   three 32 bit ints.  */
+
+#if __FLOAT_WORD_ORDER == BIG_ENDIAN
+
+typedef union
+{
+  long double value;
+  struct
+  {
+    int sign_exponent:16;
+    unsigned int empty:16;
+    u_int32_t msw;
+    u_int32_t lsw;
+  } parts;
+} ieee_long_double_shape_type;
+
+#endif
+
+#if __FLOAT_WORD_ORDER == LITTLE_ENDIAN
+
+typedef union
+{
+  long double value;
+  struct
+  {
+    u_int32_t lsw;
+    u_int32_t msw;
+    int sign_exponent:16;
+    unsigned int empty:16;
+  } parts;
+} ieee_long_double_shape_type;
+
+#endif
+
+/* Get three 32 bit ints from a double.  */
+
+#define GET_LDOUBLE_WORDS(exp,ix0,ix1,d)			\
+do {								\
+  ieee_long_double_shape_type ew_u;				\
+  ew_u.value = (d);						\
+  (exp) = ew_u.parts.sign_exponent;				\
+  (ix0) = ew_u.parts.msw;					\
+  (ix1) = ew_u.parts.lsw;					\
+} while (0)
+
+/* Set a double from two 32 bit ints.  */
+
+#define SET_LDOUBLE_WORDS(d,exp,ix0,ix1)			\
+do {								\
+  ieee_long_double_shape_type iw_u;				\
+  iw_u.parts.sign_exponent = (exp);				\
+  iw_u.parts.msw = (ix0);					\
+  iw_u.parts.lsw = (ix1);					\
+  (d) = iw_u.value;						\
+} while (0)
+
+/* Get the more significant 32 bits of a long double mantissa.  */
+
+#define GET_LDOUBLE_MSW(v,d)					\
+do {								\
+  ieee_long_double_shape_type sh_u;				\
+  sh_u.value = (d);						\
+  (v) = sh_u.parts.msw;						\
+} while (0)
+
+/* Set the more significant 32 bits of a long double mantissa from an int.  */
+
+#define SET_LDOUBLE_MSW(d,v)					\
+do {								\
+  ieee_long_double_shape_type sh_u;				\
+  sh_u.value = (d);						\
+  sh_u.parts.msw = (v);						\
+  (d) = sh_u.value;						\
+} while (0)
+
+/* Get int from the exponent of a long double.  */
+
+#define GET_LDOUBLE_EXP(exp,d)					\
+do {								\
+  ieee_long_double_shape_type ge_u;				\
+  ge_u.value = (d);						\
+  (exp) = ge_u.parts.sign_exponent;				\
+} while (0)
+
+/* Set exponent of a long double from an int.  */
+
+#define SET_LDOUBLE_EXP(d,exp)					\
+do {								\
+  ieee_long_double_shape_type se_u;				\
+  se_u.value = (d);						\
+  se_u.parts.sign_exponent = (exp);				\
+  (d) = se_u.value;						\
+} while (0)
Index: /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/math_private.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/math_private.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/ieee754/ldbl-96/math_private.h	(revision 2448)
@@ -0,0 +1,3 @@
+#include <endian.h>
+#include "../../../../msun/src/math_private.h"
+#include "math_ldbl.h"
Index: /trunk/libc/src/glibc/sysdeps/os2/__spawni.c
===================================================================
--- /trunk/libc/src/glibc/sysdeps/os2/__spawni.c	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/os2/__spawni.c	(revision 2448)
@@ -0,0 +1,387 @@
+/* $Id$ */
+/** @file
+ *
+ * System dependent worker for POSIX spawn.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of Innotek LIBC.
+ *
+ * Innotek LIBC 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Innotek LIBC 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 Innotek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <spawn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <process.h>
+#include <emx/io.h>
+#include <emx/umalloc.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+#include "../../posix/spawn_int.h"
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+typedef struct RestoreAction
+{
+    int fdClose;                        /* handle to close before restoring fdRestore. */
+    int fdRestore;                      /* fd which fdSaved is a saved version of. */
+    int fdSaved;                        /* close-on-exec dup of fdRestore. */
+    int fSavedCoE;                      /* the original close-on-exec flag. */
+} RESTOREACTION, *PRESTOREACTION;
+
+/**
+ * Save the handle fdToSave save it's Close-on-Exec flag in *pfCoE and the
+ * duplicate save handle in *pfdSaved.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure. No handles were duplicated.
+ * @param   fdToSave    Handle to save.
+ * @param   pfdMin      First usable handle for the duplicate save handle.
+ * @param   pfdSaved    Where to store the saved handle.
+ *                      Set to -1 on failure.
+ * @param   pfCoE       Where to store the close-on-exec flag.
+ *                      Set to -1 on failure.
+ */
+static int save_handle(int fdToSave, int *pfdMin, PRESTOREACTION pRAction)
+{
+    int fdSaved;
+    int fSavedCoE;
+
+    pRAction->fdRestore = - 1;
+    pRAction->fdSaved = -1;
+    pRAction->fSavedCoE = -1;
+    if (!__libc_FH(fdToSave))
+        return 0;                       /* no such handle. */
+
+    /* Get close on exec flag. */
+    fSavedCoE = fcntl(fdToSave, F_GETFD);
+    if (fSavedCoE < 0)
+        return -1;
+
+    /* find free handle and duplicate fdToSave onto it */
+    while (__libc_FH(*pfdMin))
+        (*pfdMin)++;
+    if (*pfdMin >= 0x10000)
+        return -1;
+    fdSaved = dup2(fdToSave, *pfdMin);
+    if (fdSaved < 0)
+        return -1;
+
+    /* marke it close on exit. */
+    if (    !(fSavedCoE & FD_CLOEXEC)
+        &&  fcntl(fdSaved, F_SETFD, FD_CLOEXEC) < 0)
+    {
+        /* shit! cleanup */
+        close(fdSaved);
+        return -1;
+    }
+    pRAction->fdRestore = fdToSave;
+    pRAction->fdSaved   = fdSaved;
+    pRAction->fSavedCoE = fSavedCoE;
+    return 0;
+}
+
+
+/**
+ * Restore a handle saved with save_handle().
+ *
+ * @param   fdToRestore The original handle which is to be restored.
+ * @param   pRAction    Restore action structure.
+ */
+static void restore_handle(PRESTOREACTION pRAction)
+{
+    int saved_errno = errno;
+
+    if (pRAction->fdClose >= 0)
+    {
+#ifndef DEBUG
+        close(pRAction->fdClose);
+#else
+        if (close(pRAction->fdClose))
+            assert(!"__spawni: restore close() failed");
+#endif
+        pRAction->fdClose = -1;
+    }
+
+    if (pRAction->fdSaved >= 0)
+    {
+#ifndef DEBUG
+        dup2(pRAction->fdSaved, pRAction->fdRestore);
+        close(pRAction->fdSaved);
+        fcntl(pRAction->fdRestore, F_SETFD, pRAction->fSavedCoE);
+#else
+        if (dup2(pRAction->fdSaved, pRAction->fdRestore) < 0)
+            assert(!"__spawni: restore dup2() failed");
+        if (close(pRAction->fdSaved) < 0)
+            assert(!"__spawni: restore close(saved) failed");
+        if (fcntl(pRAction->fdRestore, F_SETFD, pRAction->fSavedCoE) < 0)
+            assert(!"__spawni: restore fcntl() failed");
+#endif
+        pRAction->fdSaved = -1;
+        pRAction->fSavedCoE = -1;
+    }
+
+    errno = saved_errno;
+}
+
+
+/* Internal OS dependent worker. */
+int __spawni(
+    pid_t *pid,
+    const char *path,
+    const posix_spawn_file_actions_t *file_actions,
+    const posix_spawnattr_t *attrp,
+    char *const argv[],
+    char *const envp[],
+    int use_path)
+{
+    int             iFileAction = 0;    /* where to start cleaning up file actions from.  */
+    PRESTOREACTION  paRestore = NULL;
+    int             rc;                 /* result. */
+    pid_t           pidChild;
+#if 0 /* requires some process management from LIBC */
+    unsigned    fFlags = attrp ? attrp->__flags : 0;
+
+    /*
+     * Create child process.
+     */
+    pChild = __libc_PSExec();
+
+    /*
+     * Signal settings to be picked up by the child.
+     */
+    if (fFlags & POSIX_SPAWN_SETSIGMASK)
+        pChild->SigMask = attrp->__ss;
+    if (fFlags & POSIX_SPAWN_SETSIGDEF)
+        pChild->fSigAction = LIBC_SETSIGDEF;
+
+    /*
+     * Scheduler fun - don't think we should try apply this
+     * and let the child enherit it, it's better having the child setting these things.
+     */
+    if (fFlags & POSIX_SPAWN_SETSCHEDPARAM)
+        pChild->SchedParam = attrp->__sp;
+    if (fFlags & POSIX_SPAWN_SETSCHEDULER)
+        pChild->SchedPolicy = attrp->__policy;
+#endif
+    /* Ignore POSIX_SPAWN_SETPGROUP & POSIX_SPAWN_RESETIDS  for now. */
+
+
+    /*
+     * Apply file actions - this is gonna be fun.
+     *      - Dup2() with two file handle is ok.
+     *      - If there is any dup2 with target as -1 or and any open we're
+     *        in for some work.
+     *        The reason is that we have to save any handles which we close
+     *        with close() or dup2(), and these saved handles must not crash with
+     *        any we might open thru open() or dup2(,-1).
+     */
+    rc = 0;
+    if (file_actions)
+    {
+        int i;
+        int fdMin;
+        int cOpens;
+
+        /* TODO: lock the file handle table for other threads. */
+
+        /* Verify handles and predict what open() and dup2() will return so we can
+           find the min save handle number.
+           Note. we're counting too many opens here... but who cares. */
+        for (i = cOpens = 0; !rc && i < file_actions->__used; ++i)
+        {
+            struct __spawn_action  *pAction = (struct __spawn_action *)&file_actions->__actions[i]; /* nasty - const */
+            switch (pAction->tag)
+            {
+                case spawn_do_close:
+                    if (!__libc_FH(pAction->action.close_action.fd))
+                        rc = -1;
+                    break;
+                case spawn_do_open:
+                    cOpens++;
+                    break;
+                case spawn_do_dup2:
+                    if (!__libc_FH(pAction->action.dup2_action.fd))
+                        rc = -1;
+                    if (pAction->action.dup2_action.newfd == -1)
+                        cOpens++;
+                    break;
+            }
+        }
+        if (rc)
+        {
+            /* TODO: release the file handle table lock. */
+            errno = EINVAL;
+            return -1;
+        }
+
+        paRestore = _hmalloc(sizeof(RESTOREACTION) * file_actions->__used);
+        if (!paRestore)
+        {
+            /* TODO: release the file handle table lock. */
+            return -1;
+        }
+        memset(paRestore, -1, sizeof(RESTOREACTION) * file_actions->__used);
+
+        for (fdMin = 0; cOpens >= 0 && fdMin < 0x10000; fdMin++)
+        {
+            int fClosed;
+            int fDuped;
+            for (i = fClosed = fDuped = 0; i < file_actions->__used; ++i)
+            {
+                struct __spawn_action  *pAction = (struct __spawn_action *)&file_actions->__actions[i]; /* nasty - const */
+                switch (pAction->tag)
+                {
+                    case spawn_do_close:
+                        if (pAction->action.close_action.fd == fdMin)
+                            fClosed = 1;
+                        break;
+                    case spawn_do_dup2:
+                        if (pAction->action.dup2_action.newfd == fdMin)
+                            fDuped = 1;
+                        break;
+                    case spawn_do_open:
+                        if (pAction->action.open_action.fd == fdMin)
+                            fDuped = 1;
+                        break;
+                }
+            }
+
+            /* if duped we cannot use it. */
+            if (fDuped)
+                continue;
+            /* if not closed or not being freed we cannot use it. */
+            if (!fClosed && __libc_FH(fdMin))
+                continue;
+            /* it's either closed or free */
+            cOpens--;
+        }
+
+        /* Execute the actions. */
+        for (i = rc = 0; !rc && i < file_actions->__used; ++i)
+        {
+            struct __spawn_action  *pAction = (struct __spawn_action *)&file_actions->__actions[i]; /* nasty - const */
+            PRESTOREACTION          pRAction = &paRestore[i];
+
+            switch (pAction->tag)
+            {
+                case spawn_do_close:
+                    rc = save_handle(pAction->action.close_action.fd, &fdMin, pRAction);
+                    if (rc)
+                        break;
+                    if (close(pAction->action.close_action.fd))
+                    {
+                        restore_handle(pRAction);
+                        rc = -1;
+                    }
+                    break;
+
+                case spawn_do_open:
+                    pRAction->fdClose = open(pAction->action.open_action.path,
+                                             pAction->action.open_action.oflag,
+                                             pAction->action.open_action.mode);
+                    if (pRAction->fdClose < 0)
+                        rc = -1;
+                    else if (   pRAction->fdClose != pAction->action.open_action.fd
+                             && pAction->action.open_action.fd != -1   /* -1 is not standard */)
+                    {
+                        int fd = pRAction->fdClose;
+                        pRAction->fdClose = -1;
+                        rc = save_handle(pAction->action.open_action.fd, &fdMin, pRAction);
+                        if (!rc)
+                        {
+                            if (dup2(fd, pAction->action.open_action.fd) < 0)
+                            {
+                                restore_handle(pRAction);
+                                rc = -1;
+                            }
+                        }
+                        close(fd);
+                    }
+                    break;
+
+                case spawn_do_dup2:
+                    if (pAction->action.dup2_action.newfd != -1)
+                    {
+                        rc = save_handle(pAction->action.dup2_action.newfd, &fdMin, pRAction);
+                        if (rc)
+                            break;
+                    }
+
+                    pRAction->fdClose = dup2(pAction->action.dup2_action.fd, pAction->action.dup2_action.newfd);
+                    if (pRAction->fdClose < 0)
+                    {
+                        restore_handle(pRAction);
+                        rc = -1;
+                    }
+                    break;
+            }
+        }
+        iFileAction = i;                 /* restore loop starts by decrementing it. */
+    } /* fileactions */
+
+
+    /*
+     * Spawn the child process (if all went well so far).
+     */
+    if (!rc)
+    {
+        if (use_path)
+            pidChild = spawnve(P_NOWAIT, path, argv, envp);
+        else
+            pidChild = spawnvpe(P_NOWAIT, path, argv, envp);
+        if (pidChild >= 0)
+        {
+            #if 0
+            /* Update child */
+            pChild->pid = pidChild;
+            #endif
+            /* Set return */
+            *pid = pidChild;
+        }
+        else
+            rc = -1;
+    }
+    else
+        errno = EINVAL;                 /* error in file_actions or attrp. */
+
+    /*
+     * Restore the file handles.
+     */
+    if (paRestore)
+    {
+        int save_errno = errno;
+        while (iFileAction-- > 0)
+            restore_handle(&paRestore[iFileAction]);
+        free(paRestore);
+        errno = save_errno;
+    }
+
+    /* TODO: release file handle table. */
+
+    return rc;
+}
Index: /trunk/libc/src/glibc/sysdeps/os2/bits/libc-lock.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/os2/bits/libc-lock.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/os2/bits/libc-lock.h	(revision 2448)
@@ -0,0 +1,113 @@
+/* libc-internal interface for mutex locks.  NPTL version.
+   Copyright (C) 1996-2001, 2002, 2003, 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; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _BITS_LIBC_LOCK_H
+#define _BITS_LIBC_LOCK_H 1
+
+#include <InnoTekLIBC/thread.h>
+
+#if 1 /* There is a hev leak problem with using fmutexes. */
+#include <sys/smutex.h>
+
+typedef _smutex                         __libc_lock_t;
+#define __libc_lock_define(CLASS,NAME) \
+  CLASS __libc_lock_t NAME;
+#define __libc_lock_define_initialized(CLASS,NAME) \
+  CLASS __libc_lock_t NAME = 0;
+#define __libc_lock_init(NAME)          (NAME) = 0
+#define __libc_lock_fini(NAME)          (NAME) = 0
+#define __libc_lock_lock(NAME)          _smutex_request(&(NAME))
+#define __libc_lock_trylock(NAME)       (!_smutex_try_request(&(NAME)))
+#define __libc_lock_unlock(NAME)        _smutex_release(&(NAME))
+
+#else
+
+#include <sys/fmutex.h>
+
+typedef _fmutex                         __libc_lock_t;
+#define __libc_lock_define(CLASS,NAME) \
+  CLASS __libc_lock_t NAME;
+#define __libc_lock_define_initialized(CLASS,NAME) \
+  CLASS __libc_lock_t NAME = _FMUTEX_INITIALIZER;
+#define __libc_lock_init(NAME)          _fmutex_create(&(NAME), 0)
+#define __libc_lock_fini(NAME)          _fmutex_close(&(NAME))
+#define __libc_lock_lock(NAME)          _fmutex_request(&(NAME), 0)
+#define __libc_lock_trylock(NAME)       _fmutex_request(&(NAME),  _FMR_NOWAIT)
+#define __libc_lock_unlock(NAME)        _fmutex_release(&(NAME))
+#endif
+
+
+
+
+typedef struct __LIBC_LOCK      __libc_lock_recursive_t;
+typedef struct __LIBC_RWLOCK    __libc_rwlock_t;
+typedef struct __LIBC_LOCK      __rtld_lock_recursive_t;
+typedef int __libc_key_t;
+
+#define __libc_rwlock_define(CLASS,NAME) \
+  CLASS __libc_rwlock_t NAME;
+#define __libc_lock_define_recursive(CLASS,NAME) \
+  CLASS __libc_lock_recursive_t NAME;
+#define __rtld_lock_define_recursive(CLASS,NAME) \
+  CLASS __rtld_lock_recursive_t NAME;
+
+#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
+  CLASS __libc_lock_t NAME = NOT_IMPLEMENTED;
+#define __libc_rwlock_define_initialized(CLASS,NAME) \
+  CLASS __libc_rwlock_t NAME = NOT_IMPLEMENTED;
+#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
+  CLASS __rtld_lock_recursive_t NAME = NOT_IMPLEMENTED;
+#define __rtld_lock_initialize(NAME) \
+  NOT_IMPLEMENTED
+
+#define __libc_rwlock_init(NAME)        NOT_IMPLEMENTED
+#define __libc_lock_init_recursive(NAME) NOT_IMPLEMENTED
+
+#define __libc_rwlock_fini(NAME)        NOT_IMPLEMENTED
+#define __libc_lock_fini_recursive(NAME) NOT_IMPLEMENTED
+
+#define __libc_rwlock_rdlock(NAME)      NOT_IMPLEMENTED
+#define __libc_lock_lock_recursive(NAME) NOT_IMPLEMENTED
+
+#define __libc_lock_trylock_recursive(NAME) NOT_IMPLEMENTED
+#define __libc_rwlock_tryrdlock(NAME)   NOT_IMPLEMENTED
+#define __rtld_lock_trylock_recursive(NAME) NOT_IMPLEMENTED
+
+#define __libc_rwlock_unlock(NAME) NOT_IMPLEMENTED
+#define __libc_lock_unlock_recursive(NAME) NOT_IMPLEMENTED
+
+#define __rtld_lock_default_lock_recursive(lock) NOT_IMPLEMENTED
+#define __rtld_lock_default_unlock_recursive(lock) NOT_IMPLEMENTED
+#define __rtld_lock_lock_recursive(NAME) NOT_IMPLEMENTED
+#define __rtld_lock_unlock_recursive(NAME) NOT_IMPLEMENTED
+
+#define __libc_once_define(CLASS, NAME)            NOT_IMPLEMENTED
+#define __libc_once(ONCE_CONTROL, INIT_FUNCTION)    NOT_IMPLEMENTED
+#define __libc_cleanup_region_start(DOIT, FCT, ARG) NOT_IMPLEMENTED
+#define __libc_cleanup_region_end(DOIT)     NOT_IMPLEMENTED
+#define __libc_cleanup_end(DOIT)            NOT_IMPLEMENTED
+#define __libc_cleanup_routine(fct, arg)    NOT_IMPLEMENTED
+#define __libc_cleanup_push(fct, arg)       NOT_IMPLEMENTED
+#define __libc_cleanup_pop(execute)         NOT_IMPLEMENTED
+#define __libc_key_create(KEY, DESTRUCTOR)  NOT_IMPLEMENTED
+#define __libc_getspecific(KEY)             NOT_IMPLEMENTED
+#define __libc_setspecific(KEY, VALUE)      NOT_IMPLEMENTED
+
+#endif	/* bits/libc-lock.h */
+
Index: /trunk/libc/src/glibc/sysdeps/os2/sysdep.h
===================================================================
--- /trunk/libc/src/glibc/sysdeps/os2/sysdep.h	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/os2/sysdep.h	(revision 2448)
@@ -0,0 +1,45 @@
+/* Copyright (C) 1991, 92, 93, 96, 98, 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.  */
+
+/* should've been an -include but anyway, this'll do for now. */
+#include <libc-symbols.h>
+
+/* config.h candidates? */
+#undef NO_UNDERSCORES
+#define HAVE_CPP_ASM_DEBUGINFO
+#define HAVE_ASM_SET_DIRECTIVE
+#define HAVE_ASM_WEAKEXT_DIRECTIVE
+#ifndef __BOUNDED_POINTERS__
+#define __BOUNDED_POINTERS__ 0
+#endif
+
+/* unix/i386/sysdep.h */
+#ifdef	__ASSEMBLER__
+
+#define	r0		%eax	/* Normal return-value register.  */
+#define	r1		%edx	/* Secondary return-value register.  */
+#define scratch 	%ecx	/* Call-clobbered register for random use.  */
+#define MOVE(x,y)	movl x, y
+
+#endif	/* __ASSEMBLER__ */
+
+/* unix/sysdep.h */
+#undef HAVE_SYSCALLS
+
+/* include i386 sysdep.h, which in turn includes the generic one. */
+#include <sysdeps/i386/sysdep.h>
Index: /trunk/libc/src/glibc/sysdeps/sysdeps.smak
===================================================================
--- /trunk/libc/src/glibc/sysdeps/sysdeps.smak	(revision 2448)
+++ /trunk/libc/src/glibc/sysdeps/sysdeps.smak	(revision 2448)
@@ -0,0 +1,6 @@
+libc.TSRC += $(wildcard src/glibc/sysdeps/os2/*.c) \
+	$(wildcard src/glibc/sysdeps/i386/*.S) \
+	$(wildcard src/glibc/sysdeps/i386/fpu/*.S) \
+	$(wildcard src/glibc/sysdeps/i386/fpu/*.c) \
+	$(wildcard src/glibc/sysdeps/generic/*.c) \
+	$(wildcard src/glibc/sysdeps/ieee754/ldbl-96/*.c)
Index: /trunk/libc/src/legacy/libdl/dl.smak
===================================================================
--- /trunk/libc/src/legacy/libdl/dl.smak	(revision 2447)
+++ /trunk/libc/src/legacy/libdl/dl.smak	(revision 2448)
@@ -4,5 +4,4 @@
 .MODULE	:= libdl
 .MDESC	:= Stub dynamic loading library (move into libc)
-.MDEP   := emxomf
 
 .TARGET	:= libdl_p.a
Index: /trunk/libc/src/legacy/libm/m.smak
===================================================================
--- /trunk/libc/src/legacy/libm/m.smak	(revision 2447)
+++ /trunk/libc/src/legacy/libm/m.smak	(revision 2448)
@@ -3,5 +3,4 @@
 .MODULE	:= libm
 .MDESC	:= Stub math library (move into libc)
-.MDEP   := emxomf
 
 .TARGET	:= libm_p.a
Index: /trunk/libc/src/libc/libc.smak
===================================================================
--- /trunk/libc/src/libc/libc.smak	(revision 2447)
+++ /trunk/libc/src/libc/libc.smak	(revision 2448)
@@ -9,5 +9,9 @@
 
 # First of all, include all second-level libc submakefiles
-LIBC.SUBMAK := $(wildcard src/libc/*/*.smak) $(wildcard src/libc/bsd/*/*.smak) $(wildcard src/libc/lgpl/*/*.smak)
+LIBC.SUBMAK := \
+	$(wildcard src/libc/*/*.smak) \
+	$(wildcard src/fbsdlibc/*/*.smak) \
+	$(wildcard src/glibc/*/*.smak) \
+	$(wildcard src/msun/*.smak)
 -include $(LIBC.SUBMAK)
 # Add to the list of genrules.smak dependencies
@@ -39,11 +43,11 @@
  -D_BSD_NAMESPACE_POLLUTION \
  -I$.	\
- -Isrc/libc/bsd/include \
- -Isrc/libc/bsd/locale \
- -Isrc/libc/lgpl \
- -Isrc/libc/lgpl/sysdeps/os2 \
- -Isrc/libc/lgpl/sysdeps/i386 \
- -Isrc/libc/lgpl/sysdeps/generic \
- -Isrc/libc/lgpl/include
+ -Isrc/fbsdlibc/include \
+ -Isrc/fbsdlibc/locale \
+ -Isrc/glibc \
+ -Isrc/glibc/sysdeps/os2 \
+ -Isrc/glibc/sysdeps/i386 \
+ -Isrc/glibc/sysdeps/generic \
+ -Isrc/glibc/include
 .TSF	+= $(.TCF)
 .INSDIR	= lib/
@@ -351,5 +355,5 @@
 all: libc-dll
 ifndef LIBC_CORE_ONLY
-libc-dll: emxbind emxexp app alias libc libos2 libos2@omf \
+libc-dll: app alias libc libos2 libos2@omf \
 			$(LIBC.DIRS) $(LIBC.DLL) $(LIBC.IMPLIB) $(LIBC.IMPLIB.TCPIPV4) \
 			$(LIBC.PRF.DIRS) $(LIBC.PRF.DLL) \
@@ -357,5 +361,5 @@
 			$(LIBC.ELH.DIRS) $(LIBC.ELH.DLL)
 else
-libc-dll: emxbind emxexp app alias libc libos2 libos2@omf \
+libc-dll: alias libc libos2 libos2@omf \
 			$(LIBC.DIRS) $(LIBC.DLL) $(LIBC.IMPLIB) $(LIBC.IMPLIB.TCPIPV4)
 endif
@@ -422,16 +426,16 @@
 	src/libc/msun/*/*.c \
 	src/libc/msun/*/*.S \
-	src/libc/bsd/*/*.c \
-	src/libc/bsd/*/glue/*.c \
-	src/libc/lgpl/*/*.c \
-	src/libc/lgpl/sysdeps/i386/*.S \
-	src/libc/lgpl/sysdeps/i386/*.c \
-	src/libc/lgpl/sysdeps/i386/i486/*.S \
-	src/libc/lgpl/sysdeps/i386/fpu/*.S \
-	src/libc/lgpl/sysdeps/i386/fpu/*.c \
-	src/libc/lgpl/sysdeps/generic/*.c \
-	src/libc/lgpl/sysdeps/ieee754/ldbl-96/*.c
+	src/fbsdlibc/*/*.c \
+	src/fbsdlibc/*/glue/*.c \
+	src/glibc/*/*.c \
+	src/glibc/sysdeps/i386/*.S \
+	src/glibc/sysdeps/i386/*.c \
+	src/glibc/sysdeps/i386/i486/*.S \
+	src/glibc/sysdeps/i386/fpu/*.S \
+	src/glibc/sysdeps/i386/fpu/*.c \
+	src/glibc/sysdeps/generic/*.c \
+	src/glibc/sysdeps/ieee754/ldbl-96/*.c
 $.stmp-libc-std: $(wildcard $(_STD_WILDWILD))
-	cd src/libc && gawk -f ./mkstd.awk $(patsubst src/libc/%,%,$^) > ../../__tmp__
+	cd src/libc && gawk -f ./mkstd.awk $(patsubst src/%,../%,$(patsubst src/libc/%,%,$^)) > ../../__tmp__
 	$(call UPDATE,__tmp__,$.libc-std.h)
 	$(call TOUCH,$@)
Index: /trunk/libc/src/libc/startup/startup.smak
===================================================================
--- /trunk/libc/src/libc/startup/startup.smak	(revision 2447)
+++ /trunk/libc/src/libc/startup/startup.smak	(revision 2448)
@@ -78,5 +78,5 @@
 	$(call CP,$^,$(dir $@))
 
-libc: emxomf ld $(.DIRS) $(.OBJS)
+libc:    $(.DIRS) $(.OBJS)
 startup: $(.DIRS) $(.OBJS)
 
Index: /trunk/libc/src/libos2/os2.smak
===================================================================
--- /trunk/libc/src/libos2/os2.smak	(revision 2447)
+++ /trunk/libc/src/libos2/os2.smak	(revision 2448)
@@ -3,5 +3,4 @@
 .MODULE := libos2
 .MDESC  := OS/2 import library (similar to os2386.lib)
-.MDEP   := emxomf emximp
 .INSDIR := lib/
 
Index: /trunk/libc/src/libsocket/socket.smak
===================================================================
--- /trunk/libc/src/libsocket/socket.smak	(revision 2447)
+++ /trunk/libc/src/libsocket/socket.smak	(revision 2448)
@@ -4,5 +4,4 @@
 .MDESC	:= The socket library
 #_MDIRS  := $.aout/tcpipv4 $.aout-prof/tcpipv4 $.aout/dep-tcpipv4 $.aout-prof/dep-tcpipv4
-.MDEP   := emxomf emximp
 #$(_MDIRS)
 #TARGDIRS += $(_MDIRS)
Index: /trunk/libc/src/libsyslog/syslog.smak
===================================================================
--- /trunk/libc/src/libsyslog/syslog.smak	(revision 2447)
+++ /trunk/libc/src/libsyslog/syslog.smak	(revision 2448)
@@ -4,5 +4,4 @@
 .MODULE	:= libsyslog
 .MDESC	:= syslog library.
-.MDEP   := emxomf
 
 .TARGET	:= libsyslog_p.a
Index: /trunk/libc/src/msun/Makefile
===================================================================
--- /trunk/libc/src/msun/Makefile	(revision 2448)
+++ /trunk/libc/src/msun/Makefile	(revision 2448)
@@ -0,0 +1,158 @@
+#  @(#)Makefile 5.1beta 93/09/24
+# $FreeBSD: src/lib/msun/Makefile,v 1.71 2005/04/17 19:57:52 ache Exp $
+#
+#  ====================================================
+#  Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+#
+#  Developed at SunPro, a Sun Microsystems, Inc. business.
+#  Permission to use, copy, modify, and distribute this
+#  software is freely granted, provided that this notice
+#  is preserved.
+#  ====================================================
+#
+#
+
+.if ${MACHINE_ARCH} == "i386"
+ARCH_SUBDIR= i387
+.else
+ARCH_SUBDIR= ${MACHINE_ARCH}
+.endif
+
+.include "${ARCH_SUBDIR}/Makefile.inc"
+
+.PATH:	${.CURDIR}/bsdsrc
+.PATH:	${.CURDIR}/man
+.PATH:	${.CURDIR}/src
+
+LIB=	m
+SHLIBDIR?= /lib
+SHLIB_MAJOR= 3
+COMMON_SRCS= b_exp.c b_log.c b_tgamma.c \
+	e_acos.c e_acosf.c e_acosh.c e_acoshf.c e_asin.c e_asinf.c \
+	e_atan2.c e_atan2f.c e_atanh.c e_atanhf.c e_cosh.c e_coshf.c e_exp.c \
+	e_expf.c e_fmod.c e_fmodf.c e_gamma.c e_gamma_r.c e_gammaf.c \
+	e_gammaf_r.c e_hypot.c e_hypotf.c e_j0.c e_j0f.c e_j1.c e_j1f.c \
+	e_jn.c e_jnf.c e_lgamma.c e_lgamma_r.c e_lgammaf.c e_lgammaf_r.c \
+	e_log.c e_log10.c e_log10f.c e_logf.c e_pow.c e_powf.c e_rem_pio2.c \
+	e_rem_pio2f.c e_remainder.c e_remainderf.c e_scalb.c e_scalbf.c \
+	e_sinh.c e_sinhf.c e_sqrt.c e_sqrtf.c fenv.c \
+	k_cos.c k_cosf.c k_rem_pio2.c k_rem_pio2f.c k_sin.c k_sinf.c \
+	k_tan.c k_tanf.c \
+	s_asinh.c s_asinhf.c s_atan.c s_atanf.c s_cbrt.c s_cbrtf.c \
+	s_ceil.c s_ceilf.c s_ceill.c \
+	s_copysign.c s_copysignf.c s_cos.c s_cosf.c s_erf.c s_erff.c \
+	s_exp2.c s_exp2f.c s_expm1.c s_expm1f.c s_fabsf.c s_fdim.c \
+	s_finite.c s_finitef.c \
+	s_floor.c s_floorf.c s_floorl.c s_fma.c s_fmaf.c \
+	s_fmax.c s_fmaxf.c s_fmaxl.c s_fmin.c \
+	s_fminf.c s_fminl.c s_frexp.c s_frexpf.c s_ilogb.c s_ilogbf.c \
+	s_ilogbl.c s_isfinite.c s_isnan.c s_isnormal.c \
+	s_llrint.c s_llrintf.c s_llround.c s_llroundf.c s_llroundl.c \
+	s_log1p.c s_log1pf.c s_logb.c s_logbf.c s_lrint.c s_lrintf.c \
+	s_lround.c s_lroundf.c s_lroundl.c s_modff.c \
+	s_nearbyint.c s_nextafter.c s_nextafterf.c \
+	s_nexttowardf.c s_remquo.c s_remquof.c \
+	s_rint.c s_rintf.c s_round.c s_roundf.c s_roundl.c \
+	s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \
+	s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c s_tan.c \
+	s_tanf.c s_tanh.c s_tanhf.c s_trunc.c s_truncf.c s_truncl.c \
+	w_cabs.c w_cabsf.c w_drem.c w_dremf.c
+
+# Location of fpmath.h and _fpmath.h
+LIBCDIR=	${.CURDIR}/../libc
+CFLAGS+=	-I${LIBCDIR}/include -I${LIBCDIR}/${MACHINE_ARCH}
+
+# C99 long double functions
+COMMON_SRCS+=	s_copysignl.c s_fabsl.c
+.if ${LDBL_PREC} != 53
+# If long double != double use these; otherwise, we alias the double versions.
+COMMON_SRCS+=	s_fmal.c s_frexpl.c s_nextafterl.c s_nexttoward.c s_scalbnl.c
+.endif
+
+# C99 complex functions
+COMMON_SRCS+=	s_cimag.c s_cimagf.c s_cimagl.c s_conj.c s_conjf.c s_conjl.c \
+	s_creal.c s_crealf.c s_creall.c
+
+# FreeBSD's C library supplies these functions:
+#COMMON_SRCS+=	s_fabs.c s_frexp.c s_isnan.c s_ldexp.c s_modf.c
+
+# Exclude the generic versions of what we provide in the MD area.
+.PATH:	${.CURDIR}/${ARCH_SUBDIR}
+.if defined(ARCH_SRCS)
+.for i in ${ARCH_SRCS}
+COMMON_SRCS:=  ${COMMON_SRCS:N${i:R}.c}
+.endfor
+.endif
+
+SRCS=	${COMMON_SRCS} ${ARCH_SRCS}
+
+INCS=	fenv.h math.h
+
+MAN=	acos.3 acosh.3 asin.3 asinh.3 atan.3 atan2.3 atanh.3 ceil.3 \
+	cimag.3 copysign.3 cos.3 cosh.3 erf.3 exp.3 fabs.3 fdim.3 \
+	feclearexcept.3 feenableexcept.3 fegetenv.3 \
+	fegetround.3 fenv.3 floor.3 \
+	fma.3 fmax.3 fmod.3 hypot.3 ieee.3 ieee_test.3 ilogb.3 j0.3 \
+	lgamma.3 lrint.3 lround.3 math.3 nextafter.3 remainder.3 rint.3 \
+	round.3 scalbn.3 signbit.3 sin.3 sinh.3 sqrt.3 tan.3 tanh.3 trunc.3
+
+MLINKS+=acos.3 acosf.3
+MLINKS+=acosh.3 acoshf.3
+MLINKS+=asin.3 asinf.3
+MLINKS+=asinh.3 asinhf.3
+MLINKS+=atan.3 atanf.3
+MLINKS+=atanh.3 atanhf.3
+MLINKS+=atan2.3 atan2f.3
+MLINKS+=ceil.3 ceilf.3 ceil.3 ceill.3
+MLINKS+=cimag.3 cimagf.3 cimag.3 cimagl.3 \
+	cimag.3 conj.3 cimag.3 conjf.3 cimag.3 conjl.3 \
+	cimag.3 creal.3 cimag.3 crealf.3 cimag.3 creall.3
+MLINKS+=copysign.3 copysignf.3 copysign.3 copysignl.3
+MLINKS+=cos.3 cosf.3
+MLINKS+=cosh.3 coshf.3
+MLINKS+=erf.3 erfc.3 erf.3 erff.3 erf.3 erfcf.3
+MLINKS+=exp.3 expm1.3 exp.3 log.3 exp.3 log10.3 exp.3 log1p.3 exp.3 pow.3 \
+	exp.3 exp2.3 exp.3 exp2f.3 exp.3 expf.3 \
+	exp.3 expm1f.3 exp.3 logf.3 exp.3 powf.3 \
+	exp.3 log10f.3 exp.3 log1pf.3
+MLINKS+=fabs.3 fabsf.3 fabs.3 fabsl.3
+MLINKS+=fdim.3 fdimf.3 fdim.3 fdiml.3
+MLINKS+=feclearexcept.3 fegetexceptflag.3 feclearexcept.3 feraiseexcept.3 \
+	feclearexcept.3 fesetexceptflag.3 feclearexcept.3 fetestexcept.3
+MLINKS+=feenableexcept.3 fedisableexcept.3 feenableexcept.3 fegetexcept.3
+MLINKS+=fegetenv.3 feholdexcept.3 fegetenv.3 fesetenv.3 \
+	fegetenv.3 feupdateenv.3
+MLINKS+=fegetround.3 fesetround.3
+MLINKS+=floor.3 floorf.3 floor.3 floorl.3
+MLINKS+=fma.3 fmaf.3 fma.3 fmal.3
+MLINKS+=fmax.3 fmaxf.3 fmax.3 fmaxl.3 \
+	fmax.3 fmin.3 fmax.3 fminf.3 fmax.3 fminl.3
+MLINKS+=fmod.3 fmodf.3
+MLINKS+=hypot.3 cabs.3 hypot.3 cabsf.3 hypot.3 hypotf.3
+MLINKS+=ieee_test.3 logb.3 ieee_test.3 logbf.3
+MLINKS+=ieee_test.3 scalb.3 ieee_test.3 scalbf.3
+MLINKS+=ieee_test.3 significand.3 ieee_test.3 significandf.3
+MLINKS+=ilogb.3 ilogbf.3 ilogb.3 ilogbl.3
+MLINKS+=j0.3 j1.3 j0.3 jn.3 j0.3 y0.3 j0.3 y1.3 j0.3 y1f.3 j0.3 yn.3
+MLINKS+=j0.3 j0f.3 j0.3 j1f.3 j0.3 jnf.3 j0.3 y0f.3 j0.3 ynf.3
+MLINKS+=lgamma.3 gamma.3 lgamma.3 gammaf.3 lgamma.3 lgammaf.3 lgamma.3 tgamma.3
+MLINKS+=lrint.3 llrint.3 lrint.3 llrintf.3 lrint.3 lrintf.3
+MLINKS+=lround.3 llround.3 lround.3 llroundf.3 lround.3 llroundl.3 \
+	lround.3 lroundf.3 lround.3 lroundl.3
+MLINKS+=nextafter.3 nextafterf.3 nextafter.3 nextafterl.3
+MLINKS+=nextafter.3 nexttoward.3 nextafter.3 nexttowardf.3
+MLINKS+=nextafter.3 nexttowardl.3
+MLINKS+=remainder.3 remainderf.3
+MLINKS+=remainder.3 remquo.3 remainder.3 remquof.3
+MLINKS+=rint.3 rintf.3 rint.3 nearbyint.3 rint.3 nearbyintf.3
+MLINKS+=round.3 roundf.3 round.3 roundl.3
+MLINKS+=scalbn.3 scalbln.3 scalbn.3 scalblnf.3 scalbn.3 scalblnl.3
+MLINKS+=scalbn.3 scalbnf.3 scalbn.3 scalbnl.3
+MLINKS+=sin.3 sinf.3
+MLINKS+=sinh.3 sinhf.3
+MLINKS+=sqrt.3 cbrt.3 sqrt.3 cbrtf.3 sqrt.3 sqrtf.3
+MLINKS+=tan.3 tanf.3
+MLINKS+=tanh.3 tanhf.3
+MLINKS+=trunc.3 truncf.3 trunc.3 truncl.3
+
+.include <bsd.lib.mk>
Index: /trunk/libc/src/msun/bsdsrc/b_exp.c
===================================================================
--- /trunk/libc/src/msun/bsdsrc/b_exp.c	(revision 2448)
+++ /trunk/libc/src/msun/bsdsrc/b_exp.c	(revision 2448)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 1985, 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.
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char sccsid[] = "@(#)exp.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/bsdsrc/b_exp.c,v 1.7 2004/12/16 20:40:37 das Exp $");
+
+
+/* EXP(X)
+ * RETURN THE EXPONENTIAL OF X
+ * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
+ * CODED IN C BY K.C. NG, 1/19/85;
+ * REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86.
+ *
+ * Required system supported functions:
+ *	scalb(x,n)
+ *	copysign(x,y)
+ *	finite(x)
+ *
+ * Method:
+ *	1. Argument Reduction: given the input x, find r and integer k such
+ *	   that
+ *	                   x = k*ln2 + r,  |r| <= 0.5*ln2 .
+ *	   r will be represented as r := z+c for better accuracy.
+ *
+ *	2. Compute exp(r) by
+ *
+ *		exp(r) = 1 + r + r*R1/(2-R1),
+ *	   where
+ *		R1 = x - x^2*(p1+x^2*(p2+x^2*(p3+x^2*(p4+p5*x^2)))).
+ *
+ *	3. exp(x) = 2^k * exp(r) .
+ *
+ * Special cases:
+ *	exp(INF) is INF, exp(NaN) is NaN;
+ *	exp(-INF)=  0;
+ *	for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ *	exp(x) returns the exponential of x nearly rounded. In a test run
+ *	with 1,156,000 random arguments on a VAX, the maximum observed
+ *	error was 0.869 ulps (units in the last place).
+ */
+
+#include "mathimpl.h"
+
+const static double p1 = 0x1.555555555553ep-3;
+const static double p2 = -0x1.6c16c16bebd93p-9;
+const static double p3 = 0x1.1566aaf25de2cp-14;
+const static double p4 = -0x1.bbd41c5d26bf1p-20;
+const static double p5 = 0x1.6376972bea4d0p-25;
+const static double ln2hi = 0x1.62e42fee00000p-1;
+const static double ln2lo = 0x1.a39ef35793c76p-33;
+const static double lnhuge = 0x1.6602b15b7ecf2p9;
+const static double lntiny = -0x1.77af8ebeae354p9;
+const static double invln2 = 0x1.71547652b82fep0;
+
+#if 0
+double exp(x)
+double x;
+{
+	double  z,hi,lo,c;
+	int k;
+
+#if !defined(vax)&&!defined(tahoe)
+	if(x!=x) return(x);	/* x is NaN */
+#endif	/* !defined(vax)&&!defined(tahoe) */
+	if( x <= lnhuge ) {
+		if( x >= lntiny ) {
+
+		    /* argument reduction : x --> x - k*ln2 */
+
+			k=invln2*x+copysign(0.5,x);	/* k=NINT(x/ln2) */
+
+		    /* express x-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+			hi=x-k*ln2hi;
+			x=hi-(lo=k*ln2lo);
+
+		    /* return 2^k*[1+x+x*c/(2+c)]  */
+			z=x*x;
+			c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+			return  scalb(1.0+(hi-(lo-(x*c)/(2.0-c))),k);
+
+		}
+		/* end of x > lntiny */
+
+		else
+		     /* exp(-big#) underflows to zero */
+		     if(finite(x))  return(scalb(1.0,-5000));
+
+		     /* exp(-INF) is zero */
+		     else return(0.0);
+	}
+	/* end of x < lnhuge */
+
+	else
+	/* exp(INF) is INF, exp(+big#) overflows to INF */
+	    return( finite(x) ?  scalb(1.0,5000)  : x);
+}
+#endif
+
+/* returns exp(r = x + c) for |c| < |x| with no overlap.  */
+
+double __exp__D(x, c)
+double x, c;
+{
+	double  z,hi,lo;
+	int k;
+
+	if (x != x)	/* x is NaN */
+		return(x);
+	if ( x <= lnhuge ) {
+		if ( x >= lntiny ) {
+
+		    /* argument reduction : x --> x - k*ln2 */
+			z = invln2*x;
+			k = z + copysign(.5, x);
+
+		    /* express (x+c)-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+			hi=(x-k*ln2hi);			/* Exact. */
+			x= hi - (lo = k*ln2lo-c);
+		    /* return 2^k*[1+x+x*c/(2+c)]  */
+			z=x*x;
+			c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+			c = (x*c)/(2.0-c);
+
+			return  scalb(1.+(hi-(lo - c)), k);
+		}
+		/* end of x > lntiny */
+
+		else
+		     /* exp(-big#) underflows to zero */
+		     if(finite(x))  return(scalb(1.0,-5000));
+
+		     /* exp(-INF) is zero */
+		     else return(0.0);
+	}
+	/* end of x < lnhuge */
+
+	else
+	/* exp(INF) is INF, exp(+big#) overflows to INF */
+	    return( finite(x) ?  scalb(1.0,5000)  : x);
+}
Index: /trunk/libc/src/msun/bsdsrc/b_log.c
===================================================================
--- /trunk/libc/src/msun/bsdsrc/b_log.c	(revision 2448)
+++ /trunk/libc/src/msun/bsdsrc/b_log.c	(revision 2448)
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 1992, 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.
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char sccsid[] = "@(#)log.c	8.2 (Berkeley) 11/30/93";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/bsdsrc/b_log.c,v 1.7 2004/12/16 20:40:37 das Exp $");
+
+#include <math.h>
+#include <errno.h>
+
+#include "mathimpl.h"
+
+/* Table-driven natural logarithm.
+ *
+ * This code was derived, with minor modifications, from:
+ *	Peter Tang, "Table-Driven Implementation of the
+ *	Logarithm in IEEE Floating-Point arithmetic." ACM Trans.
+ *	Math Software, vol 16. no 4, pp 378-400, Dec 1990).
+ *
+ * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
+ * where F = j/128 for j an integer in [0, 128].
+ *
+ * log(2^m) = log2_hi*m + log2_tail*m
+ * since m is an integer, the dominant term is exact.
+ * m has at most 10 digits (for subnormal numbers),
+ * and log2_hi has 11 trailing zero bits.
+ *
+ * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h
+ * logF_hi[] + 512 is exact.
+ *
+ * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
+ * the leading term is calculated to extra precision in two
+ * parts, the larger of which adds exactly to the dominant
+ * m and F terms.
+ * There are two cases:
+ *	1. when m, j are non-zero (m | j), use absolute
+ *	   precision for the leading term.
+ *	2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1).
+ *	   In this case, use a relative precision of 24 bits.
+ * (This is done differently in the original paper)
+ *
+ * Special cases:
+ *	0	return signalling -Inf
+ *	neg	return signalling NaN
+ *	+Inf	return +Inf
+*/
+
+#define endian		(((*(int *) &one)) ? 1 : 0)
+#define TRUNC(x)	*(((int *) &x) + endian) &= 0xf8000000
+
+#define N 128
+
+/* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128.
+ * Used for generation of extend precision logarithms.
+ * The constant 35184372088832 is 2^45, so the divide is exact.
+ * It ensures correct reading of logF_head, even for inaccurate
+ * decimal-to-binary conversion routines.  (Everybody gets the
+ * right answer for integers less than 2^53.)
+ * Values for log(F) were generated using error < 10^-57 absolute
+ * with the bc -l package.
+*/
+static double	A1 = 	  .08333333333333178827;
+static double	A2 = 	  .01250000000377174923;
+static double	A3 =	 .002232139987919447809;
+static double	A4 =	.0004348877777076145742;
+
+static double logF_head[N+1] = {
+	0.,
+	.007782140442060381246,
+	.015504186535963526694,
+	.023167059281547608406,
+	.030771658666765233647,
+	.038318864302141264488,
+	.045809536031242714670,
+	.053244514518837604555,
+	.060624621816486978786,
+	.067950661908525944454,
+	.075223421237524235039,
+	.082443669210988446138,
+	.089612158689760690322,
+	.096729626458454731618,
+	.103796793681567578460,
+	.110814366340264314203,
+	.117783035656430001836,
+	.124703478501032805070,
+	.131576357788617315236,
+	.138402322859292326029,
+	.145182009844575077295,
+	.151916042025732167530,
+	.158605030176659056451,
+	.165249572895390883786,
+	.171850256926518341060,
+	.178407657472689606947,
+	.184922338493834104156,
+	.191394852999565046047,
+	.197825743329758552135,
+	.204215541428766300668,
+	.210564769107350002741,
+	.216873938300523150246,
+	.223143551314024080056,
+	.229374101064877322642,
+	.235566071312860003672,
+	.241719936886966024758,
+	.247836163904594286577,
+	.253915209980732470285,
+	.259957524436686071567,
+	.265963548496984003577,
+	.271933715484010463114,
+	.277868451003087102435,
+	.283768173130738432519,
+	.289633292582948342896,
+	.295464212893421063199,
+	.301261330578199704177,
+	.307025035294827830512,
+	.312755710004239517729,
+	.318453731118097493890,
+	.324119468654316733591,
+	.329753286372579168528,
+	.335355541920762334484,
+	.340926586970454081892,
+	.346466767346100823488,
+	.351976423156884266063,
+	.357455888922231679316,
+	.362905493689140712376,
+	.368325561158599157352,
+	.373716409793814818840,
+	.379078352934811846353,
+	.384411698910298582632,
+	.389716751140440464951,
+	.394993808240542421117,
+	.400243164127459749579,
+	.405465108107819105498,
+	.410659924985338875558,
+	.415827895143593195825,
+	.420969294644237379543,
+	.426084395310681429691,
+	.431173464818130014464,
+	.436236766774527495726,
+	.441274560805140936281,
+	.446287102628048160113,
+	.451274644139630254358,
+	.456237433481874177232,
+	.461175715122408291790,
+	.466089729924533457960,
+	.470979715219073113985,
+	.475845904869856894947,
+	.480688529345570714212,
+	.485507815781602403149,
+	.490303988045525329653,
+	.495077266798034543171,
+	.499827869556611403822,
+	.504556010751912253908,
+	.509261901790523552335,
+	.513945751101346104405,
+	.518607764208354637958,
+	.523248143765158602036,
+	.527867089620485785417,
+	.532464798869114019908,
+	.537041465897345915436,
+	.541597282432121573947,
+	.546132437597407260909,
+	.550647117952394182793,
+	.555141507540611200965,
+	.559615787935399566777,
+	.564070138285387656651,
+	.568504735352689749561,
+	.572919753562018740922,
+	.577315365035246941260,
+	.581691739635061821900,
+	.586049045003164792433,
+	.590387446602107957005,
+	.594707107746216934174,
+	.599008189645246602594,
+	.603290851438941899687,
+	.607555250224322662688,
+	.611801541106615331955,
+	.616029877215623855590,
+	.620240409751204424537,
+	.624433288012369303032,
+	.628608659422752680256,
+	.632766669570628437213,
+	.636907462236194987781,
+	.641031179420679109171,
+	.645137961373620782978,
+	.649227946625615004450,
+	.653301272011958644725,
+	.657358072709030238911,
+	.661398482245203922502,
+	.665422632544505177065,
+	.669430653942981734871,
+	.673422675212350441142,
+	.677398823590920073911,
+	.681359224807238206267,
+	.685304003098281100392,
+	.689233281238557538017,
+	.693147180560117703862
+};
+
+static double logF_tail[N+1] = {
+	0.,
+	-.00000000000000543229938420049,
+	 .00000000000000172745674997061,
+	-.00000000000001323017818229233,
+	-.00000000000001154527628289872,
+	-.00000000000000466529469958300,
+	 .00000000000005148849572685810,
+	-.00000000000002532168943117445,
+	-.00000000000005213620639136504,
+	-.00000000000001819506003016881,
+	 .00000000000006329065958724544,
+	 .00000000000008614512936087814,
+	-.00000000000007355770219435028,
+	 .00000000000009638067658552277,
+	 .00000000000007598636597194141,
+	 .00000000000002579999128306990,
+	-.00000000000004654729747598444,
+	-.00000000000007556920687451336,
+	 .00000000000010195735223708472,
+	-.00000000000017319034406422306,
+	-.00000000000007718001336828098,
+	 .00000000000010980754099855238,
+	-.00000000000002047235780046195,
+	-.00000000000008372091099235912,
+	 .00000000000014088127937111135,
+	 .00000000000012869017157588257,
+	 .00000000000017788850778198106,
+	 .00000000000006440856150696891,
+	 .00000000000016132822667240822,
+	-.00000000000007540916511956188,
+	-.00000000000000036507188831790,
+	 .00000000000009120937249914984,
+	 .00000000000018567570959796010,
+	-.00000000000003149265065191483,
+	-.00000000000009309459495196889,
+	 .00000000000017914338601329117,
+	-.00000000000001302979717330866,
+	 .00000000000023097385217586939,
+	 .00000000000023999540484211737,
+	 .00000000000015393776174455408,
+	-.00000000000036870428315837678,
+	 .00000000000036920375082080089,
+	-.00000000000009383417223663699,
+	 .00000000000009433398189512690,
+	 .00000000000041481318704258568,
+	-.00000000000003792316480209314,
+	 .00000000000008403156304792424,
+	-.00000000000034262934348285429,
+	 .00000000000043712191957429145,
+	-.00000000000010475750058776541,
+	-.00000000000011118671389559323,
+	 .00000000000037549577257259853,
+	 .00000000000013912841212197565,
+	 .00000000000010775743037572640,
+	 .00000000000029391859187648000,
+	-.00000000000042790509060060774,
+	 .00000000000022774076114039555,
+	 .00000000000010849569622967912,
+	-.00000000000023073801945705758,
+	 .00000000000015761203773969435,
+	 .00000000000003345710269544082,
+	-.00000000000041525158063436123,
+	 .00000000000032655698896907146,
+	-.00000000000044704265010452446,
+	 .00000000000034527647952039772,
+	-.00000000000007048962392109746,
+	 .00000000000011776978751369214,
+	-.00000000000010774341461609578,
+	 .00000000000021863343293215910,
+	 .00000000000024132639491333131,
+	 .00000000000039057462209830700,
+	-.00000000000026570679203560751,
+	 .00000000000037135141919592021,
+	-.00000000000017166921336082431,
+	-.00000000000028658285157914353,
+	-.00000000000023812542263446809,
+	 .00000000000006576659768580062,
+	-.00000000000028210143846181267,
+	 .00000000000010701931762114254,
+	 .00000000000018119346366441110,
+	 .00000000000009840465278232627,
+	-.00000000000033149150282752542,
+	-.00000000000018302857356041668,
+	-.00000000000016207400156744949,
+	 .00000000000048303314949553201,
+	-.00000000000071560553172382115,
+	 .00000000000088821239518571855,
+	-.00000000000030900580513238244,
+	-.00000000000061076551972851496,
+	 .00000000000035659969663347830,
+	 .00000000000035782396591276383,
+	-.00000000000046226087001544578,
+	 .00000000000062279762917225156,
+	 .00000000000072838947272065741,
+	 .00000000000026809646615211673,
+	-.00000000000010960825046059278,
+	 .00000000000002311949383800537,
+	-.00000000000058469058005299247,
+	-.00000000000002103748251144494,
+	-.00000000000023323182945587408,
+	-.00000000000042333694288141916,
+	-.00000000000043933937969737844,
+	 .00000000000041341647073835565,
+	 .00000000000006841763641591466,
+	 .00000000000047585534004430641,
+	 .00000000000083679678674757695,
+	-.00000000000085763734646658640,
+	 .00000000000021913281229340092,
+	-.00000000000062242842536431148,
+	-.00000000000010983594325438430,
+	 .00000000000065310431377633651,
+	-.00000000000047580199021710769,
+	-.00000000000037854251265457040,
+	 .00000000000040939233218678664,
+	 .00000000000087424383914858291,
+	 .00000000000025218188456842882,
+	-.00000000000003608131360422557,
+	-.00000000000050518555924280902,
+	 .00000000000078699403323355317,
+	-.00000000000067020876961949060,
+	 .00000000000016108575753932458,
+	 .00000000000058527188436251509,
+	-.00000000000035246757297904791,
+	-.00000000000018372084495629058,
+	 .00000000000088606689813494916,
+	 .00000000000066486268071468700,
+	 .00000000000063831615170646519,
+	 .00000000000025144230728376072,
+	-.00000000000017239444525614834
+};
+
+#if 0
+double
+#ifdef _ANSI_SOURCE
+log(double x)
+#else
+log(x) double x;
+#endif
+{
+	int m, j;
+	double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0;
+	volatile double u1;
+
+	/* Catch special cases */
+	if (x <= 0)
+		if (x == zero)	/* log(0) = -Inf */
+			return (-one/zero);
+		else		/* log(neg) = NaN */
+			return (zero/zero);
+	else if (!finite(x))
+		return (x+x);		/* x = NaN, Inf */
+
+	/* Argument reduction: 1 <= g < 2; x/2^m = g;	*/
+	/* y = F*(1 + f/F) for |f| <= 2^-8		*/
+
+	m = logb(x);
+	g = ldexp(x, -m);
+	if (m == -1022) {
+		j = logb(g), m += j;
+		g = ldexp(g, -j);
+	}
+	j = N*(g-1) + .5;
+	F = (1.0/N) * j + 1;	/* F*128 is an integer in [128, 512] */
+	f = g - F;
+
+	/* Approximate expansion for log(1+f/F) ~= u + q */
+	g = 1/(2*F+f);
+	u = 2*f*g;
+	v = u*u;
+	q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+
+    /* case 1: u1 = u rounded to 2^-43 absolute.  Since u < 2^-8,
+     * 	       u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
+     *         It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
+    */
+	if (m | j)
+		u1 = u + 513, u1 -= 513;
+
+    /* case 2:	|1-x| < 1/256. The m- and j- dependent terms are zero;
+     * 		u1 = u to 24 bits.
+    */
+	else
+		u1 = u, TRUNC(u1);
+	u2 = (2.0*(f - F*u1) - u1*f) * g;
+			/* u1 + u2 = 2f/(2F+f) to extra precision.	*/
+
+	/* log(x) = log(2^m*F*(1+f/F)) =				*/
+	/* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q);	*/
+	/* (exact) + (tiny)						*/
+
+	u1 += m*logF_head[N] + logF_head[j];		/* exact */
+	u2 = (u2 + logF_tail[j]) + q;			/* tiny */
+	u2 += logF_tail[N]*m;
+	return (u1 + u2);
+}
+#endif
+
+/*
+ * Extra precision variant, returning struct {double a, b;};
+ * log(x) = a+b to 63 bits, with a rounded to 26 bits.
+ */
+struct Double
+#ifdef _ANSI_SOURCE
+__log__D(double x)
+#else
+__log__D(x) double x;
+#endif
+{
+	int m, j;
+	double F, f, g, q, u, v, u2, one = 1.0;
+	volatile double u1;
+	struct Double r;
+
+	/* Argument reduction: 1 <= g < 2; x/2^m = g;	*/
+	/* y = F*(1 + f/F) for |f| <= 2^-8		*/
+
+	m = logb(x);
+	g = ldexp(x, -m);
+	if (m == -1022) {
+		j = logb(g), m += j;
+		g = ldexp(g, -j);
+	}
+	j = N*(g-1) + .5;
+	F = (1.0/N) * j + 1;
+	f = g - F;
+
+	g = 1/(2*F+f);
+	u = 2*f*g;
+	v = u*u;
+	q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+	if (m | j)
+		u1 = u + 513, u1 -= 513;
+	else
+		u1 = u, TRUNC(u1);
+	u2 = (2.0*(f - F*u1) - u1*f) * g;
+
+	u1 += m*logF_head[N] + logF_head[j];
+
+	u2 +=  logF_tail[j]; u2 += q;
+	u2 += logF_tail[N]*m;
+	r.a = u1 + u2;			/* Only difference is here */
+	TRUNC(r.a);
+	r.b = (u1 - r.a) + u2;
+	return (r);
+}
Index: /trunk/libc/src/msun/bsdsrc/b_tgamma.c
===================================================================
--- /trunk/libc/src/msun/bsdsrc/b_tgamma.c	(revision 2448)
+++ /trunk/libc/src/msun/bsdsrc/b_tgamma.c	(revision 2448)
@@ -0,0 +1,324 @@
+/*-
+ * Copyright (c) 1992, 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.
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char sccsid[] = "@(#)gamma.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/bsdsrc/b_tgamma.c,v 1.6 2004/12/16 20:40:37 das Exp $");
+
+/*
+ * This code by P. McIlroy, Oct 1992;
+ *
+ * The financial support of UUNET Communications Services is greatfully
+ * acknowledged.
+ */
+
+#include <math.h>
+#include "mathimpl.h"
+#include <errno.h>
+
+/* METHOD:
+ * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x))
+ * 	At negative integers, return +Inf, and set errno.
+ *
+ * x < 6.5:
+ *	Use argument reduction G(x+1) = xG(x) to reach the
+ *	range [1.066124,2.066124].  Use a rational
+ *	approximation centered at the minimum (x0+1) to
+ *	ensure monotonicity.
+ *
+ * x >= 6.5: Use the asymptotic approximation (Stirling's formula)
+ *	adjusted for equal-ripples:
+ *
+ *	log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x))
+ *
+ *	Keep extra precision in multiplying (x-.5)(log(x)-1), to
+ *	avoid premature round-off.
+ *
+ * Special values:
+ *	non-positive integer:	Set overflow trap; return +Inf;
+ *	x > 171.63:		Set overflow trap; return +Inf;
+ *	NaN: 			Set invalid trap;  return NaN
+ *
+ * Accuracy: Gamma(x) is accurate to within
+ *	x > 0:  error provably < 0.9ulp.
+ *	Maximum observed in 1,000,000 trials was .87ulp.
+ *	x < 0:
+ *	Maximum observed error < 4ulp in 1,000,000 trials.
+ */
+
+static double neg_gam(double);
+static double small_gam(double);
+static double smaller_gam(double);
+static struct Double large_gam(double);
+static struct Double ratfun_gam(double, double);
+
+/*
+ * Rational approximation, A0 + x*x*P(x)/Q(x), on the interval
+ * [1.066.., 2.066..] accurate to 4.25e-19.
+ */
+#define LEFT -.3955078125	/* left boundary for rat. approx */
+#define x0 .461632144968362356785	/* xmin - 1 */
+
+#define a0_hi 0.88560319441088874992
+#define a0_lo -.00000000000000004996427036469019695
+#define P0	 6.21389571821820863029017800727e-01
+#define P1	 2.65757198651533466104979197553e-01
+#define P2	 5.53859446429917461063308081748e-03
+#define P3	 1.38456698304096573887145282811e-03
+#define P4	 2.40659950032711365819348969808e-03
+#define Q0	 1.45019531250000000000000000000e+00
+#define Q1	 1.06258521948016171343454061571e+00
+#define Q2	-2.07474561943859936441469926649e-01
+#define Q3	-1.46734131782005422506287573015e-01
+#define Q4	 3.07878176156175520361557573779e-02
+#define Q5	 5.12449347980666221336054633184e-03
+#define Q6	-1.76012741431666995019222898833e-03
+#define Q7	 9.35021023573788935372153030556e-05
+#define Q8	 6.13275507472443958924745652239e-06
+/*
+ * Constants for large x approximation (x in [6, Inf])
+ * (Accurate to 2.8*10^-19 absolute)
+ */
+#define lns2pi_hi 0.418945312500000
+#define lns2pi_lo -.000006779295327258219670263595
+#define Pa0	 8.33333333333333148296162562474e-02
+#define Pa1	-2.77777777774548123579378966497e-03
+#define Pa2	 7.93650778754435631476282786423e-04
+#define Pa3	-5.95235082566672847950717262222e-04
+#define Pa4	 8.41428560346653702135821806252e-04
+#define Pa5	-1.89773526463879200348872089421e-03
+#define Pa6	 5.69394463439411649408050664078e-03
+#define Pa7	-1.44705562421428915453880392761e-02
+
+static const double zero = 0., one = 1.0, tiny = 1e-300;
+static int endian;
+
+/*
+ * TRUNC sets trailing bits in a floating-point number to zero.
+ * is a temporary variable.
+ */
+#define TRUNC(x)	*(((int *) &x) + endian) &= 0xf8000000
+
+double
+tgamma(x)
+	double x;
+{
+	struct Double u;
+	endian = (*(int *) &one) ? 1 : 0;
+
+	if (x >= 6) {
+		if(x > 171.63)
+			return(one/zero);
+		u = large_gam(x);
+		return(__exp__D(u.a, u.b));
+	} else if (x >= 1.0 + LEFT + x0)
+		return (small_gam(x));
+	else if (x > 1.e-17)
+		return (smaller_gam(x));
+	else if (x > -1.e-17) {
+		if (x == 0.0)
+			return (one/x);
+		one+1e-20;		/* Raise inexact flag. */
+		return (one/x);
+	} else if (!finite(x))
+		return (x*x);		/* x = NaN, -Inf */
+	else
+		return (neg_gam(x));
+}
+/*
+ * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
+ */
+static struct Double
+large_gam(x)
+	double x;
+{
+	double z, p;
+	struct Double t, u, v;
+
+	z = one/(x*x);
+	p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7))))));
+	p = p/x;
+
+	u = __log__D(x);
+	u.a -= one;
+	v.a = (x -= .5);
+	TRUNC(v.a);
+	v.b = x - v.a;
+	t.a = v.a*u.a;			/* t = (x-.5)*(log(x)-1) */
+	t.b = v.b*u.a + x*u.b;
+	/* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */
+	t.b += lns2pi_lo; t.b += p;
+	u.a = lns2pi_hi + t.b; u.a += t.a;
+	u.b = t.a - u.a;
+	u.b += lns2pi_hi; u.b += t.b;
+	return (u);
+}
+/*
+ * Good to < 1 ulp.  (provably .90 ulp; .87 ulp on 1,000,000 runs.)
+ * It also has correct monotonicity.
+ */
+static double
+small_gam(x)
+	double x;
+{
+	double y, ym1, t;
+	struct Double yy, r;
+	y = x - one;
+	ym1 = y - one;
+	if (y <= 1.0 + (LEFT + x0)) {
+		yy = ratfun_gam(y - x0, 0);
+		return (yy.a + yy.b);
+	}
+	r.a = y;
+	TRUNC(r.a);
+	yy.a = r.a - one;
+	y = ym1;
+	yy.b = r.b = y - yy.a;
+	/* Argument reduction: G(x+1) = x*G(x) */
+	for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) {
+		t = r.a*yy.a;
+		r.b = r.a*yy.b + y*r.b;
+		r.a = t;
+		TRUNC(r.a);
+		r.b += (t - r.a);
+	}
+	/* Return r*tgamma(y). */
+	yy = ratfun_gam(y - x0, 0);
+	y = r.b*(yy.a + yy.b) + r.a*yy.b;
+	y += yy.a*r.a;
+	return (y);
+}
+/*
+ * Good on (0, 1+x0+LEFT].  Accurate to 1ulp.
+ */
+static double
+smaller_gam(x)
+	double x;
+{
+	double t, d;
+	struct Double r, xx;
+	if (x < x0 + LEFT) {
+		t = x, TRUNC(t);
+		d = (t+x)*(x-t);
+		t *= t;
+		xx.a = (t + x), TRUNC(xx.a);
+		xx.b = x - xx.a; xx.b += t; xx.b += d;
+		t = (one-x0); t += x;
+		d = (one-x0); d -= t; d += x;
+		x = xx.a + xx.b;
+	} else {
+		xx.a =  x, TRUNC(xx.a);
+		xx.b = x - xx.a;
+		t = x - x0;
+		d = (-x0 -t); d += x;
+	}
+	r = ratfun_gam(t, d);
+	d = r.a/x, TRUNC(d);
+	r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b;
+	return (d + r.a/x);
+}
+/*
+ * returns (z+c)^2 * P(z)/Q(z) + a0
+ */
+static struct Double
+ratfun_gam(z, c)
+	double z, c;
+{
+	double p, q;
+	struct Double r, t;
+
+	q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8)))))));
+	p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4)));
+
+	/* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */
+	p = p/q;
+	t.a = z, TRUNC(t.a);		/* t ~= z + c */
+	t.b = (z - t.a) + c;
+	t.b *= (t.a + z);
+	q = (t.a *= t.a);		/* t = (z+c)^2 */
+	TRUNC(t.a);
+	t.b += (q - t.a);
+	r.a = p, TRUNC(r.a);		/* r = P/Q */
+	r.b = p - r.a;
+	t.b = t.b*p + t.a*r.b + a0_lo;
+	t.a *= r.a;			/* t = (z+c)^2*(P/Q) */
+	r.a = t.a + a0_hi, TRUNC(r.a);
+	r.b = ((a0_hi-r.a) + t.a) + t.b;
+	return (r);			/* r = a0 + t */
+}
+
+static double
+neg_gam(x)
+	double x;
+{
+	int sgn = 1;
+	struct Double lg, lsine;
+	double y, z;
+
+	y = floor(x + .5);
+	if (y == x)		/* Negative integer. */
+		return (one/zero);
+	z = fabs(x - y);
+	y = .5*ceil(x);
+	if (y == ceil(y))
+		sgn = -1;
+	if (z < .25)
+		z = sin(M_PI*z);
+	else
+		z = cos(M_PI*(0.5-z));
+	/* Special case: G(1-x) = Inf; G(x) may be nonzero. */
+	if (x < -170) {
+		if (x < -190)
+			return ((double)sgn*tiny*tiny);
+		y = one - x;		/* exact: 128 < |x| < 255 */
+		lg = large_gam(y);
+		lsine = __log__D(M_PI/z);	/* = TRUNC(log(u)) + small */
+		lg.a -= lsine.a;		/* exact (opposite signs) */
+		lg.b -= lsine.b;
+		y = -(lg.a + lg.b);
+		z = (y + lg.a) + lg.b;
+		y = __exp__D(y, z);
+		if (sgn < 0) y = -y;
+		return (y);
+	}
+	y = one-x;
+	if (one-y == x)
+		y = tgamma(y);
+	else		/* 1-x is inexact */
+		y = -x*tgamma(-x);
+	if (sgn < 0) y = -y;
+	return (M_PI / (y*z));
+}
Index: /trunk/libc/src/msun/bsdsrc/mathimpl.h
===================================================================
--- /trunk/libc/src/msun/bsdsrc/mathimpl.h	(revision 2448)
+++ /trunk/libc/src/msun/bsdsrc/mathimpl.h	(revision 2448)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 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.
+ *
+ *	@(#)mathimpl.h	8.1 (Berkeley) 6/4/93
+ * $FreeBSD: src/lib/msun/bsdsrc/mathimpl.h,v 1.5 2004/12/16 20:40:49 das Exp $
+ */
+
+#include <sys/cdefs.h>
+#include <math.h>
+
+/*
+ * Functions internal to the math package, yet not static.
+ */
+extern double	__exp__E();
+
+struct Double {double a, b;};
+double __exp__D(double, double);
+struct Double __log__D(double);
Index: /trunk/libc/src/msun/i387/Makefile.inc
===================================================================
--- /trunk/libc/src/msun/i387/Makefile.inc	(revision 2448)
+++ /trunk/libc/src/msun/i387/Makefile.inc	(revision 2448)
@@ -0,0 +1,18 @@
+# $FreeBSD: src/lib/msun/i387/Makefile.inc,v 1.7 2005/04/16 21:12:55 das Exp $
+
+ARCH_SRCS = e_exp.S e_fmod.S e_log.S e_log10.S \
+	    e_remainder.S e_scalb.S e_sqrt.S s_ceil.S s_copysign.S \
+	    s_cos.S s_finite.S s_floor.S s_llrint.S s_logb.S s_lrint.S \
+	    s_remquo.S s_rint.S s_scalbn.S s_significand.S s_sin.S s_tan.S \
+	    s_trunc.S
+
+# float counterparts
+ARCH_SRCS+= e_log10f.S e_logf.S e_remainderf.S e_scalbf.S \
+	    e_sqrtf.S s_ceilf.S s_copysignf.S s_floorf.S \
+	    s_llrintf.S s_logbf.S s_lrintf.S \
+	    s_remquof.S s_rintf.S s_scalbnf.S s_significandf.S s_truncf.S
+
+# long double counterparts
+ARCH_SRCS+= s_ceill.S s_copysignl.S s_floorl.S s_scalbnl.S s_truncl.S
+
+LDBL_PREC = 64	# XXX 64-bit format, but truncated to 53 bits
Index: /trunk/libc/src/msun/i387/e_exp.S
===================================================================
--- /trunk/libc/src/msun/i387/e_exp.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_exp.S	(revision 2448)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/e_exp.S,v 1.10 2005/02/04 14:08:32 das Exp $")
+
+/* e^x = 2^(x * log2(e)) */
+STDENTRY(exp)
+	/*
+	 * If x is +-Inf, then the subtraction would give Inf-Inf = NaN.
+	 * Avoid this.  Also avoid it if x is NaN for convenience.
+	 */
+	movl	8(%esp),%eax
+	andl	$0x7fffffff,%eax
+	cmpl	$0x7ff00000,%eax
+	jae	x_Inf_or_NaN
+
+	fldl	4(%esp)
+
+	/*
+	 * Ensure that the rounding mode is to nearest (to give the smallest
+	 * possible fraction) and that the precision is as high as possible.
+	 * We may as well mask interrupts if we switch the mode.
+	 */
+	fstcw	4(%esp)
+	movl	4(%esp),%eax
+	andl	$0x0300,%eax
+	cmpl	$0x0300,%eax		/* RC == 0 && PC == 3? */
+	je	1f			/* jump if mode is good */
+	movl	$0x137f,8(%esp)
+	fldcw	8(%esp)
+1:
+	fldl2e
+	fmulp				/* x * log2(e) */
+	fst	%st(1)
+	frndint				/* int(x * log2(e)) */
+	fst	%st(2)
+	fsubrp				/* fract(x * log2(e)) */
+	f2xm1				/* 2^(fract(x * log2(e))) - 1 */
+	fld1
+	faddp				/* 2^(fract(x * log2(e))) */
+	fscale				/* e^x */
+	fstp	%st(1)
+	je	1f
+	fldcw	4(%esp)
+1:
+	ret
+
+x_Inf_or_NaN:
+	/*
+	 * Return 0 if x is -Inf.  Otherwise just return x, although the
+	 * C version would return (x + x) (Real Indefinite) if x is a NaN.
+	 */
+	cmpl	$0xfff00000,8(%esp)
+	jne	x_not_minus_Inf
+	cmpl	$0,4(%esp)
+	jne	x_not_minus_Inf
+	fldz
+	ret
+
+x_not_minus_Inf:
+	fldl	4(%esp)
+	ret
Index: /trunk/libc/src/msun/i387/e_fmod.S
===================================================================
--- /trunk/libc/src/msun/i387/e_fmod.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_fmod.S	(revision 2448)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/e_fmod.S,v 1.8 2005/02/04 14:08:32 das Exp $")
+
+STDENTRY(fmod)
+	fldl	12(%esp)
+	fldl	4(%esp)
+1:	fprem
+	fstsw	%ax
+	sahf
+	jp	1b
+	fstp	%st(1)
+	ret
Index: /trunk/libc/src/msun/i387/e_log.S
===================================================================
--- /trunk/libc/src/msun/i387/e_log.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_log.S	(revision 2448)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/e_log.S,v 1.7 2005/02/04 14:08:32 das Exp $")
+
+STDENTRY(log)
+	fldln2
+	fldl	4(%esp)
+	fyl2x
+	ret
Index: /trunk/libc/src/msun/i387/e_log10.S
===================================================================
--- /trunk/libc/src/msun/i387/e_log10.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_log10.S	(revision 2448)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/e_log10.S,v 1.7 2005/02/04 14:08:32 das Exp $")
+
+STDENTRY(log10)
+	fldlg2
+	fldl	4(%esp)
+	fyl2x
+	ret
Index: /trunk/libc/src/msun/i387/e_log10f.S
===================================================================
--- /trunk/libc/src/msun/i387/e_log10f.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_log10f.S	(revision 2448)
@@ -0,0 +1,15 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/e_log10f.S,v 1.2 2005/02/04 14:08:32 das Exp $");
+/* RCSID("$NetBSD: e_log10f.S,v 1.1 1996/07/03 16:50:22 jtc Exp $") */
+
+STDENTRY(log10f)
+	fldlg2
+	flds	4(%esp)
+	fyl2x
+	ret
Index: /trunk/libc/src/msun/i387/e_logf.S
===================================================================
--- /trunk/libc/src/msun/i387/e_logf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_logf.S	(revision 2448)
@@ -0,0 +1,15 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/e_logf.S,v 1.2 2005/02/04 14:08:32 das Exp $");
+/* RCSID("$NetBSD: e_logf.S,v 1.2 1996/07/06 00:15:45 jtc Exp $") */
+
+STDENTRY(logf)
+	fldln2
+	flds	4(%esp)
+	fyl2x
+	ret
Index: /trunk/libc/src/msun/i387/e_remainder.S
===================================================================
--- /trunk/libc/src/msun/i387/e_remainder.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_remainder.S	(revision 2448)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/e_remainder.S,v 1.8 2005/02/04 14:08:32 das Exp $")
+
+STDENTRY(remainder)
+	fldl	12(%esp)
+	fldl	4(%esp)
+1:	fprem1
+	fstsw	%ax
+	sahf
+	jp	1b
+	fstp	%st(1)
+	ret
Index: /trunk/libc/src/msun/i387/e_remainderf.S
===================================================================
--- /trunk/libc/src/msun/i387/e_remainderf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_remainderf.S	(revision 2448)
@@ -0,0 +1,19 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/e_remainderf.S,v 1.2 2005/02/04 14:08:32 das Exp $");
+/* RCSID("$NetBSD: e_remainderf.S,v 1.2 1995/05/08 23:49:47 jtc Exp $") */
+
+STDENTRY(remainderf)
+	flds	8(%esp)
+	flds	4(%esp)
+1:	fprem1
+	fstsw	%ax
+	sahf
+	jp	1b
+	fstp	%st(1)
+	ret
Index: /trunk/libc/src/msun/i387/e_scalb.S
===================================================================
--- /trunk/libc/src/msun/i387/e_scalb.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_scalb.S	(revision 2448)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1994 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/e_scalb.S,v 1.8 2005/02/04 14:08:32 das Exp $")
+
+STDENTRY(scalb)
+	fldl	12(%esp)
+	fldl	4(%esp)
+	fscale
+	fstp	%st(1)
+	ret
Index: /trunk/libc/src/msun/i387/e_scalbf.S
===================================================================
--- /trunk/libc/src/msun/i387/e_scalbf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_scalbf.S	(revision 2448)
@@ -0,0 +1,15 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/e_scalbf.S,v 1.2 2005/02/04 14:08:32 das Exp $");
+/* RCSID("$NetBSD: e_scalbf.S,v 1.1 1996/07/03 16:50:24 jtc Exp $") */
+
+STDENTRY(scalbf)
+	flds	8(%esp)
+	flds	4(%esp)
+	fscale
+	ret
Index: /trunk/libc/src/msun/i387/e_sqrt.S
===================================================================
--- /trunk/libc/src/msun/i387/e_sqrt.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_sqrt.S	(revision 2448)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/e_sqrt.S,v 1.7 2005/02/04 14:08:32 das Exp $")
+
+STDENTRY(sqrt)
+	fldl	4(%esp)
+	fsqrt
+	ret
Index: /trunk/libc/src/msun/i387/e_sqrtf.S
===================================================================
--- /trunk/libc/src/msun/i387/e_sqrtf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/e_sqrtf.S	(revision 2448)
@@ -0,0 +1,14 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/e_sqrtf.S,v 1.2 2005/02/04 14:08:32 das Exp $");
+/* RCSID("$NetBSD: e_sqrtf.S,v 1.2 1995/05/08 23:50:14 jtc Exp $") */
+
+STDENTRY(sqrtf)
+	flds	4(%esp)
+	fsqrt
+	ret
Index: /trunk/libc/src/msun/i387/fenv.c
===================================================================
--- /trunk/libc/src/msun/i387/fenv.c	(revision 2448)
+++ /trunk/libc/src/msun/i387/fenv.c	(revision 2448)
@@ -0,0 +1,212 @@
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/i387/fenv.c,v 1.2 2005/03/17 22:21:46 das Exp $
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <machine/npx.h>
+#include "fenv.h"
+
+const fenv_t __fe_dfl_env = {
+	__INITIAL_NPXCW__,
+	0x0000,
+	0x0000,
+	0x1f80,
+	0xffffffff,
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }
+};
+
+enum __sse_support __has_sse =
+#ifdef __SSE__
+	__SSE_YES;
+#else
+	__SSE_UNK;
+#endif
+
+#define	getfl(x)	__asm __volatile("pushfl\n\tpopl %0" : "=mr" (*(x)))
+#define	setfl(x)	__asm __volatile("pushl %0\n\tpopfl" : : "g" (x))
+#define	cpuid_dx(x)	__asm __volatile("pushl %%ebx\n\tmovl $1, %%eax\n\t"  \
+					 "cpuid\n\tpopl %%ebx"		      \
+					: "=d" (*(x)) : : "eax", "ecx")
+
+/*
+ * Test for SSE support on this processor.  We need to do this because
+ * we need to use ldmxcsr/stmxcsr to get correct results if any part
+ * of the program was compiled to use SSE floating-point, but we can't
+ * use SSE on older processors.
+ */
+int
+__test_sse(void)
+{
+	int flag, nflag;
+	int dx_features;
+
+	/* Am I a 486? */
+	getfl(&flag);
+	nflag = flag ^ 0x200000;
+	setfl(nflag);
+	getfl(&nflag);
+	if (flag != nflag) {
+		/* Not a 486, so CPUID should work. */
+		cpuid_dx(&dx_features);
+		if (dx_features & 0x2000000) {
+			__has_sse = __SSE_YES;
+			return (1);
+		}
+	}
+	__has_sse = __SSE_NO;
+	return (0);
+}
+
+int
+_STD(fesetexceptflag)(const fexcept_t *flagp, int excepts)
+{
+	fenv_t env;
+	int mxcsr;
+
+	__fnstenv(&env);
+	env.__status &= ~excepts;
+	env.__status |= *flagp & excepts;
+	__fldenv(env);
+
+	if (__HAS_SSE()) {
+		__stmxcsr(&mxcsr);
+		mxcsr &= ~excepts;
+		mxcsr |= *flagp & excepts;
+		__ldmxcsr(mxcsr);
+	}
+
+	return (0);
+}
+
+int
+_STD(feraiseexcept)(int excepts)
+{
+	fexcept_t ex = excepts;
+
+	fesetexceptflag(&ex, excepts);
+	__fwait();
+	return (0);
+}
+
+int
+_STD(fegetenv)(fenv_t *envp)
+{
+	int control, mxcsr;
+
+	/*
+	 * fnstenv masks all exceptions, so we need to save and
+	 * restore the control word to avoid this side effect.
+	 */
+	__fnstcw(&control);
+	__fnstenv(envp);
+	if (__HAS_SSE()) {
+		__stmxcsr(&mxcsr);
+		__set_mxcsr(*envp, mxcsr);
+	}
+	__fldcw(control);
+	return (0);
+}
+
+int
+_STD(feholdexcept)(fenv_t *envp)
+{
+	int mxcsr;
+
+	__fnstenv(envp);
+	__fnclex();
+	if (__HAS_SSE()) {
+		__stmxcsr(&mxcsr);
+		__set_mxcsr(*envp, mxcsr);
+		mxcsr &= ~FE_ALL_EXCEPT;
+		mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
+		__ldmxcsr(mxcsr);
+	}
+	return (0);
+}
+
+int
+_STD(feupdateenv)(const fenv_t *envp)
+{
+	int mxcsr, status;
+
+	__fnstsw(&status);
+	if (__HAS_SSE())
+		__stmxcsr(&mxcsr);
+	else
+		mxcsr = 0;
+	fesetenv(envp);
+	feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT);
+	return (0);
+}
+
+int
+__feenableexcept(int mask)
+{
+	int mxcsr, control, omask;
+
+	mask &= FE_ALL_EXCEPT;
+	__fnstcw(&control);
+	if (__HAS_SSE())
+		__stmxcsr(&mxcsr);
+	else
+		mxcsr = 0;
+	omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+	control &= ~mask;
+	__fldcw(control);
+	if (__HAS_SSE()) {
+		mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
+		__ldmxcsr(mxcsr);
+	}
+	return (~omask);
+}
+
+int
+__fedisableexcept(int mask)
+{
+	int mxcsr, control, omask;
+
+	mask &= FE_ALL_EXCEPT;
+	__fnstcw(&control);
+	if (__HAS_SSE())
+		__stmxcsr(&mxcsr);
+	else
+		mxcsr = 0;
+	omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+	control |= mask;
+	__fldcw(control);
+	if (__HAS_SSE()) {
+		mxcsr |= mask << _SSE_EMASK_SHIFT;
+		__ldmxcsr(mxcsr);
+	}
+	return (~omask);
+}
+
+__weak_reference(__feenableexcept, feenableexcept);
+__weak_reference(__fedisableexcept, fedisableexcept);
Index: /trunk/libc/src/msun/i387/s_ceil.S
===================================================================
--- /trunk/libc/src/msun/i387/s_ceil.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_ceil.S	(revision 2448)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_ceil.S,v 1.7 1999/08/28 00:06:11 peter Exp $")
+
+STDENTRY(ceil)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
+	orw	$0x0800,%dx		/* round towards +oo */
+	andw	$0xfbff,%dx
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
+
+	fldl	8(%ebp);		/* round */
+	frndint
+
+	fldcw	-4(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/i387/s_ceilf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_ceilf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_ceilf.S	(revision 2448)
@@ -0,0 +1,29 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_ceilf.S,v 1.1 2005/01/13 18:58:25 das Exp $");
+/* RCSID("$NetBSD: s_ceilf.S,v 1.3 1995/05/08 23:52:44 jtc Exp $") */
+
+STDENTRY(ceilf)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-12(%ebp)		/* store fpu control word */
+	movw	-12(%ebp),%dx
+	orw	$0x0800,%dx		/* round towards +oo */
+	andw	$0xfbff,%dx
+	movw	%dx,-16(%ebp)
+	fldcw	-16(%ebp)		/* load modfied control word */
+
+	flds	8(%ebp);		/* round */
+	frndint
+
+	fldcw	-12(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/i387/s_ceill.S
===================================================================
--- /trunk/libc/src/msun/i387/s_ceill.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_ceill.S	(revision 2448)
@@ -0,0 +1,27 @@
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+	
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_ceill.S,v 1.1 2005/04/16 21:12:55 das Exp $")
+
+STDENTRY(ceill)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
+	orw	$0x0800,%dx		/* round towards +oo */
+	andw	$0xfbff,%dx
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
+
+	fldt	8(%ebp)			/* round */
+	frndint
+
+	fldcw	-4(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/i387/s_copysign.S
===================================================================
--- /trunk/libc/src/msun/i387/s_copysign.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_copysign.S	(revision 2448)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_copysign.S,v 1.6 1999/08/28 00:06:11 peter Exp $")
+
+STDENTRY(copysign)
+	movl	16(%esp),%edx
+	andl	$0x80000000,%edx
+	movl	8(%esp),%eax
+	andl	$0x7fffffff,%eax
+	orl	%edx,%eax
+	movl	%eax,8(%esp)
+	fldl	4(%esp)
+	ret
Index: /trunk/libc/src/msun/i387/s_copysignf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_copysignf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_copysignf.S	(revision 2448)
@@ -0,0 +1,19 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_copysignf.S,v 1.1 2005/01/13 18:58:25 das Exp $");
+/* RCSID("$NetBSD: s_copysignf.S,v 1.3 1995/05/08 23:53:25 jtc Exp $") */
+
+STDENTRY(copysignf)
+	movl	8(%esp),%edx
+	andl	$0x80000000,%edx
+	movl	4(%esp),%eax
+	andl	$0x7fffffff,%eax
+	orl	%edx,%eax
+	movl	%eax,4(%esp)
+	flds	4(%esp)
+	ret
Index: /trunk/libc/src/msun/i387/s_copysignl.S
===================================================================
--- /trunk/libc/src/msun/i387/s_copysignl.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_copysignl.S	(revision 2448)
@@ -0,0 +1,17 @@
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_copysignl.S,v 1.1 2005/04/16 21:12:55 das Exp $")
+
+STDENTRY(copysignl)
+	movl	24(%esp),%edx
+	andl	$0x8000,%edx
+	movl	12(%esp),%eax
+	andl	$0x7fff,%eax
+	orl	%edx,%eax
+	movl	%eax,12(%esp)
+	fldt	4(%esp)
+	ret
Index: /trunk/libc/src/msun/i387/s_cos.S
===================================================================
--- /trunk/libc/src/msun/i387/s_cos.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_cos.S	(revision 2448)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1994 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_cos.S,v 1.6 1999/08/28 00:06:12 peter Exp $")
+
+STDENTRY(cos)
+	fldl	4(%esp)
+	fcos
+	fnstsw	%ax
+	andw	$0x400,%ax
+	jnz	1f
+	ret	
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fnstsw	%ax
+	andw	$0x400,%ax
+	jnz	2b
+	fstp	%st(1)
+	fcos
+	ret
Index: /trunk/libc/src/msun/i387/s_finite.S
===================================================================
--- /trunk/libc/src/msun/i387/s_finite.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_finite.S	(revision 2448)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_finite.S,v 1.7 1999/08/28 00:06:12 peter Exp $")
+
+STDENTRY(finite)
+	movl	8(%esp),%eax
+	andl	$0x7ff00000, %eax
+	cmpl	$0x7ff00000, %eax
+	setneb	%al
+	andl	$0x000000ff, %eax
+	ret
Index: /trunk/libc/src/msun/i387/s_floor.S
===================================================================
--- /trunk/libc/src/msun/i387/s_floor.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_floor.S	(revision 2448)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_floor.S,v 1.7 1999/08/28 00:06:12 peter Exp $")
+
+STDENTRY(floor)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
+	orw	$0x0400,%dx		/* round towards -oo */
+	andw	$0xf7ff,%dx
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
+
+	fldl	8(%ebp);		/* round */
+	frndint
+
+	fldcw	-4(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/i387/s_floorf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_floorf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_floorf.S	(revision 2448)
@@ -0,0 +1,29 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_floorf.S,v 1.1 2005/01/13 18:58:25 das Exp $");
+/* RCSID("$NetBSD: s_floorf.S,v 1.3 1995/05/09 00:04:32 jtc Exp $") */
+
+STDENTRY(floorf)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-12(%ebp)		/* store fpu control word */
+	movw	-12(%ebp),%dx
+	orw	$0x0400,%dx		/* round towards -oo */
+	andw	$0xf7ff,%dx
+	movw	%dx,-16(%ebp)
+	fldcw	-16(%ebp)		/* load modfied control word */
+
+	flds	8(%ebp);		/* round */
+	frndint
+
+	fldcw	-12(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/i387/s_floorl.S
===================================================================
--- /trunk/libc/src/msun/i387/s_floorl.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_floorl.S	(revision 2448)
@@ -0,0 +1,27 @@
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_floorl.S,v 1.1 2005/04/16 21:12:55 das Exp $")
+
+STDENTRY(floorl)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
+	orw	$0x0400,%dx		/* round towards -oo */
+	andw	$0xf7ff,%dx
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
+
+	fldt	8(%ebp)			/* round */
+	frndint
+
+	fldcw	-4(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/i387/s_llrint.S
===================================================================
--- /trunk/libc/src/msun/i387/s_llrint.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_llrint.S	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_llrint.S,v 1.1 2005/01/11 23:10:53 das Exp $");
+	
+STDENTRY(llrint)
+	fldl	4(%esp)
+	subl	$8,%esp
+	fistpll	(%esp)
+	popl	%eax
+	popl	%edx
+	ret
Index: /trunk/libc/src/msun/i387/s_llrintf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_llrintf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_llrintf.S	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_llrintf.S,v 1.1 2005/04/16 21:12:55 das Exp $")
+	
+STDENTRY(llrintf)
+	flds	4(%esp)
+	subl	$8,%esp
+	fistpll	(%esp)
+	popl	%eax
+	popl	%edx
+	ret
Index: /trunk/libc/src/msun/i387/s_logb.S
===================================================================
--- /trunk/libc/src/msun/i387/s_logb.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_logb.S	(revision 2448)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_logb.S,v 1.7 2000/06/06 12:12:36 bde Exp $")
+
+STDENTRY(logb)
+	fldl	4(%esp)
+	fxtract
+	fstp	%st
+	ret
Index: /trunk/libc/src/msun/i387/s_logbf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_logbf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_logbf.S	(revision 2448)
@@ -0,0 +1,15 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_logbf.S,v 1.1 2005/01/13 18:58:25 das Exp $");
+/* RCSID("$NetBSD: s_logbf.S,v 1.3 1995/05/09 00:15:12 jtc Exp $") */
+
+STDENTRY(logbf)
+	flds	4(%esp)
+	fxtract
+	fstp	%st
+	ret
Index: /trunk/libc/src/msun/i387/s_lrint.S
===================================================================
--- /trunk/libc/src/msun/i387/s_lrint.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_lrint.S	(revision 2448)
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_lrint.S,v 1.1 2005/01/11 23:10:53 das Exp $");
+	
+STDENTRY(lrint)
+	fldl	4(%esp)
+	subl	$4,%esp
+	fistpl	(%esp)
+	popl	%eax
+	ret
Index: /trunk/libc/src/msun/i387/s_lrintf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_lrintf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_lrintf.S	(revision 2448)
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_lrintf.S,v 1.1 2005/04/16 21:12:55 das Exp $")
+	
+STDENTRY(lrintf)
+	flds	4(%esp)
+	subl	$4,%esp
+	fistpl	(%esp)
+	popl	%eax
+	ret
Index: /trunk/libc/src/msun/i387/s_remquo.S
===================================================================
--- /trunk/libc/src/msun/i387/s_remquo.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_remquo.S	(revision 2448)
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_remquo.S,v 1.1 2005/03/25 04:40:44 das Exp $");
+	
+STDENTRY(remquo)
+	fldl	12(%esp)
+	fldl	4(%esp)
+1:	fprem1
+	fstsw	%ax
+	sahf
+	jp	1b
+	fstp	%st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+	shrl	$6,%eax
+	movl	%eax,%ecx
+	andl	$0x108,%eax
+	rorl	$7,%eax
+	orl	%eax,%ecx
+	roll	$4,%eax
+	orl	%ecx,%eax
+	andl	$7,%eax
+/* Negate the quotient bits if x*y<0.  Avoid using an unpredictable branch. */
+	movl	16(%esp),%ecx
+	xorl	8(%esp),%ecx
+	sarl	$16,%ecx
+	sarl	$16,%ecx
+	xorl	%ecx,%eax
+	andl	$1,%ecx
+	addl	%ecx,%eax
+/* Store the quotient and return. */
+	movl	20(%esp),%ecx
+	movl	%eax,(%ecx)
+	ret
Index: /trunk/libc/src/msun/i387/s_remquof.S
===================================================================
--- /trunk/libc/src/msun/i387/s_remquof.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_remquof.S	(revision 2448)
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_remquof.S,v 1.1 2005/03/25 04:40:44 das Exp $");
+	
+STDENTRY(remquof)
+	flds	8(%esp)
+	flds	4(%esp)
+1:	fprem1
+	fstsw	%ax
+	sahf
+	jp	1b
+	fstp	%st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+	shrl	$6,%eax
+	movl	%eax,%ecx
+	andl	$0x108,%eax
+	rorl	$7,%eax
+	orl	%eax,%ecx
+	roll	$4,%eax
+	orl	%ecx,%eax
+	andl	$7,%eax
+/* Negate the quotient bits if x*y<0.  Avoid using an unpredictable branch. */
+	movl	8(%esp),%ecx
+	xorl	4(%esp),%ecx
+	sarl	$16,%ecx
+	sarl	$16,%ecx
+	xorl	%ecx,%eax
+	andl	$1,%ecx
+	addl	%ecx,%eax
+/* Store the quotient and return. */
+	movl	12(%esp),%ecx
+	movl	%eax,(%ecx)
+	ret
Index: /trunk/libc/src/msun/i387/s_rint.S
===================================================================
--- /trunk/libc/src/msun/i387/s_rint.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_rint.S	(revision 2448)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_rint.S,v 1.6 1999/08/28 00:06:13 peter Exp $")
+
+STDENTRY(rint)
+	fldl	4(%esp)
+	frndint
+	ret
Index: /trunk/libc/src/msun/i387/s_rintf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_rintf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_rintf.S	(revision 2448)
@@ -0,0 +1,14 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_rintf.S,v 1.1 2005/01/13 18:58:25 das Exp $");
+/* RCSID("$NetBSD: s_rintf.S,v 1.3 1995/05/09 00:17:22 jtc Exp $") */
+
+STDENTRY(rintf)
+	flds	4(%esp)
+	frndint
+	ret
Index: /trunk/libc/src/msun/i387/s_scalbn.S
===================================================================
--- /trunk/libc/src/msun/i387/s_scalbn.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_scalbn.S	(revision 2448)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1994 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_scalbn.S,v 1.7 1999/08/28 00:06:13 peter Exp $")
+
+STDENTRY(scalbn)
+	fildl	12(%esp)
+	fldl	4(%esp)
+	fscale
+	fstp	%st(1)
+	ret
Index: /trunk/libc/src/msun/i387/s_scalbnf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_scalbnf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_scalbnf.S	(revision 2448)
@@ -0,0 +1,19 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_scalbnf.S,v 1.2 2005/03/07 04:52:43 das Exp $");
+/* RCSID("$NetBSD: s_scalbnf.S,v 1.4 1999/01/02 05:15:40 kristerw Exp $") */
+
+STDENTRY(scalbnf)
+	fildl	8(%esp)
+	flds	4(%esp)
+	fscale
+	fstp	%st(1)		/* bug fix for fp stack overflow */
+	ret
+
+.globl STDCNAME(ldexpf)
+.set	STDCNAME(ldexpf),STDCNAME(scalbnf)
Index: /trunk/libc/src/msun/i387/s_scalbnl.S
===================================================================
--- /trunk/libc/src/msun/i387/s_scalbnl.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_scalbnl.S	(revision 2448)
@@ -0,0 +1,19 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_scalbnl.S,v 1.1 2005/03/07 04:52:57 das Exp $");
+/* RCSID("$NetBSD: s_scalbnf.S,v 1.4 1999/01/02 05:15:40 kristerw Exp $") */
+
+STDENTRY(scalbnl)
+	fildl	16(%esp)
+	fldt	4(%esp)
+	fscale
+	fstp	%st(1)
+	ret
+
+.globl STDCNAME(ldexpl)
+.set	STDCNAME(ldexpl),STDCNAME(scalbnl)
Index: /trunk/libc/src/msun/i387/s_significand.S
===================================================================
--- /trunk/libc/src/msun/i387/s_significand.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_significand.S	(revision 2448)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_significand.S,v 1.7 2000/06/06 12:12:36 bde Exp $")
+
+STDENTRY(significand)
+	fldl	4(%esp)
+	fxtract
+	fstp	%st(1)
+	ret
Index: /trunk/libc/src/msun/i387/s_significandf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_significandf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_significandf.S	(revision 2448)
@@ -0,0 +1,15 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_significandf.S,v 1.1 2005/01/13 18:58:25 das Exp $");
+/* RCSID("$NetBSD: s_significandf.S,v 1.3 1995/05/09 00:24:07 jtc Exp $") */
+
+STDENTRY(significandf)
+	flds	4(%esp)
+	fxtract
+	fstp	%st(1)
+	ret
Index: /trunk/libc/src/msun/i387/s_sin.S
===================================================================
--- /trunk/libc/src/msun/i387/s_sin.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_sin.S	(revision 2448)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1994 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_sin.S,v 1.6 1999/08/28 00:06:14 peter Exp $")
+
+STDENTRY(sin)
+	fldl	4(%esp)
+	fsin
+	fnstsw	%ax
+	andw	$0x400,%ax
+	jnz	1f
+	ret
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fnstsw	%ax
+	andw	$0x400,%ax
+	jnz	2b
+	fstp	%st(1)
+	fsin
+	ret
Index: /trunk/libc/src/msun/i387/s_tan.S
===================================================================
--- /trunk/libc/src/msun/i387/s_tan.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_tan.S	(revision 2448)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1994 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Written by:
+ *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$FreeBSD: src/lib/msun/i387/s_tan.S,v 1.6 1999/08/28 00:06:14 peter Exp $")
+
+STDENTRY(tan)
+	fldl	4(%esp)
+	fptan
+	fnstsw	%ax
+	andw	$0x400,%ax
+	jnz	1f
+	fstp	%st(0)
+	ret
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fstsw	%ax
+	andw	$0x400,%ax
+	jnz	2b
+	fstp	%st(1)
+	fptan
+	fstp	%st(0)
+	ret
Index: /trunk/libc/src/msun/i387/s_trunc.S
===================================================================
--- /trunk/libc/src/msun/i387/s_trunc.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_trunc.S	(revision 2448)
@@ -0,0 +1,26 @@
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_trunc.S,v 1.1 2005/04/16 21:12:55 das Exp $")
+
+STDENTRY(trunc)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
+	orw	$0x0c00,%dx		/* round towards -oo */
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
+
+	fldl	8(%ebp)			/* round */
+	frndint
+
+	fldcw	-4(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/i387/s_truncf.S
===================================================================
--- /trunk/libc/src/msun/i387/s_truncf.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_truncf.S	(revision 2448)
@@ -0,0 +1,26 @@
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_truncf.S,v 1.1 2005/04/16 21:12:55 das Exp $")
+
+STDENTRY(truncf)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-12(%ebp)		/* store fpu control word */
+	movw	-12(%ebp),%dx
+	orw	$0x0c00,%dx		/* round towards -oo */
+	movw	%dx,-16(%ebp)
+	fldcw	-16(%ebp)		/* load modfied control word */
+
+	flds	8(%ebp)			/* round */
+	frndint
+
+	fldcw	-12(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/i387/s_truncl.S
===================================================================
--- /trunk/libc/src/msun/i387/s_truncl.S	(revision 2448)
+++ /trunk/libc/src/msun/i387/s_truncl.S	(revision 2448)
@@ -0,0 +1,26 @@
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: src/lib/msun/i387/s_truncl.S,v 1.1 2005/04/16 21:12:55 das Exp $")
+
+STDENTRY(truncl)
+	pushl	%ebp
+	movl	%esp,%ebp
+	subl	$8,%esp
+
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
+	orw	$0x0c00,%dx		/* round towards -oo */
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
+
+	fldt	8(%ebp)			/* round */
+	frndint
+
+	fldcw	-4(%ebp)		/* restore original control word */
+
+	leave
+	ret
Index: /trunk/libc/src/msun/msun.smak
===================================================================
--- /trunk/libc/src/msun/msun.smak	(revision 2448)
+++ /trunk/libc/src/msun/msun.smak	(revision 2448)
@@ -0,0 +1,62 @@
+# from the Makefile and i387/Makefile.inc
+COMMON_SRCS := \
+	e_acos.c e_acosf.c e_acosh.c e_acoshf.c e_asin.c e_asinf.c \
+	e_atan2.c e_atan2f.c e_atanh.c e_atanhf.c e_cosh.c e_coshf.c e_exp.c \
+	e_expf.c e_fmod.c e_fmodf.c e_gamma.c e_gamma_r.c e_gammaf.c \
+	e_gammaf_r.c e_hypot.c e_hypotf.c e_j0.c e_j0f.c e_j1.c e_j1f.c \
+	e_jn.c e_jnf.c e_lgamma.c e_lgamma_r.c e_lgammaf.c e_lgammaf_r.c \
+	e_log.c e_log10.c e_log10f.c e_logf.c e_pow.c e_powf.c e_rem_pio2.c \
+	e_rem_pio2f.c e_remainder.c e_remainderf.c e_scalb.c e_scalbf.c \
+	e_sinh.c e_sinhf.c e_sqrt.c e_sqrtf.c \
+	k_cos.c k_cosf.c k_rem_pio2.c k_rem_pio2f.c k_sin.c k_sinf.c \
+	k_tan.c k_tanf.c \
+	s_asinh.c s_asinhf.c s_atan.c s_atanf.c s_cbrt.c s_cbrtf.c \
+	s_ceil.c s_ceilf.c s_ceill.c \
+	s_copysign.c s_copysignf.c s_cos.c s_cosf.c s_erf.c s_erff.c \
+	s_exp2.c s_exp2f.c s_expm1.c s_expm1f.c s_fabsf.c s_fdim.c \
+	s_finite.c s_finitef.c \
+	s_floor.c s_floorf.c s_floorl.c s_fma.c s_fmaf.c \
+	s_fmax.c s_fmaxf.c s_fmaxl.c s_fmin.c \
+	s_fminf.c s_fminl.c s_frexp.c s_frexpf.c s_ilogb.c s_ilogbf.c \
+	s_ilogbl.c s_isfinite.c s_isnan.c s_isnormal.c \
+	s_llrint.c s_llrintf.c s_llround.c s_llroundf.c s_llroundl.c \
+	s_log1p.c s_log1pf.c s_logb.c s_logbf.c s_lrint.c s_lrintf.c \
+	s_lround.c s_lroundf.c s_lroundl.c s_modff.c \
+	s_nearbyint.c s_nextafter.c s_nextafterf.c \
+	s_nexttowardf.c s_remquo.c s_remquof.c \
+	s_rint.c s_rintf.c s_round.c s_roundf.c s_roundl.c \
+	s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \
+	s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c s_tan.c \
+	s_tanf.c s_tanh.c s_tanhf.c s_trunc.c s_truncf.c s_truncl.c \
+	w_cabs.c w_cabsf.c w_drem.c w_dremf.c
+COMMON_SRCS += s_copysignl.c s_fabsl.c
+COMMON_SRCS += s_fmal.c s_frexpl.c s_nextafterl.c s_nexttoward.c s_scalbnl.c
+COMMON_SRCS += s_cimag.c s_cimagf.c s_cimagl.c s_conj.c s_conjf.c s_conjl.c \
+    s_creal.c s_crealf.c s_creall.c
+
+BSD_SRCS = b_exp.c b_log.c b_tgamma.c
+
+ARCH_SRCS = e_exp.S e_fmod.S e_log.S e_log10.S \
+	    e_remainder.S e_scalb.S e_sqrt.S s_ceil.S s_copysign.S \
+	    s_cos.S s_finite.S s_floor.S s_llrint.S s_logb.S s_lrint.S \
+	    s_remquo.S s_rint.S s_scalbn.S s_significand.S s_sin.S s_tan.S \
+	    s_trunc.S
+ARCH_SRCS += e_log10f.S e_logf.S e_remainderf.S e_scalbf.S \
+	    e_sqrtf.S s_ceilf.S s_copysignf.S s_floorf.S \
+	    s_llrintf.S s_logbf.S s_lrintf.S \
+	    s_remquof.S s_rintf.S s_scalbnf.S s_significandf.S s_truncf.S
+ARCH_SRCS += s_ceill.S s_copysignl.S s_floorl.S s_scalbnl.S s_truncl.S
+ARCH_SRCS += fenv.c
+
+# select the sources we need.
+$(foreach asrc,$(basename $(ARCH_SRCS)),$(eval COMMON_SRCS := $(filter-out $(asrc).%,$(COMMON_SRCS))))
+MSUN_SRCS := $(wildcard src/msun/bsdsrc/*.c) \
+	$(addprefix src/msun/src/,$(COMMON_SRCS))
+	
+# No optimizations based on strict aliasing here, thank you.
+$(foreach src,$(MSUN_SRCS),$(eval .TCF.$(src):= -fno-strict-aliasing -Dlint))
+
+# Add to libc modules.
+libc.TSRC.386 += $(addprefix src/msun/i387/,$(ARCH_SRCS))
+libc.TSRC += $(MSUN_SRCS)
+
Index: /trunk/libc/src/msun/src/e_acos.c
===================================================================
--- /trunk/libc/src/msun/src/e_acos.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_acos.c	(revision 2448)
@@ -0,0 +1,105 @@
+
+/* @(#)e_acos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_acos.c,v 1.10 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_acos(x)
+ * Method :
+ *	acos(x)  = pi/2 - asin(x)
+ *	acos(-x) = pi/2 + asin(x)
+ * For |x|<=0.5
+ *	acos(x) = pi/2 - (x + x*x^2*R(x^2))	(see asin.c)
+ * For x>0.5
+ * 	acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
+ *		= 2asin(sqrt((1-x)/2))
+ *		= 2s + 2s*z*R(z) 	...z=(1-x)/2, s=sqrt(z)
+ *		= 2f + (2c + 2s*z*R(z))
+ *     where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
+ *     for f so that f+c ~ sqrt(z).
+ * For x<-0.5
+ *	acos(x) = pi - 2asin(sqrt((1-|x|)/2))
+ *		= pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
+ *
+ * Special cases:
+ *	if x is NaN, return x itself;
+ *	if |x|>1, return NaN with invalid signal.
+ *
+ * Function needed: sqrt
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+one=  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pi =  3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
+pio2_hi =  1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo =  6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pS0 =  1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 =  2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 =  7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 =  3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 =  2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+double
+__ieee754_acos(double x)
+{
+	double z,p,q,r,w,s,c,df;
+	int32_t hx,ix;
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x3ff00000) {	/* |x| >= 1 */
+	    u_int32_t lx;
+	    GET_LOW_WORD(lx,x);
+	    if(((ix-0x3ff00000)|lx)==0) {	/* |x|==1 */
+		if(hx>0) return 0.0;		/* acos(1) = 0  */
+		else return pi+2.0*pio2_lo;	/* acos(-1)= pi */
+	    }
+	    return (x-x)/(x-x);		/* acos(|x|>1) is NaN */
+	}
+	if(ix<0x3fe00000) {	/* |x| < 0.5 */
+	    if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+	    z = x*x;
+	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+	    r = p/q;
+	    return pio2_hi - (x - (pio2_lo-x*r));
+	} else  if (hx<0) {		/* x < -0.5 */
+	    z = (one+x)*0.5;
+	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+	    s = sqrt(z);
+	    r = p/q;
+	    w = r*s-pio2_lo;
+	    return pi - 2.0*(s+w);
+	} else {			/* x > 0.5 */
+	    z = (one-x)*0.5;
+	    s = sqrt(z);
+	    df = s;
+	    SET_LOW_WORD(df,0);
+	    c  = (z-df*df)/(s+df);
+	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+	    r = p/q;
+	    w = r*s+c;
+	    return 2.0*(df+w);
+	}
+}
Index: /trunk/libc/src/msun/src/e_acosf.c
===================================================================
--- /trunk/libc/src/msun/src/e_acosf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_acosf.c	(revision 2448)
@@ -0,0 +1,82 @@
+/* e_acosf.c -- float version of e_acos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_acosf.c,v 1.7 2002/05/28 17:03:12 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+one =  1.0000000000e+00, /* 0x3F800000 */
+pi =  3.1415925026e+00, /* 0x40490fda */
+pio2_hi =  1.5707962513e+00, /* 0x3fc90fda */
+pio2_lo =  7.5497894159e-08, /* 0x33a22168 */
+pS0 =  1.6666667163e-01, /* 0x3e2aaaab */
+pS1 = -3.2556581497e-01, /* 0xbea6b090 */
+pS2 =  2.0121252537e-01, /* 0x3e4e0aa8 */
+pS3 = -4.0055535734e-02, /* 0xbd241146 */
+pS4 =  7.9153501429e-04, /* 0x3a4f7f04 */
+pS5 =  3.4793309169e-05, /* 0x3811ef08 */
+qS1 = -2.4033949375e+00, /* 0xc019d139 */
+qS2 =  2.0209457874e+00, /* 0x4001572d */
+qS3 = -6.8828397989e-01, /* 0xbf303361 */
+qS4 =  7.7038154006e-02; /* 0x3d9dc62e */
+
+float
+__ieee754_acosf(float x)
+{
+	float z,p,q,r,w,s,c,df;
+	int32_t hx,ix;
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix==0x3f800000) {		/* |x|==1 */
+	    if(hx>0) return 0.0;	/* acos(1) = 0  */
+	    else return pi+(float)2.0*pio2_lo;	/* acos(-1)= pi */
+	} else if(ix>0x3f800000) {	/* |x| >= 1 */
+	    return (x-x)/(x-x);		/* acos(|x|>1) is NaN */
+	}
+	if(ix<0x3f000000) {	/* |x| < 0.5 */
+	    if(ix<=0x23000000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+	    z = x*x;
+	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+	    r = p/q;
+	    return pio2_hi - (x - (pio2_lo-x*r));
+	} else  if (hx<0) {		/* x < -0.5 */
+	    z = (one+x)*(float)0.5;
+	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+	    s = __ieee754_sqrtf(z);
+	    r = p/q;
+	    w = r*s-pio2_lo;
+	    return pi - (float)2.0*(s+w);
+	} else {			/* x > 0.5 */
+	    int32_t idf;
+	    z = (one-x)*(float)0.5;
+	    s = __ieee754_sqrtf(z);
+	    df = s;
+	    GET_FLOAT_WORD(idf,df);
+	    SET_FLOAT_WORD(df,idf&0xfffff000);
+	    c  = (z-df*df)/(s+df);
+	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+	    r = p/q;
+	    w = r*s+c;
+	    return (float)2.0*(df+w);
+	}
+}
Index: /trunk/libc/src/msun/src/e_acosh.c
===================================================================
--- /trunk/libc/src/msun/src/e_acosh.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_acosh.c	(revision 2448)
@@ -0,0 +1,64 @@
+
+/* @(#)e_acosh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_acosh.c,v 1.8 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_acosh(x)
+ * Method :
+ *	Based on
+ *		acosh(x) = log [ x + sqrt(x*x-1) ]
+ *	we have
+ *		acosh(x) := log(x)+ln2,	if x is large; else
+ *		acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
+ *		acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ *	acosh(x) is NaN with signal if x<1.
+ *	acosh(NaN) is NaN without signal.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+one	= 1.0,
+ln2	= 6.93147180559945286227e-01;  /* 0x3FE62E42, 0xFEFA39EF */
+
+double
+__ieee754_acosh(double x)
+{
+	double t;
+	int32_t hx;
+	u_int32_t lx;
+	EXTRACT_WORDS(hx,lx,x);
+	if(hx<0x3ff00000) {		/* x < 1 */
+	    return (x-x)/(x-x);
+	} else if(hx >=0x41b00000) {	/* x > 2**28 */
+	    if(hx >=0x7ff00000) {	/* x is inf of NaN */
+	        return x+x;
+	    } else
+		return __ieee754_log(x)+ln2;	/* acosh(huge)=log(2x) */
+	} else if(((hx-0x3ff00000)|lx)==0) {
+	    return 0.0;			/* acosh(1) = 0 */
+	} else if (hx > 0x40000000) {	/* 2**28 > x > 2 */
+	    t=x*x;
+	    return __ieee754_log(2.0*x-one/(x+sqrt(t-one)));
+	} else {			/* 1<x<2 */
+	    t = x-one;
+	    return log1p(t+sqrt(2.0*t+t*t));
+	}
+}
Index: /trunk/libc/src/msun/src/e_acoshf.c
===================================================================
--- /trunk/libc/src/msun/src/e_acoshf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_acoshf.c	(revision 2448)
@@ -0,0 +1,50 @@
+/* e_acoshf.c -- float version of e_acosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_acoshf.c,v 1.7 2002/05/28 17:03:12 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+one	= 1.0,
+ln2	= 6.9314718246e-01;  /* 0x3f317218 */
+
+float
+__ieee754_acoshf(float x)
+{
+	float t;
+	int32_t hx;
+	GET_FLOAT_WORD(hx,x);
+	if(hx<0x3f800000) {		/* x < 1 */
+	    return (x-x)/(x-x);
+	} else if(hx >=0x4d800000) {	/* x > 2**28 */
+	    if(hx >=0x7f800000) {	/* x is inf of NaN */
+	        return x+x;
+	    } else
+		return __ieee754_logf(x)+ln2;	/* acosh(huge)=log(2x) */
+	} else if (hx==0x3f800000) {
+	    return 0.0;			/* acosh(1) = 0 */
+	} else if (hx > 0x40000000) {	/* 2**28 > x > 2 */
+	    t=x*x;
+	    return __ieee754_logf((float)2.0*x-one/(x+__ieee754_sqrtf(t-one)));
+	} else {			/* 1<x<2 */
+	    t = x-one;
+	    return log1pf(t+__ieee754_sqrtf((float)2.0*t+t*t));
+	}
+}
Index: /trunk/libc/src/msun/src/e_asin.c
===================================================================
--- /trunk/libc/src/msun/src/e_asin.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_asin.c	(revision 2448)
@@ -0,0 +1,114 @@
+
+/* @(#)e_asin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_asin.c,v 1.11 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_asin(x)
+ * Method :
+ *	Since  asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
+ *	we approximate asin(x) on [0,0.5] by
+ *		asin(x) = x + x*x^2*R(x^2)
+ *	where
+ *		R(x^2) is a rational approximation of (asin(x)-x)/x^3
+ *	and its remez error is bounded by
+ *		|(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
+ *
+ *	For x in [0.5,1]
+ *		asin(x) = pi/2-2*asin(sqrt((1-x)/2))
+ *	Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
+ *	then for x>0.98
+ *		asin(x) = pi/2 - 2*(s+s*z*R(z))
+ *			= pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
+ *	For x<=0.98, let pio4_hi = pio2_hi/2, then
+ *		f = hi part of s;
+ *		c = sqrt(z) - f = (z-f*f)/(s+f) 	...f+c=sqrt(z)
+ *	and
+ *		asin(x) = pi/2 - 2*(s+s*z*R(z))
+ *			= pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
+ *			= pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
+ *
+ * Special cases:
+ *	if x is NaN, return x itself;
+ *	if |x|>1, return NaN with invalid signal.
+ *
+ */
+
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+huge =  1.000e+300,
+pio2_hi =  1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo =  6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pio4_hi =  7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
+	/* coefficient for R(x^2) */
+pS0 =  1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 =  2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 =  7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 =  3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 =  2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+double
+__ieee754_asin(double x)
+{
+	double t=0.0,w,p,q,c,r,s;
+	int32_t hx,ix;
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>= 0x3ff00000) {		/* |x|>= 1 */
+	    u_int32_t lx;
+	    GET_LOW_WORD(lx,x);
+	    if(((ix-0x3ff00000)|lx)==0)
+		    /* asin(1)=+-pi/2 with inexact */
+		return x*pio2_hi+x*pio2_lo;	
+	    return (x-x)/(x-x);		/* asin(|x|>1) is NaN */
+	} else if (ix<0x3fe00000) {	/* |x|<0.5 */
+	    if(ix<0x3e400000) {		/* if |x| < 2**-27 */
+		if(huge+x>one) return x;/* return x with inexact if x!=0*/
+	    } else
+		t = x*x;
+		p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+		q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+		w = p/q;
+		return x+x*w;
+	}
+	/* 1> |x|>= 0.5 */
+	w = one-fabs(x);
+	t = w*0.5;
+	p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+	q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+	s = sqrt(t);
+	if(ix>=0x3FEF3333) { 	/* if |x| > 0.975 */
+	    w = p/q;
+	    t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
+	} else {
+	    w  = s;
+	    SET_LOW_WORD(w,0);
+	    c  = (t-w*w)/(s+w);
+	    r  = p/q;
+	    p  = 2.0*s*r-(pio2_lo-2.0*c);
+	    q  = pio4_hi-2.0*w;
+	    t  = pio4_hi-(p-q);
+	}
+	if(hx>0) return t; else return -t;
+}
Index: /trunk/libc/src/msun/src/e_asinf.c
===================================================================
--- /trunk/libc/src/msun/src/e_asinf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_asinf.c	(revision 2448)
@@ -0,0 +1,85 @@
+/* e_asinf.c -- float version of e_asin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_asinf.c,v 1.8 2002/05/28 17:03:12 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+one =  1.0000000000e+00, /* 0x3F800000 */
+huge =  1.000e+30,
+pio2_hi =  1.5707962513e+00, /* 0x3fc90fda */
+pio2_lo =  7.5497894159e-08, /* 0x33a22168 */
+pio4_hi =  7.8539818525e-01, /* 0x3f490fdb */
+	/* coefficient for R(x^2) */
+pS0 =  1.6666667163e-01, /* 0x3e2aaaab */
+pS1 = -3.2556581497e-01, /* 0xbea6b090 */
+pS2 =  2.0121252537e-01, /* 0x3e4e0aa8 */
+pS3 = -4.0055535734e-02, /* 0xbd241146 */
+pS4 =  7.9153501429e-04, /* 0x3a4f7f04 */
+pS5 =  3.4793309169e-05, /* 0x3811ef08 */
+qS1 = -2.4033949375e+00, /* 0xc019d139 */
+qS2 =  2.0209457874e+00, /* 0x4001572d */
+qS3 = -6.8828397989e-01, /* 0xbf303361 */
+qS4 =  7.7038154006e-02; /* 0x3d9dc62e */
+
+float
+__ieee754_asinf(float x)
+{
+	float t=0.0,w,p,q,c,r,s;
+	int32_t hx,ix;
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix==0x3f800000) {
+		/* asin(1)=+-pi/2 with inexact */
+	    return x*pio2_hi+x*pio2_lo;
+	} else if(ix> 0x3f800000) {	/* |x|>= 1 */
+	    return (x-x)/(x-x);		/* asin(|x|>1) is NaN */
+	} else if (ix<0x3f000000) {	/* |x|<0.5 */
+	    if(ix<0x32000000) {		/* if |x| < 2**-27 */
+		if(huge+x>one) return x;/* return x with inexact if x!=0*/
+	    } else
+		t = x*x;
+		p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+		q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+		w = p/q;
+		return x+x*w;
+	}
+	/* 1> |x|>= 0.5 */
+	w = one-fabsf(x);
+	t = w*(float)0.5;
+	p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+	q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+	s = __ieee754_sqrtf(t);
+	if(ix>=0x3F79999A) { 	/* if |x| > 0.975 */
+	    w = p/q;
+	    t = pio2_hi-((float)2.0*(s+s*w)-pio2_lo);
+	} else {
+	    int32_t iw;
+	    w  = s;
+	    GET_FLOAT_WORD(iw,w);
+	    SET_FLOAT_WORD(w,iw&0xfffff000);
+	    c  = (t-w*w)/(s+w);
+	    r  = p/q;
+	    p  = (float)2.0*s*r-(pio2_lo-(float)2.0*c);
+	    q  = pio4_hi-(float)2.0*w;
+	    t  = pio4_hi-(p-q);
+	}
+	if(hx>0) return t; else return -t;
+}
Index: /trunk/libc/src/msun/src/e_atan2.c
===================================================================
--- /trunk/libc/src/msun/src/e_atan2.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_atan2.c	(revision 2448)
@@ -0,0 +1,125 @@
+
+/* @(#)e_atan2.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_atan2.c,v 1.10 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_atan2(y,x)
+ * Method :
+ *	1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
+ *	2. Reduce x to positive by (if x and y are unexceptional):
+ *		ARG (x+iy) = arctan(y/x)   	   ... if x > 0,
+ *		ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
+ *
+ * Special cases:
+ *
+ *	ATAN2((anything), NaN ) is NaN;
+ *	ATAN2(NAN , (anything) ) is NaN;
+ *	ATAN2(+-0, +(anything but NaN)) is +-0  ;
+ *	ATAN2(+-0, -(anything but NaN)) is +-pi ;
+ *	ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
+ *	ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
+ *	ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
+ *	ATAN2(+-INF,+INF ) is +-pi/4 ;
+ *	ATAN2(+-INF,-INF ) is +-3pi/4;
+ *	ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+tiny  = 1.0e-300,
+zero  = 0.0,
+pi_o_4  = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
+pi_o_2  = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
+pi      = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
+pi_lo   = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
+
+double
+__ieee754_atan2(double y, double x)
+{
+	double z;
+	int32_t k,m,hx,hy,ix,iy;
+	u_int32_t lx,ly;
+
+	EXTRACT_WORDS(hx,lx,x);
+	ix = hx&0x7fffffff;
+	EXTRACT_WORDS(hy,ly,y);
+	iy = hy&0x7fffffff;
+	if(((ix|((lx|-lx)>>31))>0x7ff00000)||
+	   ((iy|((ly|-ly)>>31))>0x7ff00000))	/* x or y is NaN */
+	   return x+y;
+	if((hx-0x3ff00000|lx)==0) return atan(y);   /* x=1.0 */
+	m = ((hy>>31)&1)|((hx>>30)&2);	/* 2*sign(x)+sign(y) */
+
+    /* when y = 0 */
+	if((iy|ly)==0) {
+	    switch(m) {
+		case 0:
+		case 1: return y; 	/* atan(+-0,+anything)=+-0 */
+		case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
+		case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+	    }
+	}
+    /* when x = 0 */
+	if((ix|lx)==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
+	
+    /* when x is INF */
+	if(ix==0x7ff00000) {
+	    if(iy==0x7ff00000) {
+		switch(m) {
+		    case 0: return  pi_o_4+tiny;/* atan(+INF,+INF) */
+		    case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+		    case 2: return  3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+		    case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+		}
+	    } else {
+		switch(m) {
+		    case 0: return  zero  ;	/* atan(+...,+INF) */
+		    case 1: return -zero  ;	/* atan(-...,+INF) */
+		    case 2: return  pi+tiny  ;	/* atan(+...,-INF) */
+		    case 3: return -pi-tiny  ;	/* atan(-...,-INF) */
+		}
+	    }
+	}
+    /* when y is INF */
+	if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+    /* compute y/x */
+	k = (iy-ix)>>20;
+	if(k > 60) z=pi_o_2+0.5*pi_lo; 	/* |y/x| >  2**60 */
+	else if(hx<0&&k<-60) z=0.0; 	/* |y|/x < -2**60 */
+	else z=atan(fabs(y/x));		/* safe to do y/x */
+	switch (m) {
+	    case 0: return       z  ;	/* atan(+,+) */
+	    case 1: {
+	    	      u_int32_t zh;
+		      GET_HIGH_WORD(zh,z);
+		      SET_HIGH_WORD(z,zh ^ 0x80000000);
+		    }
+		    return       z  ;	/* atan(-,+) */
+	    case 2: return  pi-(z-pi_lo);/* atan(+,-) */
+	    default: /* case 3 */
+	    	    return  (z-pi_lo)-pi;/* atan(-,-) */
+	}
+}
Index: /trunk/libc/src/msun/src/e_atan2f.c
===================================================================
--- /trunk/libc/src/msun/src/e_atan2f.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_atan2f.c	(revision 2448)
@@ -0,0 +1,98 @@
+/* e_atan2f.c -- float version of e_atan2.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_atan2f.c,v 1.7 2004/06/02 17:09:05 bde Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+tiny  = 1.0e-30,
+zero  = 0.0,
+pi_o_4  = 7.8539818525e-01, /* 0x3f490fdb */
+pi_o_2  = 1.5707963705e+00, /* 0x3fc90fdb */
+pi      = 3.1415927410e+00, /* 0x40490fdb */
+pi_lo   = -8.7422776573e-08; /* 0xb3bbbd2e */
+
+float
+__ieee754_atan2f(float y, float x)
+{
+	float z;
+	int32_t k,m,hx,hy,ix,iy;
+
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	GET_FLOAT_WORD(hy,y);
+	iy = hy&0x7fffffff;
+	if((ix>0x7f800000)||
+	   (iy>0x7f800000))	/* x or y is NaN */
+	   return x+y;
+	if(hx==0x3f800000) return atanf(y);   /* x=1.0 */
+	m = ((hy>>31)&1)|((hx>>30)&2);	/* 2*sign(x)+sign(y) */
+
+    /* when y = 0 */
+	if(iy==0) {
+	    switch(m) {
+		case 0:
+		case 1: return y; 	/* atan(+-0,+anything)=+-0 */
+		case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
+		case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+	    }
+	}
+    /* when x = 0 */
+	if(ix==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
+
+    /* when x is INF */
+	if(ix==0x7f800000) {
+	    if(iy==0x7f800000) {
+		switch(m) {
+		    case 0: return  pi_o_4+tiny;/* atan(+INF,+INF) */
+		    case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+		    case 2: return  (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+		    case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+		}
+	    } else {
+		switch(m) {
+		    case 0: return  zero  ;	/* atan(+...,+INF) */
+		    case 1: return -zero  ;	/* atan(-...,+INF) */
+		    case 2: return  pi+tiny  ;	/* atan(+...,-INF) */
+		    case 3: return -pi-tiny  ;	/* atan(-...,-INF) */
+		}
+	    }
+	}
+    /* when y is INF */
+	if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+    /* compute y/x */
+	k = (iy-ix)>>23;
+	if(k > 60) z=pi_o_2+(float)0.5*pi_lo; 	/* |y/x| >  2**60 */
+	else if(hx<0&&k<-60) z=0.0; 	/* |y|/x < -2**60 */
+	else z=atanf(fabsf(y/x));	/* safe to do y/x */
+	switch (m) {
+	    case 0: return       z  ;	/* atan(+,+) */
+	    case 1: {
+	    	      u_int32_t zh;
+		      GET_FLOAT_WORD(zh,z);
+		      SET_FLOAT_WORD(z,zh ^ 0x80000000);
+		    }
+		    return       z  ;	/* atan(-,+) */
+	    case 2: return  pi-(z-pi_lo);/* atan(+,-) */
+	    default: /* case 3 */
+	    	    return  (z-pi_lo)-pi;/* atan(-,-) */
+	}
+}
Index: /trunk/libc/src/msun/src/e_atanh.c
===================================================================
--- /trunk/libc/src/msun/src/e_atanh.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_atanh.c	(revision 2448)
@@ -0,0 +1,64 @@
+
+/* @(#)e_atanh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_atanh.c,v 1.7 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_atanh(x)
+ * Method :
+ *    1.Reduced x to positive by atanh(-x) = -atanh(x)
+ *    2.For x>=0.5
+ *                  1              2x                          x
+ *	atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ *                  2             1 - x                      1 - x
+ *	
+ * 	For x<0.5
+ *	atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
+ *
+ * Special cases:
+ *	atanh(x) is NaN if |x| > 1 with signal;
+ *	atanh(NaN) is that NaN with no signal;
+ *	atanh(+-1) is +-INF with signal.
+ *
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double one = 1.0, huge = 1e300;
+static const double zero = 0.0;
+
+double
+__ieee754_atanh(double x)
+{
+	double t;
+	int32_t hx,ix;
+	u_int32_t lx;
+	EXTRACT_WORDS(hx,lx,x);
+	ix = hx&0x7fffffff;
+	if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
+	    return (x-x)/(x-x);
+	if(ix==0x3ff00000)
+	    return x/zero;
+	if(ix<0x3e300000&&(huge+x)>zero) return x;	/* x<2**-28 */
+	SET_HIGH_WORD(x,ix);
+	if(ix<0x3fe00000) {		/* x < 0.5 */
+	    t = x+x;
+	    t = 0.5*log1p(t+t*x/(one-x));
+	} else
+	    t = 0.5*log1p((x+x)/(one-x));
+	if(hx>=0) return t; else return -t;
+}
Index: /trunk/libc/src/msun/src/e_atanhf.c
===================================================================
--- /trunk/libc/src/msun/src/e_atanhf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_atanhf.c	(revision 2448)
@@ -0,0 +1,47 @@
+/* e_atanhf.c -- float version of e_atanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_atanhf.c,v 1.6 2002/05/28 17:03:12 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float one = 1.0, huge = 1e30;
+
+static const float zero = 0.0;
+
+float
+__ieee754_atanhf(float x)
+{
+	float t;
+	int32_t hx,ix;
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if (ix>0x3f800000) 		/* |x|>1 */
+	    return (x-x)/(x-x);
+	if(ix==0x3f800000)
+	    return x/zero;
+	if(ix<0x31800000&&(huge+x)>zero) return x;	/* x<2**-28 */
+	SET_FLOAT_WORD(x,ix);
+	if(ix<0x3f000000) {		/* x < 0.5 */
+	    t = x+x;
+	    t = (float)0.5*log1pf(t+t*x/(one-x));
+	} else
+	    t = (float)0.5*log1pf((x+x)/(one-x));
+	if(hx>=0) return t; else return -t;
+}
Index: /trunk/libc/src/msun/src/e_cosh.c
===================================================================
--- /trunk/libc/src/msun/src/e_cosh.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_cosh.c	(revision 2448)
@@ -0,0 +1,87 @@
+
+/* @(#)e_cosh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_cosh.c,v 1.8 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_cosh(x)
+ * Method :
+ * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
+ *	1. Replace x by |x| (cosh(x) = cosh(-x)).
+ *	2.
+ *		                                        [ exp(x) - 1 ]^2
+ *	    0        <= x <= ln2/2  :  cosh(x) := 1 + -------------------
+ *			       			           2*exp(x)
+ *
+ *		                                  exp(x) +  1/exp(x)
+ *	    ln2/2    <= x <= 22     :  cosh(x) := -------------------
+ *			       			          2
+ *	    22       <= x <= lnovft :  cosh(x) := exp(x)/2
+ *	    lnovft   <= x <= ln2ovft:  cosh(x) := exp(x/2)/2 * exp(x/2)
+ *	    ln2ovft  <  x	    :  cosh(x) := huge*huge (overflow)
+ *
+ * Special cases:
+ *	cosh(x) is |x| if x is +INF, -INF, or NaN.
+ *	only cosh(0)=1 is exact for finite x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double one = 1.0, half=0.5, huge = 1.0e300;
+
+double
+__ieee754_cosh(double x)
+{
+	double t,w;
+	int32_t ix;
+	u_int32_t lx;
+
+    /* High word of |x|. */
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;
+
+    /* x is INF or NaN */
+	if(ix>=0x7ff00000) return x*x;	
+
+    /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
+	if(ix<0x3fd62e43) {
+	    t = expm1(fabs(x));
+	    w = one+t;
+	    if (ix<0x3c800000) return w;	/* cosh(tiny) = 1 */
+	    return one+(t*t)/(w+w);
+	}
+
+    /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+	if (ix < 0x40360000) {
+		t = __ieee754_exp(fabs(x));
+		return half*t+half/t;
+	}
+
+    /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
+	if (ix < 0x40862E42)  return half*__ieee754_exp(fabs(x));
+
+    /* |x| in [log(maxdouble), overflowthresold] */
+	GET_LOW_WORD(lx,x);
+	if (ix<0x408633CE ||
+	      ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) {
+	    w = __ieee754_exp(half*fabs(x));
+	    t = half*w;
+	    return t*w;
+	}
+
+    /* |x| > overflowthresold, cosh(x) overflow */
+	return huge*huge;
+}
Index: /trunk/libc/src/msun/src/e_coshf.c
===================================================================
--- /trunk/libc/src/msun/src/e_coshf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_coshf.c	(revision 2448)
@@ -0,0 +1,64 @@
+/* e_coshf.c -- float version of e_cosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_coshf.c,v 1.6 2002/05/28 17:03:12 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float one = 1.0, half=0.5, huge = 1.0e30;
+
+float
+__ieee754_coshf(float x)
+{
+	float t,w;
+	int32_t ix;
+
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;
+
+    /* x is INF or NaN */
+	if(ix>=0x7f800000) return x*x;
+
+    /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
+	if(ix<0x3eb17218) {
+	    t = expm1f(fabsf(x));
+	    w = one+t;
+	    if (ix<0x24000000) return w;	/* cosh(tiny) = 1 */
+	    return one+(t*t)/(w+w);
+	}
+
+    /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+	if (ix < 0x41b00000) {
+		t = __ieee754_expf(fabsf(x));
+		return half*t+half/t;
+	}
+
+    /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
+	if (ix < 0x42b17180)  return half*__ieee754_expf(fabsf(x));
+
+    /* |x| in [log(maxdouble), overflowthresold] */
+	if (ix<=0x42b2d4fc) {
+	    w = __ieee754_expf(half*fabsf(x));
+	    t = half*w;
+	    return t*w;
+	}
+
+    /* |x| > overflowthresold, cosh(x) overflow */
+	return huge*huge;
+}
Index: /trunk/libc/src/msun/src/e_exp.c
===================================================================
--- /trunk/libc/src/msun/src/e_exp.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_exp.c	(revision 2448)
@@ -0,0 +1,160 @@
+
+/* @(#)e_exp.c 1.6 04/04/22 */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_exp.c,v 1.10 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_exp(x)
+ * Returns the exponential of x.
+ *
+ * Method
+ *   1. Argument reduction:
+ *      Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ *	Given x, find r and integer k such that
+ *
+ *               x = k*ln2 + r,  |r| <= 0.5*ln2.
+ *
+ *      Here r will be represented as r = hi-lo for better
+ *	accuracy.
+ *
+ *   2. Approximation of exp(r) by a special rational function on
+ *	the interval [0,0.34658]:
+ *	Write
+ *	    R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ *      We use a special Remes algorithm on [0,0.34658] to generate
+ * 	a polynomial of degree 5 to approximate R. The maximum error
+ *	of this polynomial approximation is bounded by 2**-59. In
+ *	other words,
+ *	    R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ *  	(where z=r*r, and the values of P1 to P5 are listed below)
+ *	and
+ *	    |                  5          |     -59
+ *	    | 2.0+P1*z+...+P5*z   -  R(z) | <= 2
+ *	    |                             |
+ *	The computation of exp(r) thus becomes
+ *                             2*r
+ *		exp(r) = 1 + -------
+ *		              R - r
+ *                                 r*R1(r)	
+ *		       = 1 + r + ----------- (for better accuracy)
+ *		                  2 - R1(r)
+ *	where
+ *			         2       4             10
+ *		R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
+ *	
+ *   3. Scale back to obtain exp(x):
+ *	From step 1, we have
+ *	   exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ *	exp(INF) is INF, exp(NaN) is NaN;
+ *	exp(-INF) is 0, and
+ *	for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ *	according to an error analysis, the error is always less than
+ *	1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ *	For IEEE double
+ *	    if x >  7.09782712893383973096e+02 then exp(x) overflow
+ *	    if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+one	= 1.0,
+halF[2]	= {0.5,-0.5,},
+huge	= 1.0e+300,
+twom1000= 9.33263618503218878990e-302,     /* 2**-1000=0x01700000,0*/
+o_threshold=  7.09782712893383973096e+02,  /* 0x40862E42, 0xFEFA39EF */
+u_threshold= -7.45133219101941108420e+02,  /* 0xc0874910, 0xD52D3051 */
+ln2HI[2]   ={ 6.93147180369123816490e-01,  /* 0x3fe62e42, 0xfee00000 */
+	     -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */
+ln2LO[2]   ={ 1.90821492927058770002e-10,  /* 0x3dea39ef, 0x35793c76 */
+	     -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
+invln2 =  1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
+P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5   =  4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
+
+
+double
+__ieee754_exp(double x)	/* default IEEE double exp */
+{
+	double y,hi=0.0,lo=0.0,c,t;
+	int32_t k=0,xsb;
+	u_int32_t hx;
+
+	GET_HIGH_WORD(hx,x);
+	xsb = (hx>>31)&1;		/* sign bit of x */
+	hx &= 0x7fffffff;		/* high word of |x| */
+
+    /* filter out non-finite argument */
+	if(hx >= 0x40862E42) {			/* if |x|>=709.78... */
+            if(hx>=0x7ff00000) {
+	        u_int32_t lx;
+		GET_LOW_WORD(lx,x);
+		if(((hx&0xfffff)|lx)!=0)
+		     return x+x; 		/* NaN */
+		else return (xsb==0)? x:0.0;	/* exp(+-inf)={inf,0} */
+	    }
+	    if(x > o_threshold) return huge*huge; /* overflow */
+	    if(x < u_threshold) return twom1000*twom1000; /* underflow */
+	}
+
+    /* argument reduction */
+	if(hx > 0x3fd62e42) {		/* if  |x| > 0.5 ln2 */
+	    if(hx < 0x3FF0A2B2) {	/* and |x| < 1.5 ln2 */
+		hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+	    } else {
+		k  = (int)(invln2*x+halF[xsb]);
+		t  = k;
+		hi = x - t*ln2HI[0];	/* t*ln2HI is exact here */
+		lo = t*ln2LO[0];
+	    }
+	    x  = hi - lo;
+	}
+	else if(hx < 0x3e300000)  {	/* when |x|<2**-28 */
+	    if(huge+x>one) return one+x;/* trigger inexact */
+	}
+	else k = 0;
+
+    /* x is now in primary range */
+	t  = x*x;
+	c  = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+	if(k==0) 	return one-((x*c)/(c-2.0)-x);
+	else 		y = one-((lo-(x*c)/(2.0-c))-hi);
+	if(k >= -1021) {
+	    u_int32_t hy;
+	    GET_HIGH_WORD(hy,y);
+	    SET_HIGH_WORD(y,hy+(k<<20));	/* add k to y's exponent */
+	    return y;
+	} else {
+	    u_int32_t hy;
+	    GET_HIGH_WORD(hy,y);
+	    SET_HIGH_WORD(y,hy+((k+1000)<<20));	/* add k to y's exponent */
+	    return y*twom1000;
+	}
+}
Index: /trunk/libc/src/msun/src/e_expf.c
===================================================================
--- /trunk/libc/src/msun/src/e_expf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_expf.c	(revision 2448)
@@ -0,0 +1,96 @@
+/* e_expf.c -- float version of e_exp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_expf.c,v 1.9 2005/02/24 06:32:13 das Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+one	= 1.0,
+halF[2]	= {0.5,-0.5,},
+huge	= 1.0e+30,
+twom100 = 7.8886090522e-31,      /* 2**-100=0x0d800000 */
+o_threshold=  8.8721679688e+01,  /* 0x42b17180 */
+u_threshold= -1.0397208405e+02,  /* 0xc2cff1b5 */
+ln2HI[2]   ={ 6.9313812256e-01,		/* 0x3f317180 */
+	     -6.9313812256e-01,},	/* 0xbf317180 */
+ln2LO[2]   ={ 9.0580006145e-06,  	/* 0x3717f7d1 */
+	     -9.0580006145e-06,},	/* 0xb717f7d1 */
+invln2 =  1.4426950216e+00, 		/* 0x3fb8aa3b */
+P1   =  1.6666667163e-01, /* 0x3e2aaaab */
+P2   = -2.7777778450e-03, /* 0xbb360b61 */
+P3   =  6.6137559770e-05, /* 0x388ab355 */
+P4   = -1.6533901999e-06, /* 0xb5ddea0e */
+P5   =  4.1381369442e-08; /* 0x3331bb4c */
+
+float
+__ieee754_expf(float x)	/* default IEEE double exp */
+{
+	float y,hi=0.0,lo=0.0,c,t;
+	int32_t k=0,xsb;
+	u_int32_t hx;
+
+	GET_FLOAT_WORD(hx,x);
+	xsb = (hx>>31)&1;		/* sign bit of x */
+	hx &= 0x7fffffff;		/* high word of |x| */
+
+    /* filter out non-finite argument */
+	if(hx >= 0x42b17218) {			/* if |x|>=88.721... */
+	    if(hx>0x7f800000)
+		 return x+x;	 		/* NaN */
+            if(hx==0x7f800000)
+		return (xsb==0)? x:0.0;		/* exp(+-inf)={inf,0} */
+	    if(x > o_threshold) return huge*huge; /* overflow */
+	    if(x < u_threshold) return twom100*twom100; /* underflow */
+	}
+
+    /* argument reduction */
+	if(hx > 0x3eb17218) {		/* if  |x| > 0.5 ln2 */
+	    if(hx < 0x3F851592) {	/* and |x| < 1.5 ln2 */
+		hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+	    } else {
+		k  = invln2*x+halF[xsb];
+		t  = k;
+		hi = x - t*ln2HI[0];	/* t*ln2HI is exact here */
+		lo = t*ln2LO[0];
+	    }
+	    x  = hi - lo;
+	}
+	else if(hx < 0x31800000)  {	/* when |x|<2**-28 */
+	    if(huge+x>one) return one+x;/* trigger inexact */
+	}
+	else k = 0;
+
+    /* x is now in primary range */
+	t  = x*x;
+	c  = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+	if(k==0) 	return one-((x*c)/(c-(float)2.0)-x);
+	else 		y = one-((lo-(x*c)/((float)2.0-c))-hi);
+	if(k >= -125) {
+	    u_int32_t hy;
+	    GET_FLOAT_WORD(hy,y);
+	    SET_FLOAT_WORD(y,hy+(k<<23));	/* add k to y's exponent */
+	    return y;
+	} else {
+	    u_int32_t hy;
+	    GET_FLOAT_WORD(hy,y);
+	    SET_FLOAT_WORD(y,hy+((k+100)<<23));	/* add k to y's exponent */
+	    return y*twom100;
+	}
+}
Index: /trunk/libc/src/msun/src/e_fmod.c
===================================================================
--- /trunk/libc/src/msun/src/e_fmod.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_fmod.c	(revision 2448)
@@ -0,0 +1,134 @@
+
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_fmod.c,v 1.9 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/*
+ * __ieee754_fmod(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double one = 1.0, Zero[] = {0.0, -0.0,};
+
+double
+__ieee754_fmod(double x, double y)
+{
+	int32_t n,hx,hy,hz,ix,iy,sx,i;
+	u_int32_t lx,ly,lz;
+
+	EXTRACT_WORDS(hx,lx,x);
+	EXTRACT_WORDS(hy,ly,y);
+	sx = hx&0x80000000;		/* sign of x */
+	hx ^=sx;		/* |x| */
+	hy &= 0x7fffffff;	/* |y| */
+
+    /* purge off exception values */
+	if((hy|ly)==0||(hx>=0x7ff00000)||	/* y=0,or x not finite */
+	  ((hy|((ly|-ly)>>31))>0x7ff00000))	/* or y is NaN */
+	    return (x*y)/(x*y);
+	if(hx<=hy) {
+	    if((hx<hy)||(lx<ly)) return x;	/* |x|<|y| return x */
+	    if(lx==ly)
+		return Zero[(u_int32_t)sx>>31];	/* |x|=|y| return x*0*/
+	}
+
+    /* determine ix = ilogb(x) */
+	if(hx<0x00100000) {	/* subnormal x */
+	    if(hx==0) {
+		for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+	    } else {
+		for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+	    }
+	} else ix = (hx>>20)-1023;
+
+    /* determine iy = ilogb(y) */
+	if(hy<0x00100000) {	/* subnormal y */
+	    if(hy==0) {
+		for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+	    } else {
+		for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+	    }
+	} else iy = (hy>>20)-1023;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+	if(ix >= -1022)
+	    hx = 0x00100000|(0x000fffff&hx);
+	else {		/* subnormal x, shift x to normal */
+	    n = -1022-ix;
+	    if(n<=31) {
+	        hx = (hx<<n)|(lx>>(32-n));
+	        lx <<= n;
+	    } else {
+		hx = lx<<(n-32);
+		lx = 0;
+	    }
+	}
+	if(iy >= -1022)
+	    hy = 0x00100000|(0x000fffff&hy);
+	else {		/* subnormal y, shift y to normal */
+	    n = -1022-iy;
+	    if(n<=31) {
+	        hy = (hy<<n)|(ly>>(32-n));
+	        ly <<= n;
+	    } else {
+		hy = ly<<(n-32);
+		ly = 0;
+	    }
+	}
+
+    /* fix point fmod */
+	n = ix - iy;
+	while(n--) {
+	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	    if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
+	    else {
+	    	if((hz|lz)==0) 		/* return sign(x)*0 */
+		    return Zero[(u_int32_t)sx>>31];
+	    	hx = hz+hz+(lz>>31); lx = lz+lz;
+	    }
+	}
+	hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	if(hz>=0) {hx=hz;lx=lz;}
+
+    /* convert back to floating value and restore the sign */
+	if((hx|lx)==0) 			/* return sign(x)*0 */
+	    return Zero[(u_int32_t)sx>>31];
+	while(hx<0x00100000) {		/* normalize x */
+	    hx = hx+hx+(lx>>31); lx = lx+lx;
+	    iy -= 1;
+	}
+	if(iy>= -1022) {	/* normalize output */
+	    hx = ((hx-0x00100000)|((iy+1023)<<20));
+	    INSERT_WORDS(x,hx|sx,lx);
+	} else {		/* subnormal output */
+	    n = -1022 - iy;
+	    if(n<=20) {
+		lx = (lx>>n)|((u_int32_t)hx<<(32-n));
+		hx >>= n;
+	    } else if (n<=31) {
+		lx = (hx<<(32-n))|(lx>>n); hx = sx;
+	    } else {
+		lx = hx>>(n-32); hx = sx;
+	    }
+	    INSERT_WORDS(x,hx|sx,lx);
+	    x *= one;		/* create necessary signal */
+	}
+	return x;		/* exact output */
+}
Index: /trunk/libc/src/msun/src/e_fmodf.c
===================================================================
--- /trunk/libc/src/msun/src/e_fmodf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_fmodf.c	(revision 2448)
@@ -0,0 +1,106 @@
+/* e_fmodf.c -- float version of e_fmod.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_fmodf.c,v 1.6 2002/05/28 17:03:12 alfred Exp $";
+#endif
+
+/*
+ * __ieee754_fmodf(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const float one = 1.0, Zero[] = {0.0, -0.0,};
+
+float
+__ieee754_fmodf(float x, float y)
+{
+	int32_t n,hx,hy,hz,ix,iy,sx,i;
+
+	GET_FLOAT_WORD(hx,x);
+	GET_FLOAT_WORD(hy,y);
+	sx = hx&0x80000000;		/* sign of x */
+	hx ^=sx;		/* |x| */
+	hy &= 0x7fffffff;	/* |y| */
+
+    /* purge off exception values */
+	if(hy==0||(hx>=0x7f800000)||		/* y=0,or x not finite */
+	   (hy>0x7f800000))			/* or y is NaN */
+	    return (x*y)/(x*y);
+	if(hx<hy) return x;			/* |x|<|y| return x */
+	if(hx==hy)
+	    return Zero[(u_int32_t)sx>>31];	/* |x|=|y| return x*0*/
+
+    /* determine ix = ilogb(x) */
+	if(hx<0x00800000) {	/* subnormal x */
+	    for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
+	} else ix = (hx>>23)-127;
+
+    /* determine iy = ilogb(y) */
+	if(hy<0x00800000) {	/* subnormal y */
+	    for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
+	} else iy = (hy>>23)-127;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+	if(ix >= -126)
+	    hx = 0x00800000|(0x007fffff&hx);
+	else {		/* subnormal x, shift x to normal */
+	    n = -126-ix;
+	    hx = hx<<n;
+	}
+	if(iy >= -126)
+	    hy = 0x00800000|(0x007fffff&hy);
+	else {		/* subnormal y, shift y to normal */
+	    n = -126-iy;
+	    hy = hy<<n;
+	}
+
+    /* fix point fmod */
+	n = ix - iy;
+	while(n--) {
+	    hz=hx-hy;
+	    if(hz<0){hx = hx+hx;}
+	    else {
+	    	if(hz==0) 		/* return sign(x)*0 */
+		    return Zero[(u_int32_t)sx>>31];
+	    	hx = hz+hz;
+	    }
+	}
+	hz=hx-hy;
+	if(hz>=0) {hx=hz;}
+
+    /* convert back to floating value and restore the sign */
+	if(hx==0) 			/* return sign(x)*0 */
+	    return Zero[(u_int32_t)sx>>31];
+	while(hx<0x00800000) {		/* normalize x */
+	    hx = hx+hx;
+	    iy -= 1;
+	}
+	if(iy>= -126) {		/* normalize output */
+	    hx = ((hx-0x00800000)|((iy+127)<<23));
+	    SET_FLOAT_WORD(x,hx|sx);
+	} else {		/* subnormal output */
+	    n = -126 - iy;
+	    hx >>= n;
+	    SET_FLOAT_WORD(x,hx|sx);
+	    x *= one;		/* create necessary signal */
+	}
+	return x;		/* exact output */
+}
Index: /trunk/libc/src/msun/src/e_gamma.c
===================================================================
--- /trunk/libc/src/msun/src/e_gamma.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_gamma.c	(revision 2448)
@@ -0,0 +1,35 @@
+
+/* @(#)e_gamma.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_gamma.c,v 1.7 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_gamma(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_gamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+double
+__ieee754_gamma(double x)
+{
+	return __ieee754_gamma_r(x,&signgam);
+}
Index: /trunk/libc/src/msun/src/e_gamma_r.c
===================================================================
--- /trunk/libc/src/msun/src/e_gamma_r.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_gamma_r.c	(revision 2448)
@@ -0,0 +1,34 @@
+
+/* @(#)e_gamma_r.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_gamma_r.c,v 1.7 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_gamma_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method: See __ieee754_lgamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+__ieee754_gamma_r(double x, int *signgamp)
+{
+	return __ieee754_lgamma_r(x,signgamp);
+}
Index: /trunk/libc/src/msun/src/e_gammaf.c
===================================================================
--- /trunk/libc/src/msun/src/e_gammaf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_gammaf.c	(revision 2448)
@@ -0,0 +1,36 @@
+/* e_gammaf.c -- float version of e_gamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_gammaf.c,v 1.6 2002/05/28 17:03:12 alfred Exp $";
+#endif
+
+/* __ieee754_gammaf(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_gammaf_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+float
+__ieee754_gammaf(float x)
+{
+	return __ieee754_gammaf_r(x,&signgam);
+}
Index: /trunk/libc/src/msun/src/e_gammaf_r.c
===================================================================
--- /trunk/libc/src/msun/src/e_gammaf_r.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_gammaf_r.c	(revision 2448)
@@ -0,0 +1,35 @@
+/* e_gammaf_r.c -- float version of e_gamma_r.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_gammaf_r.c,v 1.7 2002/05/28 18:15:03 alfred Exp $";
+#endif
+
+/* __ieee754_gammaf_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method: See __ieee754_lgammaf_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+float
+__ieee754_gammaf_r(float x, int *signgamp)
+{
+	return __ieee754_lgammaf_r(x,signgamp);
+}
Index: /trunk/libc/src/msun/src/e_hypot.c
===================================================================
--- /trunk/libc/src/msun/src/e_hypot.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_hypot.c	(revision 2448)
@@ -0,0 +1,126 @@
+
+/* @(#)e_hypot.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_hypot.c,v 1.9 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_hypot(x,y)
+ *
+ * Method :
+ *	If (assume round-to-nearest) z=x*x+y*y
+ *	has error less than sqrt(2)/2 ulp, than
+ *	sqrt(z) has error less than 1 ulp (exercise).
+ *
+ *	So, compute sqrt(x*x+y*y) with some care as
+ *	follows to get the error below 1 ulp:
+ *
+ *	Assume x>y>0;
+ *	(if possible, set rounding to round-to-nearest)
+ *	1. if x > 2y  use
+ *		x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
+ *	where x1 = x with lower 32 bits cleared, x2 = x-x1; else
+ *	2. if x <= 2y use
+ *		t1*y1+((x-y)*(x-y)+(t1*y2+t2*y))
+ *	where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
+ *	y1= y with lower 32 bits chopped, y2 = y-y1.
+ *		
+ *	NOTE: scaling may be necessary if some argument is too
+ *	      large or too tiny
+ *
+ * Special cases:
+ *	hypot(x,y) is INF if x or y is +INF or -INF; else
+ *	hypot(x,y) is NAN if x or y is NAN.
+ *
+ * Accuracy:
+ * 	hypot(x,y) returns sqrt(x^2+y^2) with error less
+ * 	than 1 ulps (units in the last place)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+__ieee754_hypot(double x, double y)
+{
+	double a=x,b=y,t1,t2,y1,y2,w;
+	int32_t j,k,ha,hb;
+
+	GET_HIGH_WORD(ha,x);
+	ha &= 0x7fffffff;
+	GET_HIGH_WORD(hb,y);
+	hb &= 0x7fffffff;
+	if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+	SET_HIGH_WORD(a,ha);	/* a <- |a| */
+	SET_HIGH_WORD(b,hb);	/* b <- |b| */
+	if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */
+	k=0;
+	if(ha > 0x5f300000) {	/* a>2**500 */
+	   if(ha >= 0x7ff00000) {	/* Inf or NaN */
+	       u_int32_t low;
+	       w = a+b;			/* for sNaN */
+	       GET_LOW_WORD(low,a);
+	       if(((ha&0xfffff)|low)==0) w = a;
+	       GET_LOW_WORD(low,b);
+	       if(((hb^0x7ff00000)|low)==0) w = b;
+	       return w;
+	   }
+	   /* scale a and b by 2**-600 */
+	   ha -= 0x25800000; hb -= 0x25800000;	k += 600;
+	   SET_HIGH_WORD(a,ha);
+	   SET_HIGH_WORD(b,hb);
+	}
+	if(hb < 0x20b00000) {	/* b < 2**-500 */
+	    if(hb <= 0x000fffff) {	/* subnormal b or 0 */
+	        u_int32_t low;
+		GET_LOW_WORD(low,b);
+		if((hb|low)==0) return a;
+		t1=0;
+		SET_HIGH_WORD(t1,0x7fd00000);	/* t1=2^1022 */
+		b *= t1;
+		a *= t1;
+		k -= 1022;
+	    } else {		/* scale a and b by 2^600 */
+	        ha += 0x25800000; 	/* a *= 2^600 */
+		hb += 0x25800000;	/* b *= 2^600 */
+		k -= 600;
+		SET_HIGH_WORD(a,ha);
+		SET_HIGH_WORD(b,hb);
+	    }
+	}
+    /* medium size a and b */
+	w = a-b;
+	if (w>b) {
+	    t1 = 0;
+	    SET_HIGH_WORD(t1,ha);
+	    t2 = a-t1;
+	    w  = sqrt(t1*t1-(b*(-b)-t2*(a+t1)));
+	} else {
+	    a  = a+a;
+	    y1 = 0;
+	    SET_HIGH_WORD(y1,hb);
+	    y2 = b - y1;
+	    t1 = 0;
+	    SET_HIGH_WORD(t1,ha+0x00100000);
+	    t2 = a - t1;
+	    w  = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+	}
+	if(k!=0) {
+	    u_int32_t high;
+	    t1 = 1.0;
+	    GET_HIGH_WORD(high,t1);
+	    SET_HIGH_WORD(t1,high+(k<<20));
+	    return t1*w;
+	} else return w;
+}
Index: /trunk/libc/src/msun/src/e_hypotf.c
===================================================================
--- /trunk/libc/src/msun/src/e_hypotf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_hypotf.c	(revision 2448)
@@ -0,0 +1,84 @@
+/* e_hypotf.c -- float version of e_hypot.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_hypotf.c,v 1.9 2002/05/28 18:15:03 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+float
+__ieee754_hypotf(float x, float y)
+{
+	float a=x,b=y,t1,t2,y1,y2,w;
+	int32_t j,k,ha,hb;
+
+	GET_FLOAT_WORD(ha,x);
+	ha &= 0x7fffffff;
+	GET_FLOAT_WORD(hb,y);
+	hb &= 0x7fffffff;
+	if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+	SET_FLOAT_WORD(a,ha);	/* a <- |a| */
+	SET_FLOAT_WORD(b,hb);	/* b <- |b| */
+	if((ha-hb)>0xf000000) {return a+b;} /* x/y > 2**30 */
+	k=0;
+	if(ha > 0x58800000) {	/* a>2**50 */
+	   if(ha >= 0x7f800000) {	/* Inf or NaN */
+	       w = a+b;			/* for sNaN */
+	       if(ha == 0x7f800000) w = a;
+	       if(hb == 0x7f800000) w = b;
+	       return w;
+	   }
+	   /* scale a and b by 2**-68 */
+	   ha -= 0x22000000; hb -= 0x22000000;	k += 68;
+	   SET_FLOAT_WORD(a,ha);
+	   SET_FLOAT_WORD(b,hb);
+	}
+	if(hb < 0x26800000) {	/* b < 2**-50 */
+	    if(hb <= 0x007fffff) {	/* subnormal b or 0 */
+	        if(hb==0) return a;
+		SET_FLOAT_WORD(t1,0x7e800000);	/* t1=2^126 */
+		b *= t1;
+		a *= t1;
+		k -= 126;
+	    } else {		/* scale a and b by 2^68 */
+	        ha += 0x22000000; 	/* a *= 2^68 */
+		hb += 0x22000000;	/* b *= 2^68 */
+		k -= 68;
+		SET_FLOAT_WORD(a,ha);
+		SET_FLOAT_WORD(b,hb);
+	    }
+	}
+    /* medium size a and b */
+	w = a-b;
+	if (w>b) {
+	    SET_FLOAT_WORD(t1,ha&0xfffff000);
+	    t2 = a-t1;
+	    w  = __ieee754_sqrtf(t1*t1-(b*(-b)-t2*(a+t1)));
+	} else {
+	    a  = a+a;
+	    SET_FLOAT_WORD(y1,hb&0xfffff000);
+	    y2 = b - y1;
+	    SET_FLOAT_WORD(t1,ha+0x00800000);
+	    t2 = a - t1;
+	    w  = __ieee754_sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+	}
+	if(k!=0) {
+	    SET_FLOAT_WORD(t1,0x3f800000+(k<<23));
+	    return t1*w;
+	} else return w;
+}
Index: /trunk/libc/src/msun/src/e_j0.c
===================================================================
--- /trunk/libc/src/msun/src/e_j0.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_j0.c	(revision 2448)
@@ -0,0 +1,383 @@
+
+/* @(#)e_j0.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_j0.c,v 1.8 2005/02/04 18:26:05 das Exp $";
+#endif
+
+/* __ieee754_j0(x), __ieee754_y0(x)
+ * Bessel function of the first and second kinds of order zero.
+ * Method -- j0(x):
+ *	1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ...
+ *	2. Reduce x to |x| since j0(x)=j0(-x),  and
+ *	   for x in (0,2)
+ *		j0(x) = 1-z/4+ z^2*R0/S0,  where z = x*x;
+ *	   (precision:  |j0-1+z/4-z^2R0/S0 |<2**-63.67 )
+ *	   for x in (2,inf)
+ * 		j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0))
+ * 	   where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+ *	   as follow:
+ *		cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+ *			= 1/sqrt(2) * (cos(x) + sin(x))
+ *		sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4)
+ *			= 1/sqrt(2) * (sin(x) - cos(x))
+ * 	   (To avoid cancellation, use
+ *		sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * 	    to compute the worse one.)
+ *	
+ *	3 Special cases
+ *		j0(nan)= nan
+ *		j0(0) = 1
+ *		j0(inf) = 0
+ *		
+ * Method -- y0(x):
+ *	1. For x<2.
+ *	   Since
+ *		y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...)
+ *	   therefore y0(x)-2/pi*j0(x)*ln(x) is an even function.
+ *	   We use the following function to approximate y0,
+ *		y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2
+ *	   where
+ *		U(z) = u00 + u01*z + ... + u06*z^6
+ *		V(z) = 1  + v01*z + ... + v04*z^4
+ *	   with absolute approximation error bounded by 2**-72.
+ *	   Note: For tiny x, U/V = u0 and j0(x)~1, hence
+ *		y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27)
+ *	2. For x>=2.
+ * 		y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0))
+ * 	   where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+ *	   by the method mentioned above.
+ *	3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static double pzero(double), qzero(double);
+
+static const double
+huge 	= 1e300,
+one	= 1.0,
+invsqrtpi=  5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+tpi      =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+ 		/* R0/S0 on [0, 2.00] */
+R02  =  1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */
+R03  = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */
+R04  =  1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */
+R05  = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */
+S01  =  1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */
+S02  =  1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */
+S03  =  5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */
+S04  =  1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */
+
+static const double zero = 0.0;
+
+double
+__ieee754_j0(double x)
+{
+	double z, s,c,ss,cc,r,u,v;
+	int32_t hx,ix;
+
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7ff00000) return one/(x*x);
+	x = fabs(x);
+	if(ix >= 0x40000000) {	/* |x| >= 2.0 */
+		s = sin(x);
+		c = cos(x);
+		ss = s-c;
+		cc = s+c;
+		if(ix<0x7fe00000) {  /* make sure x+x not overflow */
+		    z = -cos(x+x);
+		    if ((s*c)<zero) cc = z/ss;
+		    else 	    ss = z/cc;
+		}
+	/*
+	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+	 */
+		if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(x);
+		else {
+		    u = pzero(x); v = qzero(x);
+		    z = invsqrtpi*(u*cc-v*ss)/sqrt(x);
+		}
+		return z;
+	}
+	if(ix<0x3f200000) {	/* |x| < 2**-13 */
+	    if(huge+x>one) {	/* raise inexact if x != 0 */
+	        if(ix<0x3e400000) return one;	/* |x|<2**-27 */
+	        else 	      return one - 0.25*x*x;
+	    }
+	}
+	z = x*x;
+	r =  z*(R02+z*(R03+z*(R04+z*R05)));
+	s =  one+z*(S01+z*(S02+z*(S03+z*S04)));
+	if(ix < 0x3FF00000) {	/* |x| < 1.00 */
+	    return one + z*(-0.25+(r/s));
+	} else {
+	    u = 0.5*x;
+	    return((one+u)*(one-u)+z*(r/s));
+	}
+}
+
+static const double
+u00  = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */
+u01  =  1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */
+u02  = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */
+u03  =  3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */
+u04  = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */
+u05  =  1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */
+u06  = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */
+v01  =  1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */
+v02  =  7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */
+v03  =  2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */
+v04  =  4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
+
+double
+__ieee754_y0(double x)
+{
+	double z, s,c,ss,cc,u,v;
+	int32_t hx,ix,lx;
+
+	EXTRACT_WORDS(hx,lx,x);
+        ix = 0x7fffffff&hx;
+    /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0  */
+	if(ix>=0x7ff00000) return  one/(x+x*x);
+        if((ix|lx)==0) return -one/zero;
+        if(hx<0) return zero/zero;
+        if(ix >= 0x40000000) {  /* |x| >= 2.0 */
+        /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
+         * where x0 = x-pi/4
+         *      Better formula:
+         *              cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+         *                      =  1/sqrt(2) * (sin(x) + cos(x))
+         *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+         *                      =  1/sqrt(2) * (sin(x) - cos(x))
+         * To avoid cancellation, use
+         *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+         * to compute the worse one.
+         */
+                s = sin(x);
+                c = cos(x);
+                ss = s-c;
+                cc = s+c;
+	/*
+	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+	 */
+                if(ix<0x7fe00000) {  /* make sure x+x not overflow */
+                    z = -cos(x+x);
+                    if ((s*c)<zero) cc = z/ss;
+                    else            ss = z/cc;
+                }
+                if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x);
+                else {
+                    u = pzero(x); v = qzero(x);
+                    z = invsqrtpi*(u*ss+v*cc)/sqrt(x);
+                }
+                return z;
+	}
+	if(ix<=0x3e400000) {	/* x < 2**-27 */
+	    return(u00 + tpi*__ieee754_log(x));
+	}
+	z = x*x;
+	u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
+	v = one+z*(v01+z*(v02+z*(v03+z*v04)));
+	return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x)));
+}
+
+/* The asymptotic expansions of pzero is
+ *	1 - 9/128 s^2 + 11025/98304 s^4 - ...,	where s = 1/x.
+ * For x >= 2, We approximate pzero by
+ * 	pzero(x) = 1 + (R/S)
+ * where  R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10
+ * 	  S = 1 + pS0*s^2 + ... + pS4*s^10
+ * and
+ *	| pzero(x)-1-R/S | <= 2  ** ( -60.26)
+ */
+static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */
+ -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */
+ -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */
+ -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */
+ -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */
+};
+static const double pS8[5] = {
+  1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */
+  3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */
+  4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */
+  1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */
+  4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */
+};
+
+static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */
+ -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */
+ -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */
+ -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */
+ -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */
+ -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */
+};
+static const double pS5[5] = {
+  6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */
+  1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */
+  5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */
+  9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */
+  2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */
+};
+
+static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+ -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */
+ -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */
+ -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */
+ -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */
+ -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */
+ -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */
+};
+static const double pS3[5] = {
+  3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */
+  3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */
+  1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */
+  1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */
+  1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */
+};
+
+static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */
+ -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */
+ -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */
+ -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */
+ -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */
+ -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */
+};
+static const double pS2[5] = {
+  2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */
+  1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */
+  2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */
+  1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */
+  1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */
+};
+
+	static double pzero(double x)
+{
+	const double *p,*q;
+	double z,r,s;
+	int32_t ix;
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;
+	if(ix>=0x40200000)     {p = pR8; q= pS8;}
+	else if(ix>=0x40122E8B){p = pR5; q= pS5;}
+	else if(ix>=0x4006DB6D){p = pR3; q= pS3;}
+	else if(ix>=0x40000000){p = pR2; q= pS2;}
+	z = one/(x*x);
+	r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+	s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+	return one+ r/s;
+}
+		
+
+/* For x >= 8, the asymptotic expansions of qzero is
+ *	-1/8 s + 75/1024 s^3 - ..., where s = 1/x.
+ * We approximate pzero by
+ * 	qzero(x) = s*(-1.25 + (R/S))
+ * where  R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10
+ * 	  S = 1 + qS0*s^2 + ... + qS5*s^12
+ * and
+ *	| qzero(x)/s +1.25-R/S | <= 2  ** ( -61.22)
+ */
+static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+  7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */
+  1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */
+  5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */
+  8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */
+  3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */
+};
+static const double qS8[6] = {
+  1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */
+  8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */
+  1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */
+  8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */
+  8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */
+ -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */
+};
+
+static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+  1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */
+  7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */
+  5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */
+  1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */
+  1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */
+  1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */
+};
+static const double qS5[6] = {
+  8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */
+  2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */
+  1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */
+  5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */
+  3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */
+ -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */
+};
+
+static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+  4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */
+  7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */
+  3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */
+  4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */
+  1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */
+  1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */
+};
+static const double qS3[6] = {
+  4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */
+  7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */
+  3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */
+  6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */
+  2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */
+ -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */
+};
+
+static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+  1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */
+  7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */
+  1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */
+  1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */
+  3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */
+  1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */
+};
+static const double qS2[6] = {
+  3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */
+  2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */
+  8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */
+  8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */
+  2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */
+ -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */
+};
+
+	static double qzero(double x)
+{
+	const double *p,*q;
+	double s,r,z;
+	int32_t ix;
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;
+	if(ix>=0x40200000)     {p = qR8; q= qS8;}
+	else if(ix>=0x40122E8B){p = qR5; q= qS5;}
+	else if(ix>=0x4006DB6D){p = qR3; q= qS3;}
+	else if(ix>=0x40000000){p = qR2; q= qS2;}
+	z = one/(x*x);
+	r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+	s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+	return (-.125 + r/s)/x;
+}
Index: /trunk/libc/src/msun/src/e_j0f.c
===================================================================
--- /trunk/libc/src/msun/src/e_j0f.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_j0f.c	(revision 2448)
@@ -0,0 +1,339 @@
+/* e_j0f.c -- float version of e_j0.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_j0f.c,v 1.7 2002/05/28 18:15:03 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static float pzerof(float), qzerof(float);
+
+static const float
+huge 	= 1e30,
+one	= 1.0,
+invsqrtpi=  5.6418961287e-01, /* 0x3f106ebb */
+tpi      =  6.3661974669e-01, /* 0x3f22f983 */
+ 		/* R0/S0 on [0, 2.00] */
+R02  =  1.5625000000e-02, /* 0x3c800000 */
+R03  = -1.8997929874e-04, /* 0xb947352e */
+R04  =  1.8295404516e-06, /* 0x35f58e88 */
+R05  = -4.6183270541e-09, /* 0xb19eaf3c */
+S01  =  1.5619102865e-02, /* 0x3c7fe744 */
+S02  =  1.1692678527e-04, /* 0x38f53697 */
+S03  =  5.1354652442e-07, /* 0x3509daa6 */
+S04  =  1.1661400734e-09; /* 0x30a045e8 */
+
+static const float zero = 0.0;
+
+float
+__ieee754_j0f(float x)
+{
+	float z, s,c,ss,cc,r,u,v;
+	int32_t hx,ix;
+
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7f800000) return one/(x*x);
+	x = fabsf(x);
+	if(ix >= 0x40000000) {	/* |x| >= 2.0 */
+		s = sinf(x);
+		c = cosf(x);
+		ss = s-c;
+		cc = s+c;
+		if(ix<0x7f000000) {  /* make sure x+x not overflow */
+		    z = -cosf(x+x);
+		    if ((s*c)<zero) cc = z/ss;
+		    else 	    ss = z/cc;
+		}
+	/*
+	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+	 */
+		if(ix>0x80000000) z = (invsqrtpi*cc)/sqrtf(x);
+		else {
+		    u = pzerof(x); v = qzerof(x);
+		    z = invsqrtpi*(u*cc-v*ss)/sqrtf(x);
+		}
+		return z;
+	}
+	if(ix<0x39000000) {	/* |x| < 2**-13 */
+	    if(huge+x>one) {	/* raise inexact if x != 0 */
+	        if(ix<0x32000000) return one;	/* |x|<2**-27 */
+	        else 	      return one - (float)0.25*x*x;
+	    }
+	}
+	z = x*x;
+	r =  z*(R02+z*(R03+z*(R04+z*R05)));
+	s =  one+z*(S01+z*(S02+z*(S03+z*S04)));
+	if(ix < 0x3F800000) {	/* |x| < 1.00 */
+	    return one + z*((float)-0.25+(r/s));
+	} else {
+	    u = (float)0.5*x;
+	    return((one+u)*(one-u)+z*(r/s));
+	}
+}
+
+static const float
+u00  = -7.3804296553e-02, /* 0xbd9726b5 */
+u01  =  1.7666645348e-01, /* 0x3e34e80d */
+u02  = -1.3818567619e-02, /* 0xbc626746 */
+u03  =  3.4745343146e-04, /* 0x39b62a69 */
+u04  = -3.8140706238e-06, /* 0xb67ff53c */
+u05  =  1.9559013964e-08, /* 0x32a802ba */
+u06  = -3.9820518410e-11, /* 0xae2f21eb */
+v01  =  1.2730483897e-02, /* 0x3c509385 */
+v02  =  7.6006865129e-05, /* 0x389f65e0 */
+v03  =  2.5915085189e-07, /* 0x348b216c */
+v04  =  4.4111031494e-10; /* 0x2ff280c2 */
+
+float
+__ieee754_y0f(float x)
+{
+	float z, s,c,ss,cc,u,v;
+	int32_t hx,ix;
+
+	GET_FLOAT_WORD(hx,x);
+        ix = 0x7fffffff&hx;
+    /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0  */
+	if(ix>=0x7f800000) return  one/(x+x*x);
+        if(ix==0) return -one/zero;
+        if(hx<0) return zero/zero;
+        if(ix >= 0x40000000) {  /* |x| >= 2.0 */
+        /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
+         * where x0 = x-pi/4
+         *      Better formula:
+         *              cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+         *                      =  1/sqrt(2) * (sin(x) + cos(x))
+         *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+         *                      =  1/sqrt(2) * (sin(x) - cos(x))
+         * To avoid cancellation, use
+         *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+         * to compute the worse one.
+         */
+                s = sinf(x);
+                c = cosf(x);
+                ss = s-c;
+                cc = s+c;
+	/*
+	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+	 */
+                if(ix<0x7f000000) {  /* make sure x+x not overflow */
+                    z = -cosf(x+x);
+                    if ((s*c)<zero) cc = z/ss;
+                    else            ss = z/cc;
+                }
+                if(ix>0x80000000) z = (invsqrtpi*ss)/sqrtf(x);
+                else {
+                    u = pzerof(x); v = qzerof(x);
+                    z = invsqrtpi*(u*ss+v*cc)/sqrtf(x);
+                }
+                return z;
+	}
+	if(ix<=0x32000000) {	/* x < 2**-27 */
+	    return(u00 + tpi*__ieee754_logf(x));
+	}
+	z = x*x;
+	u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
+	v = one+z*(v01+z*(v02+z*(v03+z*v04)));
+	return(u/v + tpi*(__ieee754_j0f(x)*__ieee754_logf(x)));
+}
+
+/* The asymptotic expansions of pzero is
+ *	1 - 9/128 s^2 + 11025/98304 s^4 - ...,	where s = 1/x.
+ * For x >= 2, We approximate pzero by
+ * 	pzero(x) = 1 + (R/S)
+ * where  R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10
+ * 	  S = 1 + pS0*s^2 + ... + pS4*s^10
+ * and
+ *	| pzero(x)-1-R/S | <= 2  ** ( -60.26)
+ */
+static const float pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+  0.0000000000e+00, /* 0x00000000 */
+ -7.0312500000e-02, /* 0xbd900000 */
+ -8.0816707611e+00, /* 0xc1014e86 */
+ -2.5706311035e+02, /* 0xc3808814 */
+ -2.4852163086e+03, /* 0xc51b5376 */
+ -5.2530439453e+03, /* 0xc5a4285a */
+};
+static const float pS8[5] = {
+  1.1653436279e+02, /* 0x42e91198 */
+  3.8337448730e+03, /* 0x456f9beb */
+  4.0597855469e+04, /* 0x471e95db */
+  1.1675296875e+05, /* 0x47e4087c */
+  4.7627726562e+04, /* 0x473a0bba */
+};
+static const float pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ -1.1412546255e-11, /* 0xad48c58a */
+ -7.0312492549e-02, /* 0xbd8fffff */
+ -4.1596107483e+00, /* 0xc0851b88 */
+ -6.7674766541e+01, /* 0xc287597b */
+ -3.3123129272e+02, /* 0xc3a59d9b */
+ -3.4643338013e+02, /* 0xc3ad3779 */
+};
+static const float pS5[5] = {
+  6.0753936768e+01, /* 0x42730408 */
+  1.0512523193e+03, /* 0x44836813 */
+  5.9789707031e+03, /* 0x45bad7c4 */
+  9.6254453125e+03, /* 0x461665c8 */
+  2.4060581055e+03, /* 0x451660ee */
+};
+
+static const float pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+ -2.5470459075e-09, /* 0xb12f081b */
+ -7.0311963558e-02, /* 0xbd8fffb8 */
+ -2.4090321064e+00, /* 0xc01a2d95 */
+ -2.1965976715e+01, /* 0xc1afba52 */
+ -5.8079170227e+01, /* 0xc2685112 */
+ -3.1447946548e+01, /* 0xc1fb9565 */
+};
+static const float pS3[5] = {
+  3.5856033325e+01, /* 0x420f6c94 */
+  3.6151397705e+02, /* 0x43b4c1ca */
+  1.1936077881e+03, /* 0x44953373 */
+  1.1279968262e+03, /* 0x448cffe6 */
+  1.7358093262e+02, /* 0x432d94b8 */
+};
+
+static const float pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ -8.8753431271e-08, /* 0xb3be98b7 */
+ -7.0303097367e-02, /* 0xbd8ffb12 */
+ -1.4507384300e+00, /* 0xbfb9b1cc */
+ -7.6356959343e+00, /* 0xc0f4579f */
+ -1.1193166733e+01, /* 0xc1331736 */
+ -3.2336456776e+00, /* 0xc04ef40d */
+};
+static const float pS2[5] = {
+  2.2220300674e+01, /* 0x41b1c32d */
+  1.3620678711e+02, /* 0x430834f0 */
+  2.7047027588e+02, /* 0x43873c32 */
+  1.5387539673e+02, /* 0x4319e01a */
+  1.4657617569e+01, /* 0x416a859a */
+};
+
+	static float pzerof(float x)
+{
+	const float *p,*q;
+	float z,r,s;
+	int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;
+	if(ix>=0x41000000)     {p = pR8; q= pS8;}
+	else if(ix>=0x40f71c58){p = pR5; q= pS5;}
+	else if(ix>=0x4036db68){p = pR3; q= pS3;}
+	else if(ix>=0x40000000){p = pR2; q= pS2;}
+	z = one/(x*x);
+	r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+	s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+	return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qzero is
+ *	-1/8 s + 75/1024 s^3 - ..., where s = 1/x.
+ * We approximate pzero by
+ * 	qzero(x) = s*(-1.25 + (R/S))
+ * where  R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10
+ * 	  S = 1 + qS0*s^2 + ... + qS5*s^12
+ * and
+ *	| qzero(x)/s +1.25-R/S | <= 2  ** ( -61.22)
+ */
+static const float qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+  0.0000000000e+00, /* 0x00000000 */
+  7.3242187500e-02, /* 0x3d960000 */
+  1.1768206596e+01, /* 0x413c4a93 */
+  5.5767340088e+02, /* 0x440b6b19 */
+  8.8591972656e+03, /* 0x460a6cca */
+  3.7014625000e+04, /* 0x471096a0 */
+};
+static const float qS8[6] = {
+  1.6377603149e+02, /* 0x4323c6aa */
+  8.0983447266e+03, /* 0x45fd12c2 */
+  1.4253829688e+05, /* 0x480b3293 */
+  8.0330925000e+05, /* 0x49441ed4 */
+  8.4050156250e+05, /* 0x494d3359 */
+ -3.4389928125e+05, /* 0xc8a7eb69 */
+};
+
+static const float qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+  1.8408595828e-11, /* 0x2da1ec79 */
+  7.3242180049e-02, /* 0x3d95ffff */
+  5.8356351852e+00, /* 0x40babd86 */
+  1.3511157227e+02, /* 0x43071c90 */
+  1.0272437744e+03, /* 0x448067cd */
+  1.9899779053e+03, /* 0x44f8bf4b */
+};
+static const float qS5[6] = {
+  8.2776611328e+01, /* 0x42a58da0 */
+  2.0778142090e+03, /* 0x4501dd07 */
+  1.8847289062e+04, /* 0x46933e94 */
+  5.6751113281e+04, /* 0x475daf1d */
+  3.5976753906e+04, /* 0x470c88c1 */
+ -5.3543427734e+03, /* 0xc5a752be */
+};
+
+static const float qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+  4.3774099900e-09, /* 0x3196681b */
+  7.3241114616e-02, /* 0x3d95ff70 */
+  3.3442313671e+00, /* 0x405607e3 */
+  4.2621845245e+01, /* 0x422a7cc5 */
+  1.7080809021e+02, /* 0x432acedf */
+  1.6673394775e+02, /* 0x4326bbe4 */
+};
+static const float qS3[6] = {
+  4.8758872986e+01, /* 0x42430916 */
+  7.0968920898e+02, /* 0x44316c1c */
+  3.7041481934e+03, /* 0x4567825f */
+  6.4604252930e+03, /* 0x45c9e367 */
+  2.5163337402e+03, /* 0x451d4557 */
+ -1.4924745178e+02, /* 0xc3153f59 */
+};
+
+static const float qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+  1.5044444979e-07, /* 0x342189db */
+  7.3223426938e-02, /* 0x3d95f62a */
+  1.9981917143e+00, /* 0x3fffc4bf */
+  1.4495602608e+01, /* 0x4167edfd */
+  3.1666231155e+01, /* 0x41fd5471 */
+  1.6252708435e+01, /* 0x4182058c */
+};
+static const float qS2[6] = {
+  3.0365585327e+01, /* 0x41f2ecb8 */
+  2.6934811401e+02, /* 0x4386ac8f */
+  8.4478375244e+02, /* 0x44533229 */
+  8.8293585205e+02, /* 0x445cbbe5 */
+  2.1266638184e+02, /* 0x4354aa98 */
+ -5.3109550476e+00, /* 0xc0a9f358 */
+};
+
+	static float qzerof(float x)
+{
+	const float *p,*q;
+	float s,r,z;
+	int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;
+	if(ix>=0x41000000)     {p = qR8; q= qS8;}
+	else if(ix>=0x40f71c58){p = qR5; q= qS5;}
+	else if(ix>=0x4036db68){p = qR3; q= qS3;}
+	else if(ix>=0x40000000){p = qR2; q= qS2;}
+	z = one/(x*x);
+	r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+	s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+	return (-(float).125 + r/s)/x;
+}
Index: /trunk/libc/src/msun/src/e_j1.c
===================================================================
--- /trunk/libc/src/msun/src/e_j1.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_j1.c	(revision 2448)
@@ -0,0 +1,378 @@
+
+/* @(#)e_j1.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_j1.c,v 1.8 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_j1(x), __ieee754_y1(x)
+ * Bessel function of the first and second kinds of order zero.
+ * Method -- j1(x):
+ *	1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ...
+ *	2. Reduce x to |x| since j1(x)=-j1(-x),  and
+ *	   for x in (0,2)
+ *		j1(x) = x/2 + x*z*R0/S0,  where z = x*x;
+ *	   (precision:  |j1/x - 1/2 - R0/S0 |<2**-61.51 )
+ *	   for x in (2,inf)
+ * 		j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1))
+ * 		y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+ * 	   where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+ *	   as follow:
+ *		cos(x1) =  cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+ *			=  1/sqrt(2) * (sin(x) - cos(x))
+ *		sin(x1) =  sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ *			= -1/sqrt(2) * (sin(x) + cos(x))
+ * 	   (To avoid cancellation, use
+ *		sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * 	    to compute the worse one.)
+ *	
+ *	3 Special cases
+ *		j1(nan)= nan
+ *		j1(0) = 0
+ *		j1(inf) = 0
+ *		
+ * Method -- y1(x):
+ *	1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN
+ *	2. For x<2.
+ *	   Since
+ *		y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...)
+ *	   therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function.
+ *	   We use the following function to approximate y1,
+ *		y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2
+ *	   where for x in [0,2] (abs err less than 2**-65.89)
+ *		U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4
+ *		V(z) = 1  + v0[0]*z + ... + v0[4]*z^5
+ *	   Note: For tiny x, 1/x dominate y1 and hence
+ *		y1(tiny) = -2/pi/tiny, (choose tiny<2**-54)
+ *	3. For x>=2.
+ * 		y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+ * 	   where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+ *	   by method mentioned above.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static double pone(double), qone(double);
+
+static const double
+huge    = 1e300,
+one	= 1.0,
+invsqrtpi=  5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+tpi      =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+	/* R0/S0 on [0,2] */
+r00  = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */
+r01  =  1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */
+r02  = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */
+r03  =  4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */
+s01  =  1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */
+s02  =  1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */
+s03  =  1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */
+s04  =  5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */
+s05  =  1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */
+
+static const double zero    = 0.0;
+
+double
+__ieee754_j1(double x)
+{
+	double z, s,c,ss,cc,r,u,v,y;
+	int32_t hx,ix;
+
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7ff00000) return one/x;
+	y = fabs(x);
+	if(ix >= 0x40000000) {	/* |x| >= 2.0 */
+		s = sin(y);
+		c = cos(y);
+		ss = -s-c;
+		cc = s-c;
+		if(ix<0x7fe00000) {  /* make sure y+y not overflow */
+		    z = cos(y+y);
+		    if ((s*c)>zero) cc = z/ss;
+		    else 	    ss = z/cc;
+		}
+	/*
+	 * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
+	 * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
+	 */
+		if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(y);
+		else {
+		    u = pone(y); v = qone(y);
+		    z = invsqrtpi*(u*cc-v*ss)/sqrt(y);
+		}
+		if(hx<0) return -z;
+		else  	 return  z;
+	}
+	if(ix<0x3e400000) {	/* |x|<2**-27 */
+	    if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */
+	}
+	z = x*x;
+	r =  z*(r00+z*(r01+z*(r02+z*r03)));
+	s =  one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
+	r *= x;
+	return(x*0.5+r/s);
+}
+
+static const double U0[5] = {
+ -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */
+  5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */
+ -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */
+  2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */
+ -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */
+};
+static const double V0[5] = {
+  1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */
+  2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */
+  1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */
+  6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */
+  1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */
+};
+
+double
+__ieee754_y1(double x)
+{
+	double z, s,c,ss,cc,u,v;
+	int32_t hx,ix,lx;
+
+	EXTRACT_WORDS(hx,lx,x);
+        ix = 0x7fffffff&hx;
+    /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
+	if(ix>=0x7ff00000) return  one/(x+x*x);
+        if((ix|lx)==0) return -one/zero;
+        if(hx<0) return zero/zero;
+        if(ix >= 0x40000000) {  /* |x| >= 2.0 */
+                s = sin(x);
+                c = cos(x);
+                ss = -s-c;
+                cc = s-c;
+                if(ix<0x7fe00000) {  /* make sure x+x not overflow */
+                    z = cos(x+x);
+                    if ((s*c)>zero) cc = z/ss;
+                    else            ss = z/cc;
+                }
+        /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
+         * where x0 = x-3pi/4
+         *      Better formula:
+         *              cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+         *                      =  1/sqrt(2) * (sin(x) - cos(x))
+         *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+         *                      = -1/sqrt(2) * (cos(x) + sin(x))
+         * To avoid cancellation, use
+         *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+         * to compute the worse one.
+         */
+                if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x);
+                else {
+                    u = pone(x); v = qone(x);
+                    z = invsqrtpi*(u*ss+v*cc)/sqrt(x);
+                }
+                return z;
+        }
+        if(ix<=0x3c900000) {    /* x < 2**-54 */
+            return(-tpi/x);
+        }
+        z = x*x;
+        u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
+        v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
+        return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x));
+}
+
+/* For x >= 8, the asymptotic expansions of pone is
+ *	1 + 15/128 s^2 - 4725/2^15 s^4 - ...,	where s = 1/x.
+ * We approximate pone by
+ * 	pone(x) = 1 + (R/S)
+ * where  R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
+ * 	  S = 1 + ps0*s^2 + ... + ps4*s^10
+ * and
+ *	| pone(x)-1-R/S | <= 2  ** ( -60.06)
+ */
+
+static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+  1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */
+  1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */
+  4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */
+  3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */
+  7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */
+};
+static const double ps8[5] = {
+  1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */
+  3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */
+  3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */
+  9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */
+  3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */
+};
+
+static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+  1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */
+  1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */
+  6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */
+  1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */
+  5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */
+  5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */
+};
+static const double ps5[5] = {
+  5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */
+  9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */
+  5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */
+  7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */
+  1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */
+};
+
+static const double pr3[6] = {
+  3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */
+  1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */
+  3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */
+  3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */
+  9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */
+  4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */
+};
+static const double ps3[5] = {
+  3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */
+  3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */
+  1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */
+  8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */
+  1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */
+};
+
+static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+  1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */
+  1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */
+  2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */
+  1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */
+  1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */
+  5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */
+};
+static const double ps2[5] = {
+  2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */
+  1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */
+  2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */
+  1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */
+  8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */
+};
+
+	static double pone(double x)
+{
+	const double *p,*q;
+	double z,r,s;
+        int32_t ix;
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;
+        if(ix>=0x40200000)     {p = pr8; q= ps8;}
+        else if(ix>=0x40122E8B){p = pr5; q= ps5;}
+        else if(ix>=0x4006DB6D){p = pr3; q= ps3;}
+        else if(ix>=0x40000000){p = pr2; q= ps2;}
+        z = one/(x*x);
+        r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+        s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+        return one+ r/s;
+}
+		
+
+/* For x >= 8, the asymptotic expansions of qone is
+ *	3/8 s - 105/1024 s^3 - ..., where s = 1/x.
+ * We approximate pone by
+ * 	qone(x) = s*(0.375 + (R/S))
+ * where  R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
+ * 	  S = 1 + qs1*s^2 + ... + qs6*s^12
+ * and
+ *	| qone(x)/s -0.375-R/S | <= 2  ** ( -61.13)
+ */
+
+static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */
+ -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */
+ -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */
+ -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */
+ -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */
+};
+static const double qs8[6] = {
+  1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */
+  7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */
+  1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */
+  7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */
+  6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */
+ -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */
+};
+
+static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */
+ -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */
+ -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */
+ -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */
+ -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */
+ -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */
+};
+static const double qs5[6] = {
+  8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */
+  1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */
+  1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */
+  4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */
+  2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */
+ -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */
+};
+
+static const double qr3[6] = {
+ -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */
+ -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */
+ -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */
+ -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */
+ -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */
+ -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */
+};
+static const double qs3[6] = {
+  4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */
+  6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */
+  3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */
+  5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */
+  1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */
+ -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */
+};
+
+static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */
+ -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */
+ -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */
+ -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */
+ -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */
+ -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */
+};
+static const double qs2[6] = {
+  2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */
+  2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */
+  7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */
+  7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */
+  1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */
+ -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */
+};
+
+	static double qone(double x)
+{
+	const double *p,*q;
+	double  s,r,z;
+	int32_t ix;
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;
+	if(ix>=0x40200000)     {p = qr8; q= qs8;}
+	else if(ix>=0x40122E8B){p = qr5; q= qs5;}
+	else if(ix>=0x4006DB6D){p = qr3; q= qs3;}
+	else if(ix>=0x40000000){p = qr2; q= qs2;}
+	z = one/(x*x);
+	r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+	s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+	return (.375 + r/s)/x;
+}
Index: /trunk/libc/src/msun/src/e_j1f.c
===================================================================
--- /trunk/libc/src/msun/src/e_j1f.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_j1f.c	(revision 2448)
@@ -0,0 +1,335 @@
+/* e_j1f.c -- float version of e_j1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_j1f.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static float ponef(float), qonef(float);
+
+static const float
+huge    = 1e30,
+one	= 1.0,
+invsqrtpi=  5.6418961287e-01, /* 0x3f106ebb */
+tpi      =  6.3661974669e-01, /* 0x3f22f983 */
+	/* R0/S0 on [0,2] */
+r00  = -6.2500000000e-02, /* 0xbd800000 */
+r01  =  1.4070566976e-03, /* 0x3ab86cfd */
+r02  = -1.5995563444e-05, /* 0xb7862e36 */
+r03  =  4.9672799207e-08, /* 0x335557d2 */
+s01  =  1.9153760746e-02, /* 0x3c9ce859 */
+s02  =  1.8594678841e-04, /* 0x3942fab6 */
+s03  =  1.1771846857e-06, /* 0x359dffc2 */
+s04  =  5.0463624390e-09, /* 0x31ad6446 */
+s05  =  1.2354227016e-11; /* 0x2d59567e */
+
+static const float zero    = 0.0;
+
+float
+__ieee754_j1f(float x)
+{
+	float z, s,c,ss,cc,r,u,v,y;
+	int32_t hx,ix;
+
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7f800000) return one/x;
+	y = fabsf(x);
+	if(ix >= 0x40000000) {	/* |x| >= 2.0 */
+		s = sinf(y);
+		c = cosf(y);
+		ss = -s-c;
+		cc = s-c;
+		if(ix<0x7f000000) {  /* make sure y+y not overflow */
+		    z = cosf(y+y);
+		    if ((s*c)>zero) cc = z/ss;
+		    else 	    ss = z/cc;
+		}
+	/*
+	 * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
+	 * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
+	 */
+		if(ix>0x80000000) z = (invsqrtpi*cc)/sqrtf(y);
+		else {
+		    u = ponef(y); v = qonef(y);
+		    z = invsqrtpi*(u*cc-v*ss)/sqrtf(y);
+		}
+		if(hx<0) return -z;
+		else  	 return  z;
+	}
+	if(ix<0x32000000) {	/* |x|<2**-27 */
+	    if(huge+x>one) return (float)0.5*x;/* inexact if x!=0 necessary */
+	}
+	z = x*x;
+	r =  z*(r00+z*(r01+z*(r02+z*r03)));
+	s =  one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
+	r *= x;
+	return(x*(float)0.5+r/s);
+}
+
+static const float U0[5] = {
+ -1.9605709612e-01, /* 0xbe48c331 */
+  5.0443872809e-02, /* 0x3d4e9e3c */
+ -1.9125689287e-03, /* 0xbafaaf2a */
+  2.3525259166e-05, /* 0x37c5581c */
+ -9.1909917899e-08, /* 0xb3c56003 */
+};
+static const float V0[5] = {
+  1.9916731864e-02, /* 0x3ca3286a */
+  2.0255257550e-04, /* 0x3954644b */
+  1.3560879779e-06, /* 0x35b602d4 */
+  6.2274145840e-09, /* 0x31d5f8eb */
+  1.6655924903e-11, /* 0x2d9281cf */
+};
+
+float
+__ieee754_y1f(float x)
+{
+	float z, s,c,ss,cc,u,v;
+	int32_t hx,ix;
+
+	GET_FLOAT_WORD(hx,x);
+        ix = 0x7fffffff&hx;
+    /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
+	if(ix>=0x7f800000) return  one/(x+x*x);
+        if(ix==0) return -one/zero;
+        if(hx<0) return zero/zero;
+        if(ix >= 0x40000000) {  /* |x| >= 2.0 */
+                s = sinf(x);
+                c = cosf(x);
+                ss = -s-c;
+                cc = s-c;
+                if(ix<0x7f000000) {  /* make sure x+x not overflow */
+                    z = cosf(x+x);
+                    if ((s*c)>zero) cc = z/ss;
+                    else            ss = z/cc;
+                }
+        /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
+         * where x0 = x-3pi/4
+         *      Better formula:
+         *              cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+         *                      =  1/sqrt(2) * (sin(x) - cos(x))
+         *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+         *                      = -1/sqrt(2) * (cos(x) + sin(x))
+         * To avoid cancellation, use
+         *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+         * to compute the worse one.
+         */
+                if(ix>0x48000000) z = (invsqrtpi*ss)/sqrtf(x);
+                else {
+                    u = ponef(x); v = qonef(x);
+                    z = invsqrtpi*(u*ss+v*cc)/sqrtf(x);
+                }
+                return z;
+        }
+        if(ix<=0x24800000) {    /* x < 2**-54 */
+            return(-tpi/x);
+        }
+        z = x*x;
+        u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
+        v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
+        return(x*(u/v) + tpi*(__ieee754_j1f(x)*__ieee754_logf(x)-one/x));
+}
+
+/* For x >= 8, the asymptotic expansions of pone is
+ *	1 + 15/128 s^2 - 4725/2^15 s^4 - ...,	where s = 1/x.
+ * We approximate pone by
+ * 	pone(x) = 1 + (R/S)
+ * where  R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
+ * 	  S = 1 + ps0*s^2 + ... + ps4*s^10
+ * and
+ *	| pone(x)-1-R/S | <= 2  ** ( -60.06)
+ */
+
+static const float pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+  0.0000000000e+00, /* 0x00000000 */
+  1.1718750000e-01, /* 0x3df00000 */
+  1.3239480972e+01, /* 0x4153d4ea */
+  4.1205184937e+02, /* 0x43ce06a3 */
+  3.8747453613e+03, /* 0x45722bed */
+  7.9144794922e+03, /* 0x45f753d6 */
+};
+static const float ps8[5] = {
+  1.1420736694e+02, /* 0x42e46a2c */
+  3.6509309082e+03, /* 0x45642ee5 */
+  3.6956207031e+04, /* 0x47105c35 */
+  9.7602796875e+04, /* 0x47bea166 */
+  3.0804271484e+04, /* 0x46f0a88b */
+};
+
+static const float pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+  1.3199052094e-11, /* 0x2d68333f */
+  1.1718749255e-01, /* 0x3defffff */
+  6.8027510643e+00, /* 0x40d9b023 */
+  1.0830818176e+02, /* 0x42d89dca */
+  5.1763616943e+02, /* 0x440168b7 */
+  5.2871520996e+02, /* 0x44042dc6 */
+};
+static const float ps5[5] = {
+  5.9280597687e+01, /* 0x426d1f55 */
+  9.9140142822e+02, /* 0x4477d9b1 */
+  5.3532670898e+03, /* 0x45a74a23 */
+  7.8446904297e+03, /* 0x45f52586 */
+  1.5040468750e+03, /* 0x44bc0180 */
+};
+
+static const float pr3[6] = {
+  3.0250391081e-09, /* 0x314fe10d */
+  1.1718686670e-01, /* 0x3defffab */
+  3.9329774380e+00, /* 0x407bb5e7 */
+  3.5119403839e+01, /* 0x420c7a45 */
+  9.1055007935e+01, /* 0x42b61c2a */
+  4.8559066772e+01, /* 0x42423c7c */
+};
+static const float ps3[5] = {
+  3.4791309357e+01, /* 0x420b2a4d */
+  3.3676245117e+02, /* 0x43a86198 */
+  1.0468714600e+03, /* 0x4482dbe3 */
+  8.9081134033e+02, /* 0x445eb3ed */
+  1.0378793335e+02, /* 0x42cf936c */
+};
+
+static const float pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+  1.0771083225e-07, /* 0x33e74ea8 */
+  1.1717621982e-01, /* 0x3deffa16 */
+  2.3685150146e+00, /* 0x401795c0 */
+  1.2242610931e+01, /* 0x4143e1bc */
+  1.7693971634e+01, /* 0x418d8d41 */
+  5.0735230446e+00, /* 0x40a25a4d */
+};
+static const float ps2[5] = {
+  2.1436485291e+01, /* 0x41ab7dec */
+  1.2529022980e+02, /* 0x42fa9499 */
+  2.3227647400e+02, /* 0x436846c7 */
+  1.1767937469e+02, /* 0x42eb5bd7 */
+  8.3646392822e+00, /* 0x4105d590 */
+};
+
+	static float ponef(float x)
+{
+	const float *p,*q;
+	float z,r,s;
+        int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;
+        if(ix>=0x41000000)     {p = pr8; q= ps8;}
+        else if(ix>=0x40f71c58){p = pr5; q= ps5;}
+        else if(ix>=0x4036db68){p = pr3; q= ps3;}
+        else if(ix>=0x40000000){p = pr2; q= ps2;}
+        z = one/(x*x);
+        r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+        s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+        return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qone is
+ *	3/8 s - 105/1024 s^3 - ..., where s = 1/x.
+ * We approximate pone by
+ * 	qone(x) = s*(0.375 + (R/S))
+ * where  R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
+ * 	  S = 1 + qs1*s^2 + ... + qs6*s^12
+ * and
+ *	| qone(x)/s -0.375-R/S | <= 2  ** ( -61.13)
+ */
+
+static const float qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+  0.0000000000e+00, /* 0x00000000 */
+ -1.0253906250e-01, /* 0xbdd20000 */
+ -1.6271753311e+01, /* 0xc1822c8d */
+ -7.5960174561e+02, /* 0xc43de683 */
+ -1.1849806641e+04, /* 0xc639273a */
+ -4.8438511719e+04, /* 0xc73d3683 */
+};
+static const float qs8[6] = {
+  1.6139537048e+02, /* 0x43216537 */
+  7.8253862305e+03, /* 0x45f48b17 */
+  1.3387534375e+05, /* 0x4802bcd6 */
+  7.1965775000e+05, /* 0x492fb29c */
+  6.6660125000e+05, /* 0x4922be94 */
+ -2.9449025000e+05, /* 0xc88fcb48 */
+};
+
+static const float qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ -2.0897993405e-11, /* 0xadb7d219 */
+ -1.0253904760e-01, /* 0xbdd1fffe */
+ -8.0564479828e+00, /* 0xc100e736 */
+ -1.8366960144e+02, /* 0xc337ab6b */
+ -1.3731937256e+03, /* 0xc4aba633 */
+ -2.6124443359e+03, /* 0xc523471c */
+};
+static const float qs5[6] = {
+  8.1276550293e+01, /* 0x42a28d98 */
+  1.9917987061e+03, /* 0x44f8f98f */
+  1.7468484375e+04, /* 0x468878f8 */
+  4.9851425781e+04, /* 0x4742bb6d */
+  2.7948074219e+04, /* 0x46da5826 */
+ -4.7191835938e+03, /* 0xc5937978 */
+};
+
+static const float qr3[6] = {
+ -5.0783124372e-09, /* 0xb1ae7d4f */
+ -1.0253783315e-01, /* 0xbdd1ff5b */
+ -4.6101160049e+00, /* 0xc0938612 */
+ -5.7847221375e+01, /* 0xc267638e */
+ -2.2824453735e+02, /* 0xc3643e9a */
+ -2.1921012878e+02, /* 0xc35b35cb */
+};
+static const float qs3[6] = {
+  4.7665153503e+01, /* 0x423ea91e */
+  6.7386511230e+02, /* 0x4428775e */
+  3.3801528320e+03, /* 0x45534272 */
+  5.5477290039e+03, /* 0x45ad5dd5 */
+  1.9031191406e+03, /* 0x44ede3d0 */
+ -1.3520118713e+02, /* 0xc3073381 */
+};
+
+static const float qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ -1.7838172539e-07, /* 0xb43f8932 */
+ -1.0251704603e-01, /* 0xbdd1f475 */
+ -2.7522056103e+00, /* 0xc0302423 */
+ -1.9663616180e+01, /* 0xc19d4f16 */
+ -4.2325313568e+01, /* 0xc2294d1f */
+ -2.1371921539e+01, /* 0xc1aaf9b2 */
+};
+static const float qs2[6] = {
+  2.9533363342e+01, /* 0x41ec4454 */
+  2.5298155212e+02, /* 0x437cfb47 */
+  7.5750280762e+02, /* 0x443d602e */
+  7.3939318848e+02, /* 0x4438d92a */
+  1.5594900513e+02, /* 0x431bf2f2 */
+ -4.9594988823e+00, /* 0xc09eb437 */
+};
+
+	static float qonef(float x)
+{
+	const float *p,*q;
+	float  s,r,z;
+	int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;
+	if(ix>=0x40200000)     {p = qr8; q= qs8;}
+	else if(ix>=0x40f71c58){p = qr5; q= qs5;}
+	else if(ix>=0x4036db68){p = qr3; q= qs3;}
+	else if(ix>=0x40000000){p = qr2; q= qs2;}
+	z = one/(x*x);
+	r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+	s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+	return ((float).375 + r/s)/x;
+}
Index: /trunk/libc/src/msun/src/e_jn.c
===================================================================
--- /trunk/libc/src/msun/src/e_jn.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_jn.c	(revision 2448)
@@ -0,0 +1,267 @@
+
+/* @(#)e_jn.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_jn.c,v 1.9 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/*
+ * __ieee754_jn(n, x), __ieee754_yn(n, x)
+ * floating point Bessel's function of the 1st and 2nd kind
+ * of order n
+ *
+ * Special cases:
+ *	y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
+ *	y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
+ * Note 2. About jn(n,x), yn(n,x)
+ *	For n=0, j0(x) is called,
+ *	for n=1, j1(x) is called,
+ *	for n<x, forward recursion us used starting
+ *	from values of j0(x) and j1(x).
+ *	for n>x, a continued fraction approximation to
+ *	j(n,x)/j(n-1,x) is evaluated and then backward
+ *	recursion is used starting from a supposed value
+ *	for j(n,x). The resulting value of j(0,x) is
+ *	compared with the actual value to correct the
+ *	supposed value of j(n,x).
+ *
+ *	yn(n,x) is similar in all respects, except
+ *	that forward recursion is used for all
+ *	values of n>1.
+ *	
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+invsqrtpi=  5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+two   =  2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
+one   =  1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
+
+static const double zero  =  0.00000000000000000000e+00;
+
+double
+__ieee754_jn(int n, double x)
+{
+	int32_t i,hx,ix,lx, sgn;
+	double a, b, temp, di;
+	double z, w;
+
+    /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
+     * Thus, J(-n,x) = J(n,-x)
+     */
+	EXTRACT_WORDS(hx,lx,x);
+	ix = 0x7fffffff&hx;
+    /* if J(n,NaN) is NaN */
+	if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
+	if(n<0){		
+		n = -n;
+		x = -x;
+		hx ^= 0x80000000;
+	}
+	if(n==0) return(__ieee754_j0(x));
+	if(n==1) return(__ieee754_j1(x));
+	sgn = (n&1)&(hx>>31);	/* even n -- 0, odd n -- sign(x) */
+	x = fabs(x);
+	if((ix|lx)==0||ix>=0x7ff00000) 	/* if x is 0 or inf */
+	    b = zero;
+	else if((double)n<=x) {
+		/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
+	    if(ix>=0x52D00000) { /* x > 2**302 */
+    /* (x >> n**2)
+     *	    Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+     *	    Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+     *	    Let s=sin(x), c=cos(x),
+     *		xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+     *
+     *		   n	sin(xn)*sqt2	cos(xn)*sqt2
+     *		----------------------------------
+     *		   0	 s-c		 c+s
+     *		   1	-s-c 		-c+s
+     *		   2	-s+c		-c-s
+     *		   3	 s+c		 c-s
+     */
+		switch(n&3) {
+		    case 0: temp =  cos(x)+sin(x); break;
+		    case 1: temp = -cos(x)+sin(x); break;
+		    case 2: temp = -cos(x)-sin(x); break;
+		    case 3: temp =  cos(x)-sin(x); break;
+		}
+		b = invsqrtpi*temp/sqrt(x);
+	    } else {	
+	        a = __ieee754_j0(x);
+	        b = __ieee754_j1(x);
+	        for(i=1;i<n;i++){
+		    temp = b;
+		    b = b*((double)(i+i)/x) - a; /* avoid underflow */
+		    a = temp;
+	        }
+	    }
+	} else {
+	    if(ix<0x3e100000) {	/* x < 2**-29 */
+    /* x is tiny, return the first Taylor expansion of J(n,x)
+     * J(n,x) = 1/n!*(x/2)^n  - ...
+     */
+		if(n>33)	/* underflow */
+		    b = zero;
+		else {
+		    temp = x*0.5; b = temp;
+		    for (a=one,i=2;i<=n;i++) {
+			a *= (double)i;		/* a = n! */
+			b *= temp;		/* b = (x/2)^n */
+		    }
+		    b = b/a;
+		}
+	    } else {
+		/* use backward recurrence */
+		/* 			x      x^2      x^2
+		 *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
+		 *			2n  - 2(n+1) - 2(n+2)
+		 *
+		 * 			1      1        1
+		 *  (for large x)   =  ----  ------   ------   .....
+		 *			2n   2(n+1)   2(n+2)
+		 *			-- - ------ - ------ -
+		 *			 x     x         x
+		 *
+		 * Let w = 2n/x and h=2/x, then the above quotient
+		 * is equal to the continued fraction:
+		 *		    1
+		 *	= -----------------------
+		 *		       1
+		 *	   w - -----------------
+		 *			  1
+		 * 	        w+h - ---------
+		 *		       w+2h - ...
+		 *
+		 * To determine how many terms needed, let
+		 * Q(0) = w, Q(1) = w(w+h) - 1,
+		 * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+		 * When Q(k) > 1e4	good for single
+		 * When Q(k) > 1e9	good for double
+		 * When Q(k) > 1e17	good for quadruple
+		 */
+	    /* determine k */
+		double t,v;
+		double q0,q1,h,tmp; int32_t k,m;
+		w  = (n+n)/(double)x; h = 2.0/(double)x;
+		q0 = w;  z = w+h; q1 = w*z - 1.0; k=1;
+		while(q1<1.0e9) {
+			k += 1; z += h;
+			tmp = z*q1 - q0;
+			q0 = q1;
+			q1 = tmp;
+		}
+		m = n+n;
+		for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
+		a = t;
+		b = one;
+		/*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+		 *  Hence, if n*(log(2n/x)) > ...
+		 *  single 8.8722839355e+01
+		 *  double 7.09782712893383973096e+02
+		 *  long double 1.1356523406294143949491931077970765006170e+04
+		 *  then recurrent value may overflow and the result is
+		 *  likely underflow to zero
+		 */
+		tmp = n;
+		v = two/x;
+		tmp = tmp*__ieee754_log(fabs(v*tmp));
+		if(tmp<7.09782712893383973096e+02) {
+	    	    for(i=n-1,di=(double)(i+i);i>0;i--){
+		        temp = b;
+			b *= di;
+			b  = b/x - a;
+		        a = temp;
+			di -= two;
+	     	    }
+		} else {
+	    	    for(i=n-1,di=(double)(i+i);i>0;i--){
+		        temp = b;
+			b *= di;
+			b  = b/x - a;
+		        a = temp;
+			di -= two;
+		    /* scale b to avoid spurious overflow */
+			if(b>1e100) {
+			    a /= b;
+			    t /= b;
+			    b  = one;
+			}
+	     	    }
+		}
+	    	b = (t*__ieee754_j0(x)/b);
+	    }
+	}
+	if(sgn==1) return -b; else return b;
+}
+
+double
+__ieee754_yn(int n, double x)
+{
+	int32_t i,hx,ix,lx;
+	int32_t sign;
+	double a, b, temp;
+
+	EXTRACT_WORDS(hx,lx,x);
+	ix = 0x7fffffff&hx;
+    /* if Y(n,NaN) is NaN */
+	if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
+	if((ix|lx)==0) return -one/zero;
+	if(hx<0) return zero/zero;
+	sign = 1;
+	if(n<0){
+		n = -n;
+		sign = 1 - ((n&1)<<1);
+	}
+	if(n==0) return(__ieee754_y0(x));
+	if(n==1) return(sign*__ieee754_y1(x));
+	if(ix==0x7ff00000) return zero;
+	if(ix>=0x52D00000) { /* x > 2**302 */
+    /* (x >> n**2)
+     *	    Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+     *	    Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+     *	    Let s=sin(x), c=cos(x),
+     *		xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+     *
+     *		   n	sin(xn)*sqt2	cos(xn)*sqt2
+     *		----------------------------------
+     *		   0	 s-c		 c+s
+     *		   1	-s-c 		-c+s
+     *		   2	-s+c		-c-s
+     *		   3	 s+c		 c-s
+     */
+		switch(n&3) {
+		    case 0: temp =  sin(x)-cos(x); break;
+		    case 1: temp = -sin(x)-cos(x); break;
+		    case 2: temp = -sin(x)+cos(x); break;
+		    case 3: temp =  sin(x)+cos(x); break;
+		}
+		b = invsqrtpi*temp/sqrt(x);
+	} else {
+	    u_int32_t high;
+	    a = __ieee754_y0(x);
+	    b = __ieee754_y1(x);
+	/* quit if b is -inf */
+	    GET_HIGH_WORD(high,b);
+	    for(i=1;i<n&&high!=0xfff00000;i++){
+		temp = b;
+		b = ((double)(i+i)/x)*b - a;
+		GET_HIGH_WORD(high,b);
+		a = temp;
+	    }
+	}
+	if(sign>0) return b; else return -b;
+}
Index: /trunk/libc/src/msun/src/e_jnf.c
===================================================================
--- /trunk/libc/src/msun/src/e_jnf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_jnf.c	(revision 2448)
@@ -0,0 +1,197 @@
+/* e_jnf.c -- float version of e_jn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_jnf.c,v 1.8 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+invsqrtpi=  5.6418961287e-01, /* 0x3f106ebb */
+two   =  2.0000000000e+00, /* 0x40000000 */
+one   =  1.0000000000e+00; /* 0x3F800000 */
+
+static const float zero  =  0.0000000000e+00;
+
+float
+__ieee754_jnf(int n, float x)
+{
+	int32_t i,hx,ix, sgn;
+	float a, b, temp, di;
+	float z, w;
+
+    /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
+     * Thus, J(-n,x) = J(n,-x)
+     */
+	GET_FLOAT_WORD(hx,x);
+	ix = 0x7fffffff&hx;
+    /* if J(n,NaN) is NaN */
+	if(ix>0x7f800000) return x+x;
+	if(n<0){
+		n = -n;
+		x = -x;
+		hx ^= 0x80000000;
+	}
+	if(n==0) return(__ieee754_j0f(x));
+	if(n==1) return(__ieee754_j1f(x));
+	sgn = (n&1)&(hx>>31);	/* even n -- 0, odd n -- sign(x) */
+	x = fabsf(x);
+	if(ix==0||ix>=0x7f800000) 	/* if x is 0 or inf */
+	    b = zero;
+	else if((float)n<=x) {
+		/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
+	    a = __ieee754_j0f(x);
+	    b = __ieee754_j1f(x);
+	    for(i=1;i<n;i++){
+		temp = b;
+		b = b*((float)(i+i)/x) - a; /* avoid underflow */
+		a = temp;
+	    }
+	} else {
+	    if(ix<0x30800000) {	/* x < 2**-29 */
+    /* x is tiny, return the first Taylor expansion of J(n,x)
+     * J(n,x) = 1/n!*(x/2)^n  - ...
+     */
+		if(n>33)	/* underflow */
+		    b = zero;
+		else {
+		    temp = x*(float)0.5; b = temp;
+		    for (a=one,i=2;i<=n;i++) {
+			a *= (float)i;		/* a = n! */
+			b *= temp;		/* b = (x/2)^n */
+		    }
+		    b = b/a;
+		}
+	    } else {
+		/* use backward recurrence */
+		/* 			x      x^2      x^2
+		 *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
+		 *			2n  - 2(n+1) - 2(n+2)
+		 *
+		 * 			1      1        1
+		 *  (for large x)   =  ----  ------   ------   .....
+		 *			2n   2(n+1)   2(n+2)
+		 *			-- - ------ - ------ -
+		 *			 x     x         x
+		 *
+		 * Let w = 2n/x and h=2/x, then the above quotient
+		 * is equal to the continued fraction:
+		 *		    1
+		 *	= -----------------------
+		 *		       1
+		 *	   w - -----------------
+		 *			  1
+		 * 	        w+h - ---------
+		 *		       w+2h - ...
+		 *
+		 * To determine how many terms needed, let
+		 * Q(0) = w, Q(1) = w(w+h) - 1,
+		 * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+		 * When Q(k) > 1e4	good for single
+		 * When Q(k) > 1e9	good for double
+		 * When Q(k) > 1e17	good for quadruple
+		 */
+	    /* determine k */
+		float t,v;
+		float q0,q1,h,tmp; int32_t k,m;
+		w  = (n+n)/(float)x; h = (float)2.0/(float)x;
+		q0 = w;  z = w+h; q1 = w*z - (float)1.0; k=1;
+		while(q1<(float)1.0e9) {
+			k += 1; z += h;
+			tmp = z*q1 - q0;
+			q0 = q1;
+			q1 = tmp;
+		}
+		m = n+n;
+		for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
+		a = t;
+		b = one;
+		/*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+		 *  Hence, if n*(log(2n/x)) > ...
+		 *  single 8.8722839355e+01
+		 *  double 7.09782712893383973096e+02
+		 *  long double 1.1356523406294143949491931077970765006170e+04
+		 *  then recurrent value may overflow and the result is
+		 *  likely underflow to zero
+		 */
+		tmp = n;
+		v = two/x;
+		tmp = tmp*__ieee754_logf(fabsf(v*tmp));
+		if(tmp<(float)8.8721679688e+01) {
+	    	    for(i=n-1,di=(float)(i+i);i>0;i--){
+		        temp = b;
+			b *= di;
+			b  = b/x - a;
+		        a = temp;
+			di -= two;
+	     	    }
+		} else {
+	    	    for(i=n-1,di=(float)(i+i);i>0;i--){
+		        temp = b;
+			b *= di;
+			b  = b/x - a;
+		        a = temp;
+			di -= two;
+		    /* scale b to avoid spurious overflow */
+			if(b>(float)1e10) {
+			    a /= b;
+			    t /= b;
+			    b  = one;
+			}
+	     	    }
+		}
+	    	b = (t*__ieee754_j0f(x)/b);
+	    }
+	}
+	if(sgn==1) return -b; else return b;
+}
+
+float
+__ieee754_ynf(int n, float x)
+{
+	int32_t i,hx,ix,ib;
+	int32_t sign;
+	float a, b, temp;
+
+	GET_FLOAT_WORD(hx,x);
+	ix = 0x7fffffff&hx;
+    /* if Y(n,NaN) is NaN */
+	if(ix>0x7f800000) return x+x;
+	if(ix==0) return -one/zero;
+	if(hx<0) return zero/zero;
+	sign = 1;
+	if(n<0){
+		n = -n;
+		sign = 1 - ((n&1)<<1);
+	}
+	if(n==0) return(__ieee754_y0f(x));
+	if(n==1) return(sign*__ieee754_y1f(x));
+	if(ix==0x7f800000) return zero;
+
+	a = __ieee754_y0f(x);
+	b = __ieee754_y1f(x);
+	/* quit if b is -inf */
+	GET_FLOAT_WORD(ib,b);
+	for(i=1;i<n&&ib!=0xff800000;i++){
+	    temp = b;
+	    b = ((float)(i+i)/x)*b - a;
+	    GET_FLOAT_WORD(ib,b);
+	    a = temp;
+	}
+	if(sign>0) return b; else return -b;
+}
Index: /trunk/libc/src/msun/src/e_lgamma.c
===================================================================
--- /trunk/libc/src/msun/src/e_lgamma.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_lgamma.c	(revision 2448)
@@ -0,0 +1,35 @@
+
+/* @(#)e_lgamma.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_lgamma.c,v 1.8 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_lgamma(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_lgamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+double
+__ieee754_lgamma(double x)
+{
+	return __ieee754_lgamma_r(x,&signgam);
+}
Index: /trunk/libc/src/msun/src/e_lgamma_r.c
===================================================================
--- /trunk/libc/src/msun/src/e_lgamma_r.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_lgamma_r.c	(revision 2448)
@@ -0,0 +1,298 @@
+
+/* @(#)e_lgamma_r.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_lgamma_r.c,v 1.8 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_lgamma_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method:
+ *   1. Argument Reduction for 0 < x <= 8
+ * 	Since gamma(1+s)=s*gamma(s), for x in [0,8], we may
+ * 	reduce x to a number in [1.5,2.5] by
+ * 		lgamma(1+s) = log(s) + lgamma(s)
+ *	for example,
+ *		lgamma(7.3) = log(6.3) + lgamma(6.3)
+ *			    = log(6.3*5.3) + lgamma(5.3)
+ *			    = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)
+ *   2. Polynomial approximation of lgamma around its
+ *	minimun ymin=1.461632144968362245 to maintain monotonicity.
+ *	On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use
+ *		Let z = x-ymin;
+ *		lgamma(x) = -1.214862905358496078218 + z^2*poly(z)
+ *	where
+ *		poly(z) is a 14 degree polynomial.
+ *   2. Rational approximation in the primary interval [2,3]
+ *	We use the following approximation:
+ *		s = x-2.0;
+ *		lgamma(x) = 0.5*s + s*P(s)/Q(s)
+ *	with accuracy
+ *		|P/Q - (lgamma(x)-0.5s)| < 2**-61.71
+ *	Our algorithms are based on the following observation
+ *
+ *                             zeta(2)-1    2    zeta(3)-1    3
+ * lgamma(2+s) = s*(1-Euler) + --------- * s  -  --------- * s  + ...
+ *                                 2                 3
+ *
+ *	where Euler = 0.5771... is the Euler constant, which is very
+ *	close to 0.5.
+ *
+ *   3. For x>=8, we have
+ *	lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+....
+ *	(better formula:
+ *	   lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...)
+ *	Let z = 1/x, then we approximation
+ *		f(z) = lgamma(x) - (x-0.5)(log(x)-1)
+ *	by
+ *	  			    3       5             11
+ *		w = w0 + w1*z + w2*z  + w3*z  + ... + w6*z
+ *	where
+ *		|w - f(z)| < 2**-58.74
+ *		
+ *   4. For negative x, since (G is gamma function)
+ *		-x*G(-x)*G(x) = pi/sin(pi*x),
+ * 	we have
+ * 		G(x) = pi/(sin(pi*x)*(-x)*G(-x))
+ *	since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0
+ *	Hence, for x<0, signgam = sign(sin(pi*x)) and
+ *		lgamma(x) = log(|Gamma(x)|)
+ *			  = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);
+ *	Note: one should avoid compute pi*(-x) directly in the
+ *	      computation of sin(pi*(-x)).
+ *		
+ *   5. Special Cases
+ *		lgamma(2+s) ~ s*(1-Euler) for tiny s
+ *		lgamma(1)=lgamma(2)=0
+ *		lgamma(x) ~ -log(x) for tiny x
+ *		lgamma(0) = lgamma(inf) = inf
+ *	 	lgamma(-integer) = +-inf
+ *	
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+two52=  4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+half=  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pi  =  3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
+a0  =  7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */
+a1  =  3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */
+a2  =  6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */
+a3  =  2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */
+a4  =  7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */
+a5  =  2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */
+a6  =  1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */
+a7  =  5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */
+a8  =  2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */
+a9  =  1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */
+a10 =  2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */
+a11 =  4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */
+tc  =  1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */
+tf  = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */
+/* tt = -(tail of tf) */
+tt  = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */
+t0  =  4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */
+t1  = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */
+t2  =  6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */
+t3  = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */
+t4  =  1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */
+t5  = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */
+t6  =  6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */
+t7  = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */
+t8  =  2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */
+t9  = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */
+t10 =  8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */
+t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */
+t12 =  3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */
+t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */
+t14 =  3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */
+u0  = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */
+u1  =  6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */
+u2  =  1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */
+u3  =  9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */
+u4  =  2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */
+u5  =  1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */
+v1  =  2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */
+v2  =  2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */
+v3  =  7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */
+v4  =  1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */
+v5  =  3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */
+s0  = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */
+s1  =  2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */
+s2  =  3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */
+s3  =  1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */
+s4  =  2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */
+s5  =  1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */
+s6  =  3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */
+r1  =  1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */
+r2  =  7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */
+r3  =  1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */
+r4  =  1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */
+r5  =  7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */
+r6  =  7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */
+w0  =  4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */
+w1  =  8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */
+w2  = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */
+w3  =  7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */
+w4  = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */
+w5  =  8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */
+w6  = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */
+
+static const double zero=  0.00000000000000000000e+00;
+
+	static double sin_pi(double x)
+{
+	double y,z;
+	int n,ix;
+
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;
+
+	if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0);
+	y = -x;		/* x is assume negative */
+
+    /*
+     * argument reduction, make sure inexact flag not raised if input
+     * is an integer
+     */
+	z = floor(y);
+	if(z!=y) {				/* inexact anyway */
+	    y  *= 0.5;
+	    y   = 2.0*(y - floor(y));		/* y = |x| mod 2.0 */
+	    n   = (int) (y*4.0);
+	} else {
+            if(ix>=0x43400000) {
+                y = zero; n = 0;                 /* y must be even */
+            } else {
+                if(ix<0x43300000) z = y+two52;	/* exact */
+		GET_LOW_WORD(n,z);
+		n &= 1;
+                y  = n;
+                n<<= 2;
+            }
+        }
+	switch (n) {
+	    case 0:   y =  __kernel_sin(pi*y,zero,0); break;
+	    case 1:
+	    case 2:   y =  __kernel_cos(pi*(0.5-y),zero); break;
+	    case 3:
+	    case 4:   y =  __kernel_sin(pi*(one-y),zero,0); break;
+	    case 5:
+	    case 6:   y = -__kernel_cos(pi*(y-1.5),zero); break;
+	    default:  y =  __kernel_sin(pi*(y-2.0),zero,0); break;
+	    }
+	return -y;
+}
+
+
+double
+__ieee754_lgamma_r(double x, int *signgamp)
+{
+	double t,y,z,nadj,p,p1,p2,p3,q,r,w;
+	int i,hx,lx,ix;
+
+	EXTRACT_WORDS(hx,lx,x);
+
+    /* purge off +-inf, NaN, +-0, and negative arguments */
+	*signgamp = 1;
+	ix = hx&0x7fffffff;
+	if(ix>=0x7ff00000) return x*x;
+	if((ix|lx)==0) return one/zero;
+	if(ix<0x3b900000) {	/* |x|<2**-70, return -log(|x|) */
+	    if(hx<0) {
+	        *signgamp = -1;
+	        return -__ieee754_log(-x);
+	    } else return -__ieee754_log(x);
+	}
+	if(hx<0) {
+	    if(ix>=0x43300000) 	/* |x|>=2**52, must be -integer */
+		return one/zero;
+	    t = sin_pi(x);
+	    if(t==zero) return one/zero; /* -integer */
+	    nadj = __ieee754_log(pi/fabs(t*x));
+	    if(t<zero) *signgamp = -1;
+	    x = -x;
+	}
+
+    /* purge off 1 and 2 */
+	if((((ix-0x3ff00000)|lx)==0)||(((ix-0x40000000)|lx)==0)) r = 0;
+    /* for x < 2.0 */
+	else if(ix<0x40000000) {
+	    if(ix<=0x3feccccc) { 	/* lgamma(x) = lgamma(x+1)-log(x) */
+		r = -__ieee754_log(x);
+		if(ix>=0x3FE76944) {y = one-x; i= 0;}
+		else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;}
+	  	else {y = x; i=2;}
+	    } else {
+	  	r = zero;
+	        if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */
+	        else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */
+		else {y=x-one;i=2;}
+	    }
+	    switch(i) {
+	      case 0:
+		z = y*y;
+		p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
+		p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
+		p  = y*p1+p2;
+		r  += (p-0.5*y); break;
+	      case 1:
+		z = y*y;
+		w = z*y;
+		p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12)));	/* parallel comp */
+		p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
+		p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
+		p  = z*p1-(tt-w*(p2+y*p3));
+		r += (tf + p); break;
+	      case 2:	
+		p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
+		p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
+		r += (-0.5*y + p1/p2);
+	    }
+	}
+	else if(ix<0x40200000) { 			/* x < 8.0 */
+	    i = (int)x;
+	    t = zero;
+	    y = x-(double)i;
+	    p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
+	    q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
+	    r = half*y+p/q;
+	    z = one;	/* lgamma(1+s) = log(s) + lgamma(s) */
+	    switch(i) {
+	    case 7: z *= (y+6.0);	/* FALLTHRU */
+	    case 6: z *= (y+5.0);	/* FALLTHRU */
+	    case 5: z *= (y+4.0);	/* FALLTHRU */
+	    case 4: z *= (y+3.0);	/* FALLTHRU */
+	    case 3: z *= (y+2.0);	/* FALLTHRU */
+		    r += __ieee754_log(z); break;
+	    }
+    /* 8.0 <= x < 2**58 */
+	} else if (ix < 0x43900000) {
+	    t = __ieee754_log(x);
+	    z = one/x;
+	    y = z*z;
+	    w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
+	    r = (x-half)*(t-one)+w;
+	} else
+    /* 2**58 <= x <= inf */
+	    r =  x*(__ieee754_log(x)-one);
+	if(hx<0) r = nadj - r;
+	return r;
+}
Index: /trunk/libc/src/msun/src/e_lgammaf.c
===================================================================
--- /trunk/libc/src/msun/src/e_lgammaf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_lgammaf.c	(revision 2448)
@@ -0,0 +1,36 @@
+/* e_lgammaf.c -- float version of e_lgamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_lgammaf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/* __ieee754_lgammaf(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_lgammaf_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+float
+__ieee754_lgammaf(float x)
+{
+	return __ieee754_lgammaf_r(x,&signgam);
+}
Index: /trunk/libc/src/msun/src/e_lgammaf_r.c
===================================================================
--- /trunk/libc/src/msun/src/e_lgammaf_r.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_lgammaf_r.c	(revision 2448)
@@ -0,0 +1,232 @@
+/* e_lgammaf_r.c -- float version of e_lgamma_r.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_lgammaf_r.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+two23=  8.3886080000e+06, /* 0x4b000000 */
+half=  5.0000000000e-01, /* 0x3f000000 */
+one =  1.0000000000e+00, /* 0x3f800000 */
+pi  =  3.1415927410e+00, /* 0x40490fdb */
+a0  =  7.7215664089e-02, /* 0x3d9e233f */
+a1  =  3.2246702909e-01, /* 0x3ea51a66 */
+a2  =  6.7352302372e-02, /* 0x3d89f001 */
+a3  =  2.0580807701e-02, /* 0x3ca89915 */
+a4  =  7.3855509982e-03, /* 0x3bf2027e */
+a5  =  2.8905137442e-03, /* 0x3b3d6ec6 */
+a6  =  1.1927076848e-03, /* 0x3a9c54a1 */
+a7  =  5.1006977446e-04, /* 0x3a05b634 */
+a8  =  2.2086278477e-04, /* 0x39679767 */
+a9  =  1.0801156895e-04, /* 0x38e28445 */
+a10 =  2.5214456400e-05, /* 0x37d383a2 */
+a11 =  4.4864096708e-05, /* 0x383c2c75 */
+tc  =  1.4616321325e+00, /* 0x3fbb16c3 */
+tf  = -1.2148628384e-01, /* 0xbdf8cdcd */
+/* tt = -(tail of tf) */
+tt  =  6.6971006518e-09, /* 0x31e61c52 */
+t0  =  4.8383611441e-01, /* 0x3ef7b95e */
+t1  = -1.4758771658e-01, /* 0xbe17213c */
+t2  =  6.4624942839e-02, /* 0x3d845a15 */
+t3  = -3.2788541168e-02, /* 0xbd064d47 */
+t4  =  1.7970675603e-02, /* 0x3c93373d */
+t5  = -1.0314224288e-02, /* 0xbc28fcfe */
+t6  =  6.1005386524e-03, /* 0x3bc7e707 */
+t7  = -3.6845202558e-03, /* 0xbb7177fe */
+t8  =  2.2596477065e-03, /* 0x3b141699 */
+t9  = -1.4034647029e-03, /* 0xbab7f476 */
+t10 =  8.8108185446e-04, /* 0x3a66f867 */
+t11 = -5.3859531181e-04, /* 0xba0d3085 */
+t12 =  3.1563205994e-04, /* 0x39a57b6b */
+t13 = -3.1275415677e-04, /* 0xb9a3f927 */
+t14 =  3.3552918467e-04, /* 0x39afe9f7 */
+u0  = -7.7215664089e-02, /* 0xbd9e233f */
+u1  =  6.3282704353e-01, /* 0x3f2200f4 */
+u2  =  1.4549225569e+00, /* 0x3fba3ae7 */
+u3  =  9.7771751881e-01, /* 0x3f7a4bb2 */
+u4  =  2.2896373272e-01, /* 0x3e6a7578 */
+u5  =  1.3381091878e-02, /* 0x3c5b3c5e */
+v1  =  2.4559779167e+00, /* 0x401d2ebe */
+v2  =  2.1284897327e+00, /* 0x4008392d */
+v3  =  7.6928514242e-01, /* 0x3f44efdf */
+v4  =  1.0422264785e-01, /* 0x3dd572af */
+v5  =  3.2170924824e-03, /* 0x3b52d5db */
+s0  = -7.7215664089e-02, /* 0xbd9e233f */
+s1  =  2.1498242021e-01, /* 0x3e5c245a */
+s2  =  3.2577878237e-01, /* 0x3ea6cc7a */
+s3  =  1.4635047317e-01, /* 0x3e15dce6 */
+s4  =  2.6642270386e-02, /* 0x3cda40e4 */
+s5  =  1.8402845599e-03, /* 0x3af135b4 */
+s6  =  3.1947532989e-05, /* 0x3805ff67 */
+r1  =  1.3920053244e+00, /* 0x3fb22d3b */
+r2  =  7.2193557024e-01, /* 0x3f38d0c5 */
+r3  =  1.7193385959e-01, /* 0x3e300f6e */
+r4  =  1.8645919859e-02, /* 0x3c98bf54 */
+r5  =  7.7794247773e-04, /* 0x3a4beed6 */
+r6  =  7.3266842264e-06, /* 0x36f5d7bd */
+w0  =  4.1893854737e-01, /* 0x3ed67f1d */
+w1  =  8.3333335817e-02, /* 0x3daaaaab */
+w2  = -2.7777778450e-03, /* 0xbb360b61 */
+w3  =  7.9365057172e-04, /* 0x3a500cfd */
+w4  = -5.9518753551e-04, /* 0xba1c065c */
+w5  =  8.3633989561e-04, /* 0x3a5b3dd2 */
+w6  = -1.6309292987e-03; /* 0xbad5c4e8 */
+
+static const float zero=  0.0000000000e+00;
+
+	static float sin_pif(float x)
+{
+	float y,z;
+	int n,ix;
+
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;
+
+	if(ix<0x3e800000) return __kernel_sinf(pi*x,zero,0);
+	y = -x;		/* x is assume negative */
+
+    /*
+     * argument reduction, make sure inexact flag not raised if input
+     * is an integer
+     */
+	z = floorf(y);
+	if(z!=y) {				/* inexact anyway */
+	    y  *= (float)0.5;
+	    y   = (float)2.0*(y - floorf(y));	/* y = |x| mod 2.0 */
+	    n   = (int) (y*(float)4.0);
+	} else {
+            if(ix>=0x4b800000) {
+                y = zero; n = 0;                 /* y must be even */
+            } else {
+                if(ix<0x4b000000) z = y+two23;	/* exact */
+		GET_FLOAT_WORD(n,z);
+		n &= 1;
+                y  = n;
+                n<<= 2;
+            }
+        }
+	switch (n) {
+	    case 0:   y =  __kernel_sinf(pi*y,zero,0); break;
+	    case 1:
+	    case 2:   y =  __kernel_cosf(pi*((float)0.5-y),zero); break;
+	    case 3:
+	    case 4:   y =  __kernel_sinf(pi*(one-y),zero,0); break;
+	    case 5:
+	    case 6:   y = -__kernel_cosf(pi*(y-(float)1.5),zero); break;
+	    default:  y =  __kernel_sinf(pi*(y-(float)2.0),zero,0); break;
+	    }
+	return -y;
+}
+
+
+float
+__ieee754_lgammaf_r(float x, int *signgamp)
+{
+	float t,y,z,nadj,p,p1,p2,p3,q,r,w;
+	int i,hx,ix;
+
+	GET_FLOAT_WORD(hx,x);
+
+    /* purge off +-inf, NaN, +-0, and negative arguments */
+	*signgamp = 1;
+	ix = hx&0x7fffffff;
+	if(ix>=0x7f800000) return x*x;
+	if(ix==0) return one/zero;
+	if(ix<0x1c800000) {	/* |x|<2**-70, return -log(|x|) */
+	    if(hx<0) {
+	        *signgamp = -1;
+	        return -__ieee754_logf(-x);
+	    } else return -__ieee754_logf(x);
+	}
+	if(hx<0) {
+	    if(ix>=0x4b000000) 	/* |x|>=2**23, must be -integer */
+		return one/zero;
+	    t = sin_pif(x);
+	    if(t==zero) return one/zero; /* -integer */
+	    nadj = __ieee754_logf(pi/fabsf(t*x));
+	    if(t<zero) *signgamp = -1;
+	    x = -x;
+	}
+
+    /* purge off 1 and 2 */
+	if (ix==0x3f800000||ix==0x40000000) r = 0;
+    /* for x < 2.0 */
+	else if(ix<0x40000000) {
+	    if(ix<=0x3f666666) { 	/* lgamma(x) = lgamma(x+1)-log(x) */
+		r = -__ieee754_logf(x);
+		if(ix>=0x3f3b4a20) {y = one-x; i= 0;}
+		else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;}
+	  	else {y = x; i=2;}
+	    } else {
+	  	r = zero;
+	        if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */
+	        else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */
+		else {y=x-one;i=2;}
+	    }
+	    switch(i) {
+	      case 0:
+		z = y*y;
+		p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
+		p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
+		p  = y*p1+p2;
+		r  += (p-(float)0.5*y); break;
+	      case 1:
+		z = y*y;
+		w = z*y;
+		p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12)));	/* parallel comp */
+		p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
+		p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
+		p  = z*p1-(tt-w*(p2+y*p3));
+		r += (tf + p); break;
+	      case 2:
+		p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
+		p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
+		r += (-(float)0.5*y + p1/p2);
+	    }
+	}
+	else if(ix<0x41000000) { 			/* x < 8.0 */
+	    i = (int)x;
+	    t = zero;
+	    y = x-(float)i;
+	    p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
+	    q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
+	    r = half*y+p/q;
+	    z = one;	/* lgamma(1+s) = log(s) + lgamma(s) */
+	    switch(i) {
+	    case 7: z *= (y+(float)6.0);	/* FALLTHRU */
+	    case 6: z *= (y+(float)5.0);	/* FALLTHRU */
+	    case 5: z *= (y+(float)4.0);	/* FALLTHRU */
+	    case 4: z *= (y+(float)3.0);	/* FALLTHRU */
+	    case 3: z *= (y+(float)2.0);	/* FALLTHRU */
+		    r += __ieee754_logf(z); break;
+	    }
+    /* 8.0 <= x < 2**58 */
+	} else if (ix < 0x5c800000) {
+	    t = __ieee754_logf(x);
+	    z = one/x;
+	    y = z*z;
+	    w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
+	    r = (x-half)*(t-one)+w;
+	} else
+    /* 2**58 <= x <= inf */
+	    r =  x*(__ieee754_logf(x)-one);
+	if(hx<0) r = nadj - r;
+	return r;
+}
Index: /trunk/libc/src/msun/src/e_log.c
===================================================================
--- /trunk/libc/src/msun/src/e_log.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_log.c	(revision 2448)
@@ -0,0 +1,136 @@
+
+/* @(#)e_log.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_log.c,v 1.10 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_log(x)
+ * Return the logrithm of x
+ *
+ * Method :
+ *   1. Argument Reduction: find k and f such that
+ *			x = 2^k * (1+f),
+ *	   where  sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ *   2. Approximation of log(1+f).
+ *	Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ *		 = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *	     	 = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ * 	a polynomial of degree 14 to approximate R The maximum error
+ *	of this polynomial approximation is bounded by 2**-58.45. In
+ *	other words,
+ *		        2      4      6      8      10      12      14
+ *	    R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
+ *  	(the values of Lg1 to Lg7 are listed in the program)
+ *	and
+ *	    |      2          14          |     -58.45
+ *	    | Lg1*s +...+Lg7*s    -  R(z) | <= 2
+ *	    |                             |
+ *	Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *	In order to guarantee error in log below 1ulp, we compute log
+ *	by
+ *		log(1+f) = f - s*(f - R)	(if f is not too large)
+ *		log(1+f) = f - (hfsq - s*(hfsq+R)).	(better accuracy)
+ *	
+ *	3. Finally,  log(x) = k*ln2 + log(1+f).
+ *			    = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *	   Here ln2 is split into two floating point number:
+ *			ln2_hi + ln2_lo,
+ *	   where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *	log(x) is NaN with signal if x < 0 (including -INF) ;
+ *	log(+INF) is +INF; log(0) is -INF with signal;
+ *	log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *	according to an error analysis, the error is always less than
+ *	1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+ln2_hi  =  6.93147180369123816490e-01,	/* 3fe62e42 fee00000 */
+ln2_lo  =  1.90821492927058770002e-10,	/* 3dea39ef 35793c76 */
+two54   =  1.80143985094819840000e+16,  /* 43500000 00000000 */
+Lg1 = 6.666666666666735130e-01,  /* 3FE55555 55555593 */
+Lg2 = 3.999999999940941908e-01,  /* 3FD99999 9997FA04 */
+Lg3 = 2.857142874366239149e-01,  /* 3FD24924 94229359 */
+Lg4 = 2.222219843214978396e-01,  /* 3FCC71C5 1D8E78AF */
+Lg5 = 1.818357216161805012e-01,  /* 3FC74664 96CB03DE */
+Lg6 = 1.531383769920937332e-01,  /* 3FC39A09 D078C69F */
+Lg7 = 1.479819860511658591e-01;  /* 3FC2F112 DF3E5244 */
+
+static const double zero   =  0.0;
+
+double
+__ieee754_log(double x)
+{
+	double hfsq,f,s,z,R,w,t1,t2,dk;
+	int32_t k,hx,i,j;
+	u_int32_t lx;
+
+	EXTRACT_WORDS(hx,lx,x);
+
+	k=0;
+	if (hx < 0x00100000) {			/* x < 2**-1022  */
+	    if (((hx&0x7fffffff)|lx)==0)
+		return -two54/zero;		/* log(+-0)=-inf */
+	    if (hx<0) return (x-x)/zero;	/* log(-#) = NaN */
+	    k -= 54; x *= two54; /* subnormal number, scale up x */
+	    GET_HIGH_WORD(hx,x);
+	}
+	if (hx >= 0x7ff00000) return x+x;
+	k += (hx>>20)-1023;
+	hx &= 0x000fffff;
+	i = (hx+0x95f64)&0x100000;
+	SET_HIGH_WORD(x,hx|(i^0x3ff00000));	/* normalize x or x/2 */
+	k += (i>>20);
+	f = x-1.0;
+	if((0x000fffff&(2+hx))<3) {	/* |f| < 2**-20 */
+	    if(f==zero) if(k==0) return zero;  else {dk=(double)k;
+				 return dk*ln2_hi+dk*ln2_lo;}
+	    R = f*f*(0.5-0.33333333333333333*f);
+	    if(k==0) return f-R; else {dk=(double)k;
+	    	     return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+	}
+ 	s = f/(2.0+f);
+	dk = (double)k;
+	z = s*s;
+	i = hx-0x6147a;
+	w = z*z;
+	j = 0x6b851-hx;
+	t1= w*(Lg2+w*(Lg4+w*Lg6));
+	t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
+	i |= j;
+	R = t2+t1;
+	if(i>0) {
+	    hfsq=0.5*f*f;
+	    if(k==0) return f-(hfsq-s*(hfsq+R)); else
+		     return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+	} else {
+	    if(k==0) return f-s*(f-R); else
+		     return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+	}
+}
Index: /trunk/libc/src/msun/src/e_log10.c
===================================================================
--- /trunk/libc/src/msun/src/e_log10.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_log10.c	(revision 2448)
@@ -0,0 +1,88 @@
+
+/* @(#)e_log10.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_log10.c,v 1.11 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_log10(x)
+ * Return the base 10 logarithm of x
+ *
+ * Method :
+ *	Let log10_2hi = leading 40 bits of log10(2) and
+ *	    log10_2lo = log10(2) - log10_2hi,
+ *	    ivln10   = 1/log(10) rounded.
+ *	Then
+ *		n = ilogb(x),
+ *		if(n<0)  n = n+1;
+ *		x = scalbn(x,-n);
+ *		log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
+ *
+ * Note 1:
+ *	To guarantee log10(10**n)=n, where 10**n is normal, the rounding
+ *	mode must set to Round-to-Nearest.
+ * Note 2:
+ *	[1/log(10)] rounded to 53 bits has error  .198   ulps;
+ *	log10 is monotonic at all binary break points.
+ *
+ * Special cases:
+ *	log10(x) is NaN with signal if x < 0;
+ *	log10(+INF) is +INF with no signal; log10(0) is -INF with signal;
+ *	log10(NaN) is that NaN with no signal;
+ *	log10(10**N) = N  for N=0,1,...,22.
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+two54      =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+ivln10     =  4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
+log10_2hi  =  3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
+log10_2lo  =  3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
+
+static const double zero   =  0.0;
+
+double
+__ieee754_log10(double x)
+{
+	double y,z;
+	int32_t i,k,hx;
+	u_int32_t lx;
+
+	EXTRACT_WORDS(hx,lx,x);
+
+        k=0;
+        if (hx < 0x00100000) {                  /* x < 2**-1022  */
+            if (((hx&0x7fffffff)|lx)==0)
+                return -two54/zero;             /* log(+-0)=-inf */
+            if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
+            k -= 54; x *= two54; /* subnormal number, scale up x */
+	    GET_HIGH_WORD(hx,x);
+        }
+	if (hx >= 0x7ff00000) return x+x;
+	k += (hx>>20)-1023;
+	i  = ((u_int32_t)k&0x80000000)>>31;
+        hx = (hx&0x000fffff)|((0x3ff-i)<<20);
+        y  = (double)(k+i);
+	SET_HIGH_WORD(x,hx);
+	z  = y*log10_2lo + ivln10*__ieee754_log(x);
+	return  z+y*log10_2hi;
+}
Index: /trunk/libc/src/msun/src/e_log10f.c
===================================================================
--- /trunk/libc/src/msun/src/e_log10f.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_log10f.c	(revision 2448)
@@ -0,0 +1,56 @@
+/* e_log10f.c -- float version of e_log10.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_log10f.c,v 1.8 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+two25      =  3.3554432000e+07, /* 0x4c000000 */
+ivln10     =  4.3429449201e-01, /* 0x3ede5bd9 */
+log10_2hi  =  3.0102920532e-01, /* 0x3e9a2080 */
+log10_2lo  =  7.9034151668e-07; /* 0x355427db */
+
+static const float zero   =  0.0;
+
+float
+__ieee754_log10f(float x)
+{
+	float y,z;
+	int32_t i,k,hx;
+
+	GET_FLOAT_WORD(hx,x);
+
+        k=0;
+        if (hx < 0x00800000) {                  /* x < 2**-126  */
+            if ((hx&0x7fffffff)==0)
+                return -two25/zero;             /* log(+-0)=-inf */
+            if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
+            k -= 25; x *= two25; /* subnormal number, scale up x */
+	    GET_FLOAT_WORD(hx,x);
+        }
+	if (hx >= 0x7f800000) return x+x;
+	k += (hx>>23)-127;
+	i  = ((u_int32_t)k&0x80000000)>>31;
+        hx = (hx&0x007fffff)|((0x7f-i)<<23);
+        y  = (float)(k+i);
+	SET_FLOAT_WORD(x,hx);
+	z  = y*log10_2lo + ivln10*__ieee754_logf(x);
+	return  z+y*log10_2hi;
+}
Index: /trunk/libc/src/msun/src/e_logf.c
===================================================================
--- /trunk/libc/src/msun/src/e_logf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_logf.c	(revision 2448)
@@ -0,0 +1,86 @@
+/* e_logf.c -- float version of e_log.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_logf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+ln2_hi =   6.9313812256e-01,	/* 0x3f317180 */
+ln2_lo =   9.0580006145e-06,	/* 0x3717f7d1 */
+two25 =    3.355443200e+07,	/* 0x4c000000 */
+Lg1 = 6.6666668653e-01,	/* 3F2AAAAB */
+Lg2 = 4.0000000596e-01,	/* 3ECCCCCD */
+Lg3 = 2.8571429849e-01, /* 3E924925 */
+Lg4 = 2.2222198546e-01, /* 3E638E29 */
+Lg5 = 1.8183572590e-01, /* 3E3A3325 */
+Lg6 = 1.5313838422e-01, /* 3E1CD04F */
+Lg7 = 1.4798198640e-01; /* 3E178897 */
+
+static const float zero   =  0.0;
+
+float
+__ieee754_logf(float x)
+{
+	float hfsq,f,s,z,R,w,t1,t2,dk;
+	int32_t k,ix,i,j;
+
+	GET_FLOAT_WORD(ix,x);
+
+	k=0;
+	if (ix < 0x00800000) {			/* x < 2**-126  */
+	    if ((ix&0x7fffffff)==0)
+		return -two25/zero;		/* log(+-0)=-inf */
+	    if (ix<0) return (x-x)/zero;	/* log(-#) = NaN */
+	    k -= 25; x *= two25; /* subnormal number, scale up x */
+	    GET_FLOAT_WORD(ix,x);
+	}
+	if (ix >= 0x7f800000) return x+x;
+	k += (ix>>23)-127;
+	ix &= 0x007fffff;
+	i = (ix+(0x95f64<<3))&0x800000;
+	SET_FLOAT_WORD(x,ix|(i^0x3f800000));	/* normalize x or x/2 */
+	k += (i>>23);
+	f = x-(float)1.0;
+	if((0x007fffff&(15+ix))<16) {	/* |f| < 2**-20 */
+	    if(f==zero) if(k==0) return zero;  else {dk=(float)k;
+				 return dk*ln2_hi+dk*ln2_lo;}
+	    R = f*f*((float)0.5-(float)0.33333333333333333*f);
+	    if(k==0) return f-R; else {dk=(float)k;
+	    	     return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+	}
+ 	s = f/((float)2.0+f);
+	dk = (float)k;
+	z = s*s;
+	i = ix-(0x6147a<<3);
+	w = z*z;
+	j = (0x6b851<<3)-ix;
+	t1= w*(Lg2+w*(Lg4+w*Lg6));
+	t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
+	i |= j;
+	R = t2+t1;
+	if(i>0) {
+	    hfsq=(float)0.5*f*f;
+	    if(k==0) return f-(hfsq-s*(hfsq+R)); else
+		     return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+	} else {
+	    if(k==0) return f-s*(f-R); else
+		     return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+	}
+}
Index: /trunk/libc/src/msun/src/e_pow.c
===================================================================
--- /trunk/libc/src/msun/src/e_pow.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_pow.c	(revision 2448)
@@ -0,0 +1,305 @@
+/* @(#)e_pow.c 1.5 04/04/22 SMI */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_pow.c,v 1.11 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_pow(x,y) return x**y
+ *
+ *		      n
+ * Method:  Let x =  2   * (1+f)
+ *	1. Compute and return log2(x) in two pieces:
+ *		log2(x) = w1 + w2,
+ *	   where w1 has 53-24 = 29 bit trailing zeros.
+ *	2. Perform y*log2(x) = n+y' by simulating muti-precision
+ *	   arithmetic, where |y'|<=0.5.
+ *	3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ *	1.  (anything) ** 0  is 1
+ *	2.  (anything) ** 1  is itself
+ *	3.  (anything) ** NAN is NAN
+ *	4.  NAN ** (anything except 0) is NAN
+ *	5.  +-(|x| > 1) **  +INF is +INF
+ *	6.  +-(|x| > 1) **  -INF is +0
+ *	7.  +-(|x| < 1) **  +INF is +0
+ *	8.  +-(|x| < 1) **  -INF is +INF
+ *	9.  +-1         ** +-INF is NAN
+ *	10. +0 ** (+anything except 0, NAN)               is +0
+ *	11. -0 ** (+anything except 0, NAN, odd integer)  is +0
+ *	12. +0 ** (-anything except 0, NAN)               is +INF
+ *	13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
+ *	14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ *	15. +INF ** (+anything except 0,NAN) is +INF
+ *	16. +INF ** (-anything except 0,NAN) is +0
+ *	17. -INF ** (anything)  = -0 ** (-anything)
+ *	18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ *	19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ *	pow(x,y) returns x**y nearly rounded. In particular
+ *			pow(integer,integer)
+ *	always returns the correct integer provided it is
+ *	representable.
+ *
+ * Constants :
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+zero    =  0.0,
+one	=  1.0,
+two	=  2.0,
+two53	=  9007199254740992.0,	/* 0x43400000, 0x00000000 */
+huge	=  1.0e300,
+tiny    =  1.0e-300,
+	/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1  =  5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2  =  4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3  =  3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4  =  2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5  =  2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6  =  2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5   =  4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2  =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h  =  6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l  = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt =  8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp    =  9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h  =  9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l  = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2    =  1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h  =  1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l  =  1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+double
+__ieee754_pow(double x, double y)
+{
+	double z,ax,z_h,z_l,p_h,p_l;
+	double y1,t1,t2,r,s,t,u,v,w;
+	int32_t i,j,k,yisint,n;
+	int32_t hx,hy,ix,iy;
+	u_int32_t lx,ly;
+
+	EXTRACT_WORDS(hx,lx,x);
+	EXTRACT_WORDS(hy,ly,y);
+	ix = hx&0x7fffffff;  iy = hy&0x7fffffff;
+
+    /* y==zero: x**0 = 1 */
+	if((iy|ly)==0) return one; 	
+
+    /* +-NaN return x+y */
+	if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
+	   iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
+		return x+y;	
+
+    /* determine if y is an odd int when x < 0
+     * yisint = 0	... y is not an integer
+     * yisint = 1	... y is an odd int
+     * yisint = 2	... y is an even int
+     */
+	yisint  = 0;
+	if(hx<0) {	
+	    if(iy>=0x43400000) yisint = 2; /* even integer y */
+	    else if(iy>=0x3ff00000) {
+		k = (iy>>20)-0x3ff;	   /* exponent */
+		if(k>20) {
+		    j = ly>>(52-k);
+		    if((j<<(52-k))==ly) yisint = 2-(j&1);
+		} else if(ly==0) {
+		    j = iy>>(20-k);
+		    if((j<<(20-k))==iy) yisint = 2-(j&1);
+		}
+	    }		
+	}
+
+    /* special value of y */
+	if(ly==0) { 	
+	    if (iy==0x7ff00000) {	/* y is +-inf */
+	        if(((ix-0x3ff00000)|lx)==0)
+		    return  y - y;	/* inf**+-1 is NaN */
+	        else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
+		    return (hy>=0)? y: zero;
+	        else			/* (|x|<1)**-,+inf = inf,0 */
+		    return (hy<0)?-y: zero;
+	    }
+	    if(iy==0x3ff00000) {	/* y is  +-1 */
+		if(hy<0) return one/x; else return x;
+	    }
+	    if(hy==0x40000000) return x*x; /* y is  2 */
+	    if(hy==0x3fe00000) {	/* y is  0.5 */
+		if(hx>=0)	/* x >= +0 */
+		return sqrt(x);	
+	    }
+	}
+
+	ax   = fabs(x);
+    /* special value of x */
+	if(lx==0) {
+	    if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
+		z = ax;			/*x is +-0,+-inf,+-1*/
+		if(hy<0) z = one/z;	/* z = (1/|x|) */
+		if(hx<0) {
+		    if(((ix-0x3ff00000)|yisint)==0) {
+			z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+		    } else if(yisint==1)
+			z = -z;		/* (x<0)**odd = -(|x|**odd) */
+		}
+		return z;
+	    }
+	}
+
+    /* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be
+	n = (hx>>31)+1;
+       but ANSI C says a right shift of a signed negative quantity is
+       implementation defined.  */
+	n = ((u_int32_t)hx>>31)-1;
+
+    /* (x<0)**(non-int) is NaN */
+	if((n|yisint)==0) return (x-x)/(x-x);
+
+	s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+	if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */
+
+    /* |y| is huge */
+	if(iy>0x41e00000) { /* if |y| > 2**31 */
+	    if(iy>0x43f00000){	/* if |y| > 2**64, must o/uflow */
+		if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+		if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+	    }
+	/* over/underflow if x is not close to one */
+	    if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny;
+	    if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny;
+	/* now |1-x| is tiny <= 2**-20, suffice to compute
+	   log(x) by x-x^2/2+x^3/3-x^4/4 */
+	    t = ax-one;		/* t has 20 trailing zeros */
+	    w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
+	    u = ivln2_h*t;	/* ivln2_h has 21 sig. bits */
+	    v = t*ivln2_l-w*ivln2;
+	    t1 = u+v;
+	    SET_LOW_WORD(t1,0);
+	    t2 = v-(t1-u);
+	} else {
+	    double ss,s2,s_h,s_l,t_h,t_l;
+	    n = 0;
+	/* take care subnormal number */
+	    if(ix<0x00100000)
+		{ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); }
+	    n  += ((ix)>>20)-0x3ff;
+	    j  = ix&0x000fffff;
+	/* determine interval */
+	    ix = j|0x3ff00000;		/* normalize ix */
+	    if(j<=0x3988E) k=0;		/* |x|<sqrt(3/2) */
+	    else if(j<0xBB67A) k=1;	/* |x|<sqrt(3)   */
+	    else {k=0;n+=1;ix -= 0x00100000;}
+	    SET_HIGH_WORD(ax,ix);
+
+	/* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+	    u = ax-bp[k];		/* bp[0]=1.0, bp[1]=1.5 */
+	    v = one/(ax+bp[k]);
+	    ss = u*v;
+	    s_h = ss;
+	    SET_LOW_WORD(s_h,0);
+	/* t_h=ax+bp[k] High */
+	    t_h = zero;
+	    SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
+	    t_l = ax - (t_h-bp[k]);
+	    s_l = v*((u-s_h*t_h)-s_h*t_l);
+	/* compute log(ax) */
+	    s2 = ss*ss;
+	    r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+	    r += s_l*(s_h+ss);
+	    s2  = s_h*s_h;
+	    t_h = 3.0+s2+r;
+	    SET_LOW_WORD(t_h,0);
+	    t_l = r-((t_h-3.0)-s2);
+	/* u+v = ss*(1+...) */
+	    u = s_h*t_h;
+	    v = s_l*t_h+t_l*ss;
+	/* 2/(3log2)*(ss+...) */
+	    p_h = u+v;
+	    SET_LOW_WORD(p_h,0);
+	    p_l = v-(p_h-u);
+	    z_h = cp_h*p_h;		/* cp_h+cp_l = 2/(3*log2) */
+	    z_l = cp_l*p_h+p_l*cp+dp_l[k];
+	/* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+	    t = (double)n;
+	    t1 = (((z_h+z_l)+dp_h[k])+t);
+	    SET_LOW_WORD(t1,0);
+	    t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+	}
+
+    /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+	y1  = y;
+	SET_LOW_WORD(y1,0);
+	p_l = (y-y1)*t1+y*t2;
+	p_h = y1*t1;
+	z = p_l+p_h;
+	EXTRACT_WORDS(j,i,z);
+	if (j>=0x40900000) {				/* z >= 1024 */
+	    if(((j-0x40900000)|i)!=0)			/* if z > 1024 */
+		return s*huge*huge;			/* overflow */
+	    else {
+		if(p_l+ovt>z-p_h) return s*huge*huge;	/* overflow */
+	    }
+	} else if((j&0x7fffffff)>=0x4090cc00 ) {	/* z <= -1075 */
+	    if(((j-0xc090cc00)|i)!=0) 		/* z < -1075 */
+		return s*tiny*tiny;		/* underflow */
+	    else {
+		if(p_l<=z-p_h) return s*tiny*tiny;	/* underflow */
+	    }
+	}
+    /*
+     * compute 2**(p_h+p_l)
+     */
+	i = j&0x7fffffff;
+	k = (i>>20)-0x3ff;
+	n = 0;
+	if(i>0x3fe00000) {		/* if |z| > 0.5, set n = [z+0.5] */
+	    n = j+(0x00100000>>(k+1));
+	    k = ((n&0x7fffffff)>>20)-0x3ff;	/* new k for n */
+	    t = zero;
+	    SET_HIGH_WORD(t,n&~(0x000fffff>>k));
+	    n = ((n&0x000fffff)|0x00100000)>>(20-k);
+	    if(j<0) n = -n;
+	    p_h -= t;
+	}
+	t = p_l+p_h;
+	SET_LOW_WORD(t,0);
+	u = t*lg2_h;
+	v = (p_l-(t-p_h))*lg2+t*lg2_l;
+	z = u+v;
+	w = v-(z-u);
+	t  = z*z;
+	t1  = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+	r  = (z*t1)/(t1-two)-(w+z*w);
+	z  = one-(r-z);
+	GET_HIGH_WORD(j,z);
+	j += (n<<20);
+	if((j>>20)<=0) z = scalbn(z,n);	/* subnormal output */
+	else SET_HIGH_WORD(z,j);
+	return s*z;
+}
Index: /trunk/libc/src/msun/src/e_powf.c
===================================================================
--- /trunk/libc/src/msun/src/e_powf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_powf.c	(revision 2448)
@@ -0,0 +1,248 @@
+/* e_powf.c -- float version of e_pow.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_powf.c,v 1.12 2004/06/01 19:33:30 bde Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */
+dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */
+zero    =  0.0,
+one	=  1.0,
+two	=  2.0,
+two24	=  16777216.0,	/* 0x4b800000 */
+huge	=  1.0e30,
+tiny    =  1.0e-30,
+	/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1  =  6.0000002384e-01, /* 0x3f19999a */
+L2  =  4.2857143283e-01, /* 0x3edb6db7 */
+L3  =  3.3333334327e-01, /* 0x3eaaaaab */
+L4  =  2.7272811532e-01, /* 0x3e8ba305 */
+L5  =  2.3066075146e-01, /* 0x3e6c3255 */
+L6  =  2.0697501302e-01, /* 0x3e53f142 */
+P1   =  1.6666667163e-01, /* 0x3e2aaaab */
+P2   = -2.7777778450e-03, /* 0xbb360b61 */
+P3   =  6.6137559770e-05, /* 0x388ab355 */
+P4   = -1.6533901999e-06, /* 0xb5ddea0e */
+P5   =  4.1381369442e-08, /* 0x3331bb4c */
+lg2  =  6.9314718246e-01, /* 0x3f317218 */
+lg2_h  =  6.93145752e-01, /* 0x3f317200 */
+lg2_l  =  1.42860654e-06, /* 0x35bfbe8c */
+ovt =  4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */
+cp    =  9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */
+cp_h  =  9.6179199219e-01, /* 0x3f763800 =head of cp */
+cp_l  =  4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */
+ivln2    =  1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */
+ivln2_h  =  1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/
+ivln2_l  =  7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
+
+float
+__ieee754_powf(float x, float y)
+{
+	float z,ax,z_h,z_l,p_h,p_l;
+	float y1,t1,t2,r,s,sn,t,u,v,w;
+	int32_t i,j,k,yisint,n;
+	int32_t hx,hy,ix,iy,is;
+
+	GET_FLOAT_WORD(hx,x);
+	GET_FLOAT_WORD(hy,y);
+	ix = hx&0x7fffffff;  iy = hy&0x7fffffff;
+
+    /* y==zero: x**0 = 1 */
+	if(iy==0) return one;
+
+    /* +-NaN return x+y */
+	if(ix > 0x7f800000 ||
+	   iy > 0x7f800000)
+		return x+y;
+
+    /* determine if y is an odd int when x < 0
+     * yisint = 0	... y is not an integer
+     * yisint = 1	... y is an odd int
+     * yisint = 2	... y is an even int
+     */
+	yisint  = 0;
+	if(hx<0) {
+	    if(iy>=0x4b800000) yisint = 2; /* even integer y */
+	    else if(iy>=0x3f800000) {
+		k = (iy>>23)-0x7f;	   /* exponent */
+		j = iy>>(23-k);
+		if((j<<(23-k))==iy) yisint = 2-(j&1);
+	    }
+	}
+
+    /* special value of y */
+	if (iy==0x7f800000) {	/* y is +-inf */
+	    if (ix==0x3f800000)
+	        return  y - y;	/* inf**+-1 is NaN */
+	    else if (ix > 0x3f800000)/* (|x|>1)**+-inf = inf,0 */
+	        return (hy>=0)? y: zero;
+	    else			/* (|x|<1)**-,+inf = inf,0 */
+	        return (hy<0)?-y: zero;
+	}
+	if(iy==0x3f800000) {	/* y is  +-1 */
+	    if(hy<0) return one/x; else return x;
+	}
+	if(hy==0x40000000) return x*x; /* y is  2 */
+	if(hy==0x3f000000) {	/* y is  0.5 */
+	    if(hx>=0)	/* x >= +0 */
+	    return __ieee754_sqrtf(x);
+	}
+
+	ax   = fabsf(x);
+    /* special value of x */
+	if(ix==0x7f800000||ix==0||ix==0x3f800000){
+	    z = ax;			/*x is +-0,+-inf,+-1*/
+	    if(hy<0) z = one/z;	/* z = (1/|x|) */
+	    if(hx<0) {
+		if(((ix-0x3f800000)|yisint)==0) {
+		    z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+		} else if(yisint==1)
+		    z = -z;		/* (x<0)**odd = -(|x|**odd) */
+	    }
+	    return z;
+	}
+
+	n = ((u_int32_t)hx>>31)-1;
+
+    /* (x<0)**(non-int) is NaN */
+	if((n|yisint)==0) return (x-x)/(x-x);
+
+	sn = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+	if((n|(yisint-1))==0) sn = -one;/* (-ve)**(odd int) */
+
+    /* |y| is huge */
+	if(iy>0x4d000000) { /* if |y| > 2**27 */
+	/* over/underflow if x is not close to one */
+	    if(ix<0x3f7ffff8) return (hy<0)? sn*huge*huge:sn*tiny*tiny;
+	    if(ix>0x3f800007) return (hy>0)? sn*huge*huge:sn*tiny*tiny;
+	/* now |1-x| is tiny <= 2**-20, suffice to compute
+	   log(x) by x-x^2/2+x^3/3-x^4/4 */
+	    t = ax-1;		/* t has 20 trailing zeros */
+	    w = (t*t)*((float)0.5-t*((float)0.333333333333-t*(float)0.25));
+	    u = ivln2_h*t;	/* ivln2_h has 16 sig. bits */
+	    v = t*ivln2_l-w*ivln2;
+	    t1 = u+v;
+	    GET_FLOAT_WORD(is,t1);
+	    SET_FLOAT_WORD(t1,is&0xfffff000);
+	    t2 = v-(t1-u);
+	} else {
+	    float s2,s_h,s_l,t_h,t_l;
+	    n = 0;
+	/* take care subnormal number */
+	    if(ix<0x00800000)
+		{ax *= two24; n -= 24; GET_FLOAT_WORD(ix,ax); }
+	    n  += ((ix)>>23)-0x7f;
+	    j  = ix&0x007fffff;
+	/* determine interval */
+	    ix = j|0x3f800000;		/* normalize ix */
+	    if(j<=0x1cc471) k=0;	/* |x|<sqrt(3/2) */
+	    else if(j<0x5db3d7) k=1;	/* |x|<sqrt(3)   */
+	    else {k=0;n+=1;ix -= 0x00800000;}
+	    SET_FLOAT_WORD(ax,ix);
+
+	/* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+	    u = ax-bp[k];		/* bp[0]=1.0, bp[1]=1.5 */
+	    v = one/(ax+bp[k]);
+	    s = u*v;
+	    s_h = s;
+	    GET_FLOAT_WORD(is,s_h);
+	    SET_FLOAT_WORD(s_h,is&0xfffff000);
+	/* t_h=ax+bp[k] High */
+	    is = ((ix>>1)&0xfffff000)|0x20000000;
+	    SET_FLOAT_WORD(t_h,is+0x00400000+(k<<21));
+	    t_l = ax - (t_h-bp[k]);
+	    s_l = v*((u-s_h*t_h)-s_h*t_l);
+	/* compute log(ax) */
+	    s2 = s*s;
+	    r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+	    r += s_l*(s_h+s);
+	    s2  = s_h*s_h;
+	    t_h = (float)3.0+s2+r;
+	    GET_FLOAT_WORD(is,t_h);
+	    SET_FLOAT_WORD(t_h,is&0xfffff000);
+	    t_l = r-((t_h-(float)3.0)-s2);
+	/* u+v = s*(1+...) */
+	    u = s_h*t_h;
+	    v = s_l*t_h+t_l*s;
+	/* 2/(3log2)*(s+...) */
+	    p_h = u+v;
+	    GET_FLOAT_WORD(is,p_h);
+	    SET_FLOAT_WORD(p_h,is&0xfffff000);
+	    p_l = v-(p_h-u);
+	    z_h = cp_h*p_h;		/* cp_h+cp_l = 2/(3*log2) */
+	    z_l = cp_l*p_h+p_l*cp+dp_l[k];
+	/* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+	    t = (float)n;
+	    t1 = (((z_h+z_l)+dp_h[k])+t);
+	    GET_FLOAT_WORD(is,t1);
+	    SET_FLOAT_WORD(t1,is&0xfffff000);
+	    t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+	}
+
+    /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+	GET_FLOAT_WORD(is,y);
+	SET_FLOAT_WORD(y1,is&0xfffff000);
+	p_l = (y-y1)*t1+y*t2;
+	p_h = y1*t1;
+	z = p_l+p_h;
+	GET_FLOAT_WORD(j,z);
+	if (j>0x43000000)				/* if z > 128 */
+	    return sn*huge*huge;			/* overflow */
+	else if (j==0x43000000) {			/* if z == 128 */
+	    if(p_l+ovt>z-p_h) return sn*huge*huge;	/* overflow */
+	}
+	else if ((j&0x7fffffff)>0x43160000)		/* z <= -150 */
+	    return sn*tiny*tiny;			/* underflow */
+	else if (j==0xc3160000){			/* z == -150 */
+	    if(p_l<=z-p_h) return sn*tiny*tiny;		/* underflow */
+	}
+    /*
+     * compute 2**(p_h+p_l)
+     */
+	i = j&0x7fffffff;
+	k = (i>>23)-0x7f;
+	n = 0;
+	if(i>0x3f000000) {		/* if |z| > 0.5, set n = [z+0.5] */
+	    n = j+(0x00800000>>(k+1));
+	    k = ((n&0x7fffffff)>>23)-0x7f;	/* new k for n */
+	    SET_FLOAT_WORD(t,n&~(0x007fffff>>k));
+	    n = ((n&0x007fffff)|0x00800000)>>(23-k);
+	    if(j<0) n = -n;
+	    p_h -= t;
+	}
+	t = p_l+p_h;
+	GET_FLOAT_WORD(is,t);
+	SET_FLOAT_WORD(t,is&0xffff8000);
+	u = t*lg2_h;
+	v = (p_l-(t-p_h))*lg2+t*lg2_l;
+	z = u+v;
+	w = v-(z-u);
+	t  = z*z;
+	t1  = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+	r  = (z*t1)/(t1-two)-(w+z*w);
+	z  = one-(r-z);
+	GET_FLOAT_WORD(j,z);
+	j += (n<<23);
+	if((j>>23)<=0) z = scalbnf(z,n);	/* subnormal output */
+	else SET_FLOAT_WORD(z,j);
+	return sn*z;
+}
Index: /trunk/libc/src/msun/src/e_rem_pio2.c
===================================================================
--- /trunk/libc/src/msun/src/e_rem_pio2.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_rem_pio2.c	(revision 2448)
@@ -0,0 +1,169 @@
+
+/* @(#)e_rem_pio2.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_rem_pio2.c,v 1.8 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_rem_pio2(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ */
+static const int32_t two_over_pi[] = {
+0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
+0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
+0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
+0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
+0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
+0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
+0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
+0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
+0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
+0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
+0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
+};
+
+static const int32_t npio2_hw[] = {
+0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
+0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
+0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
+0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
+0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
+0x404858EB, 0x404921FB,
+};
+
+/*
+ * invpio2:  53 bits of 2/pi
+ * pio2_1:   first  33 bit of pi/2
+ * pio2_1t:  pi/2 - pio2_1
+ * pio2_2:   second 33 bit of pi/2
+ * pio2_2t:  pi/2 - (pio2_1+pio2_2)
+ * pio2_3:   third  33 bit of pi/2
+ * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const double
+zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+pio2_1  =  1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
+pio2_1t =  6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
+pio2_2  =  6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
+pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
+pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
+pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
+
+	int32_t __ieee754_rem_pio2(double x, double *y)
+{
+	double z,w,t,r,fn;
+	double tx[3];
+	int32_t e0,i,j,nx,n,ix,hx;
+	u_int32_t low;
+
+	GET_HIGH_WORD(hx,x);		/* high word of x */
+	ix = hx&0x7fffffff;
+	if(ix<=0x3fe921fb)   /* |x| ~<= pi/4 , no need for reduction */
+	    {y[0] = x; y[1] = 0; return 0;}
+	if(ix<0x4002d97c) {  /* |x| < 3pi/4, special case with n=+-1 */
+	    if(hx>0) {
+		z = x - pio2_1;
+		if(ix!=0x3ff921fb) { 	/* 33+53 bit pi is good enough */
+		    y[0] = z - pio2_1t;
+		    y[1] = (z-y[0])-pio2_1t;
+		} else {		/* near pi/2, use 33+33+53 bit pi */
+		    z -= pio2_2;
+		    y[0] = z - pio2_2t;
+		    y[1] = (z-y[0])-pio2_2t;
+		}
+		return 1;
+	    } else {	/* negative x */
+		z = x + pio2_1;
+		if(ix!=0x3ff921fb) { 	/* 33+53 bit pi is good enough */
+		    y[0] = z + pio2_1t;
+		    y[1] = (z-y[0])+pio2_1t;
+		} else {		/* near pi/2, use 33+33+53 bit pi */
+		    z += pio2_2;
+		    y[0] = z + pio2_2t;
+		    y[1] = (z-y[0])+pio2_2t;
+		}
+		return -1;
+	    }
+	}
+	if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
+	    t  = fabs(x);
+	    n  = (int32_t) (t*invpio2+half);
+	    fn = (double)n;
+	    r  = t-fn*pio2_1;
+	    w  = fn*pio2_1t;	/* 1st round good to 85 bit */
+	    if(n<32&&ix!=npio2_hw[n-1]) {	
+		y[0] = r-w;	/* quick check no cancellation */
+	    } else {
+	        u_int32_t high;
+	        j  = ix>>20;
+	        y[0] = r-w;
+		GET_HIGH_WORD(high,y[0]);
+	        i = j-((high>>20)&0x7ff);
+	        if(i>16) {  /* 2nd iteration needed, good to 118 */
+		    t  = r;
+		    w  = fn*pio2_2;	
+		    r  = t-w;
+		    w  = fn*pio2_2t-((t-r)-w);	
+		    y[0] = r-w;
+		    GET_HIGH_WORD(high,y[0]);
+		    i = j-((high>>20)&0x7ff);
+		    if(i>49)  {	/* 3rd iteration need, 151 bits acc */
+		    	t  = r;	/* will cover all possible cases */
+		    	w  = fn*pio2_3;	
+		    	r  = t-w;
+		    	w  = fn*pio2_3t-((t-r)-w);	
+		    	y[0] = r-w;
+		    }
+		}
+	    }
+	    y[1] = (r-y[0])-w;
+	    if(hx<0) 	{y[0] = -y[0]; y[1] = -y[1]; return -n;}
+	    else	 return n;
+	}
+    /*
+     * all other (large) arguments
+     */
+	if(ix>=0x7ff00000) {		/* x is inf or NaN */
+	    y[0]=y[1]=x-x; return 0;
+	}
+    /* set z = scalbn(|x|,ilogb(x)-23) */
+	GET_LOW_WORD(low,x);
+	SET_LOW_WORD(z,low);
+	e0 	= (ix>>20)-1046;	/* e0 = ilogb(z)-23; */
+	SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20)));
+	for(i=0;i<2;i++) {
+		tx[i] = (double)((int32_t)(z));
+		z     = (z-tx[i])*two24;
+	}
+	tx[2] = z;
+	nx = 3;
+	while(tx[nx-1]==zero) nx--;	/* skip zero term */
+	n  =  __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
+	if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+	return n;
+}
Index: /trunk/libc/src/msun/src/e_rem_pio2f.c
===================================================================
--- /trunk/libc/src/msun/src/e_rem_pio2f.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_rem_pio2f.c	(revision 2448)
@@ -0,0 +1,180 @@
+/* e_rem_pio2f.c -- float version of e_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_rem_pio2f.c,v 1.7 2002/05/28 17:51:46 alfred Exp $";
+#endif
+
+/* __ieee754_rem_pio2f(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2f()
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ */
+static const int32_t two_over_pi[] = {
+0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
+0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
+0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
+0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
+0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
+0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
+0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
+0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
+0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
+0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
+0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
+0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
+0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
+0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
+0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
+0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
+0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
+0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
+0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
+0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
+0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
+0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
+};
+
+/* This array is like the one in e_rem_pio2.c, but the numbers are
+   single precision and the last 8 bits are forced to 0.  */
+static const int32_t npio2_hw[] = {
+0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
+0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
+0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
+0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
+0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
+0x4242c700, 0x42490f00
+};
+
+/*
+ * invpio2:  24 bits of 2/pi
+ * pio2_1:   first  17 bit of pi/2
+ * pio2_1t:  pi/2 - pio2_1
+ * pio2_2:   second 17 bit of pi/2
+ * pio2_2t:  pi/2 - (pio2_1+pio2_2)
+ * pio2_3:   third  17 bit of pi/2
+ * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const float
+zero =  0.0000000000e+00, /* 0x00000000 */
+half =  5.0000000000e-01, /* 0x3f000000 */
+two8 =  2.5600000000e+02, /* 0x43800000 */
+invpio2 =  6.3661980629e-01, /* 0x3f22f984 */
+pio2_1  =  1.5707855225e+00, /* 0x3fc90f80 */
+pio2_1t =  1.0804334124e-05, /* 0x37354443 */
+pio2_2  =  1.0804273188e-05, /* 0x37354400 */
+pio2_2t =  6.0770999344e-11, /* 0x2e85a308 */
+pio2_3  =  6.0770943833e-11, /* 0x2e85a300 */
+pio2_3t =  6.1232342629e-17; /* 0x248d3132 */
+
+	int32_t __ieee754_rem_pio2f(float x, float *y)
+{
+	float z,w,t,r,fn;
+	float tx[3];
+	int32_t e0,i,j,nx,n,ix,hx;
+
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix<=0x3f490fd8)   /* |x| ~<= pi/4 , no need for reduction */
+	    {y[0] = x; y[1] = 0; return 0;}
+	if(ix<0x4016cbe4) {  /* |x| < 3pi/4, special case with n=+-1 */
+	    if(hx>0) {
+		z = x - pio2_1;
+		if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
+		    y[0] = z - pio2_1t;
+		    y[1] = (z-y[0])-pio2_1t;
+		} else {		/* near pi/2, use 24+24+24 bit pi */
+		    z -= pio2_2;
+		    y[0] = z - pio2_2t;
+		    y[1] = (z-y[0])-pio2_2t;
+		}
+		return 1;
+	    } else {	/* negative x */
+		z = x + pio2_1;
+		if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
+		    y[0] = z + pio2_1t;
+		    y[1] = (z-y[0])+pio2_1t;
+		} else {		/* near pi/2, use 24+24+24 bit pi */
+		    z += pio2_2;
+		    y[0] = z + pio2_2t;
+		    y[1] = (z-y[0])+pio2_2t;
+		}
+		return -1;
+	    }
+	}
+	if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
+	    t  = fabsf(x);
+	    n  = (int32_t) (t*invpio2+half);
+	    fn = (float)n;
+	    r  = t-fn*pio2_1;
+	    w  = fn*pio2_1t;	/* 1st round good to 40 bit */
+	    if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) {
+		y[0] = r-w;	/* quick check no cancellation */
+	    } else {
+	        u_int32_t high;
+	        j  = ix>>23;
+	        y[0] = r-w;
+		GET_FLOAT_WORD(high,y[0]);
+	        i = j-((high>>23)&0xff);
+	        if(i>8) {  /* 2nd iteration needed, good to 57 */
+		    t  = r;
+		    w  = fn*pio2_2;
+		    r  = t-w;
+		    w  = fn*pio2_2t-((t-r)-w);
+		    y[0] = r-w;
+		    GET_FLOAT_WORD(high,y[0]);
+		    i = j-((high>>23)&0xff);
+		    if(i>25)  {	/* 3rd iteration need, 74 bits acc */
+		    	t  = r;	/* will cover all possible cases */
+		    	w  = fn*pio2_3;
+		    	r  = t-w;
+		    	w  = fn*pio2_3t-((t-r)-w);
+		    	y[0] = r-w;
+		    }
+		}
+	    }
+	    y[1] = (r-y[0])-w;
+	    if(hx<0) 	{y[0] = -y[0]; y[1] = -y[1]; return -n;}
+	    else	 return n;
+	}
+    /*
+     * all other (large) arguments
+     */
+	if(ix>=0x7f800000) {		/* x is inf or NaN */
+	    y[0]=y[1]=x-x; return 0;
+	}
+    /* set z = scalbn(|x|,ilogb(x)-7) */
+	e0 	= (ix>>23)-134;		/* e0 = ilogb(z)-7; */
+	SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
+	for(i=0;i<2;i++) {
+		tx[i] = (float)((int32_t)(z));
+		z     = (z-tx[i])*two8;
+	}
+	tx[2] = z;
+	nx = 3;
+	while(tx[nx-1]==zero) nx--;	/* skip zero term */
+	n  =  __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
+	if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+	return n;
+}
Index: /trunk/libc/src/msun/src/e_remainder.c
===================================================================
--- /trunk/libc/src/msun/src/e_remainder.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_remainder.c	(revision 2448)
@@ -0,0 +1,74 @@
+
+/* @(#)e_remainder.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_remainder.c,v 1.10 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_remainder(x,p)
+ * Return :
+ * 	returns  x REM p  =  x - [x/p]*p as if in infinite
+ * 	precise arithmetic, where [x/p] is the (infinite bit)
+ *	integer nearest x/p (in half way case choose the even one).
+ * Method :
+ *	Based on fmod() return x-[x/p]chopped*p exactlp.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double zero = 0.0;
+
+
+double
+__ieee754_remainder(double x, double p)
+{
+	int32_t hx,hp;
+	u_int32_t sx,lx,lp;
+	double p_half;
+
+	EXTRACT_WORDS(hx,lx,x);
+	EXTRACT_WORDS(hp,lp,p);
+	sx = hx&0x80000000;
+	hp &= 0x7fffffff;
+	hx &= 0x7fffffff;
+
+    /* purge off exception values */
+	if((hp|lp)==0) return (x*p)/(x*p); 	/* p = 0 */
+	if((hx>=0x7ff00000)||			/* x not finite */
+	  ((hp>=0x7ff00000)&&			/* p is NaN */
+	  (((hp-0x7ff00000)|lp)!=0)))
+	    return (x*p)/(x*p);
+
+
+	if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p);	/* now x < 2p */
+	if (((hx-hp)|(lx-lp))==0) return zero*x;
+	x  = fabs(x);
+	p  = fabs(p);
+	if (hp<0x00200000) {
+	    if(x+x>p) {
+		x-=p;
+		if(x+x>=p) x -= p;
+	    }
+	} else {
+	    p_half = 0.5*p;
+	    if(x>p_half) {
+		x-=p;
+		if(x>=p_half) x -= p;
+	    }
+	}
+	GET_HIGH_WORD(hx,x);
+	SET_HIGH_WORD(x,hx^sx);
+	return x;
+}
Index: /trunk/libc/src/msun/src/e_remainderf.c
===================================================================
--- /trunk/libc/src/msun/src/e_remainderf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_remainderf.c	(revision 2448)
@@ -0,0 +1,66 @@
+/* e_remainderf.c -- float version of e_remainder.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_remainderf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float zero = 0.0;
+
+
+float
+__ieee754_remainderf(float x, float p)
+{
+	int32_t hx,hp;
+	u_int32_t sx;
+	float p_half;
+
+	GET_FLOAT_WORD(hx,x);
+	GET_FLOAT_WORD(hp,p);
+	sx = hx&0x80000000;
+	hp &= 0x7fffffff;
+	hx &= 0x7fffffff;
+
+    /* purge off exception values */
+	if(hp==0) return (x*p)/(x*p);	 	/* p = 0 */
+	if((hx>=0x7f800000)||			/* x not finite */
+	  ((hp>0x7f800000)))			/* p is NaN */
+	    return (x*p)/(x*p);
+
+
+	if (hp<=0x7effffff) x = __ieee754_fmodf(x,p+p);	/* now x < 2p */
+	if ((hx-hp)==0) return zero*x;
+	x  = fabsf(x);
+	p  = fabsf(p);
+	if (hp<0x01000000) {
+	    if(x+x>p) {
+		x-=p;
+		if(x+x>=p) x -= p;
+	    }
+	} else {
+	    p_half = (float)0.5*p;
+	    if(x>p_half) {
+		x-=p;
+		if(x>=p_half) x -= p;
+	    }
+	}
+	GET_FLOAT_WORD(hx,x);
+	SET_FLOAT_WORD(x,hx^sx);
+	return x;
+}
Index: /trunk/libc/src/msun/src/e_scalb.c
===================================================================
--- /trunk/libc/src/msun/src/e_scalb.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_scalb.c	(revision 2448)
@@ -0,0 +1,49 @@
+
+/* @(#)e_scalb.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_scalb.c,v 1.12 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/*
+ * __ieee754_scalb(x, fn) is provide for
+ * passing various standard test suite. One
+ * should use scalbn() instead.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef _SCALB_INT
+double
+__ieee754_scalb(double x, int fn)
+#else
+double
+__ieee754_scalb(double x, double fn)
+#endif
+{
+#ifdef _SCALB_INT
+	return scalbn(x,fn);
+#else
+	if (isnan(x)||isnan(fn)) return x*fn;
+	if (!finite(fn)) {
+	    if(fn>0.0) return x*fn;
+	    else       return x/(-fn);
+	}
+	if (rint(fn)!=fn) return (fn-fn)/(fn-fn);
+	if ( fn > 65000.0) return scalbn(x, 65000);
+	if (-fn > 65000.0) return scalbn(x,-65000);
+	return scalbn(x,(int)fn);
+#endif
+}
Index: /trunk/libc/src/msun/src/e_scalbf.c
===================================================================
--- /trunk/libc/src/msun/src/e_scalbf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_scalbf.c	(revision 2448)
@@ -0,0 +1,45 @@
+/* e_scalbf.c -- float version of e_scalb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_scalbf.c,v 1.9 2004/07/09 10:01:10 das Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef _SCALB_INT
+float
+__ieee754_scalbf(float x, int fn)
+#else
+float
+__ieee754_scalbf(float x, float fn)
+#endif
+{
+#ifdef _SCALB_INT
+	return scalbnf(x,fn);
+#else
+	if ((isnanf)(x)||(isnanf)(fn)) return x*fn;
+	if (!finitef(fn)) {
+	    if(fn>(float)0.0) return x*fn;
+	    else       return x/(-fn);
+	}
+	if (rintf(fn)!=fn) return (fn-fn)/(fn-fn);
+	if ( fn > (float)65000.0) return scalbnf(x, 65000);
+	if (-fn > (float)65000.0) return scalbnf(x,-65000);
+	return scalbnf(x,(int)fn);
+#endif
+}
Index: /trunk/libc/src/msun/src/e_sinh.c
===================================================================
--- /trunk/libc/src/msun/src/e_sinh.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_sinh.c	(revision 2448)
@@ -0,0 +1,80 @@
+
+/* @(#)e_sinh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_sinh.c,v 1.9 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_sinh(x)
+ * Method :
+ * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ *	1. Replace x by |x| (sinh(-x) = -sinh(x)).
+ *	2.
+ *		                                    E + E/(E+1)
+ *	    0        <= x <= 22     :  sinh(x) := --------------, E=expm1(x)
+ *			       			        2
+ *
+ *	    22       <= x <= lnovft :  sinh(x) := exp(x)/2
+ *	    lnovft   <= x <= ln2ovft:  sinh(x) := exp(x/2)/2 * exp(x/2)
+ *	    ln2ovft  <  x	    :  sinh(x) := x*shuge (overflow)
+ *
+ * Special cases:
+ *	sinh(x) is |x| if x is +INF, -INF, or NaN.
+ *	only sinh(0)=0 is exact for finite x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double one = 1.0, shuge = 1.0e307;
+
+double
+__ieee754_sinh(double x)
+{
+	double t,w,h;
+	int32_t ix,jx;
+	u_int32_t lx;
+
+    /* High word of |x|. */
+	GET_HIGH_WORD(jx,x);
+	ix = jx&0x7fffffff;
+
+    /* x is INF or NaN */
+	if(ix>=0x7ff00000) return x+x;	
+
+	h = 0.5;
+	if (jx<0) h = -h;
+    /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+	if (ix < 0x40360000) {		/* |x|<22 */
+	    if (ix<0x3e300000) 		/* |x|<2**-28 */
+		if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+	    t = expm1(fabs(x));
+	    if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one));
+	    return h*(t+t/(t+one));
+	}
+
+    /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
+	if (ix < 0x40862E42)  return h*__ieee754_exp(fabs(x));
+
+    /* |x| in [log(maxdouble), overflowthresold] */
+	GET_LOW_WORD(lx,x);
+	if (ix<0x408633CE || ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) {
+	    w = __ieee754_exp(0.5*fabs(x));
+	    t = h*w;
+	    return t*w;
+	}
+
+    /* |x| > overflowthresold, sinh(x) overflow */
+	return x*shuge;
+}
Index: /trunk/libc/src/msun/src/e_sinhf.c
===================================================================
--- /trunk/libc/src/msun/src/e_sinhf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_sinhf.c	(revision 2448)
@@ -0,0 +1,61 @@
+/* e_sinhf.c -- float version of e_sinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_sinhf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float one = 1.0, shuge = 1.0e37;
+
+float
+__ieee754_sinhf(float x)
+{
+	float t,w,h;
+	int32_t ix,jx;
+
+	GET_FLOAT_WORD(jx,x);
+	ix = jx&0x7fffffff;
+
+    /* x is INF or NaN */
+	if(ix>=0x7f800000) return x+x;
+
+	h = 0.5;
+	if (jx<0) h = -h;
+    /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+	if (ix < 0x41b00000) {		/* |x|<22 */
+	    if (ix<0x31800000) 		/* |x|<2**-28 */
+		if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+	    t = expm1f(fabsf(x));
+	    if(ix<0x3f800000) return h*((float)2.0*t-t*t/(t+one));
+	    return h*(t+t/(t+one));
+	}
+
+    /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
+	if (ix < 0x42b17180)  return h*__ieee754_expf(fabsf(x));
+
+    /* |x| in [log(maxdouble), overflowthresold] */
+	if (ix<=0x42b2d4fc) {
+	    w = __ieee754_expf((float)0.5*fabsf(x));
+	    t = h*w;
+	    return t*w;
+	}
+
+    /* |x| > overflowthresold, sinh(x) overflow */
+	return x*shuge;
+}
Index: /trunk/libc/src/msun/src/e_sqrt.c
===================================================================
--- /trunk/libc/src/msun/src/e_sqrt.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_sqrt.c	(revision 2448)
@@ -0,0 +1,447 @@
+
+/* @(#)e_sqrt.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_sqrt.c,v 1.10 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __ieee754_sqrt(x)
+ * Return correctly rounded sqrt.
+ *           ------------------------------------------
+ *	     |  Use the hardware sqrt if you have one |
+ *           ------------------------------------------
+ * Method:
+ *   Bit by bit method using integer arithmetic. (Slow, but portable)
+ *   1. Normalization
+ *	Scale x to y in [1,4) with even powers of 2:
+ *	find an integer k such that  1 <= (y=x*2^(2k)) < 4, then
+ *		sqrt(x) = 2^k * sqrt(y)
+ *   2. Bit by bit computation
+ *	Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
+ *	     i							 0
+ *                                     i+1         2
+ *	    s  = 2*q , and	y  =  2   * ( y - q  ).		(1)
+ *	     i      i            i                 i
+ *
+ *	To compute q    from q , one checks whether
+ *		    i+1       i
+ *
+ *			      -(i+1) 2
+ *			(q + 2      ) <= y.			(2)
+ *     			  i
+ *							      -(i+1)
+ *	If (2) is false, then q   = q ; otherwise q   = q  + 2      .
+ *		 	       i+1   i             i+1   i
+ *
+ *	With some algebric manipulation, it is not difficult to see
+ *	that (2) is equivalent to
+ *                             -(i+1)
+ *			s  +  2       <= y			(3)
+ *			 i                i
+ *
+ *	The advantage of (3) is that s  and y  can be computed by
+ *				      i      i
+ *	the following recurrence formula:
+ *	    if (3) is false
+ *
+ *	    s     =  s  ,	y    = y   ;			(4)
+ *	     i+1      i		 i+1    i
+ *
+ *	    otherwise,
+ *                         -i                     -(i+1)
+ *	    s	  =  s  + 2  ,  y    = y  -  s  - 2  		(5)
+ *           i+1      i          i+1    i     i
+ *				
+ *	One may easily use induction to prove (4) and (5).
+ *	Note. Since the left hand side of (3) contain only i+2 bits,
+ *	      it does not necessary to do a full (53-bit) comparison
+ *	      in (3).
+ *   3. Final rounding
+ *	After generating the 53 bits result, we compute one more bit.
+ *	Together with the remainder, we can decide whether the
+ *	result is exact, bigger than 1/2ulp, or less than 1/2ulp
+ *	(it will never equal to 1/2ulp).
+ *	The rounding mode can be detected by checking whether
+ *	huge + tiny is equal to huge, and whether huge - tiny is
+ *	equal to huge for some floating point number "huge" and "tiny".
+ *		
+ * Special cases:
+ *	sqrt(+-0) = +-0 	... exact
+ *	sqrt(inf) = inf
+ *	sqrt(-ve) = NaN		... with invalid signal
+ *	sqrt(NaN) = NaN		... with invalid signal for signaling NaN
+ *
+ * Other methods : see the appended file at the end of the program below.
+ *---------------
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static	const double	one	= 1.0, tiny=1.0e-300;
+
+double
+__ieee754_sqrt(double x)
+{
+	double z;
+	int32_t sign = (int)0x80000000;
+	int32_t ix0,s0,q,m,t,i;
+	u_int32_t r,t1,s1,ix1,q1;
+
+	EXTRACT_WORDS(ix0,ix1,x);
+
+    /* take care of Inf and NaN */
+	if((ix0&0x7ff00000)==0x7ff00000) {			
+	    return x*x+x;		/* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+					   sqrt(-inf)=sNaN */
+	}
+    /* take care of zero */
+	if(ix0<=0) {
+	    if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
+	    else if(ix0<0)
+		return (x-x)/(x-x);		/* sqrt(-ve) = sNaN */
+	}
+    /* normalize x */
+	m = (ix0>>20);
+	if(m==0) {				/* subnormal x */
+	    while(ix0==0) {
+		m -= 21;
+		ix0 |= (ix1>>11); ix1 <<= 21;
+	    }
+	    for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
+	    m -= i-1;
+	    ix0 |= (ix1>>(32-i));
+	    ix1 <<= i;
+	}
+	m -= 1023;	/* unbias exponent */
+	ix0 = (ix0&0x000fffff)|0x00100000;
+	if(m&1){	/* odd m, double x to make it even */
+	    ix0 += ix0 + ((ix1&sign)>>31);
+	    ix1 += ix1;
+	}
+	m >>= 1;	/* m = [m/2] */
+
+    /* generate sqrt(x) bit by bit */
+	ix0 += ix0 + ((ix1&sign)>>31);
+	ix1 += ix1;
+	q = q1 = s0 = s1 = 0;	/* [q,q1] = sqrt(x) */
+	r = 0x00200000;		/* r = moving bit from right to left */
+
+	while(r!=0) {
+	    t = s0+r;
+	    if(t<=ix0) {
+		s0   = t+r;
+		ix0 -= t;
+		q   += r;
+	    }
+	    ix0 += ix0 + ((ix1&sign)>>31);
+	    ix1 += ix1;
+	    r>>=1;
+	}
+
+	r = sign;
+	while(r!=0) {
+	    t1 = s1+r;
+	    t  = s0;
+	    if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
+		s1  = t1+r;
+		if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
+		ix0 -= t;
+		if (ix1 < t1) ix0 -= 1;
+		ix1 -= t1;
+		q1  += r;
+	    }
+	    ix0 += ix0 + ((ix1&sign)>>31);
+	    ix1 += ix1;
+	    r>>=1;
+	}
+
+    /* use floating add to find out rounding direction */
+	if((ix0|ix1)!=0) {
+	    z = one-tiny; /* trigger inexact flag */
+	    if (z>=one) {
+	        z = one+tiny;
+	        if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
+		else if (z>one) {
+		    if (q1==(u_int32_t)0xfffffffe) q+=1;
+		    q1+=2;
+		} else
+	            q1 += (q1&1);
+	    }
+	}
+	ix0 = (q>>1)+0x3fe00000;
+	ix1 =  q1>>1;
+	if ((q&1)==1) ix1 |= sign;
+	ix0 += (m <<20);
+	INSERT_WORDS(z,ix0,ix1);
+	return z;
+}
+
+/*
+Other methods  (use floating-point arithmetic)
+-------------
+(This is a copy of a drafted paper by Prof W. Kahan
+and K.C. Ng, written in May, 1986)
+
+	Two algorithms are given here to implement sqrt(x)
+	(IEEE double precision arithmetic) in software.
+	Both supply sqrt(x) correctly rounded. The first algorithm (in
+	Section A) uses newton iterations and involves four divisions.
+	The second one uses reciproot iterations to avoid division, but
+	requires more multiplications. Both algorithms need the ability
+	to chop results of arithmetic operations instead of round them,
+	and the INEXACT flag to indicate when an arithmetic operation
+	is executed exactly with no roundoff error, all part of the
+	standard (IEEE 754-1985). The ability to perform shift, add,
+	subtract and logical AND operations upon 32-bit words is needed
+	too, though not part of the standard.
+
+A.  sqrt(x) by Newton Iteration
+
+   (1)	Initial approximation
+
+	Let x0 and x1 be the leading and the trailing 32-bit words of
+	a floating point number x (in IEEE double format) respectively
+
+	    1    11		     52				  ...widths
+	   ------------------------------------------------------
+	x: |s|	  e     |	      f				|
+	   ------------------------------------------------------
+	      msb    lsb  msb				      lsb ...order
+
+
+	     ------------------------  	     ------------------------
+	x0:  |s|   e    |    f1     |	 x1: |          f2           |
+	     ------------------------  	     ------------------------
+
+	By performing shifts and subtracts on x0 and x1 (both regarded
+	as integers), we obtain an 8-bit approximation of sqrt(x) as
+	follows.
+
+		k  := (x0>>1) + 0x1ff80000;
+		y0 := k - T1[31&(k>>15)].	... y ~ sqrt(x) to 8 bits
+	Here k is a 32-bit integer and T1[] is an integer array containing
+	correction terms. Now magically the floating value of y (y's
+	leading 32-bit word is y0, the value of its trailing word is 0)
+	approximates sqrt(x) to almost 8-bit.
+
+	Value of T1:
+	static int T1[32]= {
+	0,	1024,	3062,	5746,	9193,	13348,	18162,	23592,
+	29598,	36145,	43202,	50740,	58733,	67158,	75992,	85215,
+	83599,	71378,	60428,	50647,	41945,	34246,	27478,	21581,
+	16499,	12183,	8588,	5674,	3403,	1742,	661,	130,};
+
+    (2)	Iterative refinement
+
+	Apply Heron's rule three times to y, we have y approximates
+	sqrt(x) to within 1 ulp (Unit in the Last Place):
+
+		y := (y+x/y)/2		... almost 17 sig. bits
+		y := (y+x/y)/2		... almost 35 sig. bits
+		y := y-(y-x/y)/2	... within 1 ulp
+
+
+	Remark 1.
+	    Another way to improve y to within 1 ulp is:
+
+		y := (y+x/y)		... almost 17 sig. bits to 2*sqrt(x)
+		y := y - 0x00100006	... almost 18 sig. bits to sqrt(x)
+
+				2
+			    (x-y )*y
+		y := y + 2* ----------	...within 1 ulp
+			       2
+			     3y  + x
+
+
+	This formula has one division fewer than the one above; however,
+	it requires more multiplications and additions. Also x must be
+	scaled in advance to avoid spurious overflow in evaluating the
+	expression 3y*y+x. Hence it is not recommended uless division
+	is slow. If division is very slow, then one should use the
+	reciproot algorithm given in section B.
+
+    (3) Final adjustment
+
+	By twiddling y's last bit it is possible to force y to be
+	correctly rounded according to the prevailing rounding mode
+	as follows. Let r and i be copies of the rounding mode and
+	inexact flag before entering the square root program. Also we
+	use the expression y+-ulp for the next representable floating
+	numbers (up and down) of y. Note that y+-ulp = either fixed
+	point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+	mode.
+
+		I := FALSE;	... reset INEXACT flag I
+		R := RZ;	... set rounding mode to round-toward-zero
+		z := x/y;	... chopped quotient, possibly inexact
+		If(not I) then {	... if the quotient is exact
+		    if(z=y) {
+		        I := i;	 ... restore inexact flag
+		        R := r;  ... restore rounded mode
+		        return sqrt(x):=y.
+		    } else {
+			z := z - ulp;	... special rounding
+		    }
+		}
+		i := TRUE;		... sqrt(x) is inexact
+		If (r=RN) then z=z+ulp	... rounded-to-nearest
+		If (r=RP) then {	... round-toward-+inf
+		    y = y+ulp; z=z+ulp;
+		}
+		y := y+z;		... chopped sum
+		y0:=y0-0x00100000;	... y := y/2 is correctly rounded.
+	        I := i;	 		... restore inexact flag
+	        R := r;  		... restore rounded mode
+	        return sqrt(x):=y.
+		
+    (4)	Special cases
+
+	Square root of +inf, +-0, or NaN is itself;
+	Square root of a negative number is NaN with invalid signal.
+
+
+B.  sqrt(x) by Reciproot Iteration
+
+   (1)	Initial approximation
+
+	Let x0 and x1 be the leading and the trailing 32-bit words of
+	a floating point number x (in IEEE double format) respectively
+	(see section A). By performing shifs and subtracts on x0 and y0,
+	we obtain a 7.8-bit approximation of 1/sqrt(x) as follows.
+
+	    k := 0x5fe80000 - (x0>>1);
+	    y0:= k - T2[63&(k>>14)].	... y ~ 1/sqrt(x) to 7.8 bits
+
+	Here k is a 32-bit integer and T2[] is an integer array
+	containing correction terms. Now magically the floating
+	value of y (y's leading 32-bit word is y0, the value of
+	its trailing word y1 is set to zero) approximates 1/sqrt(x)
+	to almost 7.8-bit.
+
+	Value of T2:
+	static int T2[64]= {
+	0x1500,	0x2ef8,	0x4d67,	0x6b02,	0x87be,	0xa395,	0xbe7a,	0xd866,
+	0xf14a,	0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f,
+	0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d,
+	0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0,
+	0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989,
+	0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd,
+	0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e,
+	0x1527f,0x1334a,0x11051,0xe951,	0xbe01,	0x8e0d,	0x5924,	0x1edd,};
+
+    (2)	Iterative refinement
+
+	Apply Reciproot iteration three times to y and multiply the
+	result by x to get an approximation z that matches sqrt(x)
+	to about 1 ulp. To be exact, we will have
+		-1ulp < sqrt(x)-z<1.0625ulp.
+	
+	... set rounding mode to Round-to-nearest
+	   y := y*(1.5-0.5*x*y*y)	... almost 15 sig. bits to 1/sqrt(x)
+	   y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x)
+	... special arrangement for better accuracy
+	   z := x*y			... 29 bits to sqrt(x), with z*y<1
+	   z := z + 0.5*z*(1-z*y)	... about 1 ulp to sqrt(x)
+
+	Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that
+	(a) the term z*y in the final iteration is always less than 1;
+	(b) the error in the final result is biased upward so that
+		-1 ulp < sqrt(x) - z < 1.0625 ulp
+	    instead of |sqrt(x)-z|<1.03125ulp.
+
+    (3)	Final adjustment
+
+	By twiddling y's last bit it is possible to force y to be
+	correctly rounded according to the prevailing rounding mode
+	as follows. Let r and i be copies of the rounding mode and
+	inexact flag before entering the square root program. Also we
+	use the expression y+-ulp for the next representable floating
+	numbers (up and down) of y. Note that y+-ulp = either fixed
+	point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+	mode.
+
+	R := RZ;		... set rounding mode to round-toward-zero
+	switch(r) {
+	    case RN:		... round-to-nearest
+	       if(x<= z*(z-ulp)...chopped) z = z - ulp; else
+	       if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp;
+	       break;
+	    case RZ:case RM:	... round-to-zero or round-to--inf
+	       R:=RP;		... reset rounding mod to round-to-+inf
+	       if(x<z*z ... rounded up) z = z - ulp; else
+	       if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp;
+	       break;
+	    case RP:		... round-to-+inf
+	       if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else
+	       if(x>z*z ...chopped) z = z+ulp;
+	       break;
+	}
+
+	Remark 3. The above comparisons can be done in fixed point. For
+	example, to compare x and w=z*z chopped, it suffices to compare
+	x1 and w1 (the trailing parts of x and w), regarding them as
+	two's complement integers.
+
+	...Is z an exact square root?
+	To determine whether z is an exact square root of x, let z1 be the
+	trailing part of z, and also let x0 and x1 be the leading and
+	trailing parts of x.
+
+	If ((z1&0x03ffffff)!=0)	... not exact if trailing 26 bits of z!=0
+	    I := 1;		... Raise Inexact flag: z is not exact
+	else {
+	    j := 1 - [(x0>>20)&1]	... j = logb(x) mod 2
+	    k := z1 >> 26;		... get z's 25-th and 26-th
+					    fraction bits
+	    I := i or (k&j) or ((k&(j+j+1))!=(x1&3));
+	}
+	R:= r		... restore rounded mode
+	return sqrt(x):=z.
+
+	If multiplication is cheaper then the foregoing red tape, the
+	Inexact flag can be evaluated by
+
+	    I := i;
+	    I := (z*z!=x) or I.
+
+	Note that z*z can overwrite I; this value must be sensed if it is
+	True.
+
+	Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be
+	zero.
+
+		    --------------------
+		z1: |        f2        |
+		    --------------------
+		bit 31		   bit 0
+
+	Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd
+	or even of logb(x) have the following relations:
+
+	-------------------------------------------------
+	bit 27,26 of z1		bit 1,0 of x1	logb(x)
+	-------------------------------------------------
+	00			00		odd and even
+	01			01		even
+	10			10		odd
+	10			00		even
+	11			01		even
+	-------------------------------------------------
+
+    (4)	Special cases (see (4) of Section A).	
+
+ */
+
Index: /trunk/libc/src/msun/src/e_sqrtf.c
===================================================================
--- /trunk/libc/src/msun/src/e_sqrtf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/e_sqrtf.c	(revision 2448)
@@ -0,0 +1,90 @@
+/* e_sqrtf.c -- float version of e_sqrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_sqrtf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static	const float	one	= 1.0, tiny=1.0e-30;
+
+float
+__ieee754_sqrtf(float x)
+{
+	float z;
+	int32_t sign = (int)0x80000000;
+	int32_t ix,s,q,m,t,i;
+	u_int32_t r;
+
+	GET_FLOAT_WORD(ix,x);
+
+    /* take care of Inf and NaN */
+	if((ix&0x7f800000)==0x7f800000) {
+	    return x*x+x;		/* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+					   sqrt(-inf)=sNaN */
+	}
+    /* take care of zero */
+	if(ix<=0) {
+	    if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
+	    else if(ix<0)
+		return (x-x)/(x-x);		/* sqrt(-ve) = sNaN */
+	}
+    /* normalize x */
+	m = (ix>>23);
+	if(m==0) {				/* subnormal x */
+	    for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
+	    m -= i-1;
+	}
+	m -= 127;	/* unbias exponent */
+	ix = (ix&0x007fffff)|0x00800000;
+	if(m&1)	/* odd m, double x to make it even */
+	    ix += ix;
+	m >>= 1;	/* m = [m/2] */
+
+    /* generate sqrt(x) bit by bit */
+	ix += ix;
+	q = s = 0;		/* q = sqrt(x) */
+	r = 0x01000000;		/* r = moving bit from right to left */
+
+	while(r!=0) {
+	    t = s+r;
+	    if(t<=ix) {
+		s    = t+r;
+		ix  -= t;
+		q   += r;
+	    }
+	    ix += ix;
+	    r>>=1;
+	}
+
+    /* use floating add to find out rounding direction */
+	if(ix!=0) {
+	    z = one-tiny; /* trigger inexact flag */
+	    if (z>=one) {
+	        z = one+tiny;
+		if (z>one)
+		    q += 2;
+		else
+		    q += (q&1);
+	    }
+	}
+	ix = (q>>1)+0x3f000000;
+	ix += (m <<23);
+	SET_FLOAT_WORD(z,ix);
+	return z;
+}
Index: /trunk/libc/src/msun/src/k_cos.c
===================================================================
--- /trunk/libc/src/msun/src/k_cos.c	(revision 2448)
+++ /trunk/libc/src/msun/src/k_cos.c	(revision 2448)
@@ -0,0 +1,90 @@
+
+/* @(#)k_cos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_cos.c,v 1.8 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/*
+ * __kernel_cos( x,  y )
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ *
+ * Algorithm
+ *	1. Since cos(-x) = cos(x), we need only to consider positive x.
+ *	2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+ *	3. cos(x) is approximated by a polynomial of degree 14 on
+ *	   [0,pi/4]
+ *		  	                 4            14
+ *	   	cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+ *	   where the remez error is
+ *	
+ * 	|              2     4     6     8     10    12     14 |     -58
+ * 	|cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  )| <= 2
+ * 	|    					               |
+ *
+ * 	               4     6     8     10    12     14
+ *	4. let r = C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  , then
+ *	       cos(x) = 1 - x*x/2 + r
+ *	   since cos(x+y) ~ cos(x) - sin(x)*y
+ *			  ~ cos(x) - x*y,
+ *	   a correction term is necessary in cos(x) and hence
+ *		cos(x+y) = 1 - (x*x/2 - (r - x*y))
+ *	   For better accuracy when x > 0.3, let qx = |x|/4 with
+ *	   the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
+ *	   Then
+ *		cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
+ *	   Note that 1-qx and (x*x/2-qx) is EXACT here, and the
+ *	   magnitude of the latter is at least a quarter of x*x/2,
+ *	   thus, reducing the rounding error in the subtraction.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+C1  =  4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+C2  = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+C3  =  2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+C4  = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+C5  =  2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
+C6  = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+
+double
+__kernel_cos(double x, double y)
+{
+	double a,hz,z,r,qx;
+	int32_t ix;
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;			/* ix = |x|'s high word*/
+	if(ix<0x3e400000) {			/* if x < 2**27 */
+	    if(((int)x)==0) return one;		/* generate inexact */
+	}
+	z  = x*x;
+	r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+	if(ix < 0x3FD33333) 			/* if |x| < 0.3 */
+	    return one - (0.5*z - (z*r - x*y));
+	else {
+	    if(ix > 0x3fe90000) {		/* x > 0.78125 */
+		qx = 0.28125;
+	    } else {
+	        INSERT_WORDS(qx,ix-0x00200000,0);	/* x/4 */
+	    }
+	    hz = 0.5*z-qx;
+	    a  = one-qx;
+	    return a - (hz - (z*r-x*y));
+	}
+}
Index: /trunk/libc/src/msun/src/k_cosf.c
===================================================================
--- /trunk/libc/src/msun/src/k_cosf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/k_cosf.c	(revision 2448)
@@ -0,0 +1,57 @@
+/* k_cosf.c -- float version of k_cos.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_cosf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+one =  1.0000000000e+00, /* 0x3f800000 */
+C1  =  4.1666667908e-02, /* 0x3d2aaaab */
+C2  = -1.3888889225e-03, /* 0xbab60b61 */
+C3  =  2.4801587642e-05, /* 0x37d00d01 */
+C4  = -2.7557314297e-07, /* 0xb493f27c */
+C5  =  2.0875723372e-09, /* 0x310f74f6 */
+C6  = -1.1359647598e-11; /* 0xad47d74e */
+
+float
+__kernel_cosf(float x, float y)
+{
+	float a,hz,z,r,qx;
+	int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;			/* ix = |x|'s high word*/
+	if(ix<0x32000000) {			/* if x < 2**27 */
+	    if(((int)x)==0) return one;		/* generate inexact */
+	}
+	z  = x*x;
+	r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+	if(ix < 0x3e99999a) 			/* if |x| < 0.3 */
+	    return one - ((float)0.5*z - (z*r - x*y));
+	else {
+	    if(ix > 0x3f480000) {		/* x > 0.78125 */
+		qx = (float)0.28125;
+	    } else {
+	        SET_FLOAT_WORD(qx,ix-0x01000000);	/* x/4 */
+	    }
+	    hz = (float)0.5*z-qx;
+	    a  = one-qx;
+	    return a - (hz - (z*r-x*y));
+	}
+}
Index: /trunk/libc/src/msun/src/k_rem_pio2.c
===================================================================
--- /trunk/libc/src/msun/src/k_rem_pio2.c	(revision 2448)
+++ /trunk/libc/src/msun/src/k_rem_pio2.c	(revision 2448)
@@ -0,0 +1,305 @@
+
+/* @(#)k_rem_pio2.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_rem_pio2.c,v 1.7 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/*
+ * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+ * double x[],y[]; int e0,nx,prec; int ipio2[];
+ *
+ * __kernel_rem_pio2 return the last three digits of N with
+ *		y = x - N*pi/2
+ * so that |y| < pi/2.
+ *
+ * The method is to compute the integer (mod 8) and fraction parts of
+ * (2/pi)*x without doing the full multiplication. In general we
+ * skip the part of the product that are known to be a huge integer (
+ * more accurately, = 0 mod 8 ). Thus the number of operations are
+ * independent of the exponent of the input.
+ *
+ * (2/pi) is represented by an array of 24-bit integers in ipio2[].
+ *
+ * Input parameters:
+ * 	x[]	The input value (must be positive) is broken into nx
+ *		pieces of 24-bit integers in double precision format.
+ *		x[i] will be the i-th 24 bit of x. The scaled exponent
+ *		of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
+ *		match x's up to 24 bits.
+ *
+ *		Example of breaking a double positive z into x[0]+x[1]+x[2]:
+ *			e0 = ilogb(z)-23
+ *			z  = scalbn(z,-e0)
+ *		for i = 0,1,2
+ *			x[i] = floor(z)
+ *			z    = (z-x[i])*2**24
+ *
+ *
+ *	y[]	ouput result in an array of double precision numbers.
+ *		The dimension of y[] is:
+ *			24-bit  precision	1
+ *			53-bit  precision	2
+ *			64-bit  precision	2
+ *			113-bit precision	3
+ *		The actual value is the sum of them. Thus for 113-bit
+ *		precison, one may have to do something like:
+ *
+ *		long double t,w,r_head, r_tail;
+ *		t = (long double)y[2] + (long double)y[1];
+ *		w = (long double)y[0];
+ *		r_head = t+w;
+ *		r_tail = w - (r_head - t);
+ *
+ *	e0	The exponent of x[0]
+ *
+ *	nx	dimension of x[]
+ *
+ *  	prec	an integer indicating the precision:
+ *			0	24  bits (single)
+ *			1	53  bits (double)
+ *			2	64  bits (extended)
+ *			3	113 bits (quad)
+ *
+ *	ipio2[]
+ *		integer array, contains the (24*i)-th to (24*i+23)-th
+ *		bit of 2/pi after binary point. The corresponding
+ *		floating value is
+ *
+ *			ipio2[i] * 2^(-24(i+1)).
+ *
+ * External function:
+ *	double scalbn(), floor();
+ *
+ *
+ * Here is the description of some local variables:
+ *
+ * 	jk	jk+1 is the initial number of terms of ipio2[] needed
+ *		in the computation. The recommended value is 2,3,4,
+ *		6 for single, double, extended,and quad.
+ *
+ * 	jz	local integer variable indicating the number of
+ *		terms of ipio2[] used.
+ *
+ *	jx	nx - 1
+ *
+ *	jv	index for pointing to the suitable ipio2[] for the
+ *		computation. In general, we want
+ *			( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
+ *		is an integer. Thus
+ *			e0-3-24*jv >= 0 or (e0-3)/24 >= jv
+ *		Hence jv = max(0,(e0-3)/24).
+ *
+ *	jp	jp+1 is the number of terms in PIo2[] needed, jp = jk.
+ *
+ * 	q[]	double array with integral value, representing the
+ *		24-bits chunk of the product of x and 2/pi.
+ *
+ *	q0	the corresponding exponent of q[0]. Note that the
+ *		exponent for q[i] would be q0-24*i.
+ *
+ *	PIo2[]	double precision array, obtained by cutting pi/2
+ *		into 24 bits chunks.
+ *
+ *	f[]	ipio2[] in floating point
+ *
+ *	iq[]	integer array by breaking up q[] in 24-bits chunk.
+ *
+ *	fq[]	final product of x*(2/pi) in fq[0],..,fq[jk]
+ *
+ *	ih	integer. If >0 it indicates q[] is >= 0.5, hence
+ *		it also indicates the *sign* of the result.
+ *
+ */
+
+
+/*
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
+
+static const double PIo2[] = {
+  1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
+  7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
+  5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
+  3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
+  1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
+  1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
+  2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
+  2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
+};
+
+static const double			
+zero   = 0.0,
+one    = 1.0,
+two24   =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+twon24  =  5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
+
+	int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2)
+{
+	int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+	double z,fw,f[20],fq[20],q[20];
+
+    /* initialize jk*/
+	jk = init_jk[prec];
+	jp = jk;
+
+    /* determine jx,jv,q0, note that 3>q0 */
+	jx =  nx-1;
+	jv = (e0-3)/24; if(jv<0) jv=0;
+	q0 =  e0-24*(jv+1);
+
+    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+	j = jv-jx; m = jx+jk;
+	for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
+
+    /* compute q[0],q[1],...q[jk] */
+	for (i=0;i<=jk;i++) {
+	    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+	}
+
+	jz = jk;
+recompute:
+    /* distill q[] into iq[] reversingly */
+	for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+	    fw    =  (double)((int32_t)(twon24* z));
+	    iq[i] =  (int32_t)(z-two24*fw);
+	    z     =  q[j-1]+fw;
+	}
+
+    /* compute n */
+	z  = scalbn(z,q0);		/* actual value of z */
+	z -= 8.0*floor(z*0.125);		/* trim off integer >= 8 */
+	n  = (int32_t) z;
+	z -= (double)n;
+	ih = 0;
+	if(q0>0) {	/* need iq[jz-1] to determine n */
+	    i  = (iq[jz-1]>>(24-q0)); n += i;
+	    iq[jz-1] -= i<<(24-q0);
+	    ih = iq[jz-1]>>(23-q0);
+	}
+	else if(q0==0) ih = iq[jz-1]>>23;
+	else if(z>=0.5) ih=2;
+
+	if(ih>0) {	/* q > 0.5 */
+	    n += 1; carry = 0;
+	    for(i=0;i<jz ;i++) {	/* compute 1-q */
+		j = iq[i];
+		if(carry==0) {
+		    if(j!=0) {
+			carry = 1; iq[i] = 0x1000000- j;
+		    }
+		} else  iq[i] = 0xffffff - j;
+	    }
+	    if(q0>0) {		/* rare case: chance is 1 in 12 */
+	        switch(q0) {
+	        case 1:
+	    	   iq[jz-1] &= 0x7fffff; break;
+	    	case 2:
+	    	   iq[jz-1] &= 0x3fffff; break;
+	        }
+	    }
+	    if(ih==2) {
+		z = one - z;
+		if(carry!=0) z -= scalbn(one,q0);
+	    }
+	}
+
+    /* check if recomputation is needed */
+	if(z==zero) {
+	    j = 0;
+	    for (i=jz-1;i>=jk;i--) j |= iq[i];
+	    if(j==0) { /* need recomputation */
+		for(k=1;iq[jk-k]==0;k++);   /* k = no. of terms needed */
+
+		for(i=jz+1;i<=jz+k;i++) {   /* add q[jz+1] to q[jz+k] */
+		    f[jx+i] = (double) ipio2[jv+i];
+		    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+		    q[i] = fw;
+		}
+		jz += k;
+		goto recompute;
+	    }
+	}
+
+    /* chop off zero terms */
+	if(z==0.0) {
+	    jz -= 1; q0 -= 24;
+	    while(iq[jz]==0) { jz--; q0-=24;}
+	} else { /* break z into 24-bit if necessary */
+	    z = scalbn(z,-q0);
+	    if(z>=two24) {
+		fw = (double)((int32_t)(twon24*z));
+		iq[jz] = (int32_t)(z-two24*fw);
+		jz += 1; q0 += 24;
+		iq[jz] = (int32_t) fw;
+	    } else iq[jz] = (int32_t) z ;
+	}
+
+    /* convert integer "bit" chunk to floating-point value */
+	fw = scalbn(one,q0);
+	for(i=jz;i>=0;i--) {
+	    q[i] = fw*(double)iq[i]; fw*=twon24;
+	}
+
+    /* compute PIo2[0,...,jp]*q[jz,...,0] */
+	for(i=jz;i>=0;i--) {
+	    for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+	    fq[jz-i] = fw;
+	}
+
+    /* compress fq[] into y[] */
+	switch(prec) {
+	    case 0:
+		fw = 0.0;
+		for (i=jz;i>=0;i--) fw += fq[i];
+		y[0] = (ih==0)? fw: -fw;
+		break;
+	    case 1:
+	    case 2:
+		fw = 0.0;
+		for (i=jz;i>=0;i--) fw += fq[i];
+		y[0] = (ih==0)? fw: -fw;
+		fw = fq[0]-fw;
+		for (i=1;i<=jz;i++) fw += fq[i];
+		y[1] = (ih==0)? fw: -fw;
+		break;
+	    case 3:	/* painful */
+		for (i=jz;i>0;i--) {
+		    fw      = fq[i-1]+fq[i];
+		    fq[i]  += fq[i-1]-fw;
+		    fq[i-1] = fw;
+		}
+		for (i=jz;i>1;i--) {
+		    fw      = fq[i-1]+fq[i];
+		    fq[i]  += fq[i-1]-fw;
+		    fq[i-1] = fw;
+		}
+		for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+		if(ih==0) {
+		    y[0] =  fq[0]; y[1] =  fq[1]; y[2] =  fw;
+		} else {
+		    y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+		}
+	}
+	return n&7;
+}
Index: /trunk/libc/src/msun/src/k_rem_pio2f.c
===================================================================
--- /trunk/libc/src/msun/src/k_rem_pio2f.c	(revision 2448)
+++ /trunk/libc/src/msun/src/k_rem_pio2f.c	(revision 2448)
@@ -0,0 +1,197 @@
+/* k_rem_pio2f.c -- float version of k_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_rem_pio2f.c,v 1.7 2005/04/05 23:27:47 das Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+/* In the float version, the input parameter x contains 8 bit
+   integers, not 24 bit integers.  113 bit precision is not supported.  */
+
+static const int init_jk[] = {4,7,9}; /* initial value for jk */
+
+static const float PIo2[] = {
+  1.5703125000e+00, /* 0x3fc90000 */
+  4.5776367188e-04, /* 0x39f00000 */
+  2.5987625122e-05, /* 0x37da0000 */
+  7.5437128544e-08, /* 0x33a20000 */
+  6.0026650317e-11, /* 0x2e840000 */
+  7.3896444519e-13, /* 0x2b500000 */
+  5.3845816694e-15, /* 0x27c20000 */
+  5.6378512969e-18, /* 0x22d00000 */
+  8.3009228831e-20, /* 0x1fc40000 */
+  3.2756352257e-22, /* 0x1bc60000 */
+  6.3331015649e-25, /* 0x17440000 */
+};
+
+static const float
+zero   = 0.0,
+one    = 1.0,
+two8   =  2.5600000000e+02, /* 0x43800000 */
+twon8  =  3.9062500000e-03; /* 0x3b800000 */
+
+	int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const int32_t *ipio2)
+{
+	int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+	float z,fw,f[20],fq[20],q[20];
+
+    /* initialize jk*/
+	jk = init_jk[prec];
+	jp = jk;
+
+    /* determine jx,jv,q0, note that 3>q0 */
+	jx =  nx-1;
+	jv = (e0-3)/8; if(jv<0) jv=0;
+	q0 =  e0-8*(jv+1);
+
+    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+	j = jv-jx; m = jx+jk;
+	for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];
+
+    /* compute q[0],q[1],...q[jk] */
+	for (i=0;i<=jk;i++) {
+	    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+	}
+
+	jz = jk;
+recompute:
+    /* distill q[] into iq[] reversingly */
+	for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+	    fw    =  (float)((int32_t)(twon8* z));
+	    iq[i] =  (int32_t)(z-two8*fw);
+	    z     =  q[j-1]+fw;
+	}
+
+    /* compute n */
+	z  = scalbnf(z,q0);		/* actual value of z */
+	z -= (float)8.0*floorf(z*(float)0.125);	/* trim off integer >= 8 */
+	n  = (int32_t) z;
+	z -= (float)n;
+	ih = 0;
+	if(q0>0) {	/* need iq[jz-1] to determine n */
+	    i  = (iq[jz-1]>>(8-q0)); n += i;
+	    iq[jz-1] -= i<<(8-q0);
+	    ih = iq[jz-1]>>(7-q0);
+	}
+	else if(q0==0) ih = iq[jz-1]>>7;
+	else if(z>=(float)0.5) ih=2;
+
+	if(ih>0) {	/* q > 0.5 */
+	    n += 1; carry = 0;
+	    for(i=0;i<jz ;i++) {	/* compute 1-q */
+		j = iq[i];
+		if(carry==0) {
+		    if(j!=0) {
+			carry = 1; iq[i] = 0x100- j;
+		    }
+		} else  iq[i] = 0xff - j;
+	    }
+	    if(q0>0) {		/* rare case: chance is 1 in 12 */
+	        switch(q0) {
+	        case 1:
+	    	   iq[jz-1] &= 0x7f; break;
+	    	case 2:
+	    	   iq[jz-1] &= 0x3f; break;
+	        }
+	    }
+	    if(ih==2) {
+		z = one - z;
+		if(carry!=0) z -= scalbnf(one,q0);
+	    }
+	}
+
+    /* check if recomputation is needed */
+	if(z==zero) {
+	    j = 0;
+	    for (i=jz-1;i>=jk;i--) j |= iq[i];
+	    if(j==0) { /* need recomputation */
+		for(k=1;iq[jk-k]==0;k++);   /* k = no. of terms needed */
+
+		for(i=jz+1;i<=jz+k;i++) {   /* add q[jz+1] to q[jz+k] */
+		    f[jx+i] = (float) ipio2[jv+i];
+		    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+		    q[i] = fw;
+		}
+		jz += k;
+		goto recompute;
+	    }
+	}
+
+    /* chop off zero terms */
+	if(z==(float)0.0) {
+	    jz -= 1; q0 -= 8;
+	    while(iq[jz]==0) { jz--; q0-=8;}
+	} else { /* break z into 8-bit if necessary */
+	    z = scalbnf(z,-q0);
+	    if(z>=two8) {
+		fw = (float)((int32_t)(twon8*z));
+		iq[jz] = (int32_t)(z-two8*fw);
+		jz += 1; q0 += 8;
+		iq[jz] = (int32_t) fw;
+	    } else iq[jz] = (int32_t) z ;
+	}
+
+    /* convert integer "bit" chunk to floating-point value */
+	fw = scalbnf(one,q0);
+	for(i=jz;i>=0;i--) {
+	    q[i] = fw*(float)iq[i]; fw*=twon8;
+	}
+
+    /* compute PIo2[0,...,jp]*q[jz,...,0] */
+	for(i=jz;i>=0;i--) {
+	    for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+	    fq[jz-i] = fw;
+	}
+
+    /* compress fq[] into y[] */
+	switch(prec) {
+	    case 0:
+		fw = 0.0;
+		for (i=jz;i>=0;i--) fw += fq[i];
+		y[0] = (ih==0)? fw: -fw;
+		break;
+	    case 1:
+	    case 2:
+		fw = 0.0;
+		for (i=jz;i>=0;i--) fw += fq[i];
+		y[0] = (ih==0)? fw: -fw;
+		fw = fq[0]-fw;
+		for (i=1;i<=jz;i++) fw += fq[i];
+		y[1] = (ih==0)? fw: -fw;
+		break;
+	    case 3:	/* painful */
+		for (i=jz;i>0;i--) {
+		    fw      = fq[i-1]+fq[i];
+		    fq[i]  += fq[i-1]-fw;
+		    fq[i-1] = fw;
+		}
+		for (i=jz;i>1;i--) {
+		    fw      = fq[i-1]+fq[i];
+		    fq[i]  += fq[i-1]-fw;
+		    fq[i-1] = fw;
+		}
+		for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+		if(ih==0) {
+		    y[0] =  fq[0]; y[1] =  fq[1]; y[2] =  fw;
+		} else {
+		    y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+		}
+	}
+	return n&7;
+}
Index: /trunk/libc/src/msun/src/k_sin.c
===================================================================
--- /trunk/libc/src/msun/src/k_sin.c	(revision 2448)
+++ /trunk/libc/src/msun/src/k_sin.c	(revision 2448)
@@ -0,0 +1,73 @@
+
+/* @(#)k_sin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_sin.c,v 1.8 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __kernel_sin( x, y, iy)
+ * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
+ *
+ * Algorithm
+ *	1. Since sin(-x) = -sin(x), we need only to consider positive x.
+ *	2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
+ *	3. sin(x) is approximated by a polynomial of degree 13 on
+ *	   [0,pi/4]
+ *		  	         3            13
+ *	   	sin(x) ~ x + S1*x + ... + S6*x
+ *	   where
+ *	
+ * 	|sin(x)         2     4     6     8     10     12  |     -58
+ * 	|----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x  +S6*x   )| <= 2
+ * 	|  x 					           |
+ *
+ *	4. sin(x+y) = sin(x) + sin'(x')*y
+ *		    ~ sin(x) + (1-x*x/2)*y
+ *	   For better accuracy, let
+ *		     3      2      2      2      2
+ *		r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+ *	   then                   3    2
+ *		sin(x) = x + (S1*x + (x *(r-y/2)+y))
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+S2  =  8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+S3  = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+S4  =  2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+S5  = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
+S6  =  1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
+
+double
+__kernel_sin(double x, double y, int iy)
+{
+	double z,r,v;
+	int32_t ix;
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;			/* high word of x */
+	if(ix<0x3e400000)			/* |x| < 2**-27 */
+	   {if((int)x==0) return x;}		/* generate inexact */
+	z	=  x*x;
+	v	=  z*x;
+	r	=  S2+z*(S3+z*(S4+z*(S5+z*S6)));
+	if(iy==0) return x+v*(S1+z*r);
+	else      return x-((z*(half*y-v*r)-y)-v*S1);
+}
Index: /trunk/libc/src/msun/src/k_sinf.c
===================================================================
--- /trunk/libc/src/msun/src/k_sinf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/k_sinf.c	(revision 2448)
@@ -0,0 +1,47 @@
+/* k_sinf.c -- float version of k_sin.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_sinf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+half =  5.0000000000e-01,/* 0x3f000000 */
+S1  = -1.6666667163e-01, /* 0xbe2aaaab */
+S2  =  8.3333337680e-03, /* 0x3c088889 */
+S3  = -1.9841270114e-04, /* 0xb9500d01 */
+S4  =  2.7557314297e-06, /* 0x3638ef1b */
+S5  = -2.5050759689e-08, /* 0xb2d72f34 */
+S6  =  1.5896910177e-10; /* 0x2f2ec9d3 */
+
+float
+__kernel_sinf(float x, float y, int iy)
+{
+	float z,r,v;
+	int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;			/* high word of x */
+	if(ix<0x32000000)			/* |x| < 2**-27 */
+	   {if((int)x==0) return x;}		/* generate inexact */
+	z	=  x*x;
+	v	=  z*x;
+	r	=  S2+z*(S3+z*(S4+z*(S5+z*S6)));
+	if(iy==0) return x+v*(S1+z*r);
+	else      return x-((z*(half*y-v*r)-y)-v*S1);
+}
Index: /trunk/libc/src/msun/src/k_tan.c
===================================================================
--- /trunk/libc/src/msun/src/k_tan.c	(revision 2448)
+++ /trunk/libc/src/msun/src/k_tan.c	(revision 2448)
@@ -0,0 +1,155 @@
+/* @(#)k_tan.c 1.5 04/04/22 SMI */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* INDENT OFF */
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_tan.c,v 1.10 2005/02/04 18:26:06 das Exp $";
+#endif
+
+/* __kernel_tan( x, y, k )
+ * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned.
+ *
+ * Algorithm
+ *	1. Since tan(-x) = -tan(x), we need only to consider positive x.
+ *	2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
+ *	3. tan(x) is approximated by a odd polynomial of degree 27 on
+ *	   [0,0.67434]
+ *		  	         3             27
+ *	   	tan(x) ~ x + T1*x + ... + T13*x
+ *	   where
+ *
+ * 	        |tan(x)         2     4            26   |     -59.2
+ * 	        |----- - (1+T1*x +T2*x +.... +T13*x    )| <= 2
+ * 	        |  x 					|
+ *
+ *	   Note: tan(x+y) = tan(x) + tan'(x)*y
+ *		          ~ tan(x) + (1+x*x)*y
+ *	   Therefore, for better accuracy in computing tan(x+y), let
+ *		     3      2      2       2       2
+ *		r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+ *	   then
+ *		 		    3    2
+ *		tan(x+y) = x + (T1*x + (x *(r+y)+y))
+ *
+ *      4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
+ *		tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+ *		       = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+ */
+
+#include "math.h"
+#include "math_private.h"
+static const double xxx[] = {
+		 3.33333333333334091986e-01,	/* 3FD55555, 55555563 */
+		 1.33333333333201242699e-01,	/* 3FC11111, 1110FE7A */
+		 5.39682539762260521377e-02,	/* 3FABA1BA, 1BB341FE */
+		 2.18694882948595424599e-02,	/* 3F9664F4, 8406D637 */
+		 8.86323982359930005737e-03,	/* 3F8226E3, E96E8493 */
+		 3.59207910759131235356e-03,	/* 3F6D6D22, C9560328 */
+		 1.45620945432529025516e-03,	/* 3F57DBC8, FEE08315 */
+		 5.88041240820264096874e-04,	/* 3F4344D8, F2F26501 */
+		 2.46463134818469906812e-04,	/* 3F3026F7, 1A8D1068 */
+		 7.81794442939557092300e-05,	/* 3F147E88, A03792A6 */
+		 7.14072491382608190305e-05,	/* 3F12B80F, 32F0A7E9 */
+		-1.85586374855275456654e-05,	/* BEF375CB, DB605373 */
+		 2.59073051863633712884e-05,	/* 3EFB2A70, 74BF7AD4 */
+/* one */	 1.00000000000000000000e+00,	/* 3FF00000, 00000000 */
+/* pio4 */	 7.85398163397448278999e-01,	/* 3FE921FB, 54442D18 */
+/* pio4lo */	 3.06161699786838301793e-17	/* 3C81A626, 33145C07 */
+};
+#define	one	xxx[13]
+#define	pio4	xxx[14]
+#define	pio4lo	xxx[15]
+#define	T	xxx
+/* INDENT ON */
+
+double
+__kernel_tan(double x, double y, int iy) {
+	double z, r, v, w, s;
+	int32_t ix, hx;
+
+	GET_HIGH_WORD(hx,x);
+	ix = hx & 0x7fffffff;			/* high word of |x| */
+	if (ix < 0x3e300000) {			/* x < 2**-28 */
+		if ((int) x == 0) {		/* generate inexact */
+			u_int32_t low;
+			GET_LOW_WORD(low,x);
+			if (((ix | low) | (iy + 1)) == 0)
+				return one / fabs(x);
+			else {
+				if (iy == 1)
+					return x;
+				else {	/* compute -1 / (x+y) carefully */
+					double a, t;
+
+					z = w = x + y;
+					SET_LOW_WORD(z, 0);
+					v = y - (z - x);
+					t = a = -one / w;
+					SET_LOW_WORD(t, 0);
+					s = one + t * z;
+					return t + a * (s + t * v);
+				}
+			}
+		}
+	}
+	if (ix >= 0x3FE59428) {	/* |x| >= 0.6744 */
+		if (hx < 0) {
+			x = -x;
+			y = -y;
+		}
+		z = pio4 - x;
+		w = pio4lo - y;
+		x = z + w;
+		y = 0.0;
+	}
+	z = x * x;
+	w = z * z;
+	/*
+	 * Break x^5*(T[1]+x^2*T[2]+...) into
+	 * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+	 * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+	 */
+	r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] +
+		w * T[11]))));
+	v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] +
+		w * T[12])))));
+	s = z * x;
+	r = y + z * (s * (r + v) + y);
+	r += T[0] * s;
+	w = x + r;
+	if (ix >= 0x3FE59428) {
+		v = (double) iy;
+		return (double) (1 - ((hx >> 30) & 2)) *
+			(v - 2.0 * (x - (w * w / (w + v) - r)));
+	}
+	if (iy == 1)
+		return w;
+	else {
+		/*
+		 * if allow error up to 2 ulp, simply return
+		 * -1.0 / (x+r) here
+		 */
+		/* compute -1.0 / (x+r) accurately */
+		double a, t;
+		z = w;
+		SET_LOW_WORD(z,0);
+		v = r - (z - x);	/* z+v = r+x */
+		t = a = -1.0 / w;	/* a = -1.0/w */
+		SET_LOW_WORD(t,0);
+		s = 1.0 + t * z;
+		return t + a * (s + t * v);
+	}
+}
Index: /trunk/libc/src/msun/src/k_tanf.c
===================================================================
--- /trunk/libc/src/msun/src/k_tanf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/k_tanf.c	(revision 2448)
@@ -0,0 +1,110 @@
+/* k_tanf.c -- float version of k_tan.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/k_tanf.c,v 1.8 2004/06/02 04:39:44 das Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+static const float
+one   =  1.0000000000e+00, /* 0x3f800000 */
+pio4  =  7.8539812565e-01, /* 0x3f490fda */
+pio4lo=  3.7748947079e-08, /* 0x33222168 */
+T[] =  {
+  3.3333334327e-01, /* 0x3eaaaaab */
+  1.3333334029e-01, /* 0x3e088889 */
+  5.3968254477e-02, /* 0x3d5d0dd1 */
+  2.1869488060e-02, /* 0x3cb327a4 */
+  8.8632395491e-03, /* 0x3c11371f */
+  3.5920790397e-03, /* 0x3b6b6916 */
+  1.4562094584e-03, /* 0x3abede48 */
+  5.8804126456e-04, /* 0x3a1a26c8 */
+  2.4646313977e-04, /* 0x398137b9 */
+  7.8179444245e-05, /* 0x38a3f445 */
+  7.1407252108e-05, /* 0x3895c07a */
+ -1.8558637748e-05, /* 0xb79bae5f */
+  2.5907305826e-05, /* 0x37d95384 */
+};
+
+float
+__kernel_tanf(float x, float y, int iy)
+{
+	float z,r,v,w,s;
+	int32_t ix,hx;
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;	/* high word of |x| */
+	if(ix<0x31800000) {			/* x < 2**-28 */
+		if ((int) x == 0) {		/* generate inexact */
+			if ((ix | (iy + 1)) == 0)
+				return one / fabsf(x);
+			else {
+				if (iy == 1)
+					return x;
+				else {	/* compute -1 / (x+y) carefully */
+					double a, t;
+
+					z = w = x + y;
+					GET_FLOAT_WORD(ix, z);
+					SET_FLOAT_WORD(z, ix & 0xfffff000);
+					v = y - (z - x);
+					t = a = -one / w;
+					GET_FLOAT_WORD(ix, t);
+					SET_FLOAT_WORD(t, ix & 0xfffff000);
+					s = one + t * z;
+					return t + a * (s + t * v);
+				}
+			}
+		}
+	}
+	if(ix>=0x3f2ca140) { 			/* |x|>=0.6744 */
+	    if(hx<0) {x = -x; y = -y;}
+	    z = pio4-x;
+	    w = pio4lo-y;
+	    x = z+w; y = 0.0;
+	}
+	z	=  x*x;
+	w 	=  z*z;
+    /* Break x^5*(T[1]+x^2*T[2]+...) into
+     *	  x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+     *	  x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+     */
+	r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
+	v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
+	s = z*x;
+	r = y + z*(s*(r+v)+y);
+	r += T[0]*s;
+	w = x+r;
+	if(ix>=0x3f2ca140) {
+	    v = (float)iy;
+	    return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r)));
+	}
+	if(iy==1) return w;
+	else {		/* if allow error up to 2 ulp,
+			   simply return -1.0/(x+r) here */
+     /*  compute -1.0/(x+r) accurately */
+	    float a,t;
+	    int32_t i;
+	    z  = w;
+	    GET_FLOAT_WORD(i,z);
+	    SET_FLOAT_WORD(z,i&0xfffff000);
+	    v  = r-(z - x); 	/* z+v = r+x */
+	    t = a  = -(float)1.0/w;	/* a = -1.0/w */
+	    GET_FLOAT_WORD(i,t);
+	    SET_FLOAT_WORD(t,i&0xfffff000);
+	    s  = (float)1.0+t*z;
+	    return t+a*(s+t*v);
+	}
+}
Index: /trunk/libc/src/msun/src/math_private.h
===================================================================
--- /trunk/libc/src/msun/src/math_private.h	(revision 2448)
+++ /trunk/libc/src/msun/src/math_private.h	(revision 2448)
@@ -0,0 +1,265 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $FreeBSD: src/lib/msun/src/math_private.h,v 1.17 2005/02/04 20:05:39 das Exp $
+ */
+
+#ifndef _MATH_PRIVATE_H_
+#define	_MATH_PRIVATE_H_
+
+#include <sys/types.h>
+#include <machine/endian.h>
+
+/*
+ * The original fdlibm code used statements like:
+ *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
+ *	ix0 = *(n0+(int*)&x);			* high word of x *
+ *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
+ * to dig two 32 bit words out of the 64 bit IEEE floating point
+ * value.  That is non-ANSI, and, moreover, the gcc instruction
+ * scheduler gets it wrong.  We instead use the following macros.
+ * Unlike the original code, we determine the endianness at compile
+ * time, not at run time; I don't see much benefit to selecting
+ * endianness at run time.
+ */
+
+/*
+ * A union which permits us to convert between a double and two 32 bit
+ * ints.
+ */
+
+#if BYTE_ORDER == BIG_ENDIAN
+
+typedef union
+{
+  double value;
+  struct
+  {
+    u_int32_t msw;
+    u_int32_t lsw;
+  } parts;
+} ieee_double_shape_type;
+
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+typedef union
+{
+  double value;
+  struct
+  {
+    u_int32_t lsw;
+    u_int32_t msw;
+  } parts;
+} ieee_double_shape_type;
+
+#endif
+
+/* Get two 32 bit ints from a double.  */
+
+#define EXTRACT_WORDS(ix0,ix1,d)				\
+do {								\
+  ieee_double_shape_type ew_u;					\
+  ew_u.value = (d);						\
+  (ix0) = ew_u.parts.msw;					\
+  (ix1) = ew_u.parts.lsw;					\
+} while (0)
+
+/* Get the more significant 32 bit int from a double.  */
+
+#define GET_HIGH_WORD(i,d)					\
+do {								\
+  ieee_double_shape_type gh_u;					\
+  gh_u.value = (d);						\
+  (i) = gh_u.parts.msw;						\
+} while (0)
+
+/* Get the less significant 32 bit int from a double.  */
+
+#define GET_LOW_WORD(i,d)					\
+do {								\
+  ieee_double_shape_type gl_u;					\
+  gl_u.value = (d);						\
+  (i) = gl_u.parts.lsw;						\
+} while (0)
+
+/* Set a double from two 32 bit ints.  */
+
+#define INSERT_WORDS(d,ix0,ix1)					\
+do {								\
+  ieee_double_shape_type iw_u;					\
+  iw_u.parts.msw = (ix0);					\
+  iw_u.parts.lsw = (ix1);					\
+  (d) = iw_u.value;						\
+} while (0)
+
+/* Set the more significant 32 bits of a double from an int.  */
+
+#define SET_HIGH_WORD(d,v)					\
+do {								\
+  ieee_double_shape_type sh_u;					\
+  sh_u.value = (d);						\
+  sh_u.parts.msw = (v);						\
+  (d) = sh_u.value;						\
+} while (0)
+
+/* Set the less significant 32 bits of a double from an int.  */
+
+#define SET_LOW_WORD(d,v)					\
+do {								\
+  ieee_double_shape_type sl_u;					\
+  sl_u.value = (d);						\
+  sl_u.parts.lsw = (v);						\
+  (d) = sl_u.value;						\
+} while (0)
+
+/*
+ * A union which permits us to convert between a float and a 32 bit
+ * int.
+ */
+
+typedef union
+{
+  float value;
+  /* FIXME: Assumes 32 bit int.  */
+  unsigned int word;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float.  */
+
+#define GET_FLOAT_WORD(i,d)					\
+do {								\
+  ieee_float_shape_type gf_u;					\
+  gf_u.value = (d);						\
+  (i) = gf_u.word;						\
+} while (0)
+
+/* Set a float from a 32 bit int.  */
+
+#define SET_FLOAT_WORD(d,i)					\
+do {								\
+  ieee_float_shape_type sf_u;					\
+  sf_u.word = (i);						\
+  (d) = sf_u.value;						\
+} while (0)
+
+/*
+ * ieee style elementary functions
+ *
+ * We rename functions here to improve other sources' diffability
+ * against fdlibm.
+ */
+#define	__ieee754_sqrt	sqrt
+#define	__ieee754_acos	acos
+#define	__ieee754_acosh	acosh
+#define	__ieee754_log	log
+#define	__ieee754_atanh	atanh
+#define	__ieee754_asin	asin
+#define	__ieee754_atan2	atan2
+#define	__ieee754_exp	exp
+#define	__ieee754_cosh	cosh
+#define	__ieee754_fmod	fmod
+#define	__ieee754_pow	pow
+#define	__ieee754_lgamma lgamma
+#define	__ieee754_gamma	gamma
+#define	__ieee754_lgamma_r lgamma_r
+#define	__ieee754_gamma_r gamma_r
+#define	__ieee754_log10	log10
+#define	__ieee754_sinh	sinh
+#define	__ieee754_hypot	hypot
+#define	__ieee754_j0	j0
+#define	__ieee754_j1	j1
+#define	__ieee754_y0	y0
+#define	__ieee754_y1	y1
+#define	__ieee754_jn	jn
+#define	__ieee754_yn	yn
+#define	__ieee754_remainder remainder
+#define	__ieee754_scalb	scalb
+#define	__ieee754_sqrtf	sqrtf
+#define	__ieee754_acosf	acosf
+#define	__ieee754_acoshf acoshf
+#define	__ieee754_logf	logf
+#define	__ieee754_atanhf atanhf
+#define	__ieee754_asinf	asinf
+#define	__ieee754_atan2f atan2f
+#define	__ieee754_expf	expf
+#define	__ieee754_coshf	coshf
+#define	__ieee754_fmodf	fmodf
+#define	__ieee754_powf	powf
+#define	__ieee754_lgammaf lgammaf
+#define	__ieee754_gammaf gammaf
+#define	__ieee754_lgammaf_r lgammaf_r
+#define	__ieee754_gammaf_r gammaf_r
+#define	__ieee754_log10f log10f
+#define	__ieee754_sinhf	sinhf
+#define	__ieee754_hypotf hypotf
+#define	__ieee754_j0f	j0f
+#define	__ieee754_j1f	j1f
+#define	__ieee754_y0f	y0f
+#define	__ieee754_y1f	y1f
+#define	__ieee754_jnf	jnf
+#define	__ieee754_ynf	ynf
+#define	__ieee754_remainderf remainderf
+#define	__ieee754_scalbf scalbf
+
+/* bird added: */
+#define	__ieee754_log10l    log10l
+#define	__ieee754_logl      logl
+#define	__ieee754_expl      expl
+#define	__ieee754_sinhl     sinhl
+#define	__ieee754_coshl     coshl
+#define	__ieee754_sqrtl     sqrtl
+#define	__ieee754_atan2l    atan2l
+#define	__ieee754_hypotl    hypotl
+#define __ieee754_gammal    gammal
+long double __ieee754_gammal(long double);
+#define __ieee754_gammal_r  gammal_r
+long double __ieee754_gammal_r(long double,int *);
+#define __ieee754_lgammal_r lgammal_r
+long double __ieee754_lgammal_r(long double, int *);
+#define __ieee754_jnl jnl
+long double __ieee754_jnl(int,long double);
+#define __ieee754_j0l j0l
+long double __ieee754_j0l(long double);
+#define __ieee754_j1l j1l
+long double __ieee754_j1l(long double);
+#define __ieee754_y0l y0l
+long double __ieee754_y0l(long double);
+#define __ieee754_y1l y1l
+long double __ieee754_y1l(long double);
+#define __ieee754_jnl jnl
+long double __ieee754_jnl(int,long double);
+#define __ieee754_ynl ynl
+long double __ieee754_ynl(int,long double);
+#define __ieee754_acoshl acoshl
+long double __ieee754_acoshl(long double);
+#define __ieee754_remainderl remainderl
+long double __ieee754_remainderl(long double,long double);
+
+
+/* fdlibm kernel function */
+int	__ieee754_rem_pio2(double,double*);
+double	__kernel_sin(double,double,int);
+double	__kernel_cos(double,double);
+double	__kernel_tan(double,double,int);
+int	__kernel_rem_pio2(double*,double*,int,int,int,const int*);
+
+/* float versions of fdlibm kernel functions */
+int	__ieee754_rem_pio2f(float,float*);
+float	__kernel_sinf(float,float,int);
+float	__kernel_cosf(float,float);
+float	__kernel_tanf(float,float,int);
+int	__kernel_rem_pio2f(float*,float*,int,int,int,const int*);
+
+#endif /* !_MATH_PRIVATE_H_ */
Index: /trunk/libc/src/msun/src/s_asinh.c
===================================================================
--- /trunk/libc/src/msun/src/s_asinh.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_asinh.c	(revision 2448)
@@ -0,0 +1,58 @@
+/* @(#)s_asinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_asinh.c,v 1.8 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/* asinh(x)
+ * Method :
+ *	Based on
+ *		asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
+ *	we have
+ *	asinh(x) := x  if  1+x*x=1,
+ *		 := sign(x)*(log(x)+ln2)) for large |x|, else
+ *		 := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
+ *		 := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+ln2 =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+huge=  1.00000000000000000000e+300;
+
+double
+asinh(double x)
+{
+	double t,w;
+	int32_t hx,ix;
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7ff00000) return x+x;	/* x is inf or NaN */
+	if(ix< 0x3e300000) {	/* |x|<2**-28 */
+	    if(huge+x>one) return x;	/* return x inexact except 0 */
+	}
+	if(ix>0x41b00000) {	/* |x| > 2**28 */
+	    w = __ieee754_log(fabs(x))+ln2;
+	} else if (ix>0x40000000) {	/* 2**28 > |x| > 2.0 */
+	    t = fabs(x);
+	    w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t));
+	} else {		/* 2.0 > |x| > 2**-28 */
+	    t = x*x;
+	    w =log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t)));
+	}
+	if(hx>0) return w; else return -w;
+}
Index: /trunk/libc/src/msun/src/s_asinhf.c
===================================================================
--- /trunk/libc/src/msun/src/s_asinhf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_asinhf.c	(revision 2448)
@@ -0,0 +1,50 @@
+/* s_asinhf.c -- float version of s_asinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_asinhf.c,v 1.8 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+one =  1.0000000000e+00, /* 0x3F800000 */
+ln2 =  6.9314718246e-01, /* 0x3f317218 */
+huge=  1.0000000000e+30;
+
+float
+asinhf(float x)
+{
+	float t,w;
+	int32_t hx,ix;
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7f800000) return x+x;	/* x is inf or NaN */
+	if(ix< 0x31800000) {	/* |x|<2**-28 */
+	    if(huge+x>one) return x;	/* return x inexact except 0 */
+	}
+	if(ix>0x4d800000) {	/* |x| > 2**28 */
+	    w = __ieee754_logf(fabsf(x))+ln2;
+	} else if (ix>0x40000000) {	/* 2**28 > |x| > 2.0 */
+	    t = fabsf(x);
+	    w = __ieee754_logf((float)2.0*t+one/(__ieee754_sqrtf(x*x+one)+t));
+	} else {		/* 2.0 > |x| > 2**-28 */
+	    t = x*x;
+	    w =log1pf(fabsf(x)+t/(one+__ieee754_sqrtf(one+t)));
+	}
+	if(hx>0) return w; else return -w;
+}
Index: /trunk/libc/src/msun/src/s_atan.c
===================================================================
--- /trunk/libc/src/msun/src/s_atan.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_atan.c	(revision 2448)
@@ -0,0 +1,120 @@
+/* @(#)s_atan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_atan.c,v 1.9 2003/07/23 04:53:46 peter Exp $";
+#endif
+
+/* atan(x)
+ * Method
+ *   1. Reduce x to positive by atan(x) = -atan(-x).
+ *   2. According to the integer k=4t+0.25 chopped, t=x, the argument
+ *      is further reduced to one of the following intervals and the
+ *      arctangent of t is evaluated by the corresponding formula:
+ *
+ *      [0,7/16]      atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
+ *      [7/16,11/16]  atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
+ *      [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
+ *      [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
+ *      [39/16,INF]   atan(x) = atan(INF) + atan( -1/t )
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double atanhi[] = {
+  4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
+  7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
+  9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
+  1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
+};
+
+static const double atanlo[] = {
+  2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
+  3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
+  1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
+  6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
+};
+
+static const double aT[] = {
+  3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
+ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
+  1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
+ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
+  9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
+ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
+  6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
+ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
+  4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
+ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
+  1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
+};
+
+	static const double
+one   = 1.0,
+huge   = 1.0e300;
+
+double
+atan(double x)
+{
+	double w,s1,s2,z;
+	int32_t ix,hx,id;
+
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x44100000) {	/* if |x| >= 2^66 */
+	    u_int32_t low;
+	    GET_LOW_WORD(low,x);
+	    if(ix>0x7ff00000||
+		(ix==0x7ff00000&&(low!=0)))
+		return x+x;		/* NaN */
+	    if(hx>0) return  atanhi[3]+atanlo[3];
+	    else     return -atanhi[3]-atanlo[3];
+	} if (ix < 0x3fdc0000) {	/* |x| < 0.4375 */
+	    if (ix < 0x3e200000) {	/* |x| < 2^-29 */
+		if(huge+x>one) return x;	/* raise inexact */
+	    }
+	    id = -1;
+	} else {
+	x = fabs(x);
+	if (ix < 0x3ff30000) {		/* |x| < 1.1875 */
+	    if (ix < 0x3fe60000) {	/* 7/16 <=|x|<11/16 */
+		id = 0; x = (2.0*x-one)/(2.0+x);
+	    } else {			/* 11/16<=|x|< 19/16 */
+		id = 1; x  = (x-one)/(x+one);
+	    }
+	} else {
+	    if (ix < 0x40038000) {	/* |x| < 2.4375 */
+		id = 2; x  = (x-1.5)/(one+1.5*x);
+	    } else {			/* 2.4375 <= |x| < 2^66 */
+		id = 3; x  = -1.0/x;
+	    }
+	}}
+    /* end of argument reduction */
+	z = x*x;
+	w = z*z;
+    /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+	s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
+	s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
+	if (id<0) return x - x*(s1+s2);
+	else {
+	    z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+	    return (hx<0)? -z:z;
+	}
+}
Index: /trunk/libc/src/msun/src/s_atanf.c
===================================================================
--- /trunk/libc/src/msun/src/s_atanf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_atanf.c	(revision 2448)
@@ -0,0 +1,100 @@
+/* s_atanf.c -- float version of s_atan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_atanf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float atanhi[] = {
+  4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
+  7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
+  9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
+  1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
+};
+
+static const float atanlo[] = {
+  5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
+  3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
+  3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
+  7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
+};
+
+static const float aT[] = {
+  3.3333334327e-01, /* 0x3eaaaaaa */
+ -2.0000000298e-01, /* 0xbe4ccccd */
+  1.4285714924e-01, /* 0x3e124925 */
+ -1.1111110449e-01, /* 0xbde38e38 */
+  9.0908870101e-02, /* 0x3dba2e6e */
+ -7.6918758452e-02, /* 0xbd9d8795 */
+  6.6610731184e-02, /* 0x3d886b35 */
+ -5.8335702866e-02, /* 0xbd6ef16b */
+  4.9768779427e-02, /* 0x3d4bda59 */
+ -3.6531571299e-02, /* 0xbd15a221 */
+  1.6285819933e-02, /* 0x3c8569d7 */
+};
+
+	static const float
+one   = 1.0,
+huge   = 1.0e30;
+
+float
+atanf(float x)
+{
+	float w,s1,s2,z;
+	int32_t ix,hx,id;
+
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x50800000) {	/* if |x| >= 2^34 */
+	    if(ix>0x7f800000)
+		return x+x;		/* NaN */
+	    if(hx>0) return  atanhi[3]+atanlo[3];
+	    else     return -atanhi[3]-atanlo[3];
+	} if (ix < 0x3ee00000) {	/* |x| < 0.4375 */
+	    if (ix < 0x31000000) {	/* |x| < 2^-29 */
+		if(huge+x>one) return x;	/* raise inexact */
+	    }
+	    id = -1;
+	} else {
+	x = fabsf(x);
+	if (ix < 0x3f980000) {		/* |x| < 1.1875 */
+	    if (ix < 0x3f300000) {	/* 7/16 <=|x|<11/16 */
+		id = 0; x = ((float)2.0*x-one)/((float)2.0+x);
+	    } else {			/* 11/16<=|x|< 19/16 */
+		id = 1; x  = (x-one)/(x+one);
+	    }
+	} else {
+	    if (ix < 0x401c0000) {	/* |x| < 2.4375 */
+		id = 2; x  = (x-(float)1.5)/(one+(float)1.5*x);
+	    } else {			/* 2.4375 <= |x| < 2^66 */
+		id = 3; x  = -(float)1.0/x;
+	    }
+	}}
+    /* end of argument reduction */
+	z = x*x;
+	w = z*z;
+    /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+	s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
+	s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
+	if (id<0) return x - x*(s1+s2);
+	else {
+	    z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+	    return (hx<0)? -z:z;
+	}
+}
Index: /trunk/libc/src/msun/src/s_cbrt.c
===================================================================
--- /trunk/libc/src/msun/src/s_cbrt.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_cbrt.c	(revision 2448)
@@ -0,0 +1,82 @@
+/* @(#)s_cbrt.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_cbrt.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+/* cbrt(x)
+ * Return cube root of x
+ */
+static const u_int32_t
+	B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */
+	B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+static const double
+C =  5.42857142857142815906e-01, /* 19/35     = 0x3FE15F15, 0xF15F15F1 */
+D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */
+E =  1.41428571428571436819e+00, /* 99/70     = 0x3FF6A0EA, 0x0EA0EA0F */
+F =  1.60714285714285720630e+00, /* 45/28     = 0x3FF9B6DB, 0x6DB6DB6E */
+G =  3.57142857142857150787e-01; /* 5/14      = 0x3FD6DB6D, 0xB6DB6DB7 */
+
+double
+cbrt(double x)
+{
+	int32_t	hx;
+	double r,s,t=0.0,w;
+	u_int32_t sign;
+	u_int32_t high,low;
+
+	GET_HIGH_WORD(hx,x);
+	sign=hx&0x80000000; 		/* sign= sign(x) */
+	hx  ^=sign;
+	if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
+	GET_LOW_WORD(low,x);
+	if((hx|low)==0)
+	    return(x);		/* cbrt(0) is itself */
+
+	SET_HIGH_WORD(x,hx);	/* x <- |x| */
+    /* rough cbrt to 5 bits */
+	if(hx<0x00100000) 		/* subnormal number */
+	  {SET_HIGH_WORD(t,0x43500000);	/* set t= 2**54 */
+	   t*=x; GET_HIGH_WORD(high,t); SET_HIGH_WORD(t,high/3+B2);
+	  }
+	else
+	  SET_HIGH_WORD(t,hx/3+B1);
+
+
+    /* new cbrt to 23 bits, may be implemented in single precision */
+	r=t*t/x;
+	s=C+r*t;
+	t*=G+F/(s+E+D/s);
+
+    /* chopped to 20 bits and make it larger than cbrt(x) */
+	GET_HIGH_WORD(high,t);
+	INSERT_WORDS(t,high+0x00000001,0);
+
+
+    /* one step newton iteration to 53 bits with error less than 0.667 ulps */
+	s=t*t;		/* t*t is exact */
+	r=x/s;
+	w=t+t;
+	r=(r-t)/(w+r);	/* r-s is exact */
+	t=t+t*r;
+
+    /* retore the sign bit */
+	GET_HIGH_WORD(high,t);
+	SET_HIGH_WORD(t,high|sign);
+	return(t);
+}
Index: /trunk/libc/src/msun/src/s_cbrtf.c
===================================================================
--- /trunk/libc/src/msun/src/s_cbrtf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_cbrtf.c	(revision 2448)
@@ -0,0 +1,72 @@
+/* s_cbrtf.c -- float version of s_cbrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_cbrtf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+/* cbrtf(x)
+ * Return cube root of x
+ */
+static const unsigned
+	B1 = 709958130, /* B1 = (84+2/3-0.03306235651)*2**23 */
+	B2 = 642849266; /* B2 = (76+2/3-0.03306235651)*2**23 */
+
+static const float
+C =  5.4285717010e-01, /* 19/35     = 0x3f0af8b0 */
+D = -7.0530611277e-01, /* -864/1225 = 0xbf348ef1 */
+E =  1.4142856598e+00, /* 99/70     = 0x3fb50750 */
+F =  1.6071428061e+00, /* 45/28     = 0x3fcdb6db */
+G =  3.5714286566e-01; /* 5/14      = 0x3eb6db6e */
+
+float
+cbrtf(float x)
+{
+	float r,s,t;
+	int32_t hx;
+	u_int32_t sign;
+	u_int32_t high;
+
+	GET_FLOAT_WORD(hx,x);
+	sign=hx&0x80000000; 		/* sign= sign(x) */
+	hx  ^=sign;
+	if(hx>=0x7f800000) return(x+x); /* cbrt(NaN,INF) is itself */
+	if(hx==0)
+	    return(x);		/* cbrt(0) is itself */
+
+	SET_FLOAT_WORD(x,hx);	/* x <- |x| */
+    /* rough cbrt to 5 bits */
+	if(hx<0x00800000) 		/* subnormal number */
+	  {SET_FLOAT_WORD(t,0x4b800000); /* set t= 2**24 */
+	   t*=x; GET_FLOAT_WORD(high,t); SET_FLOAT_WORD(t,high/3+B2);
+	  }
+	else
+	  SET_FLOAT_WORD(t,hx/3+B1);
+
+
+    /* new cbrt to 23 bits */
+	r=t*t/x;
+	s=C+r*t;
+	t*=G+F/(s+E+D/s);
+
+    /* retore the sign bit */
+	GET_FLOAT_WORD(high,t);
+	SET_FLOAT_WORD(t,high|sign);
+	return(t);
+}
Index: /trunk/libc/src/msun/src/s_ceil.c
===================================================================
--- /trunk/libc/src/msun/src/s_ceil.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_ceil.c	(revision 2448)
@@ -0,0 +1,73 @@
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_ceil.c,v 1.9 2003/07/23 04:53:46 peter Exp $";
+#endif
+
+/*
+ * ceil(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+double
+ceil(double x)
+{
+	int32_t i0,i1,j0;
+	u_int32_t i,j;
+	EXTRACT_WORDS(i0,i1,x);
+	j0 = ((i0>>20)&0x7ff)-0x3ff;
+	if(j0<20) {
+	    if(j0<0) { 	/* raise inexact if x != 0 */
+		if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+		    if(i0<0) {i0=0x80000000;i1=0;}
+		    else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
+		}
+	    } else {
+		i = (0x000fffff)>>j0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		if(huge+x>0.0) {	/* raise inexact flag */
+		    if(i0>0) i0 += (0x00100000)>>j0;
+		    i0 &= (~i); i1=0;
+		}
+	    }
+	} else if (j0>51) {
+	    if(j0==0x400) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    if(huge+x>0.0) { 		/* raise inexact flag */
+		if(i0>0) {
+		    if(j0==20) i0+=1;
+		    else {
+			j = i1 + (1<<(52-j0));
+			if(j<i1) i0+=1;	/* got a carry */
+			i1 = j;
+		    }
+		}
+		i1 &= (~i);
+	    }
+	}
+	INSERT_WORDS(x,i0,i1);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_ceilf.c
===================================================================
--- /trunk/libc/src/msun/src/s_ceilf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_ceilf.c	(revision 2448)
@@ -0,0 +1,54 @@
+/* s_ceilf.c -- float version of s_ceil.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_ceilf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float huge = 1.0e30;
+
+float
+ceilf(float x)
+{
+	int32_t i0,j0;
+	u_int32_t i;
+
+	GET_FLOAT_WORD(i0,x);
+	j0 = ((i0>>23)&0xff)-0x7f;
+	if(j0<23) {
+	    if(j0<0) { 	/* raise inexact if x != 0 */
+		if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+		    if(i0<0) {i0=0x80000000;}
+		    else if(i0!=0) { i0=0x3f800000;}
+		}
+	    } else {
+		i = (0x007fffff)>>j0;
+		if((i0&i)==0) return x; /* x is integral */
+		if(huge+x>(float)0.0) {	/* raise inexact flag */
+		    if(i0>0) i0 += (0x00800000)>>j0;
+		    i0 &= (~i);
+		}
+	    }
+	} else {
+	    if(j0==0x80) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	}
+	SET_FLOAT_WORD(x,i0);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_ceill.c
===================================================================
--- /trunk/libc/src/msun/src/s_ceill.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_ceill.c	(revision 2448)
@@ -0,0 +1,103 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_ceil.c 5.1 93/09/24
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_ceill.c,v 1.3 2005/04/22 09:57:55 stefanf Exp $";
+#endif
+
+/*
+ * ceill(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to ceill(x).
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define	MANH_SIZE	(LDBL_MANH_SIZE + 1)
+#define	INC_MANH(u, c)	do {					\
+	uint64_t o = u.bits.manh;				\
+	u.bits.manh += (c);					\
+	if (u.bits.manh < o)					\
+		u.bits.exp++;					\
+} while (0)
+#else
+#define	MANH_SIZE	LDBL_MANH_SIZE
+#define	INC_MANH(u, c)	do {					\
+	uint64_t o = u.bits.manh;				\
+	u.bits.manh += (c);					\
+	if (u.bits.manh < o) {					\
+		u.bits.exp++;					\
+		u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1);	\
+	}							\
+} while (0)
+#endif
+
+static const double huge = 1.0e300;
+
+long double
+ceill(long double x)
+{
+	union IEEEl2bits u = { .e = x };
+	int e = u.bits.exp - LDBL_MAX_EXP + 1;
+
+	if (e < MANH_SIZE - 1) {
+		if (e < 0) {			/* raise inexact if x != 0 */
+			if (huge + (double)x > 0.0)
+				if (u.bits.exp > 0 ||
+				    (u.bits.manh | u.bits.manl) != 0)
+					u.e = u.bits.sign ? 0.0 : 1.0;
+		} else {
+			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+			if (((u.bits.manh & m) | u.bits.manl) == 0)
+				return (x);	/* x is integral */
+			if (!u.bits.sign) {
+#ifdef LDBL_IMPLICIT_NBIT
+				if (e == 0)
+					u.bits.exp++;
+				else
+#endif
+				INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
+			}
+			if (huge + (double)x > 0.0) {	/* raise inexact flag */
+				u.bits.manh &= ~m;
+				u.bits.manl = 0;
+			}
+		}
+	} else if (e < LDBL_MANT_DIG - 1) {
+		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+		if ((u.bits.manl & m) == 0)
+			return (x);	/* x is integral */
+		if (!u.bits.sign) {
+			if (e == MANH_SIZE - 1)
+				INC_MANH(u, 1);
+			else {
+				uint64_t o = u.bits.manl;
+				u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
+				if (u.bits.manl < o)	/* got a carry */
+					INC_MANH(u, 1);
+			}
+		}
+		if (huge + (double)x > 0.0)	/* raise inexact flag */
+			u.bits.manl &= ~m;
+	}
+	return (u.e);
+}
Index: /trunk/libc/src/msun/src/s_cimag.c
===================================================================
--- /trunk/libc/src/msun/src/s_cimag.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_cimag.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_cimag.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+double
+cimag(double complex z)
+{
+	return -z * I;
+}
Index: /trunk/libc/src/msun/src/s_cimagf.c
===================================================================
--- /trunk/libc/src/msun/src/s_cimagf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_cimagf.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_cimagf.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+float
+cimagf(float complex z)
+{
+	return -z * I;
+}
Index: /trunk/libc/src/msun/src/s_cimagl.c
===================================================================
--- /trunk/libc/src/msun/src/s_cimagl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_cimagl.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_cimagl.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+long double
+cimagl(long double complex z)
+{
+	return -z * I;
+}
Index: /trunk/libc/src/msun/src/s_conj.c
===================================================================
--- /trunk/libc/src/msun/src/s_conj.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_conj.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_conj.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+double complex
+conj(double complex z)
+{
+	return creal(z) - I * cimag(z);
+}
Index: /trunk/libc/src/msun/src/s_conjf.c
===================================================================
--- /trunk/libc/src/msun/src/s_conjf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_conjf.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_conjf.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+float complex
+conjf(float complex z)
+{
+	return crealf(z) - I * cimagf(z);
+}
Index: /trunk/libc/src/msun/src/s_conjl.c
===================================================================
--- /trunk/libc/src/msun/src/s_conjl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_conjl.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_conjl.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+long double complex
+conjl(long double complex z)
+{
+	return creall(z) - I * cimagl(z);
+}
Index: /trunk/libc/src/msun/src/s_copysign.c
===================================================================
--- /trunk/libc/src/msun/src/s_copysign.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_copysign.c	(revision 2448)
@@ -0,0 +1,35 @@
+/* @(#)s_copysign.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_copysign.c,v 1.9 2003/07/23 04:53:46 peter Exp $";
+#endif
+
+/*
+ * copysign(double x, double y)
+ * copysign(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+copysign(double x, double y)
+{
+	u_int32_t hx,hy;
+	GET_HIGH_WORD(hx,x);
+	GET_HIGH_WORD(hy,y);
+	SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
+        return x;
+}
Index: /trunk/libc/src/msun/src/s_copysignf.c
===================================================================
--- /trunk/libc/src/msun/src/s_copysignf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_copysignf.c	(revision 2448)
@@ -0,0 +1,38 @@
+/* s_copysignf.c -- float version of s_copysign.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_copysignf.c,v 1.9 2003/07/23 04:53:46 peter Exp $";
+#endif
+
+/*
+ * copysignf(float x, float y)
+ * copysignf(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+float
+copysignf(float x, float y)
+{
+	u_int32_t ix,iy;
+	GET_FLOAT_WORD(ix,x);
+	GET_FLOAT_WORD(iy,y);
+	SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000));
+        return x;
+}
Index: /trunk/libc/src/msun/src/s_copysignl.c
===================================================================
--- /trunk/libc/src/msun/src/s_copysignl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_copysignl.c	(revision 2448)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_copysignl.c,v 1.1 2004/05/07 18:56:31 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <math.h>
+
+#include "fpmath.h"
+
+long double
+copysignl(long double x, long double y)
+{
+	union IEEEl2bits ux, uy;
+
+	ux.e = x;
+	uy.e = y;
+	ux.bits.sign = uy.bits.sign;
+	return (ux.e);
+}
Index: /trunk/libc/src/msun/src/s_cos.c
===================================================================
--- /trunk/libc/src/msun/src/s_cos.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_cos.c	(revision 2448)
@@ -0,0 +1,79 @@
+/* @(#)s_cos.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_cos.c,v 1.9 2003/07/23 04:53:46 peter Exp $";
+#endif
+
+/* cos(x)
+ * Return cosine function of x.
+ *
+ * kernel function:
+ *	__kernel_sin		... sine function on [-pi/4,pi/4]
+ *	__kernel_cos		... cosine function on [-pi/4,pi/4]
+ *	__ieee754_rem_pio2	... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *	in [-pi/4 , +pi/4], and let n = k mod 4.
+ *	We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *	    0	       S	   C		 T
+ *	    1	       C	  -S		-1/T
+ *	    2	      -S	  -C		 T
+ *	    3	      -C	   S		-1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *	TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+cos(double x)
+{
+	double y[2],z=0.0;
+	int32_t n, ix;
+
+    /* High word of x. */
+	GET_HIGH_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+	ix &= 0x7fffffff;
+	if(ix <= 0x3fe921fb) return __kernel_cos(x,z);
+
+    /* cos(Inf or NaN) is NaN */
+	else if (ix>=0x7ff00000) return x-x;
+
+    /* argument reduction needed */
+	else {
+	    n = __ieee754_rem_pio2(x,y);
+	    switch(n&3) {
+		case 0: return  __kernel_cos(y[0],y[1]);
+		case 1: return -__kernel_sin(y[0],y[1],1);
+		case 2: return -__kernel_cos(y[0],y[1]);
+		default:
+		        return  __kernel_sin(y[0],y[1],1);
+	    }
+	}
+}
Index: /trunk/libc/src/msun/src/s_cosf.c
===================================================================
--- /trunk/libc/src/msun/src/s_cosf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_cosf.c	(revision 2448)
@@ -0,0 +1,52 @@
+/* s_cosf.c -- float version of s_cos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_cosf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float one=1.0;
+
+float
+cosf(float x)
+{
+	float y[2],z=0.0;
+	int32_t n,ix;
+
+	GET_FLOAT_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+	ix &= 0x7fffffff;
+	if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
+
+    /* cos(Inf or NaN) is NaN */
+	else if (ix>=0x7f800000) return x-x;
+
+    /* argument reduction needed */
+	else {
+	    n = __ieee754_rem_pio2f(x,y);
+	    switch(n&3) {
+		case 0: return  __kernel_cosf(y[0],y[1]);
+		case 1: return -__kernel_sinf(y[0],y[1],1);
+		case 2: return -__kernel_cosf(y[0],y[1]);
+		default:
+		        return  __kernel_sinf(y[0],y[1],1);
+	    }
+	}
+}
Index: /trunk/libc/src/msun/src/s_creal.c
===================================================================
--- /trunk/libc/src/msun/src/s_creal.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_creal.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_creal.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+double
+creal(double complex z)
+{
+	return z;
+}
Index: /trunk/libc/src/msun/src/s_crealf.c
===================================================================
--- /trunk/libc/src/msun/src/s_crealf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_crealf.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_crealf.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+float
+crealf(float complex z)
+{
+	return z;
+}
Index: /trunk/libc/src/msun/src/s_creall.c
===================================================================
--- /trunk/libc/src/msun/src/s_creall.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_creall.c	(revision 2448)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_creall.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include "namespace.h"
+#include <complex.h>
+
+long double
+creall(long double complex z)
+{
+	return z;
+}
Index: /trunk/libc/src/msun/src/s_erf.c
===================================================================
--- /trunk/libc/src/msun/src/s_erf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_erf.c	(revision 2448)
@@ -0,0 +1,303 @@
+/* @(#)s_erf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_erf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/* double erf(double x)
+ * double erfc(double x)
+ *			     x
+ *		      2      |\
+ *     erf(x)  =  ---------  | exp(-t*t)dt
+ *	 	   sqrt(pi) \|
+ *			     0
+ *
+ *     erfc(x) =  1-erf(x)
+ *  Note that
+ *		erf(-x) = -erf(x)
+ *		erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ *	1. For |x| in [0, 0.84375]
+ *	    erf(x)  = x + x*R(x^2)
+ *          erfc(x) = 1 - erf(x)           if x in [-.84375,0.25]
+ *                  = 0.5 + ((0.5-x)-x*R)  if x in [0.25,0.84375]
+ *	   where R = P/Q where P is an odd poly of degree 8 and
+ *	   Q is an odd poly of degree 10.
+ *						 -57.90
+ *			| R - (erf(x)-x)/x | <= 2
+ *
+ *
+ *	   Remark. The formula is derived by noting
+ *          erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ *	   and that
+ *          2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ *	   is close to one. The interval is chosen because the fix
+ *	   point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+ *	   near 0.6174), and by some experiment, 0.84375 is chosen to
+ * 	   guarantee the error is less than one ulp for erf.
+ *
+ *      2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+ *         c = 0.84506291151 rounded to single (24 bits)
+ *         	erf(x)  = sign(x) * (c  + P1(s)/Q1(s))
+ *         	erfc(x) = (1-c)  - P1(s)/Q1(s) if x > 0
+ *			  1+(c+P1(s)/Q1(s))    if x < 0
+ *         	|P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
+ *	   Remark: here we use the taylor series expansion at x=1.
+ *		erf(1+s) = erf(1) + s*Poly(s)
+ *			 = 0.845.. + P1(s)/Q1(s)
+ *	   That is, we use rational approximation to approximate
+ *			erf(1+s) - (c = (single)0.84506291151)
+ *	   Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ *	   where
+ *		P1(s) = degree 6 poly in s
+ *		Q1(s) = degree 6 poly in s
+ *
+ *      3. For x in [1.25,1/0.35(~2.857143)],
+ *         	erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
+ *         	erf(x)  = 1 - erfc(x)
+ *	   where
+ *		R1(z) = degree 7 poly in z, (z=1/x^2)
+ *		S1(z) = degree 8 poly in z
+ *
+ *      4. For x in [1/0.35,28]
+ *         	erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+ *			= 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
+ *			= 2.0 - tiny		(if x <= -6)
+ *         	erf(x)  = sign(x)*(1.0 - erfc(x)) if x < 6, else
+ *         	erf(x)  = sign(x)*(1.0 - tiny)
+ *	   where
+ *		R2(z) = degree 6 poly in z, (z=1/x^2)
+ *		S2(z) = degree 7 poly in z
+ *
+ *      Note1:
+ *	   To compute exp(-x*x-0.5625+R/S), let s be a single
+ *	   precision number and s := x; then
+ *		-x*x = -s*s + (s-x)*(s+x)
+ *	        exp(-x*x-0.5626+R/S) =
+ *			exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ *      Note2:
+ *	   Here 4 and 5 make use of the asymptotic series
+ *			  exp(-x*x)
+ *		erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ *			  x*sqrt(pi)
+ *	   We use rational approximation to approximate
+ *      	g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
+ *	   Here is the error bound for R1/S1 and R2/S2
+ *      	|R1/S1 - f(x)|  < 2**(-62.57)
+ *      	|R2/S2 - f(x)|  < 2**(-61.52)
+ *
+ *      5. For inf > x >= 28
+ *         	erf(x)  = sign(x) *(1 - tiny)  (raise inexact)
+ *         	erfc(x) = tiny*tiny (raise underflow) if x > 0
+ *			= 2 - tiny if x<0
+ *
+ *      7. Special case:
+ *         	erf(0)  = 0, erf(inf)  = 1, erf(-inf) = -1,
+ *         	erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ *	   	erfc/erf(NaN) is NaN
+ */
+
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+tiny	    = 1e-300,
+half=  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+two =  2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
+	/* c = (float)0.84506291151 */
+erx =  8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */
+/*
+ * Coefficients for approximation to  erf on [0,0.84375]
+ */
+efx =  1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */
+efx8=  1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */
+pp0  =  1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */
+pp1  = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */
+pp2  = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */
+pp3  = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */
+pp4  = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */
+qq1  =  3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */
+qq2  =  6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */
+qq3  =  5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */
+qq4  =  1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */
+qq5  = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */
+/*
+ * Coefficients for approximation to  erf  in [0.84375,1.25]
+ */
+pa0  = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */
+pa1  =  4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */
+pa2  = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */
+pa3  =  3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */
+pa4  = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */
+pa5  =  3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */
+pa6  = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */
+qa1  =  1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */
+qa2  =  5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */
+qa3  =  7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */
+qa4  =  1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */
+qa5  =  1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */
+qa6  =  1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */
+/*
+ * Coefficients for approximation to  erfc in [1.25,1/0.35]
+ */
+ra0  = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */
+ra1  = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */
+ra2  = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */
+ra3  = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */
+ra4  = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */
+ra5  = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */
+ra6  = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */
+ra7  = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */
+sa1  =  1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */
+sa2  =  1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */
+sa3  =  4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */
+sa4  =  6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */
+sa5  =  4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */
+sa6  =  1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */
+sa7  =  6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */
+sa8  = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */
+/*
+ * Coefficients for approximation to  erfc in [1/.35,28]
+ */
+rb0  = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */
+rb1  = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */
+rb2  = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */
+rb3  = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */
+rb4  = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */
+rb5  = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */
+rb6  = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */
+sb1  =  3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */
+sb2  =  3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */
+sb3  =  1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */
+sb4  =  3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */
+sb5  =  2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */
+sb6  =  4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */
+sb7  = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */
+
+double
+erf(double x)
+{
+	int32_t hx,ix,i;
+	double R,S,P,Q,s,y,z,r;
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7ff00000) {		/* erf(nan)=nan */
+	    i = ((u_int32_t)hx>>31)<<1;
+	    return (double)(1-i)+one/x;	/* erf(+-inf)=+-1 */
+	}
+
+	if(ix < 0x3feb0000) {		/* |x|<0.84375 */
+	    if(ix < 0x3e300000) { 	/* |x|<2**-28 */
+	        if (ix < 0x00800000)
+		    return 0.125*(8.0*x+efx8*x);  /*avoid underflow */
+		return x + efx*x;
+	    }
+	    z = x*x;
+	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+	    y = r/s;
+	    return x + x*y;
+	}
+	if(ix < 0x3ff40000) {		/* 0.84375 <= |x| < 1.25 */
+	    s = fabs(x)-one;
+	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+	    if(hx>=0) return erx + P/Q; else return -erx - P/Q;
+	}
+	if (ix >= 0x40180000) {		/* inf>|x|>=6 */
+	    if(hx>=0) return one-tiny; else return tiny-one;
+	}
+	x = fabs(x);
+ 	s = one/(x*x);
+	if(ix< 0x4006DB6E) {	/* |x| < 1/0.35 */
+	    R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+				ra5+s*(ra6+s*ra7))))));
+	    S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+				sa5+s*(sa6+s*(sa7+s*sa8)))))));
+	} else {	/* |x| >= 1/0.35 */
+	    R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+				rb5+s*rb6)))));
+	    S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+				sb5+s*(sb6+s*sb7))))));
+	}
+	z  = x;
+	SET_LOW_WORD(z,0);
+	r  =  __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S);
+	if(hx>=0) return one-r/x; else return  r/x-one;
+}
+
+double
+erfc(double x)
+{
+	int32_t hx,ix;
+	double R,S,P,Q,s,y,z,r;
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7ff00000) {			/* erfc(nan)=nan */
+						/* erfc(+-inf)=0,2 */
+	    return (double)(((u_int32_t)hx>>31)<<1)+one/x;
+	}
+
+	if(ix < 0x3feb0000) {		/* |x|<0.84375 */
+	    if(ix < 0x3c700000)  	/* |x|<2**-56 */
+		return one-x;
+	    z = x*x;
+	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+	    y = r/s;
+	    if(hx < 0x3fd00000) {  	/* x<1/4 */
+		return one-(x+x*y);
+	    } else {
+		r = x*y;
+		r += (x-half);
+	        return half - r ;
+	    }
+	}
+	if(ix < 0x3ff40000) {		/* 0.84375 <= |x| < 1.25 */
+	    s = fabs(x)-one;
+	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+	    if(hx>=0) {
+	        z  = one-erx; return z - P/Q;
+	    } else {
+		z = erx+P/Q; return one+z;
+	    }
+	}
+	if (ix < 0x403c0000) {		/* |x|<28 */
+	    x = fabs(x);
+ 	    s = one/(x*x);
+	    if(ix< 0x4006DB6D) {	/* |x| < 1/.35 ~ 2.857143*/
+	        R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+				ra5+s*(ra6+s*ra7))))));
+	        S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+				sa5+s*(sa6+s*(sa7+s*sa8)))))));
+	    } else {			/* |x| >= 1/.35 ~ 2.857143 */
+		if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */
+	        R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+				rb5+s*rb6)))));
+	        S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+				sb5+s*(sb6+s*sb7))))));
+	    }
+	    z  = x;
+	    SET_LOW_WORD(z,0);
+	    r  =  __ieee754_exp(-z*z-0.5625)*
+			__ieee754_exp((z-x)*(z+x)+R/S);
+	    if(hx>0) return r/x; else return two-r/x;
+	} else {
+	    if(hx>0) return tiny*tiny; else return two-tiny;
+	}
+}
Index: /trunk/libc/src/msun/src/s_erff.c
===================================================================
--- /trunk/libc/src/msun/src/s_erff.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_erff.c	(revision 2448)
@@ -0,0 +1,212 @@
+/* s_erff.c -- float version of s_erf.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_erff.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+tiny	    = 1e-30,
+half=  5.0000000000e-01, /* 0x3F000000 */
+one =  1.0000000000e+00, /* 0x3F800000 */
+two =  2.0000000000e+00, /* 0x40000000 */
+	/* c = (subfloat)0.84506291151 */
+erx =  8.4506291151e-01, /* 0x3f58560b */
+/*
+ * Coefficients for approximation to  erf on [0,0.84375]
+ */
+efx =  1.2837916613e-01, /* 0x3e0375d4 */
+efx8=  1.0270333290e+00, /* 0x3f8375d4 */
+pp0  =  1.2837916613e-01, /* 0x3e0375d4 */
+pp1  = -3.2504209876e-01, /* 0xbea66beb */
+pp2  = -2.8481749818e-02, /* 0xbce9528f */
+pp3  = -5.7702702470e-03, /* 0xbbbd1489 */
+pp4  = -2.3763017452e-05, /* 0xb7c756b1 */
+qq1  =  3.9791721106e-01, /* 0x3ecbbbce */
+qq2  =  6.5022252500e-02, /* 0x3d852a63 */
+qq3  =  5.0813062117e-03, /* 0x3ba68116 */
+qq4  =  1.3249473704e-04, /* 0x390aee49 */
+qq5  = -3.9602282413e-06, /* 0xb684e21a */
+/*
+ * Coefficients for approximation to  erf  in [0.84375,1.25]
+ */
+pa0  = -2.3621185683e-03, /* 0xbb1acdc6 */
+pa1  =  4.1485610604e-01, /* 0x3ed46805 */
+pa2  = -3.7220788002e-01, /* 0xbebe9208 */
+pa3  =  3.1834661961e-01, /* 0x3ea2fe54 */
+pa4  = -1.1089469492e-01, /* 0xbde31cc2 */
+pa5  =  3.5478305072e-02, /* 0x3d1151b3 */
+pa6  = -2.1663755178e-03, /* 0xbb0df9c0 */
+qa1  =  1.0642088205e-01, /* 0x3dd9f331 */
+qa2  =  5.4039794207e-01, /* 0x3f0a5785 */
+qa3  =  7.1828655899e-02, /* 0x3d931ae7 */
+qa4  =  1.2617121637e-01, /* 0x3e013307 */
+qa5  =  1.3637083583e-02, /* 0x3c5f6e13 */
+qa6  =  1.1984500103e-02, /* 0x3c445aa3 */
+/*
+ * Coefficients for approximation to  erfc in [1.25,1/0.35]
+ */
+ra0  = -9.8649440333e-03, /* 0xbc21a093 */
+ra1  = -6.9385856390e-01, /* 0xbf31a0b7 */
+ra2  = -1.0558626175e+01, /* 0xc128f022 */
+ra3  = -6.2375331879e+01, /* 0xc2798057 */
+ra4  = -1.6239666748e+02, /* 0xc322658c */
+ra5  = -1.8460508728e+02, /* 0xc3389ae7 */
+ra6  = -8.1287437439e+01, /* 0xc2a2932b */
+ra7  = -9.8143291473e+00, /* 0xc11d077e */
+sa1  =  1.9651271820e+01, /* 0x419d35ce */
+sa2  =  1.3765776062e+02, /* 0x4309a863 */
+sa3  =  4.3456588745e+02, /* 0x43d9486f */
+sa4  =  6.4538726807e+02, /* 0x442158c9 */
+sa5  =  4.2900814819e+02, /* 0x43d6810b */
+sa6  =  1.0863500214e+02, /* 0x42d9451f */
+sa7  =  6.5702495575e+00, /* 0x40d23f7c */
+sa8  = -6.0424413532e-02, /* 0xbd777f97 */
+/*
+ * Coefficients for approximation to  erfc in [1/.35,28]
+ */
+rb0  = -9.8649431020e-03, /* 0xbc21a092 */
+rb1  = -7.9928326607e-01, /* 0xbf4c9dd4 */
+rb2  = -1.7757955551e+01, /* 0xc18e104b */
+rb3  = -1.6063638306e+02, /* 0xc320a2ea */
+rb4  = -6.3756646729e+02, /* 0xc41f6441 */
+rb5  = -1.0250950928e+03, /* 0xc480230b */
+rb6  = -4.8351919556e+02, /* 0xc3f1c275 */
+sb1  =  3.0338060379e+01, /* 0x41f2b459 */
+sb2  =  3.2579251099e+02, /* 0x43a2e571 */
+sb3  =  1.5367296143e+03, /* 0x44c01759 */
+sb4  =  3.1998581543e+03, /* 0x4547fdbb */
+sb5  =  2.5530502930e+03, /* 0x451f90ce */
+sb6  =  4.7452853394e+02, /* 0x43ed43a7 */
+sb7  = -2.2440952301e+01; /* 0xc1b38712 */
+
+float
+erff(float x)
+{
+	int32_t hx,ix,i;
+	float R,S,P,Q,s,y,z,r;
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7f800000) {		/* erf(nan)=nan */
+	    i = ((u_int32_t)hx>>31)<<1;
+	    return (float)(1-i)+one/x;	/* erf(+-inf)=+-1 */
+	}
+
+	if(ix < 0x3f580000) {		/* |x|<0.84375 */
+	    if(ix < 0x31800000) { 	/* |x|<2**-28 */
+	        if (ix < 0x04000000)
+		    /*avoid underflow */
+		    return (float)0.125*((float)8.0*x+efx8*x);
+		return x + efx*x;
+	    }
+	    z = x*x;
+	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+	    y = r/s;
+	    return x + x*y;
+	}
+	if(ix < 0x3fa00000) {		/* 0.84375 <= |x| < 1.25 */
+	    s = fabsf(x)-one;
+	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+	    if(hx>=0) return erx + P/Q; else return -erx - P/Q;
+	}
+	if (ix >= 0x40c00000) {		/* inf>|x|>=6 */
+	    if(hx>=0) return one-tiny; else return tiny-one;
+	}
+	x = fabsf(x);
+ 	s = one/(x*x);
+	if(ix< 0x4036DB6E) {	/* |x| < 1/0.35 */
+	    R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+				ra5+s*(ra6+s*ra7))))));
+	    S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+				sa5+s*(sa6+s*(sa7+s*sa8)))))));
+	} else {	/* |x| >= 1/0.35 */
+	    R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+				rb5+s*rb6)))));
+	    S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+				sb5+s*(sb6+s*sb7))))));
+	}
+	GET_FLOAT_WORD(ix,x);
+	SET_FLOAT_WORD(z,ix&0xfffff000);
+	r  =  __ieee754_expf(-z*z-(float)0.5625)*__ieee754_expf((z-x)*(z+x)+R/S);
+	if(hx>=0) return one-r/x; else return  r/x-one;
+}
+
+float
+erfcf(float x)
+{
+	int32_t hx,ix;
+	float R,S,P,Q,s,y,z,r;
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;
+	if(ix>=0x7f800000) {			/* erfc(nan)=nan */
+						/* erfc(+-inf)=0,2 */
+	    return (float)(((u_int32_t)hx>>31)<<1)+one/x;
+	}
+
+	if(ix < 0x3f580000) {		/* |x|<0.84375 */
+	    if(ix < 0x23800000)  	/* |x|<2**-56 */
+		return one-x;
+	    z = x*x;
+	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+	    y = r/s;
+	    if(hx < 0x3e800000) {  	/* x<1/4 */
+		return one-(x+x*y);
+	    } else {
+		r = x*y;
+		r += (x-half);
+	        return half - r ;
+	    }
+	}
+	if(ix < 0x3fa00000) {		/* 0.84375 <= |x| < 1.25 */
+	    s = fabsf(x)-one;
+	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+	    if(hx>=0) {
+	        z  = one-erx; return z - P/Q;
+	    } else {
+		z = erx+P/Q; return one+z;
+	    }
+	}
+	if (ix < 0x41e00000) {		/* |x|<28 */
+	    x = fabsf(x);
+ 	    s = one/(x*x);
+	    if(ix< 0x4036DB6D) {	/* |x| < 1/.35 ~ 2.857143*/
+	        R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+				ra5+s*(ra6+s*ra7))))));
+	        S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+				sa5+s*(sa6+s*(sa7+s*sa8)))))));
+	    } else {			/* |x| >= 1/.35 ~ 2.857143 */
+		if(hx<0&&ix>=0x40c00000) return two-tiny;/* x < -6 */
+	        R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+				rb5+s*rb6)))));
+	        S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+				sb5+s*(sb6+s*sb7))))));
+	    }
+	    GET_FLOAT_WORD(ix,x);
+	    SET_FLOAT_WORD(z,ix&0xfffff000);
+	    r  =  __ieee754_expf(-z*z-(float)0.5625)*
+			__ieee754_expf((z-x)*(z+x)+R/S);
+	    if(hx>0) return r/x; else return two-r/x;
+	} else {
+	    if(hx>0) return tiny*tiny; else return two-tiny;
+	}
+}
Index: /trunk/libc/src/msun/src/s_exp2.c
===================================================================
--- /trunk/libc/src/msun/src/s_exp2.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_exp2.c	(revision 2448)
@@ -0,0 +1,390 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_exp2.c,v 1.1 2005/04/05 02:57:15 das Exp $");
+
+#include "math.h"
+#include "math_private.h"
+
+#define	TBLBITS	8
+#define	TBLSIZE	(1 << TBLBITS)
+
+static const double
+    huge     = 0x1p1000,
+    twom1000 = 0x1p-1000,
+    redux    = 0x1.8p52 / TBLSIZE,
+    P1	     = 0x1.62e42fefa39efp-1,
+    P2	     = 0x1.ebfbdff82c575p-3,
+    P3	     = 0x1.c6b08d704a0a6p-5,
+    P4	     = 0x1.3b2ab88f70400p-7,
+    P5	     = 0x1.5d88003875c74p-10;
+
+static const double tbl[TBLSIZE * 2] = {
+/*	exp2(z + eps)		eps	*/
+	0x1.6a09e667f3d5dp-1,	 0x1.9880p-44,
+	0x1.6b052fa751744p-1,	 0x1.8000p-50,
+	0x1.6c012750bd9fep-1,	-0x1.8780p-45,
+	0x1.6cfdcddd476bfp-1,	 0x1.ec00p-46,
+	0x1.6dfb23c651a29p-1,	-0x1.8000p-50,
+	0x1.6ef9298593ae3p-1,	-0x1.c000p-52,
+	0x1.6ff7df9519386p-1,	-0x1.fd80p-45,
+	0x1.70f7466f42da3p-1,	-0x1.c880p-45,
+	0x1.71f75e8ec5fc3p-1,	 0x1.3c00p-46,
+	0x1.72f8286eacf05p-1,	-0x1.8300p-44,
+	0x1.73f9a48a58152p-1,	-0x1.0c00p-47,
+	0x1.74fbd35d7ccfcp-1,	 0x1.f880p-45,
+	0x1.75feb564267f1p-1,	 0x1.3e00p-47,
+	0x1.77024b1ab6d48p-1,	-0x1.7d00p-45,
+	0x1.780694fde5d38p-1,	-0x1.d000p-50,
+	0x1.790b938ac1d00p-1,	 0x1.3000p-49,
+	0x1.7a11473eb0178p-1,	-0x1.d000p-49,
+	0x1.7b17b0976d060p-1,	 0x1.0400p-45,
+	0x1.7c1ed0130c133p-1,	 0x1.0000p-53,
+	0x1.7d26a62ff8636p-1,	-0x1.6900p-45,
+	0x1.7e2f336cf4e3bp-1,	-0x1.2e00p-47,
+	0x1.7f3878491c3e8p-1,	-0x1.4580p-45,
+	0x1.80427543e1b4ep-1,	 0x1.3000p-44,
+	0x1.814d2add1071ap-1,	 0x1.f000p-47,
+	0x1.82589994ccd7ep-1,	-0x1.1c00p-45,
+	0x1.8364c1eb942d0p-1,	 0x1.9d00p-45,
+	0x1.8471a4623cab5p-1,	 0x1.7100p-43,
+	0x1.857f4179f5bbcp-1,	 0x1.2600p-45,
+	0x1.868d99b4491afp-1,	-0x1.2c40p-44,
+	0x1.879cad931a395p-1,	-0x1.3000p-45,
+	0x1.88ac7d98a65b8p-1,	-0x1.a800p-45,
+	0x1.89bd0a4785800p-1,	-0x1.d000p-49,
+	0x1.8ace5422aa223p-1,	 0x1.3280p-44,
+	0x1.8be05bad619fap-1,	 0x1.2b40p-43,
+	0x1.8cf3216b54383p-1,	-0x1.ed00p-45,
+	0x1.8e06a5e08664cp-1,	-0x1.0500p-45,
+	0x1.8f1ae99157807p-1,	 0x1.8280p-45,
+	0x1.902fed0282c0ep-1,	-0x1.cb00p-46,
+	0x1.9145b0b91ff96p-1,	-0x1.5e00p-47,
+	0x1.925c353aa2ff9p-1,	 0x1.5400p-48,
+	0x1.93737b0cdc64ap-1,	 0x1.7200p-46,
+	0x1.948b82b5f98aep-1,	-0x1.9000p-47,
+	0x1.95a44cbc852cbp-1,	 0x1.5680p-45,
+	0x1.96bdd9a766f21p-1,	-0x1.6d00p-44,
+	0x1.97d829fde4e2ap-1,	-0x1.1000p-47,
+	0x1.98f33e47a23a3p-1,	 0x1.d000p-45,
+	0x1.9a0f170ca0604p-1,	-0x1.8a40p-44,
+	0x1.9b2bb4d53ff89p-1,	 0x1.55c0p-44,
+	0x1.9c49182a3f15bp-1,	 0x1.6b80p-45,
+	0x1.9d674194bb8c5p-1,	-0x1.c000p-49,
+	0x1.9e86319e3238ep-1,	 0x1.7d00p-46,
+	0x1.9fa5e8d07f302p-1,	 0x1.6400p-46,
+	0x1.a0c667b5de54dp-1,	-0x1.5000p-48,
+	0x1.a1e7aed8eb8f6p-1,	 0x1.9e00p-47,
+	0x1.a309bec4a2e27p-1,	 0x1.ad80p-45,
+	0x1.a42c980460a5dp-1,	-0x1.af00p-46,
+	0x1.a5503b23e259bp-1,	 0x1.b600p-47,
+	0x1.a674a8af46213p-1,	 0x1.8880p-44,
+	0x1.a799e1330b3a7p-1,	 0x1.1200p-46,
+	0x1.a8bfe53c12e8dp-1,	 0x1.6c00p-47,
+	0x1.a9e6b5579fcd2p-1,	-0x1.9b80p-45,
+	0x1.ab0e521356fb8p-1,	 0x1.b700p-45,
+	0x1.ac36bbfd3f381p-1,	 0x1.9000p-50,
+	0x1.ad5ff3a3c2780p-1,	 0x1.4000p-49,
+	0x1.ae89f995ad2a3p-1,	-0x1.c900p-45,
+	0x1.afb4ce622f367p-1,	 0x1.6500p-46,
+	0x1.b0e07298db790p-1,	 0x1.fd40p-45,
+	0x1.b20ce6c9a89a9p-1,	 0x1.2700p-46,
+	0x1.b33a2b84f1a4bp-1,	 0x1.d470p-43,
+	0x1.b468415b747e7p-1,	-0x1.8380p-44,
+	0x1.b59728de5593ap-1,	 0x1.8000p-54,
+	0x1.b6c6e29f1c56ap-1,	 0x1.ad00p-47,
+	0x1.b7f76f2fb5e50p-1,	 0x1.e800p-50,
+	0x1.b928cf22749b2p-1,	-0x1.4c00p-47,
+	0x1.ba5b030a10603p-1,	-0x1.d700p-47,
+	0x1.bb8e0b79a6f66p-1,	 0x1.d900p-47,
+	0x1.bcc1e904bc1ffp-1,	 0x1.2a00p-47,
+	0x1.bdf69c3f3a16fp-1,	-0x1.f780p-46,
+	0x1.bf2c25bd71db8p-1,	-0x1.0a00p-46,
+	0x1.c06286141b2e9p-1,	-0x1.1400p-46,
+	0x1.c199bdd8552e0p-1,	 0x1.be00p-47,
+	0x1.c2d1cd9fa64eep-1,	-0x1.9400p-47,
+	0x1.c40ab5fffd02fp-1,	-0x1.ed00p-47,
+	0x1.c544778fafd15p-1,	 0x1.9660p-44,
+	0x1.c67f12e57d0cbp-1,	-0x1.a100p-46,
+	0x1.c7ba88988c1b6p-1,	-0x1.8458p-42,
+	0x1.c8f6d9406e733p-1,	-0x1.a480p-46,
+	0x1.ca3405751c4dfp-1,	 0x1.b000p-51,
+	0x1.cb720dcef9094p-1,	 0x1.1400p-47,
+	0x1.ccb0f2e6d1689p-1,	 0x1.0200p-48,
+	0x1.cdf0b555dc412p-1,	 0x1.3600p-48,
+	0x1.cf3155b5bab3bp-1,	-0x1.6900p-47,
+	0x1.d072d4a0789bcp-1,	 0x1.9a00p-47,
+	0x1.d1b532b08c8fap-1,	-0x1.5e00p-46,
+	0x1.d2f87080d8a85p-1,	 0x1.d280p-46,
+	0x1.d43c8eacaa203p-1,	 0x1.1a00p-47,
+	0x1.d5818dcfba491p-1,	 0x1.f000p-50,
+	0x1.d6c76e862e6a1p-1,	-0x1.3a00p-47,
+	0x1.d80e316c9834ep-1,	-0x1.cd80p-47,
+	0x1.d955d71ff6090p-1,	 0x1.4c00p-48,
+	0x1.da9e603db32aep-1,	 0x1.f900p-48,
+	0x1.dbe7cd63a8325p-1,	 0x1.9800p-49,
+	0x1.dd321f301b445p-1,	-0x1.5200p-48,
+	0x1.de7d5641c05bfp-1,	-0x1.d700p-46,
+	0x1.dfc97337b9aecp-1,	-0x1.6140p-46,
+	0x1.e11676b197d5ep-1,	 0x1.b480p-47,
+	0x1.e264614f5a3e7p-1,	 0x1.0ce0p-43,
+	0x1.e3b333b16ee5cp-1,	 0x1.c680p-47,
+	0x1.e502ee78b3fb4p-1,	-0x1.9300p-47,
+	0x1.e653924676d68p-1,	-0x1.5000p-49,
+	0x1.e7a51fbc74c44p-1,	-0x1.7f80p-47,
+	0x1.e8f7977cdb726p-1,	-0x1.3700p-48,
+	0x1.ea4afa2a490e8p-1,	 0x1.5d00p-49,
+	0x1.eb9f4867ccae4p-1,	 0x1.61a0p-46,
+	0x1.ecf482d8e680dp-1,	 0x1.5500p-48,
+	0x1.ee4aaa2188514p-1,	 0x1.6400p-51,
+	0x1.efa1bee615a13p-1,	-0x1.e800p-49,
+	0x1.f0f9c1cb64106p-1,	-0x1.a880p-48,
+	0x1.f252b376bb963p-1,	-0x1.c900p-45,
+	0x1.f3ac948dd7275p-1,	 0x1.a000p-53,
+	0x1.f50765b6e4524p-1,	-0x1.4f00p-48,
+	0x1.f6632798844fdp-1,	 0x1.a800p-51,
+	0x1.f7bfdad9cbe38p-1,	 0x1.abc0p-48,
+	0x1.f91d802243c82p-1,	-0x1.4600p-50,
+	0x1.fa7c1819e908ep-1,	-0x1.b0c0p-47,
+	0x1.fbdba3692d511p-1,	-0x1.0e00p-51,
+	0x1.fd3c22b8f7194p-1,	-0x1.0de8p-46,
+	0x1.fe9d96b2a23eep-1,	 0x1.e430p-49,
+	0x1.0000000000000p+0,	 0x0.0000p+0,
+	0x1.00b1afa5abcbep+0,	-0x1.3400p-52,
+	0x1.0163da9fb3303p+0,	-0x1.2170p-46,
+	0x1.02168143b0282p+0,	 0x1.a400p-52,
+	0x1.02c9a3e77806cp+0,	 0x1.f980p-49,
+	0x1.037d42e11bbcap+0,	-0x1.7400p-51,
+	0x1.04315e86e7f89p+0,	 0x1.8300p-50,
+	0x1.04e5f72f65467p+0,	-0x1.a3f0p-46,
+	0x1.059b0d315855ap+0,	-0x1.2840p-47,
+	0x1.0650a0e3c1f95p+0,	 0x1.1600p-48,
+	0x1.0706b29ddf71ap+0,	 0x1.5240p-46,
+	0x1.07bd42b72a82dp+0,	-0x1.9a00p-49,
+	0x1.0874518759bd0p+0,	 0x1.6400p-49,
+	0x1.092bdf66607c8p+0,	-0x1.0780p-47,
+	0x1.09e3ecac6f383p+0,	-0x1.8000p-54,
+	0x1.0a9c79b1f3930p+0,	 0x1.fa00p-48,
+	0x1.0b5586cf988fcp+0,	-0x1.ac80p-48,
+	0x1.0c0f145e46c8ap+0,	 0x1.9c00p-50,
+	0x1.0cc922b724816p+0,	 0x1.5200p-47,
+	0x1.0d83b23395dd8p+0,	-0x1.ad00p-48,
+	0x1.0e3ec32d3d1f3p+0,	 0x1.bac0p-46,
+	0x1.0efa55fdfa9a6p+0,	-0x1.4e80p-47,
+	0x1.0fb66affed2f0p+0,	-0x1.d300p-47,
+	0x1.1073028d7234bp+0,	 0x1.1500p-48,
+	0x1.11301d0125b5bp+0,	 0x1.c000p-49,
+	0x1.11edbab5e2af9p+0,	 0x1.6bc0p-46,
+	0x1.12abdc06c31d5p+0,	 0x1.8400p-49,
+	0x1.136a814f2047dp+0,	-0x1.ed00p-47,
+	0x1.1429aaea92de9p+0,	 0x1.8e00p-49,
+	0x1.14e95934f3138p+0,	 0x1.b400p-49,
+	0x1.15a98c8a58e71p+0,	 0x1.5300p-47,
+	0x1.166a45471c3dfp+0,	 0x1.3380p-47,
+	0x1.172b83c7d5211p+0,	 0x1.8d40p-45,
+	0x1.17ed48695bb9fp+0,	-0x1.5d00p-47,
+	0x1.18af9388c8d93p+0,	-0x1.c880p-46,
+	0x1.1972658375d66p+0,	 0x1.1f00p-46,
+	0x1.1a35beb6fcba7p+0,	 0x1.0480p-46,
+	0x1.1af99f81387e3p+0,	-0x1.7390p-43,
+	0x1.1bbe084045d54p+0,	 0x1.4e40p-45,
+	0x1.1c82f95281c43p+0,	-0x1.a200p-47,
+	0x1.1d4873168b9b2p+0,	 0x1.3800p-49,
+	0x1.1e0e75eb44031p+0,	 0x1.ac00p-49,
+	0x1.1ed5022fcd938p+0,	 0x1.1900p-47,
+	0x1.1f9c18438cdf7p+0,	-0x1.b780p-46,
+	0x1.2063b88628d8fp+0,	 0x1.d940p-45,
+	0x1.212be3578a81ep+0,	 0x1.8000p-50,
+	0x1.21f49917ddd41p+0,	 0x1.b340p-45,
+	0x1.22bdda2791323p+0,	 0x1.9f80p-46,
+	0x1.2387a6e7561e7p+0,	-0x1.9c80p-46,
+	0x1.2451ffb821427p+0,	 0x1.2300p-47,
+	0x1.251ce4fb2a602p+0,	-0x1.3480p-46,
+	0x1.25e85711eceb0p+0,	 0x1.2700p-46,
+	0x1.26b4565e27d16p+0,	 0x1.1d00p-46,
+	0x1.2780e341de00fp+0,	 0x1.1ee0p-44,
+	0x1.284dfe1f5633ep+0,	-0x1.4c00p-46,
+	0x1.291ba7591bb30p+0,	-0x1.3d80p-46,
+	0x1.29e9df51fdf09p+0,	 0x1.8b00p-47,
+	0x1.2ab8a66d10e9bp+0,	-0x1.27c0p-45,
+	0x1.2b87fd0dada3ap+0,	 0x1.a340p-45,
+	0x1.2c57e39771af9p+0,	-0x1.0800p-46,
+	0x1.2d285a6e402d9p+0,	-0x1.ed00p-47,
+	0x1.2df961f641579p+0,	-0x1.4200p-48,
+	0x1.2ecafa93e2ecfp+0,	-0x1.4980p-45,
+	0x1.2f9d24abd8822p+0,	-0x1.6300p-46,
+	0x1.306fe0a31b625p+0,	-0x1.2360p-44,
+	0x1.31432edeea50bp+0,	-0x1.0df8p-40,
+	0x1.32170fc4cd7b8p+0,	-0x1.2480p-45,
+	0x1.32eb83ba8e9a2p+0,	-0x1.5980p-45,
+	0x1.33c08b2641766p+0,	 0x1.ed00p-46,
+	0x1.3496266e3fa27p+0,	-0x1.c000p-50,
+	0x1.356c55f929f0fp+0,	-0x1.0d80p-44,
+	0x1.36431a2de88b9p+0,	 0x1.2c80p-45,
+	0x1.371a7373aaa39p+0,	 0x1.0600p-45,
+	0x1.37f26231e74fep+0,	-0x1.6600p-46,
+	0x1.38cae6d05d838p+0,	-0x1.ae00p-47,
+	0x1.39a401b713ec3p+0,	-0x1.4720p-43,
+	0x1.3a7db34e5a020p+0,	 0x1.8200p-47,
+	0x1.3b57fbfec6e95p+0,	 0x1.e800p-44,
+	0x1.3c32dc313a8f2p+0,	 0x1.f800p-49,
+	0x1.3d0e544ede122p+0,	-0x1.7a00p-46,
+	0x1.3dea64c1234bbp+0,	 0x1.6300p-45,
+	0x1.3ec70df1c4eccp+0,	-0x1.8a60p-43,
+	0x1.3fa4504ac7e8cp+0,	-0x1.cdc0p-44,
+	0x1.40822c367a0bbp+0,	 0x1.5b80p-45,
+	0x1.4160a21f72e95p+0,	 0x1.ec00p-46,
+	0x1.423fb27094646p+0,	-0x1.3600p-46,
+	0x1.431f5d950a920p+0,	 0x1.3980p-45,
+	0x1.43ffa3f84b9ebp+0,	 0x1.a000p-48,
+	0x1.44e0860618919p+0,	-0x1.6c00p-48,
+	0x1.45c2042a7d201p+0,	-0x1.bc00p-47,
+	0x1.46a41ed1d0016p+0,	-0x1.2800p-46,
+	0x1.4786d668b3326p+0,	 0x1.0e00p-44,
+	0x1.486a2b5c13c00p+0,	-0x1.d400p-45,
+	0x1.494e1e192af04p+0,	 0x1.c200p-47,
+	0x1.4a32af0d7d372p+0,	-0x1.e500p-46,
+	0x1.4b17dea6db801p+0,	 0x1.7800p-47,
+	0x1.4bfdad53629e1p+0,	-0x1.3800p-46,
+	0x1.4ce41b817c132p+0,	 0x1.0800p-47,
+	0x1.4dcb299fddddbp+0,	 0x1.c700p-45,
+	0x1.4eb2d81d8ab96p+0,	-0x1.ce00p-46,
+	0x1.4f9b2769d2d02p+0,	 0x1.9200p-46,
+	0x1.508417f4531c1p+0,	-0x1.8c00p-47,
+	0x1.516daa2cf662ap+0,	-0x1.a000p-48,
+	0x1.5257de83f51eap+0,	 0x1.a080p-43,
+	0x1.5342b569d4edap+0,	-0x1.6d80p-45,
+	0x1.542e2f4f6ac1ap+0,	-0x1.2440p-44,
+	0x1.551a4ca5d94dbp+0,	 0x1.83c0p-43,
+	0x1.56070dde9116bp+0,	 0x1.4b00p-45,
+	0x1.56f4736b529dep+0,	 0x1.15a0p-43,
+	0x1.57e27dbe2c40ep+0,	-0x1.9e00p-45,
+	0x1.58d12d497c76fp+0,	-0x1.3080p-45,
+	0x1.59c0827ff0b4cp+0,	 0x1.dec0p-43,
+	0x1.5ab07dd485427p+0,	-0x1.4000p-51,
+	0x1.5ba11fba87af4p+0,	 0x1.0080p-44,
+	0x1.5c9268a59460bp+0,	-0x1.6c80p-45,
+	0x1.5d84590998e3fp+0,	 0x1.69a0p-43,
+	0x1.5e76f15ad20e1p+0,	-0x1.b400p-46,
+	0x1.5f6a320dcebcap+0,	 0x1.7700p-46,
+	0x1.605e1b976dcb8p+0,	 0x1.6f80p-45,
+	0x1.6152ae6cdf715p+0,	 0x1.1000p-47,
+	0x1.6247eb03a5531p+0,	-0x1.5d00p-46,
+	0x1.633dd1d1929b5p+0,	-0x1.2d00p-46,
+	0x1.6434634ccc313p+0,	-0x1.a800p-49,
+	0x1.652b9febc8efap+0,	-0x1.8600p-45,
+	0x1.6623882553397p+0,	 0x1.1fe0p-40,
+	0x1.671c1c708328ep+0,	-0x1.7200p-44,
+	0x1.68155d44ca97ep+0,	 0x1.6800p-49,
+	0x1.690f4b19e9471p+0,	-0x1.9780p-45,
+};
+
+/*
+ * exp2(x): compute the base 2 exponential of x
+ *
+ * Accuracy: Peak error < 0.503 ulp for normalized results.
+ *
+ * Method: (accurate tables)
+ *
+ *   Reduce x:
+ *     x = 2**k + y, for integer k and |y| <= 1/2.
+ *     Thus we have exp2(x) = 2**k * exp2(y).
+ *
+ *   Reduce y:
+ *     y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE.
+ *     Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]),
+ *     with |z - eps[i]| <= 2**-9 + 2**-39 for the table used.
+ *
+ *   We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via
+ *   a degree-5 minimax polynomial with maximum error under 1.3 * 2**-61.
+ *   The values in exp2t[] and eps[] are chosen such that
+ *   exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such
+ *   that exp2t[i] is accurate to 2**-64.
+ *
+ *   Note that the range of i is +-TBLSIZE/2, so we actually index the tables
+ *   by i0 = i + TBLSIZE/2.  For cache efficiency, exp2t[] and eps[] are
+ *   virtual tables, interleaved in the real table tbl[].
+ *
+ *   This method is due to Gal, with many details due to Gal and Bachelis:
+ *
+ *	Gal, S. and Bachelis, B.  An Accurate Elementary Mathematical Library
+ *	for the IEEE Floating Point Standard.  TOMS 17(1), 26-46 (1991).
+ */
+double
+exp2(double x)
+{
+	double r, t, z;
+	uint32_t hx, hr, ix, lx, i0;
+	int k;
+
+	/* Filter out exceptional cases. */
+	GET_HIGH_WORD(hx,x);
+	ix = hx & 0x7fffffff;		/* high word of |x| */
+	if(ix >= 0x40900000) {			/* |x| >= 1024 */
+		if(ix >= 0x7ff00000) {
+			GET_LOW_WORD(lx,x);
+			if(((ix & 0xfffff) | lx) != 0 || (hx & 0x80000000) == 0)
+				return (x); 	/* x is NaN or +Inf */
+			else
+				return (0.0);	/* x is -Inf */
+		}
+		if(x >= 0x1.0p10)
+			return (huge * huge); /* overflow */
+		if(x <= -0x1.0ccp10)
+			return (twom1000 * twom1000); /* underflow */
+	} else if (ix < 0x3c900000) {		/* |x| < 0x1p-54 */
+		return (1.0 + x);
+	}
+
+	/* Reduce x, computing z, i0, and k. */
+	t = x + redux;
+	GET_LOW_WORD(i0, t);
+	i0 += TBLSIZE / 2;
+	k = (i0 >> TBLBITS) << 20;
+	i0 = (i0 & (TBLSIZE - 1)) << 1;
+	t -= redux;
+	z = x - t;
+
+	/* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */
+	t = tbl[i0];		/* exp2t[i0] */
+	z -= tbl[i0 + 1];	/* eps[i0]   */
+	r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
+
+	/* Scale by 2**(k>>20). */
+	if(k >= -1021 << 20) {
+		if (k != 0) {
+			GET_HIGH_WORD(hr, r);
+			SET_HIGH_WORD(r, hr + k);
+		}
+		return (r);
+	} else {
+		GET_HIGH_WORD(hr, r);
+		SET_HIGH_WORD(r, hr + (k + (1000 << 20)));
+		return (r * twom1000);
+	}
+}
Index: /trunk/libc/src/msun/src/s_exp2f.c
===================================================================
--- /trunk/libc/src/msun/src/s_exp2f.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_exp2f.c	(revision 2448)
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_exp2f.c,v 1.1 2005/04/05 02:57:15 das Exp $");
+
+#include "math.h"
+#include "math_private.h"
+
+#define	TBLBITS	4
+#define	TBLSIZE	(1 << TBLBITS)
+
+static const float
+    huge    = 0x1p100f,
+    twom100 = 0x1p-100f,
+    redux   = 0x1.8p23f / TBLSIZE,
+    P1	    = 0x1.62e430p-1f,
+    P2	    = 0x1.ebfbe0p-3f,
+    P3	    = 0x1.c6b348p-5f,
+    P4	    = 0x1.3b2c9cp-7f;
+
+static const double exp2ft[TBLSIZE] = {
+	0x1.6a09e667f3bcdp-1,
+	0x1.7a11473eb0187p-1,
+	0x1.8ace5422aa0dbp-1,
+	0x1.9c49182a3f090p-1,
+	0x1.ae89f995ad3adp-1,
+	0x1.c199bdd85529cp-1,
+	0x1.d5818dcfba487p-1,
+	0x1.ea4afa2a490dap-1,
+	0x1.0000000000000p+0,
+	0x1.0b5586cf9890fp+0,
+	0x1.172b83c7d517bp+0,
+	0x1.2387a6e756238p+0,
+	0x1.306fe0a31b715p+0,
+	0x1.3dea64c123422p+0,
+	0x1.4bfdad5362a27p+0,
+	0x1.5ab07dd485429p+0,
+};
+	
+/*
+ * exp2f(x): compute the base 2 exponential of x
+ *
+ * Accuracy: Peak error < 0.501 ulp; location of peak: -0.030110927.
+ *
+ * Method: (equally-spaced tables)
+ *
+ *   Reduce x:
+ *     x = 2**k + y, for integer k and |y| <= 1/2.
+ *     Thus we have exp2f(x) = 2**k * exp2(y).
+ *
+ *   Reduce y:
+ *     y = i/TBLSIZE + z for integer i near y * TBLSIZE.
+ *     Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z),
+ *     with |z| <= 2**-(TBLSIZE+1).
+ *
+ *   We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a
+ *   degree-4 minimax polynomial with maximum error under 1.4 * 2**-33.
+ *   Using double precision in the final calculation avoids roundoff error.
+ *
+ *   This method is due to Tang, but I do not use his suggested parameters:
+ *
+ *	Tang, P.  Table-driven Implementation of the Exponential Function
+ *	in IEEE Floating-Point Arithmetic.  TOMS 15(2), 144-157 (1989).
+ */
+float
+exp2f(float x)
+{
+	double tv;
+	float r, z;
+	volatile float t;	/* prevent gcc from using too much precision */
+	uint32_t hx, hr, ix, i0;
+	int32_t k;
+
+	/* Filter out exceptional cases. */
+	GET_FLOAT_WORD(hx,x);
+	ix = hx & 0x7fffffff;		/* high word of |x| */
+	if(ix >= 0x43000000) {			/* |x| >= 128 */
+		if(ix >= 0x7f800000) {
+			if ((ix & 0x7fffff) != 0 || (hx & 0x80000000) == 0)
+				return (x); 	/* x is NaN or +Inf */
+			else
+				return (0.0);	/* x is -Inf */
+		}
+		if(x >= 0x1.0p7f)
+			return (huge * huge);	/* overflow */
+		if(x <= -0x1.2cp7f)
+			return (twom100 * twom100); /* underflow */
+	} else if (ix <= 0x33000000) {		/* |x| <= 0x1p-25 */
+		return (1.0f + x);
+	}
+
+	/* Reduce x, computing z, i0, and k. */
+	t = x + redux;
+	GET_FLOAT_WORD(i0, t);
+	i0 += TBLSIZE / 2;
+	k = (i0 >> TBLBITS) << 23;
+	i0 &= TBLSIZE - 1;
+	t -= redux;
+	z = x - t;
+
+	/* Compute r = exp2(y) = exp2ft[i0] * p(z). */
+	tv = exp2ft[i0];
+	r = tv + tv * (z * (P1 + z * (P2 + z * (P3 + z * P4))));
+
+	/* Scale by 2**(k>>23). */
+	if(k >= -125 << 23) {
+		if (k != 0) {
+			GET_FLOAT_WORD(hr, r);
+			SET_FLOAT_WORD(r, hr + k);
+		}
+		return (r);
+	} else {
+		GET_FLOAT_WORD(hr, r);
+		SET_FLOAT_WORD(r, hr + (k + (100 << 23)));
+		return (r * twom100);
+	}
+}
Index: /trunk/libc/src/msun/src/s_expm1.c
===================================================================
--- /trunk/libc/src/msun/src/s_expm1.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_expm1.c	(revision 2448)
@@ -0,0 +1,221 @@
+/* @(#)s_expm1.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_expm1.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/* expm1(x)
+ * Returns exp(x)-1, the exponential of x minus 1.
+ *
+ * Method
+ *   1. Argument reduction:
+ *	Given x, find r and integer k such that
+ *
+ *               x = k*ln2 + r,  |r| <= 0.5*ln2 ~ 0.34658
+ *
+ *      Here a correction term c will be computed to compensate
+ *	the error in r when rounded to a floating-point number.
+ *
+ *   2. Approximating expm1(r) by a special rational function on
+ *	the interval [0,0.34658]:
+ *	Since
+ *	    r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
+ *	we define R1(r*r) by
+ *	    r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
+ *	That is,
+ *	    R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
+ *		     = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
+ *		     = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
+ *      We use a special Reme algorithm on [0,0.347] to generate
+ * 	a polynomial of degree 5 in r*r to approximate R1. The
+ *	maximum error of this polynomial approximation is bounded
+ *	by 2**-61. In other words,
+ *	    R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
+ *	where 	Q1  =  -1.6666666666666567384E-2,
+ * 		Q2  =   3.9682539681370365873E-4,
+ * 		Q3  =  -9.9206344733435987357E-6,
+ * 		Q4  =   2.5051361420808517002E-7,
+ * 		Q5  =  -6.2843505682382617102E-9;
+ *  	(where z=r*r, and the values of Q1 to Q5 are listed below)
+ *	with error bounded by
+ *	    |                  5           |     -61
+ *	    | 1.0+Q1*z+...+Q5*z   -  R1(z) | <= 2
+ *	    |                              |
+ *
+ *	expm1(r) = exp(r)-1 is then computed by the following
+ * 	specific way which minimize the accumulation rounding error:
+ *			       2     3
+ *			      r     r    [ 3 - (R1 + R1*r/2)  ]
+ *	      expm1(r) = r + --- + --- * [--------------------]
+ *		              2     2    [ 6 - r*(3 - R1*r/2) ]
+ *
+ *	To compensate the error in the argument reduction, we use
+ *		expm1(r+c) = expm1(r) + c + expm1(r)*c
+ *			   ~ expm1(r) + c + r*c
+ *	Thus c+r*c will be added in as the correction terms for
+ *	expm1(r+c). Now rearrange the term to avoid optimization
+ * 	screw up:
+ *		        (      2                                    2 )
+ *		        ({  ( r    [ R1 -  (3 - R1*r/2) ]  )  }    r  )
+ *	 expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
+ *	                ({  ( 2    [ 6 - r*(3 - R1*r/2) ]  )  }    2  )
+ *                      (                                             )
+ *
+ *		   = r - E
+ *   3. Scale back to obtain expm1(x):
+ *	From step 1, we have
+ *	   expm1(x) = either 2^k*[expm1(r)+1] - 1
+ *		    = or     2^k*[expm1(r) + (1-2^-k)]
+ *   4. Implementation notes:
+ *	(A). To save one multiplication, we scale the coefficient Qi
+ *	     to Qi*2^i, and replace z by (x^2)/2.
+ *	(B). To achieve maximum accuracy, we compute expm1(x) by
+ *	  (i)   if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
+ *	  (ii)  if k=0, return r-E
+ *	  (iii) if k=-1, return 0.5*(r-E)-0.5
+ *        (iv)	if k=1 if r < -0.25, return 2*((r+0.5)- E)
+ *	       	       else	     return  1.0+2.0*(r-E);
+ *	  (v)   if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
+ *	  (vi)  if k <= 20, return 2^k((1-2^-k)-(E-r)), else
+ *	  (vii) return 2^k(1-((E+2^-k)-r))
+ *
+ * Special cases:
+ *	expm1(INF) is INF, expm1(NaN) is NaN;
+ *	expm1(-INF) is -1, and
+ *	for finite argument, only expm1(0)=0 is exact.
+ *
+ * Accuracy:
+ *	according to an error analysis, the error is always less than
+ *	1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ *	For IEEE double
+ *	    if x >  7.09782712893383973096e+02 then expm1(x) overflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+one		= 1.0,
+huge		= 1.0e+300,
+tiny		= 1.0e-300,
+o_threshold	= 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */
+ln2_hi		= 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */
+ln2_lo		= 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */
+invln2		= 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */
+	/* scaled coefficients related to expm1 */
+Q1  =  -3.33333333333331316428e-02, /* BFA11111 111110F4 */
+Q2  =   1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */
+Q3  =  -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
+Q4  =   4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */
+Q5  =  -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
+
+double
+expm1(double x)
+{
+	double y,hi,lo,c,t,e,hxs,hfx,r1;
+	int32_t k,xsb;
+	u_int32_t hx;
+
+	GET_HIGH_WORD(hx,x);
+	xsb = hx&0x80000000;		/* sign bit of x */
+	if(xsb==0) y=x; else y= -x;	/* y = |x| */
+	hx &= 0x7fffffff;		/* high word of |x| */
+
+    /* filter out huge and non-finite argument */
+	if(hx >= 0x4043687A) {			/* if |x|>=56*ln2 */
+	    if(hx >= 0x40862E42) {		/* if |x|>=709.78... */
+                if(hx>=0x7ff00000) {
+		    u_int32_t low;
+		    GET_LOW_WORD(low,x);
+		    if(((hx&0xfffff)|low)!=0)
+		         return x+x; 	 /* NaN */
+		    else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
+	        }
+	        if(x > o_threshold) return huge*huge; /* overflow */
+	    }
+	    if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */
+		if(x+tiny<0.0)		/* raise inexact */
+		return tiny-one;	/* return -1 */
+	    }
+	}
+
+    /* argument reduction */
+	if(hx > 0x3fd62e42) {		/* if  |x| > 0.5 ln2 */
+	    if(hx < 0x3FF0A2B2) {	/* and |x| < 1.5 ln2 */
+		if(xsb==0)
+		    {hi = x - ln2_hi; lo =  ln2_lo;  k =  1;}
+		else
+		    {hi = x + ln2_hi; lo = -ln2_lo;  k = -1;}
+	    } else {
+		k  = invln2*x+((xsb==0)?0.5:-0.5);
+		t  = k;
+		hi = x - t*ln2_hi;	/* t*ln2_hi is exact here */
+		lo = t*ln2_lo;
+	    }
+	    x  = hi - lo;
+	    c  = (hi-x)-lo;
+	}
+	else if(hx < 0x3c900000) {  	/* when |x|<2**-54, return x */
+	    t = huge+x;	/* return x with inexact flags when x!=0 */
+	    return x - (t-(huge+x));
+	}
+	else k = 0;
+
+    /* x is now in primary range */
+	hfx = 0.5*x;
+	hxs = x*hfx;
+	r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
+	t  = 3.0-r1*hfx;
+	e  = hxs*((r1-t)/(6.0 - x*t));
+	if(k==0) return x - (x*e-hxs);		/* c is 0 */
+	else {
+	    e  = (x*(e-c)-c);
+	    e -= hxs;
+	    if(k== -1) return 0.5*(x-e)-0.5;
+	    if(k==1)
+	       	if(x < -0.25) return -2.0*(e-(x+0.5));
+	       	else 	      return  one+2.0*(x-e);
+	    if (k <= -2 || k>56) {   /* suffice to return exp(x)-1 */
+	        u_int32_t high;
+	        y = one-(e-x);
+		GET_HIGH_WORD(high,y);
+		SET_HIGH_WORD(y,high+(k<<20));	/* add k to y's exponent */
+	        return y-one;
+	    }
+	    t = one;
+	    if(k<20) {
+	        u_int32_t high;
+	        SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k));  /* t=1-2^-k */
+	       	y = t-(e-x);
+		GET_HIGH_WORD(high,y);
+		SET_HIGH_WORD(y,high+(k<<20));	/* add k to y's exponent */
+	   } else {
+	        u_int32_t high;
+		SET_HIGH_WORD(t,((0x3ff-k)<<20));	/* 2^-k */
+	       	y = x-(e+t);
+	       	y += one;
+		GET_HIGH_WORD(high,y);
+		SET_HIGH_WORD(y,high+(k<<20));	/* add k to y's exponent */
+	    }
+	}
+	return y;
+}
Index: /trunk/libc/src/msun/src/s_expm1f.c
===================================================================
--- /trunk/libc/src/msun/src/s_expm1f.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_expm1f.c	(revision 2448)
@@ -0,0 +1,126 @@
+/* s_expm1f.c -- float version of s_expm1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_expm1f.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+one		= 1.0,
+huge		= 1.0e+30,
+tiny		= 1.0e-30,
+o_threshold	= 8.8721679688e+01,/* 0x42b17180 */
+ln2_hi		= 6.9313812256e-01,/* 0x3f317180 */
+ln2_lo		= 9.0580006145e-06,/* 0x3717f7d1 */
+invln2		= 1.4426950216e+00,/* 0x3fb8aa3b */
+	/* scaled coefficients related to expm1 */
+Q1  =  -3.3333335072e-02, /* 0xbd088889 */
+Q2  =   1.5873016091e-03, /* 0x3ad00d01 */
+Q3  =  -7.9365076090e-05, /* 0xb8a670cd */
+Q4  =   4.0082177293e-06, /* 0x36867e54 */
+Q5  =  -2.0109921195e-07; /* 0xb457edbb */
+
+float
+expm1f(float x)
+{
+	float y,hi,lo,c,t,e,hxs,hfx,r1;
+	int32_t k,xsb;
+	u_int32_t hx;
+
+	GET_FLOAT_WORD(hx,x);
+	xsb = hx&0x80000000;		/* sign bit of x */
+	if(xsb==0) y=x; else y= -x;	/* y = |x| */
+	hx &= 0x7fffffff;		/* high word of |x| */
+
+    /* filter out huge and non-finite argument */
+	if(hx >= 0x4195b844) {			/* if |x|>=27*ln2 */
+	    if(hx >= 0x42b17218) {		/* if |x|>=88.721... */
+                if(hx>0x7f800000)
+		    return x+x; 	 /* NaN */
+		if(hx==0x7f800000)
+		    return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
+	        if(x > o_threshold) return huge*huge; /* overflow */
+	    }
+	    if(xsb!=0) { /* x < -27*ln2, return -1.0 with inexact */
+		if(x+tiny<(float)0.0)	/* raise inexact */
+		return tiny-one;	/* return -1 */
+	    }
+	}
+
+    /* argument reduction */
+	if(hx > 0x3eb17218) {		/* if  |x| > 0.5 ln2 */
+	    if(hx < 0x3F851592) {	/* and |x| < 1.5 ln2 */
+		if(xsb==0)
+		    {hi = x - ln2_hi; lo =  ln2_lo;  k =  1;}
+		else
+		    {hi = x + ln2_hi; lo = -ln2_lo;  k = -1;}
+	    } else {
+		k  = invln2*x+((xsb==0)?(float)0.5:(float)-0.5);
+		t  = k;
+		hi = x - t*ln2_hi;	/* t*ln2_hi is exact here */
+		lo = t*ln2_lo;
+	    }
+	    x  = hi - lo;
+	    c  = (hi-x)-lo;
+	}
+	else if(hx < 0x33000000) {  	/* when |x|<2**-25, return x */
+	    t = huge+x;	/* return x with inexact flags when x!=0 */
+	    return x - (t-(huge+x));
+	}
+	else k = 0;
+
+    /* x is now in primary range */
+	hfx = (float)0.5*x;
+	hxs = x*hfx;
+	r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
+	t  = (float)3.0-r1*hfx;
+	e  = hxs*((r1-t)/((float)6.0 - x*t));
+	if(k==0) return x - (x*e-hxs);		/* c is 0 */
+	else {
+	    e  = (x*(e-c)-c);
+	    e -= hxs;
+	    if(k== -1) return (float)0.5*(x-e)-(float)0.5;
+	    if(k==1)
+	       	if(x < (float)-0.25) return -(float)2.0*(e-(x+(float)0.5));
+	       	else 	      return  one+(float)2.0*(x-e);
+	    if (k <= -2 || k>56) {   /* suffice to return exp(x)-1 */
+	        int32_t i;
+	        y = one-(e-x);
+		GET_FLOAT_WORD(i,y);
+		SET_FLOAT_WORD(y,i+(k<<23));	/* add k to y's exponent */
+	        return y-one;
+	    }
+	    t = one;
+	    if(k<23) {
+	        int32_t i;
+	        SET_FLOAT_WORD(t,0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */
+	       	y = t-(e-x);
+		GET_FLOAT_WORD(i,y);
+		SET_FLOAT_WORD(y,i+(k<<23));	/* add k to y's exponent */
+	   } else {
+	        int32_t i;
+		SET_FLOAT_WORD(t,((0x7f-k)<<23));	/* 2^-k */
+	       	y = x-(e+t);
+	       	y += one;
+		GET_FLOAT_WORD(i,y);
+		SET_FLOAT_WORD(y,i+(k<<23));	/* add k to y's exponent */
+	    }
+	}
+	return y;
+}
Index: /trunk/libc/src/msun/src/s_fabs.c
===================================================================
--- /trunk/libc/src/msun/src/s_fabs.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fabs.c	(revision 2448)
@@ -0,0 +1,32 @@
+/* @(#)s_fabs.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_fabs.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/*
+ * fabs(x) returns the absolute value of x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+fabs(double x)
+{
+	u_int32_t high;
+	GET_HIGH_WORD(high,x);
+	SET_HIGH_WORD(x,high&0x7fffffff);
+        return x;
+}
Index: /trunk/libc/src/msun/src/s_fabsf.c
===================================================================
--- /trunk/libc/src/msun/src/s_fabsf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fabsf.c	(revision 2448)
@@ -0,0 +1,35 @@
+/* s_fabsf.c -- float version of s_fabs.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_fabsf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/*
+ * fabsf(x) returns the absolute value of x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+float
+fabsf(float x)
+{
+	u_int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	SET_FLOAT_WORD(x,ix&0x7fffffff);
+        return x;
+}
Index: /trunk/libc/src/msun/src/s_fabsl.c
===================================================================
--- /trunk/libc/src/msun/src/s_fabsl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fabsl.c	(revision 2448)
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2003 Dag-Erling Coïdan Smørgrav
+ * 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
+ *    in this position and unchanged.
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_fabsl.c,v 1.2 2003/10/25 19:53:28 des Exp $
+ */
+
+#include "namespace.h"
+#include <math.h>
+
+#include "fpmath.h"
+
+long double
+fabsl(long double x)
+{
+	union IEEEl2bits u;
+
+	u.e = x;
+	u.bits.sign = 0;
+	return (u.e);
+}
Index: /trunk/libc/src/msun/src/s_fdim.c
===================================================================
--- /trunk/libc/src/msun/src/s_fdim.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fdim.c	(revision 2448)
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fdim.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <math.h>
+
+#define	DECL(type, fn)			\
+type					\
+fn(type x, type y)			\
+{					\
+					\
+	if (isnan(x))			\
+		return (x);		\
+	if (isnan(y))			\
+		return (y);		\
+	return (x > y ? x - y : 0.0);	\
+}
+
+DECL(double, fdim)
+DECL(float, fdimf)
+DECL(long double, fdiml)
Index: /trunk/libc/src/msun/src/s_finite.c
===================================================================
--- /trunk/libc/src/msun/src/s_finite.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_finite.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* @(#)s_finite.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_finite.c,v 1.8 2003/07/23 04:53:46 peter Exp $";
+#endif
+
+/*
+ * finite(x) returns 1 is x is finite, else 0;
+ * no branching!
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+	int finite(double x)
+{
+	int32_t hx;
+	GET_HIGH_WORD(hx,x);
+	return (int)((u_int32_t)((hx&0x7fffffff)-0x7ff00000)>>31);
+}
Index: /trunk/libc/src/msun/src/s_finitef.c
===================================================================
--- /trunk/libc/src/msun/src/s_finitef.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_finitef.c	(revision 2448)
@@ -0,0 +1,34 @@
+/* s_finitef.c -- float version of s_finite.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_finitef.c,v 1.6 2002/05/28 17:51:46 alfred Exp $";
+#endif
+
+/*
+ * finitef(x) returns 1 is x is finite, else 0;
+ * no branching!
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+	int finitef(float x)
+{
+	int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	return (int)((u_int32_t)((ix&0x7fffffff)-0x7f800000)>>31);
+}
Index: /trunk/libc/src/msun/src/s_floor.c
===================================================================
--- /trunk/libc/src/msun/src/s_floor.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_floor.c	(revision 2448)
@@ -0,0 +1,74 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_floor.c,v 1.9 2003/07/23 04:53:46 peter Exp $";
+#endif
+
+/*
+ * floor(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to floor(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+double
+floor(double x)
+{
+	int32_t i0,i1,j0;
+	u_int32_t i,j;
+	EXTRACT_WORDS(i0,i1,x);
+	j0 = ((i0>>20)&0x7ff)-0x3ff;
+	if(j0<20) {
+	    if(j0<0) { 	/* raise inexact if x != 0 */
+		if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+		    if(i0>=0) {i0=i1=0;}
+		    else if(((i0&0x7fffffff)|i1)!=0)
+			{ i0=0xbff00000;i1=0;}
+		}
+	    } else {
+		i = (0x000fffff)>>j0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		if(huge+x>0.0) {	/* raise inexact flag */
+		    if(i0<0) i0 += (0x00100000)>>j0;
+		    i0 &= (~i); i1=0;
+		}
+	    }
+	} else if (j0>51) {
+	    if(j0==0x400) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    if(huge+x>0.0) { 		/* raise inexact flag */
+		if(i0<0) {
+		    if(j0==20) i0+=1;
+		    else {
+			j = i1+(1<<(52-j0));
+			if(j<i1) i0 +=1 ; 	/* got a carry */
+			i1=j;
+		    }
+		}
+		i1 &= (~i);
+	    }
+	}
+	INSERT_WORDS(x,i0,i1);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_floorf.c
===================================================================
--- /trunk/libc/src/msun/src/s_floorf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_floorf.c	(revision 2448)
@@ -0,0 +1,63 @@
+/* s_floorf.c -- float version of s_floor.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_floorf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/*
+ * floorf(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to floorf(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const float huge = 1.0e30;
+
+float
+floorf(float x)
+{
+	int32_t i0,j0;
+	u_int32_t i;
+	GET_FLOAT_WORD(i0,x);
+	j0 = ((i0>>23)&0xff)-0x7f;
+	if(j0<23) {
+	    if(j0<0) { 	/* raise inexact if x != 0 */
+		if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+		    if(i0>=0) {i0=0;}
+		    else if((i0&0x7fffffff)!=0)
+			{ i0=0xbf800000;}
+		}
+	    } else {
+		i = (0x007fffff)>>j0;
+		if((i0&i)==0) return x; /* x is integral */
+		if(huge+x>(float)0.0) {	/* raise inexact flag */
+		    if(i0<0) i0 += (0x00800000)>>j0;
+		    i0 &= (~i);
+		}
+	    }
+	} else {
+	    if(j0==0x80) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	}
+	SET_FLOAT_WORD(x,i0);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_floorl.c
===================================================================
--- /trunk/libc/src/msun/src/s_floorl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_floorl.c	(revision 2448)
@@ -0,0 +1,103 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_floorl.c,v 1.3 2005/04/22 09:57:55 stefanf Exp $";
+#endif
+
+/*
+ * floorl(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to floorl(x).
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define	MANH_SIZE	(LDBL_MANH_SIZE + 1)
+#define	INC_MANH(u, c)	do {					\
+	uint64_t o = u.bits.manh;				\
+	u.bits.manh += (c);					\
+	if (u.bits.manh < o)					\
+		u.bits.exp++;					\
+} while (0)
+#else
+#define	MANH_SIZE	LDBL_MANH_SIZE
+#define	INC_MANH(u, c)	do {					\
+	uint64_t o = u.bits.manh;				\
+	u.bits.manh += (c);					\
+	if (u.bits.manh < o) {					\
+		u.bits.exp++;					\
+		u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1);	\
+	}							\
+} while (0)
+#endif
+
+static const double huge = 1.0e300;
+
+long double
+floorl(long double x)
+{
+	union IEEEl2bits u = { .e = x };
+	int e = u.bits.exp - LDBL_MAX_EXP + 1;
+
+	if (e < MANH_SIZE - 1) {
+		if (e < 0) {			/* raise inexact if x != 0 */
+			if (huge + (double)x > 0.0)
+				if (u.bits.exp > 0 ||
+				    (u.bits.manh | u.bits.manl) != 0)
+					u.e = u.bits.sign ? -1.0 : 0.0;
+		} else {
+			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+			if (((u.bits.manh & m) | u.bits.manl) == 0)
+				return (x);	/* x is integral */
+			if (u.bits.sign) {
+#ifdef LDBL_IMPLICIT_NBIT
+				if (e == 0)
+					u.bits.exp++;
+				else
+#endif
+				INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
+			}
+			if (huge + (double)x > 0.0) {	/* raise inexact flag */
+				u.bits.manh &= ~m;
+				u.bits.manl = 0;
+			}
+		}
+	} else if (e < LDBL_MANT_DIG - 1) {
+		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+		if ((u.bits.manl & m) == 0)
+			return (x);	/* x is integral */
+		if (u.bits.sign) {
+			if (e == MANH_SIZE - 1)
+				INC_MANH(u, 1);
+			else {
+				uint64_t o = u.bits.manl;
+				u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
+				if (u.bits.manl < o)	/* got a carry */
+					INC_MANH(u, 1);
+			}
+		}
+		if (huge + (double)x > 0.0)	/* raise inexact flag */
+			u.bits.manl &= ~m;
+	}
+	return (u.e);
+}
Index: /trunk/libc/src/msun/src/s_fma.c
===================================================================
--- /trunk/libc/src/msun/src/s_fma.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fma.c	(revision 2448)
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fma.c,v 1.4 2005/03/18 02:27:59 das Exp $");
+
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * We use scaling to avoid overflow/underflow, along with the
+ * canonical precision-doubling technique adapted from:
+ *
+ *	Dekker, T.  A Floating-Point Technique for Extending the
+ *	Available Precision.  Numer. Math. 18, 224-242 (1971).
+ *
+ * This algorithm is sensitive to the rounding precision.  FPUs such
+ * as the i387 must be set in double-precision mode if variables are
+ * to be stored in FP registers in order to avoid incorrect results.
+ * This is the default on FreeBSD, but not on many other systems.
+ *
+ * Hardware instructions should be used on architectures that support it,
+ * since this implementation will likely be several times slower.
+ */
+#if LDBL_MANT_DIG != 113
+double
+fma(double x, double y, double z)
+{
+	static const double split = 0x1p27 + 1.0;
+	double xs, ys, zs;
+	double c, cc, hx, hy, p, q, tx, ty;
+	double r, rr, s;
+	int oround;
+	int ex, ey, ez;
+	int spread;
+
+	if (z == 0.0)
+		return (x * y);
+	if (x == 0.0 || y == 0.0)
+		return (x * y + z);
+
+	/* Results of frexp() are undefined for these cases. */
+	if (!isfinite(x) || !isfinite(y) || !isfinite(z))
+		return (x * y + z);
+
+	xs = frexp(x, &ex);
+	ys = frexp(y, &ey);
+	zs = frexp(z, &ez);
+	oround = fegetround();
+	spread = ex + ey - ez;
+
+	/*
+	 * If x * y and z are many orders of magnitude apart, the scaling
+	 * will overflow, so we handle these cases specially.  Rounding
+	 * modes other than FE_TONEAREST are painful.
+	 */
+	if (spread > DBL_MANT_DIG * 2) {
+		fenv_t env;
+		feraiseexcept(FE_INEXACT);
+		switch(oround) {
+		case FE_TONEAREST:
+			return (x * y);
+		case FE_TOWARDZERO:
+			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
+				return (x * y);
+			feholdexcept(&env);
+			r = x * y;
+			if (!fetestexcept(FE_INEXACT))
+				r = nextafter(r, 0);
+			feupdateenv(&env);
+			return (r);
+		case FE_DOWNWARD:
+			if (z > 0.0)
+				return (x * y);
+			feholdexcept(&env);
+			r = x * y;
+			if (!fetestexcept(FE_INEXACT))
+				r = nextafter(r, -INFINITY);
+			feupdateenv(&env);
+			return (r);
+		default:	/* FE_UPWARD */
+			if (z < 0.0)
+				return (x * y);
+			feholdexcept(&env);
+			r = x * y;
+			if (!fetestexcept(FE_INEXACT))
+				r = nextafter(r, INFINITY);
+			feupdateenv(&env);
+			return (r);
+		}
+	}
+	if (spread < -DBL_MANT_DIG) {
+		feraiseexcept(FE_INEXACT);
+		if (!isnormal(z))
+			feraiseexcept(FE_UNDERFLOW);
+		switch (oround) {
+		case FE_TONEAREST:
+			return (z);
+		case FE_TOWARDZERO:
+			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
+				return (z);
+			else
+				return (nextafter(z, 0));
+		case FE_DOWNWARD:
+			if (x > 0.0 ^ y < 0.0)
+				return (z);
+			else
+				return (nextafter(z, -INFINITY));
+		default:	/* FE_UPWARD */
+			if (x > 0.0 ^ y < 0.0)
+				return (nextafter(z, INFINITY));
+			else
+				return (z);
+		}
+	}
+
+	/*
+	 * Use Dekker's algorithm to perform the multiplication and
+	 * subsequent addition in twice the machine precision.
+	 * Arrange so that x * y = c + cc, and x * y + z = r + rr.
+	 */
+	fesetround(FE_TONEAREST);
+
+	p = xs * split;
+	hx = xs - p;
+	hx += p;
+	tx = xs - hx;
+
+	p = ys * split;
+	hy = ys - p;
+	hy += p;
+	ty = ys - hy;
+
+	p = hx * hy;
+	q = hx * ty + tx * hy;
+	c = p + q;
+	cc = p - c + q + tx * ty;
+
+	zs = ldexp(zs, -spread);
+	r = c + zs;
+	s = r - c;
+	rr = (c - (r - s)) + (zs - s) + cc;
+
+	spread = ex + ey;
+	if (spread + ilogb(r) > -1023) {
+		fesetround(oround);
+		r = r + rr;
+	} else {
+		/*
+		 * The result is subnormal, so we round before scaling to
+		 * avoid double rounding.
+		 */
+		p = ldexp(copysign(0x1p-1022, r), -spread);
+		c = r + p;
+		s = c - r;
+		cc = (r - (c - s)) + (p - s) + rr;
+		fesetround(oround);
+		r = (c + cc) - p;
+	}
+	return (ldexp(r, spread));
+}
+#else	/* LDBL_MANT_DIG == 113 */
+/*
+ * 113 bits of precision is more than twice the precision of a double,
+ * so it is enough to represent the intermediate product exactly.
+ */
+double
+fma(double x, double y, double z)
+{
+	return ((long double)x * y + z);
+}
+#endif	/* LDBL_MANT_DIG != 113 */
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fma, fmal);
+#endif
Index: /trunk/libc/src/msun/src/s_fmaf.c
===================================================================
--- /trunk/libc/src/msun/src/s_fmaf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fmaf.c	(revision 2448)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fmaf.c,v 1.1 2005/01/22 09:53:18 das Exp $");
+#include <math.h>
+
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * A double has more than twice as much precision than a float, so
+ * direct double-precision arithmetic suffices.
+ *
+ * XXX We are relying on the compiler to convert from double to float
+ *     using the current rounding mode and with the appropriate
+ *     side-effects.  But on at least one platform (gcc 3.4.2/sparc64),
+ *     this appears to be too much to ask for.  The precision
+ *     reduction should be done manually.
+ */
+float
+fmaf(float x, float y, float z)
+{
+
+	return ((double)x * y + z);
+}
Index: /trunk/libc/src/msun/src/s_fmal.c
===================================================================
--- /trunk/libc/src/msun/src/s_fmal.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fmal.c	(revision 2448)
@@ -0,0 +1,183 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fmal.c,v 1.2 2005/03/18 02:27:59 das Exp $");
+
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * We use scaling to avoid overflow/underflow, along with the
+ * canonical precision-doubling technique adapted from:
+ *
+ *	Dekker, T.  A Floating-Point Technique for Extending the
+ *	Available Precision.  Numer. Math. 18, 224-242 (1971).
+ */
+long double
+fmal(long double x, long double y, long double z)
+{
+#if LDBL_MANT_DIG == 64
+	static const long double split = 0x1p32L + 1.0;
+#elif LDBL_MANT_DIG == 113
+	static const long double split = 0x1p57L + 1.0;
+#endif
+	long double xs, ys, zs;
+	long double c, cc, hx, hy, p, q, tx, ty;
+	long double r, rr, s;
+	int oround;
+	int ex, ey, ez;
+	int spread;
+
+	if (z == 0.0)
+		return (x * y);
+	if (x == 0.0 || y == 0.0)
+		return (x * y + z);
+
+	/* Results of frexp() are undefined for these cases. */
+	if (!isfinite(x) || !isfinite(y) || !isfinite(z))
+		return (x * y + z);
+
+	xs = frexpl(x, &ex);
+	ys = frexpl(y, &ey);
+	zs = frexpl(z, &ez);
+	oround = fegetround();
+	spread = ex + ey - ez;
+
+	/*
+	 * If x * y and z are many orders of magnitude apart, the scaling
+	 * will overflow, so we handle these cases specially.  Rounding
+	 * modes other than FE_TONEAREST are painful.
+	 */
+	if (spread > LDBL_MANT_DIG * 2) {
+		fenv_t env;
+		feraiseexcept(FE_INEXACT);
+		switch(oround) {
+		case FE_TONEAREST:
+			return (x * y);
+		case FE_TOWARDZERO:
+			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
+				return (x * y);
+			feholdexcept(&env);
+			r = x * y;
+			if (!fetestexcept(FE_INEXACT))
+				r = nextafterl(r, 0);
+			feupdateenv(&env);
+			return (r);
+		case FE_DOWNWARD:
+			if (z > 0.0)
+				return (x * y);
+			feholdexcept(&env);
+			r = x * y;
+			if (!fetestexcept(FE_INEXACT))
+				r = nextafterl(r, -INFINITY);
+			feupdateenv(&env);
+			return (r);
+		default:	/* FE_UPWARD */
+			if (z < 0.0)
+				return (x * y);
+			feholdexcept(&env);
+			r = x * y;
+			if (!fetestexcept(FE_INEXACT))
+				r = nextafterl(r, INFINITY);
+			feupdateenv(&env);
+			return (r);
+		}
+	}
+	if (spread < -LDBL_MANT_DIG) {
+		feraiseexcept(FE_INEXACT);
+		if (!isnormal(z))
+			feraiseexcept(FE_UNDERFLOW);
+		switch (oround) {
+		case FE_TONEAREST:
+			return (z);
+		case FE_TOWARDZERO:
+			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
+				return (z);
+			else
+				return (nextafterl(z, 0));
+		case FE_DOWNWARD:
+			if (x > 0.0 ^ y < 0.0)
+				return (z);
+			else
+				return (nextafterl(z, -INFINITY));
+		default:	/* FE_UPWARD */
+			if (x > 0.0 ^ y < 0.0)
+				return (nextafterl(z, INFINITY));
+			else
+				return (z);
+		}
+	}
+
+	/*
+	 * Use Dekker's algorithm to perform the multiplication and
+	 * subsequent addition in twice the machine precision.
+	 * Arrange so that x * y = c + cc, and x * y + z = r + rr.
+	 */
+	fesetround(FE_TONEAREST);
+
+	p = xs * split;
+	hx = xs - p;
+	hx += p;
+	tx = xs - hx;
+
+	p = ys * split;
+	hy = ys - p;
+	hy += p;
+	ty = ys - hy;
+
+	p = hx * hy;
+	q = hx * ty + tx * hy;
+	c = p + q;
+	cc = p - c + q + tx * ty;
+
+	zs = ldexpl(zs, -spread);
+	r = c + zs;
+	s = r - c;
+	rr = (c - (r - s)) + (zs - s) + cc;
+
+	spread = ex + ey;
+	if (spread + ilogbl(r) > -16383) {
+		fesetround(oround);
+		r = r + rr;
+	} else {
+		/*
+		 * The result is subnormal, so we round before scaling to
+		 * avoid double rounding.
+		 */
+		p = ldexpl(copysignl(0x1p-16382L, r), -spread);
+		c = r + p;
+		s = c - r;
+		cc = (r - (c - s)) + (p - s) + rr;
+		fesetround(oround);
+		r = (c + cc) - p;
+	}
+	return (ldexpl(r, spread));
+}
Index: /trunk/libc/src/msun/src/s_fmax.c
===================================================================
--- /trunk/libc/src/msun/src/s_fmax.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fmax.c	(revision 2448)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fmax.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <math.h>
+
+#include "fpmath.h"
+
+double
+fmax(double x, double y)
+{
+	union IEEEd2bits u[2];
+
+	u[0].d = x;
+	u[1].d = y;
+
+	/* Check for NaNs to avoid raising spurious exceptions. */
+	if (u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0)
+		return (y);
+	if (u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0)
+		return (x);
+
+	/* Handle comparisons of signed zeroes. */
+	if (u[0].bits.sign != u[1].bits.sign)
+		return (u[u[0].bits.sign].d);
+
+	return (x > y ? x : y);
+}
Index: /trunk/libc/src/msun/src/s_fmaxf.c
===================================================================
--- /trunk/libc/src/msun/src/s_fmaxf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fmaxf.c	(revision 2448)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fmaxf.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <math.h>
+
+#include "fpmath.h"
+
+float
+fmaxf(float x, float y)
+{
+	union IEEEf2bits u[2];
+
+	u[0].f = x;
+	u[1].f = y;
+
+	/* Check for NaNs to avoid raising spurious exceptions. */
+	if (u[0].bits.exp == 255 && u[0].bits.man != 0)
+		return (y);
+	if (u[1].bits.exp == 255 && u[1].bits.man != 0)
+		return (x);
+
+	/* Handle comparisons of signed zeroes. */
+	if (u[0].bits.sign != u[1].bits.sign)
+		return (u[u[0].bits.sign].f);
+
+	return (x > y ? x : y);
+}
Index: /trunk/libc/src/msun/src/s_fmaxl.c
===================================================================
--- /trunk/libc/src/msun/src/s_fmaxl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fmaxl.c	(revision 2448)
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fmaxl.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <math.h>
+
+#include "fpmath.h"
+
+long double
+fmaxl(long double x, long double y)
+{
+	union IEEEl2bits u[2];
+
+	u[0].e = x;
+	mask_nbit_l(u[0]);
+	u[1].e = y;
+	mask_nbit_l(u[1]);
+
+	/* Check for NaNs to avoid raising spurious exceptions. */
+	if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0)
+		return (y);
+	if (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0)
+		return (x);
+
+	/* Handle comparisons of signed zeroes. */
+	if (u[0].bits.sign != u[1].bits.sign)
+		return (u[0].bits.sign ? y : x);
+
+	return (x > y ? x : y);
+}
Index: /trunk/libc/src/msun/src/s_fmin.c
===================================================================
--- /trunk/libc/src/msun/src/s_fmin.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fmin.c	(revision 2448)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fmin.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <math.h>
+
+#include "fpmath.h"
+
+double
+fmin(double x, double y)
+{
+	union IEEEd2bits u[2];
+
+	u[0].d = x;
+	u[1].d = y;
+
+	/* Check for NaNs to avoid raising spurious exceptions. */
+	if (u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0)
+		return (y);
+	if (u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0)
+		return (x);
+
+	/* Handle comparisons of signed zeroes. */
+	if (u[0].bits.sign != u[1].bits.sign)
+		return (u[u[1].bits.sign].d);
+
+	return (x < y ? x : y);
+}
Index: /trunk/libc/src/msun/src/s_fminf.c
===================================================================
--- /trunk/libc/src/msun/src/s_fminf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fminf.c	(revision 2448)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fminf.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <math.h>
+
+#include "fpmath.h"
+
+float
+fminf(float x, float y)
+{
+	union IEEEf2bits u[2];
+
+	u[0].f = x;
+	u[1].f = y;
+
+	/* Check for NaNs to avoid raising spurious exceptions. */
+	if (u[0].bits.exp == 255 && u[0].bits.man != 0)
+		return (y);
+	if (u[1].bits.exp == 255 && u[1].bits.man != 0)
+		return (x);
+
+	/* Handle comparisons of signed zeroes. */
+	if (u[0].bits.sign != u[1].bits.sign)
+		return (u[u[1].bits.sign].f);
+
+	return (x < y ? x : y);
+}
Index: /trunk/libc/src/msun/src/s_fminl.c
===================================================================
--- /trunk/libc/src/msun/src/s_fminl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_fminl.c	(revision 2448)
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_fminl.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <math.h>
+
+#include "fpmath.h"
+
+long double
+fminl(long double x, long double y)
+{
+	union IEEEl2bits u[2];
+
+	u[0].e = x;
+	mask_nbit_l(u[0]);
+	u[1].e = y;
+	mask_nbit_l(u[1]);
+
+	/* Check for NaNs to avoid raising spurious exceptions. */
+	if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0)
+		return (y);
+	if (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0)
+		return (x);
+
+	/* Handle comparisons of signed zeroes. */
+	if (u[0].bits.sign != u[1].bits.sign)
+		return (u[1].bits.sign ? y : x);
+
+	return (x < y ? x : y);
+}
Index: /trunk/libc/src/msun/src/s_frexp.c
===================================================================
--- /trunk/libc/src/msun/src/s_frexp.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_frexp.c	(revision 2448)
@@ -0,0 +1,59 @@
+/* @(#)s_frexp.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_frexp.c,v 1.10 2005/03/07 21:27:37 das Exp $";
+#endif
+
+/*
+ * for non-zero x
+ *	x = frexp(arg,&exp);
+ * return a double fp quantity x such that 0.5 <= |x| <1.0
+ * and the corresponding binary exponent "exp". That is
+ *	arg = x*2^exp.
+ * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg
+ * with *exp=0.
+ */
+
+#include <sys/cdefs.h>
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+two54 =  1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
+
+double
+frexp(double x, int *eptr)
+{
+	int32_t hx, ix, lx;
+	EXTRACT_WORDS(hx,lx,x);
+	ix = 0x7fffffff&hx;
+	*eptr = 0;
+	if(ix>=0x7ff00000||((ix|lx)==0)) return x;	/* 0,inf,nan */
+	if (ix<0x00100000) {		/* subnormal */
+	    x *= two54;
+	    GET_HIGH_WORD(hx,x);
+	    ix = hx&0x7fffffff;
+	    *eptr = -54;
+	}
+	*eptr += (ix>>20)-1022;
+	hx = (hx&0x800fffff)|0x3fe00000;
+	SET_HIGH_WORD(x,hx);
+	return x;
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(frexp, frexpl);
+#endif
Index: /trunk/libc/src/msun/src/s_frexpf.c
===================================================================
--- /trunk/libc/src/msun/src/s_frexpf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_frexpf.c	(revision 2448)
@@ -0,0 +1,45 @@
+/* s_frexpf.c -- float version of s_frexp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_frexpf.c,v 1.8 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+two25 =  3.3554432000e+07; /* 0x4c000000 */
+
+float
+frexpf(float x, int *eptr)
+{
+	int32_t hx,ix;
+	GET_FLOAT_WORD(hx,x);
+	ix = 0x7fffffff&hx;
+	*eptr = 0;
+	if(ix>=0x7f800000||(ix==0)) return x;	/* 0,inf,nan */
+	if (ix<0x00800000) {		/* subnormal */
+	    x *= two25;
+	    GET_FLOAT_WORD(hx,x);
+	    ix = hx&0x7fffffff;
+	    *eptr = -25;
+	}
+	*eptr += (ix>>23)-126;
+	hx = (hx&0x807fffff)|0x3f000000;
+	*(int*)&x = hx;
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_frexpl.c
===================================================================
--- /trunk/libc/src/msun/src/s_frexpl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_frexpl.c	(revision 2448)
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_frexpl.c,v 1.1 2005/03/07 04:54:51 das Exp $
+ */
+
+#include "namespace.h"
+#include <float.h>
+#include <math.h>
+
+#include "fpmath.h"
+
+#if LDBL_MAX_EXP != 0x4000
+#error "Unsupported long double format"
+#endif
+
+long double
+frexpl(long double x, int *ex)
+{
+	union IEEEl2bits u;
+
+	u.e = x;
+	switch (u.bits.exp) {
+	case 0:		/* 0 or subnormal */
+		if ((u.bits.manl | u.bits.manh) == 0) {
+			*ex = 0;
+		} else {
+			u.e *= 0x1.0p514;
+			*ex = u.bits.exp - 0x4200;
+			u.bits.exp = 0x3ffe;
+		}
+		break;
+	case 0x7fff:	/* infinity or NaN; value of *ex is unspecified */
+		break;
+	default:	/* normal */
+		*ex = u.bits.exp - 0x3ffe;
+		u.bits.exp = 0x3ffe;
+		break;
+	}
+	return (u.e);
+}
Index: /trunk/libc/src/msun/src/s_ilogb.c
===================================================================
--- /trunk/libc/src/msun/src/s_ilogb.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_ilogb.c	(revision 2448)
@@ -0,0 +1,50 @@
+/* @(#)s_ilogb.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_ilogb.c,v 1.9 2004/10/09 17:14:28 stefanf Exp $";
+#endif
+
+/* ilogb(double x)
+ * return the binary exponent of non-zero x
+ * ilogb(0) = FP_ILOGB0
+ * ilogb(NaN) = FP_ILOGBNAN (no signal is raised)
+ * ilogb(inf) = INT_MAX (no signal is raised)
+ */
+
+#include <limits.h>
+
+#include "math.h"
+#include "math_private.h"
+
+	int ilogb(double x)
+{
+	int32_t hx,lx,ix;
+
+	EXTRACT_WORDS(hx,lx,x);
+	hx &= 0x7fffffff;
+	if(hx<0x00100000) {
+	    if((hx|lx)==0)
+		return FP_ILOGB0;
+	    else			/* subnormal x */
+		if(hx==0) {
+		    for (ix = -1043; lx>0; lx<<=1) ix -=1;
+		} else {
+		    for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1;
+		}
+	    return ix;
+	}
+	else if (hx<0x7ff00000) return (hx>>20)-1023;
+	else if (hx>0x7ff00000 || lx!=0) return FP_ILOGBNAN;
+	else return INT_MAX;
+}
Index: /trunk/libc/src/msun/src/s_ilogbf.c
===================================================================
--- /trunk/libc/src/msun/src/s_ilogbf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_ilogbf.c	(revision 2448)
@@ -0,0 +1,42 @@
+/* s_ilogbf.c -- float version of s_ilogb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_ilogbf.c,v 1.7 2004/10/09 17:14:28 stefanf Exp $";
+#endif
+
+#include <limits.h>
+
+#include "math.h"
+#include "math_private.h"
+
+	int ilogbf(float x)
+{
+	int32_t hx,ix;
+
+	GET_FLOAT_WORD(hx,x);
+	hx &= 0x7fffffff;
+	if(hx<0x00800000) {
+	    if(hx==0)
+		return FP_ILOGB0;
+	    else			/* subnormal x */
+	        for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1;
+	    return ix;
+	}
+	else if (hx<0x7f800000) return (hx>>23)-127;
+	else if (hx>0x7f800000) return FP_ILOGBNAN;
+	else return INT_MAX;
+}
Index: /trunk/libc/src/msun/src/s_ilogbl.c
===================================================================
--- /trunk/libc/src/msun/src/s_ilogbl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_ilogbl.c	(revision 2448)
@@ -0,0 +1,55 @@
+/*
+ * From: @(#)s_ilogb.c 5.1 93/09/24
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_ilogbl.c,v 1.1 2004/10/11 18:13:52 stefanf Exp $";
+#endif
+
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+
+#include "fpmath.h"
+
+int
+ilogbl(long double x)
+{
+	union IEEEl2bits u;
+	unsigned long m;
+	int b;
+
+	u.e = x;
+	if (u.bits.exp == 0) {
+		if ((u.bits.manl | u.bits.manh) == 0)
+			return (FP_ILOGB0);
+		/* denormalized */
+		if (u.bits.manh == 0) {
+			m = 1lu << (LDBL_MANL_SIZE - 1);
+			for (b = LDBL_MANH_SIZE; !(u.bits.manl & m); m >>= 1)
+				b++;
+		} else {
+			m = 1lu << (LDBL_MANH_SIZE - 1);
+			for (b = 0; !(u.bits.manh & m); m >>= 1)
+				b++;
+		}
+#ifdef LDBL_IMPLICIT_NBIT
+		b++;
+#endif
+		return (LDBL_MIN_EXP - b - 1);
+	} else if (u.bits.exp < (LDBL_MAX_EXP << 1) - 1)
+		return (u.bits.exp - LDBL_MAX_EXP + 1);
+	else if (u.bits.manl != 0 || u.bits.manh != 0)
+		return (FP_ILOGBNAN);
+	else
+		return (INT_MAX);
+}
Index: /trunk/libc/src/msun/src/s_isfinite.c
===================================================================
--- /trunk/libc/src/msun/src/s_isfinite.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_isfinite.c	(revision 2448)
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_isfinite.c,v 1.1 2004/07/09 03:32:39 das Exp $
+ */
+
+#include "namespace.h"
+#include <math.h>
+
+#include "fpmath.h"
+
+int
+__isfinite(double d)
+{
+	union IEEEd2bits u;
+
+	u.d = d;
+	return (u.bits.exp != 2047);
+}
+
+int
+__isfinitef(float f)
+{
+	union IEEEf2bits u;
+
+	u.f = f;
+	return (u.bits.exp != 255);
+}
+
+int
+__isfinitel(long double e)
+{
+	union IEEEl2bits u;
+
+	u.e = e;
+	return (u.bits.exp != 32767);
+}
Index: /trunk/libc/src/msun/src/s_isnan.c
===================================================================
--- /trunk/libc/src/msun/src/s_isnan.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_isnan.c	(revision 2448)
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_isnan.c,v 1.8 2004/08/05 01:46:11 das Exp $
+ */
+
+#include "namespace.h"
+#include <math.h>
+
+#include "fpmath.h"
+
+/* Provided by libc */
+/*#if 0 - not by my libc */
+#undef isnan
+int
+_STD(isnan)(double d)
+{
+	union IEEEd2bits u;
+
+	u.d = d;
+	return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
+}
+/*#endif*/
+
+#undef isnanf
+int
+_STD(isnanf)(float f)
+{
+	union IEEEf2bits u;
+
+	u.f = f;
+	return (u.bits.exp == 255 && u.bits.man != 0);
+}
+
+int
+__isnanl(long double e)
+{
+	union IEEEl2bits u;
+
+	u.e = e;
+	mask_nbit_l(u);
+	return (u.bits.exp == 32767 && (u.bits.manl != 0 || u.bits.manh != 0));
+}
Index: /trunk/libc/src/msun/src/s_isnormal.c
===================================================================
--- /trunk/libc/src/msun/src/s_isnormal.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_isnormal.c	(revision 2448)
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_isnormal.c,v 1.1 2004/07/09 03:32:39 das Exp $
+ */
+
+#include "namespace.h"
+#include <math.h>
+
+#include "fpmath.h"
+
+int
+__isnormal(double d)
+{
+	union IEEEd2bits u;
+
+	u.d = d;
+	return (u.bits.exp != 0 && u.bits.exp != 2047);
+}
+
+int
+__isnormalf(float f)
+{
+	union IEEEf2bits u;
+
+	u.f = f;
+	return (u.bits.exp != 0 && u.bits.exp != 255);
+}
+
+int
+__isnormall(long double e)
+{
+	union IEEEl2bits u;
+
+	u.e = e;
+	return (u.bits.exp != 0 && u.bits.exp != 32767);
+}
Index: /trunk/libc/src/msun/src/s_llrint.c
===================================================================
--- /trunk/libc/src/msun/src/s_llrint.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_llrint.c	(revision 2448)
@@ -0,0 +1,10 @@
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_llrint.c,v 1.1 2005/01/11 23:12:55 das Exp $");
+
+#define type		double
+#define	roundit		rint
+#define dtype		long long
+#define	fn		llrint
+
+#include "s_lrint.c"
Index: /trunk/libc/src/msun/src/s_llrintf.c
===================================================================
--- /trunk/libc/src/msun/src/s_llrintf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_llrintf.c	(revision 2448)
@@ -0,0 +1,10 @@
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_llrintf.c,v 1.1 2005/01/11 23:12:55 das Exp $");
+
+#define type		float
+#define	roundit		rintf
+#define dtype		long long
+#define	fn		llrintf
+
+#include "s_lrint.c"
Index: /trunk/libc/src/msun/src/s_llround.c
===================================================================
--- /trunk/libc/src/msun/src/s_llround.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_llround.c	(revision 2448)
@@ -0,0 +1,12 @@
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_llround.c,v 1.2 2005/04/08 00:52:27 das Exp $");
+
+#define type		double
+#define	roundit		round
+#define dtype		long long
+#define	DTYPE_MIN	LLONG_MIN
+#define	DTYPE_MAX	LLONG_MAX
+#define	fn		llround
+
+#include "s_lround.c"
Index: /trunk/libc/src/msun/src/s_llroundf.c
===================================================================
--- /trunk/libc/src/msun/src/s_llroundf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_llroundf.c	(revision 2448)
@@ -0,0 +1,12 @@
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_llroundf.c,v 1.2 2005/04/08 00:52:27 das Exp $");
+
+#define type		float
+#define	roundit		roundf
+#define dtype		long long
+#define	DTYPE_MIN	LLONG_MIN
+#define	DTYPE_MAX	LLONG_MAX
+#define	fn		llroundf
+
+#include "s_lround.c"
Index: /trunk/libc/src/msun/src/s_llroundl.c
===================================================================
--- /trunk/libc/src/msun/src/s_llroundl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_llroundl.c	(revision 2448)
@@ -0,0 +1,12 @@
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_llroundl.c,v 1.1 2005/04/08 01:24:08 das Exp $");
+
+#define type		long double
+#define	roundit		roundl
+#define dtype		long long
+#define	DTYPE_MIN	LLONG_MIN
+#define	DTYPE_MAX	LLONG_MAX
+#define	fn		llroundl
+
+#include "s_lround.c"
Index: /trunk/libc/src/msun/src/s_log1p.c
===================================================================
--- /trunk/libc/src/msun/src/s_log1p.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_log1p.c	(revision 2448)
@@ -0,0 +1,162 @@
+/* @(#)s_log1p.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_log1p.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/* double log1p(double x)
+ *
+ * Method :
+ *   1. Argument Reduction: find k and f such that
+ *			1+x = 2^k * (1+f),
+ *	   where  sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ *      Note. If k=0, then f=x is exact. However, if k!=0, then f
+ *	may not be representable exactly. In that case, a correction
+ *	term is need. Let u=1+x rounded. Let c = (1+x)-u, then
+ *	log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
+ *	and add back the correction term c/u.
+ *	(Note: when x > 2**53, one can simply return log(x))
+ *
+ *   2. Approximation of log1p(f).
+ *	Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ *		 = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *	     	 = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ * 	a polynomial of degree 14 to approximate R The maximum error
+ *	of this polynomial approximation is bounded by 2**-58.45. In
+ *	other words,
+ *		        2      4      6      8      10      12      14
+ *	    R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
+ *  	(the values of Lp1 to Lp7 are listed in the program)
+ *	and
+ *	    |      2          14          |     -58.45
+ *	    | Lp1*s +...+Lp7*s    -  R(z) | <= 2
+ *	    |                             |
+ *	Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *	In order to guarantee error in log below 1ulp, we compute log
+ *	by
+ *		log1p(f) = f - (hfsq - s*(hfsq+R)).
+ *
+ *	3. Finally, log1p(x) = k*ln2 + log1p(f).
+ *		 	     = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *	   Here ln2 is split into two floating point number:
+ *			ln2_hi + ln2_lo,
+ *	   where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *	log1p(x) is NaN with signal if x < -1 (including -INF) ;
+ *	log1p(+INF) is +INF; log1p(-1) is -INF with signal;
+ *	log1p(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *	according to an error analysis, the error is always less than
+ *	1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ *
+ * Note: Assuming log() return accurate answer, the following
+ * 	 algorithm can be used to compute log1p(x) to within a few ULP:
+ *
+ *		u = 1+x;
+ *		if(u==1.0) return x ; else
+ *			   return log(u)*(x/(u-1.0));
+ *
+ *	 See HP-15C Advanced Functions Handbook, p.193.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+ln2_hi  =  6.93147180369123816490e-01,	/* 3fe62e42 fee00000 */
+ln2_lo  =  1.90821492927058770002e-10,	/* 3dea39ef 35793c76 */
+two54   =  1.80143985094819840000e+16,  /* 43500000 00000000 */
+Lp1 = 6.666666666666735130e-01,  /* 3FE55555 55555593 */
+Lp2 = 3.999999999940941908e-01,  /* 3FD99999 9997FA04 */
+Lp3 = 2.857142874366239149e-01,  /* 3FD24924 94229359 */
+Lp4 = 2.222219843214978396e-01,  /* 3FCC71C5 1D8E78AF */
+Lp5 = 1.818357216161805012e-01,  /* 3FC74664 96CB03DE */
+Lp6 = 1.531383769920937332e-01,  /* 3FC39A09 D078C69F */
+Lp7 = 1.479819860511658591e-01;  /* 3FC2F112 DF3E5244 */
+
+static const double zero = 0.0;
+
+double
+log1p(double x)
+{
+	double hfsq,f,c,s,z,R,u;
+	int32_t k,hx,hu,ax;
+
+	GET_HIGH_WORD(hx,x);
+	ax = hx&0x7fffffff;
+
+	k = 1;
+	if (hx < 0x3FDA827A) {			/* x < 0.41422  */
+	    if(ax>=0x3ff00000) {		/* x <= -1.0 */
+		if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */
+		else return (x-x)/(x-x);	/* log1p(x<-1)=NaN */
+	    }
+	    if(ax<0x3e200000) {			/* |x| < 2**-29 */
+		if(two54+x>zero			/* raise inexact */
+	            &&ax<0x3c900000) 		/* |x| < 2**-54 */
+		    return x;
+		else
+		    return x - x*x*0.5;
+	    }
+	    if(hx>0||hx<=((int32_t)0xbfd2bec3)) {
+		k=0;f=x;hu=1;}	/* -0.2929<x<0.41422 */
+	}
+	if (hx >= 0x7ff00000) return x+x;
+	if(k!=0) {
+	    if(hx<0x43400000) {
+		u  = 1.0+x;
+		GET_HIGH_WORD(hu,u);
+	        k  = (hu>>20)-1023;
+	        c  = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */
+		c /= u;
+	    } else {
+		u  = x;
+		GET_HIGH_WORD(hu,u);
+	        k  = (hu>>20)-1023;
+		c  = 0;
+	    }
+	    hu &= 0x000fffff;
+	    if(hu<0x6a09e) {
+	        SET_HIGH_WORD(u,hu|0x3ff00000);	/* normalize u */
+	    } else {
+	        k += 1;
+		SET_HIGH_WORD(u,hu|0x3fe00000);	/* normalize u/2 */
+	        hu = (0x00100000-hu)>>2;
+	    }
+	    f = u-1.0;
+	}
+	hfsq=0.5*f*f;
+	if(hu==0) {	/* |f| < 2**-20 */
+	    if(f==zero) if(k==0) return zero;
+			else {c += k*ln2_lo; return k*ln2_hi+c;}
+	    R = hfsq*(1.0-0.66666666666666666*f);
+	    if(k==0) return f-R; else
+	    	     return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+	}
+ 	s = f/(2.0+f);
+	z = s*s;
+	R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
+	if(k==0) return f-(hfsq-s*(hfsq+R)); else
+		 return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
+}
Index: /trunk/libc/src/msun/src/s_log1pf.c
===================================================================
--- /trunk/libc/src/msun/src/s_log1pf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_log1pf.c	(revision 2448)
@@ -0,0 +1,101 @@
+/* s_log1pf.c -- float version of s_log1p.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_log1pf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+ln2_hi =   6.9313812256e-01,	/* 0x3f317180 */
+ln2_lo =   9.0580006145e-06,	/* 0x3717f7d1 */
+two25 =    3.355443200e+07,	/* 0x4c000000 */
+Lp1 = 6.6666668653e-01,	/* 3F2AAAAB */
+Lp2 = 4.0000000596e-01,	/* 3ECCCCCD */
+Lp3 = 2.8571429849e-01, /* 3E924925 */
+Lp4 = 2.2222198546e-01, /* 3E638E29 */
+Lp5 = 1.8183572590e-01, /* 3E3A3325 */
+Lp6 = 1.5313838422e-01, /* 3E1CD04F */
+Lp7 = 1.4798198640e-01; /* 3E178897 */
+
+static const float zero = 0.0;
+
+float
+log1pf(float x)
+{
+	float hfsq,f,c,s,z,R,u;
+	int32_t k,hx,hu,ax;
+
+	GET_FLOAT_WORD(hx,x);
+	ax = hx&0x7fffffff;
+
+	k = 1;
+	if (hx < 0x3ed413d7) {			/* x < 0.41422  */
+	    if(ax>=0x3f800000) {		/* x <= -1.0 */
+		if(x==(float)-1.0) return -two25/zero; /* log1p(-1)=+inf */
+		else return (x-x)/(x-x);	/* log1p(x<-1)=NaN */
+	    }
+	    if(ax<0x31000000) {			/* |x| < 2**-29 */
+		if(two25+x>zero			/* raise inexact */
+	            &&ax<0x24800000) 		/* |x| < 2**-54 */
+		    return x;
+		else
+		    return x - x*x*(float)0.5;
+	    }
+	    if(hx>0||hx<=((int32_t)0xbe95f61f)) {
+		k=0;f=x;hu=1;}	/* -0.2929<x<0.41422 */
+	}
+	if (hx >= 0x7f800000) return x+x;
+	if(k!=0) {
+	    if(hx<0x5a000000) {
+		u  = (float)1.0+x;
+		GET_FLOAT_WORD(hu,u);
+	        k  = (hu>>23)-127;
+		/* correction term */
+	        c  = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
+		c /= u;
+	    } else {
+		u  = x;
+		GET_FLOAT_WORD(hu,u);
+	        k  = (hu>>23)-127;
+		c  = 0;
+	    }
+	    hu &= 0x007fffff;
+	    if(hu<0x3504f7) {
+	        SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
+	    } else {
+	        k += 1;
+		SET_FLOAT_WORD(u,hu|0x3f000000);	/* normalize u/2 */
+	        hu = (0x00800000-hu)>>2;
+	    }
+	    f = u-(float)1.0;
+	}
+	hfsq=(float)0.5*f*f;
+	if(hu==0) {	/* |f| < 2**-20 */
+	    if(f==zero) if(k==0) return zero;
+			else {c += k*ln2_lo; return k*ln2_hi+c;}
+	    R = hfsq*((float)1.0-(float)0.66666666666666666*f);
+	    if(k==0) return f-R; else
+	    	     return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+	}
+ 	s = f/((float)2.0+f);
+	z = s*s;
+	R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
+	if(k==0) return f-(hfsq-s*(hfsq+R)); else
+		 return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
+}
Index: /trunk/libc/src/msun/src/s_logb.c
===================================================================
--- /trunk/libc/src/msun/src/s_logb.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_logb.c	(revision 2448)
@@ -0,0 +1,39 @@
+/* @(#)s_logb.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_logb.c,v 1.9 2003/07/23 04:53:46 peter Exp $";
+#endif
+
+/*
+ * double logb(x)
+ * IEEE 754 logb. Included to pass IEEE test suite. Not recommend.
+ * Use ilogb instead.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+logb(double x)
+{
+	int32_t lx,ix;
+	EXTRACT_WORDS(ix,lx,x);
+	ix &= 0x7fffffff;			/* high |x| */
+	if((ix|lx)==0) return -1.0/fabs(x);
+	if(ix>=0x7ff00000) return x*x;
+	if((ix>>=20)==0) 			/* IEEE 754 logb */
+		return -1022.0;
+	else
+		return (double) (ix-1023);
+}
Index: /trunk/libc/src/msun/src/s_logbf.c
===================================================================
--- /trunk/libc/src/msun/src/s_logbf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_logbf.c	(revision 2448)
@@ -0,0 +1,36 @@
+/* s_logbf.c -- float version of s_logb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_logbf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+float
+logbf(float x)
+{
+	int32_t ix;
+	GET_FLOAT_WORD(ix,x);
+	ix &= 0x7fffffff;			/* high |x| */
+	if(ix==0) return (float)-1.0/fabsf(x);
+	if(ix>=0x7f800000) return x*x;
+	if((ix>>=23)==0) 			/* IEEE 754 logb */
+		return -126.0;
+	else
+		return (float) (ix-127);
+}
Index: /trunk/libc/src/msun/src/s_lrint.c
===================================================================
--- /trunk/libc/src/msun/src/s_lrint.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_lrint.c	(revision 2448)
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+#include <fenv.h>
+#include <math.h>
+
+#ifndef type
+__FBSDID("$FreeBSD: src/lib/msun/src/s_lrint.c,v 1.1 2005/01/11 23:12:55 das Exp $");
+#define type		double
+#define	roundit		rint
+#define dtype		long
+#define	fn		lrint
+#endif
+
+/*
+ * C99 says we should not raise a spurious inexact exception when an
+ * invalid exception is raised.  Unfortunately, the set of inputs
+ * that overflows depends on the rounding mode when 'dtype' has more
+ * significant bits than 'type'.  Hence, we bend over backwards for the
+ * sake of correctness; an MD implementation could be more efficient.
+ */
+dtype
+fn(type x)
+{
+	fenv_t env;
+	dtype d;
+
+	feholdexcept(&env);
+	d = (dtype)roundit(x);
+	if (fetestexcept(FE_INVALID))
+		feclearexcept(FE_INEXACT);
+	feupdateenv(&env);
+	return (d);
+}
Index: /trunk/libc/src/msun/src/s_lrintf.c
===================================================================
--- /trunk/libc/src/msun/src/s_lrintf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_lrintf.c	(revision 2448)
@@ -0,0 +1,10 @@
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_lrintf.c,v 1.1 2005/01/11 23:12:55 das Exp $");
+
+#define type		float
+#define	roundit		rintf
+#define dtype		long
+#define	fn		lrintf
+
+#include "s_lrint.c"
Index: /trunk/libc/src/msun/src/s_lround.c
===================================================================
--- /trunk/libc/src/msun/src/s_lround.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_lround.c	(revision 2448)
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+#include <sys/limits.h>
+#include <fenv.h>
+#include <math.h>
+
+#ifndef type
+__FBSDID("$FreeBSD: src/lib/msun/src/s_lround.c,v 1.2 2005/04/08 00:52:16 das Exp $");
+#define type		double
+#define	roundit		round
+#define dtype		long
+#define	DTYPE_MIN	LONG_MIN
+#define	DTYPE_MAX	LONG_MAX
+#define	fn		lround
+#endif
+
+/*
+ * If type has more precision than dtype, the endpoints dtype_(min|max) are
+ * of the form xxx.5; they are "out of range" because lround() rounds away
+ * from 0.  On the other hand, if type has less precision than dtype, then
+ * all values that are out of range are integral, so we might as well assume
+ * that everything is in range.  At compile time, INRANGE(x) should reduce to
+ * two floating-point comparisons in the former case, or TRUE otherwise.
+ */
+static const type dtype_min = DTYPE_MIN - 0.5;
+static const type dtype_max = DTYPE_MAX + 0.5;
+#define	INRANGE(x)	(dtype_max - DTYPE_MAX != 0.5 || \
+			 ((x) > dtype_min && (x) < dtype_max))
+
+dtype
+fn(type x)
+{
+
+	if (INRANGE(x)) {
+		x = roundit(x);
+		return ((dtype)x);
+	} else {
+		feraiseexcept(FE_INVALID);
+		return (DTYPE_MAX);
+	}
+}
+
Index: /trunk/libc/src/msun/src/s_lroundf.c
===================================================================
--- /trunk/libc/src/msun/src/s_lroundf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_lroundf.c	(revision 2448)
@@ -0,0 +1,12 @@
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_lroundf.c,v 1.2 2005/04/08 00:52:27 das Exp $");
+
+#define type		float
+#define	roundit		roundf
+#define dtype		long
+#define	DTYPE_MIN	LONG_MIN
+#define	DTYPE_MAX	LONG_MAX
+#define	fn		lroundf
+
+#include "s_lround.c"
Index: /trunk/libc/src/msun/src/s_lroundl.c
===================================================================
--- /trunk/libc/src/msun/src/s_lroundl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_lroundl.c	(revision 2448)
@@ -0,0 +1,12 @@
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_lroundl.c,v 1.1 2005/04/08 01:24:08 das Exp $");
+
+#define type		long double
+#define	roundit		roundl
+#define dtype		long
+#define	DTYPE_MIN	LONG_MIN
+#define	DTYPE_MAX	LONG_MAX
+#define	fn		lroundl
+
+#include "s_lround.c"
Index: /trunk/libc/src/msun/src/s_modf.c
===================================================================
--- /trunk/libc/src/msun/src/s_modf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_modf.c	(revision 2448)
@@ -0,0 +1,76 @@
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_modf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/*
+ * modf(double x, double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ *	Bit twiddling.
+ *
+ * Exception:
+ *	No exception.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double one = 1.0;
+
+double
+modf(double x, double *iptr)
+{
+	int32_t i0,i1,j0;
+	u_int32_t i;
+	EXTRACT_WORDS(i0,i1,x);
+	j0 = ((i0>>20)&0x7ff)-0x3ff;	/* exponent of x */
+	if(j0<20) {			/* integer part in high x */
+	    if(j0<0) {			/* |x|<1 */
+	        INSERT_WORDS(*iptr,i0&0x80000000,0);	/* *iptr = +-0 */
+		return x;
+	    } else {
+		i = (0x000fffff)>>j0;
+		if(((i0&i)|i1)==0) {		/* x is integral */
+		    u_int32_t high;
+		    *iptr = x;
+		    GET_HIGH_WORD(high,x);
+		    INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
+		    return x;
+		} else {
+		    INSERT_WORDS(*iptr,i0&(~i),0);
+		    return x - *iptr;
+		}
+	    }
+	} else if (j0>51) {		/* no fraction part */
+	    u_int32_t high;
+	    *iptr = x*one;
+	    GET_HIGH_WORD(high,x);
+	    INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
+	    return x;
+	} else {			/* fraction part in low x */
+	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
+	    if((i1&i)==0) { 		/* x is integral */
+	        u_int32_t high;
+		*iptr = x;
+		GET_HIGH_WORD(high,x);
+		INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
+		return x;
+	    } else {
+	        INSERT_WORDS(*iptr,i0,i1&(~i));
+		return x - *iptr;
+	    }
+	}
+}
Index: /trunk/libc/src/msun/src/s_modff.c
===================================================================
--- /trunk/libc/src/msun/src/s_modff.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_modff.c	(revision 2448)
@@ -0,0 +1,57 @@
+/* s_modff.c -- float version of s_modf.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_modff.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float one = 1.0;
+
+float
+modff(float x, float *iptr)
+{
+	int32_t i0,j0;
+	u_int32_t i;
+	GET_FLOAT_WORD(i0,x);
+	j0 = ((i0>>23)&0xff)-0x7f;	/* exponent of x */
+	if(j0<23) {			/* integer part in x */
+	    if(j0<0) {			/* |x|<1 */
+	        SET_FLOAT_WORD(*iptr,i0&0x80000000);	/* *iptr = +-0 */
+		return x;
+	    } else {
+		i = (0x007fffff)>>j0;
+		if((i0&i)==0) {			/* x is integral */
+		    u_int32_t ix;
+		    *iptr = x;
+		    GET_FLOAT_WORD(ix,x);
+		    SET_FLOAT_WORD(x,ix&0x80000000);	/* return +-0 */
+		    return x;
+		} else {
+		    SET_FLOAT_WORD(*iptr,i0&(~i));
+		    return x - *iptr;
+		}
+	    }
+	} else {			/* no fraction part */
+	    u_int32_t ix;
+	    *iptr = x*one;
+	    GET_FLOAT_WORD(ix,x);
+	    SET_FLOAT_WORD(x,ix&0x80000000);	/* return +-0 */
+	    return x;
+	}
+}
Index: /trunk/libc/src/msun/src/s_nearbyint.c
===================================================================
--- /trunk/libc/src/msun/src/s_nearbyint.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_nearbyint.c	(revision 2448)
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_nearbyint.c,v 1.1 2004/07/06 04:46:08 das Exp $");
+
+#include <fenv.h>
+#include <math.h>
+
+/*
+ * We save and restore the floating-point environment to avoid raising
+ * an inexact exception.  We can get away with using fesetenv()
+ * instead of feclearexcept()/feupdateenv() to restore the environment
+ * because the only exception defined for rint() is overflow, and
+ * rounding can't overflow as long as emax >= p.
+ */
+#define	DECL(type, fn, rint)	\
+type				\
+fn(type x)			\
+{				\
+	type ret;		\
+	fenv_t env;		\
+				\
+	fegetenv(&env);		\
+	ret = rint(x);		\
+	fesetenv(&env);		\
+	return (ret);		\
+}
+
+DECL(double, nearbyint, rint)
+DECL(float, nearbyintf, rintf)
Index: /trunk/libc/src/msun/src/s_nextafter.c
===================================================================
--- /trunk/libc/src/msun/src/s_nextafter.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_nextafter.c	(revision 2448)
@@ -0,0 +1,86 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_nextafter.c,v 1.11 2005/03/07 21:27:37 das Exp $";
+#endif
+
+/* IEEE functions
+ *	nextafter(x,y)
+ *	return the next machine floating-point number of x in the
+ *	direction toward y.
+ *   Special cases:
+ */
+
+#include <sys/cdefs.h>
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+
+double
+nextafter(double x, double y)
+{
+	volatile double t;
+	int32_t hx,hy,ix,iy;
+	u_int32_t lx,ly;
+
+	EXTRACT_WORDS(hx,lx,x);
+	EXTRACT_WORDS(hy,ly,y);
+	ix = hx&0x7fffffff;		/* |x| */
+	iy = hy&0x7fffffff;		/* |y| */
+
+	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
+	   ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))     /* y is nan */
+	   return x+y;
+	if(x==y) return y;		/* x=y, return y */
+	if((ix|lx)==0) {			/* x == 0 */
+	    INSERT_WORDS(x,hy&0x80000000,1);	/* return +-minsubnormal */
+	    t = x*x;
+	    if(t==x) return t; else return x;	/* raise underflow flag */
+	}
+	if(hx>=0) {				/* x > 0 */
+	    if(hx>hy||((hx==hy)&&(lx>ly))) {	/* x > y, x -= ulp */
+		if(lx==0) hx -= 1;
+		lx -= 1;
+	    } else {				/* x < y, x += ulp */
+		lx += 1;
+		if(lx==0) hx += 1;
+	    }
+	} else {				/* x < 0 */
+	    if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
+		if(lx==0) hx -= 1;
+		lx -= 1;
+	    } else {				/* x > y, x += ulp */
+		lx += 1;
+		if(lx==0) hx += 1;
+	    }
+	}
+	hy = hx&0x7ff00000;
+	if(hy>=0x7ff00000) return x+x;	/* overflow  */
+	if(hy<0x00100000) {		/* underflow */
+	    t = x*x;
+	    if(t!=x) {		/* raise underflow flag */
+	        INSERT_WORDS(y,hx,lx);
+		return y;
+	    }
+	}
+	INSERT_WORDS(x,hx,lx);
+	return x;
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(nextafter, nexttoward);
+__weak_reference(nextafter, nexttowardl);
+__weak_reference(nextafter, nextafterl);
+#endif
Index: /trunk/libc/src/msun/src/s_nextafterf.c
===================================================================
--- /trunk/libc/src/msun/src/s_nextafterf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_nextafterf.c	(revision 2448)
@@ -0,0 +1,68 @@
+/* s_nextafterf.c -- float version of s_nextafter.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_nextafterf.c,v 1.10 2005/03/07 04:55:58 das Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+float
+nextafterf(float x, float y)
+{
+	volatile float t;
+	int32_t hx,hy,ix,iy;
+
+	GET_FLOAT_WORD(hx,x);
+	GET_FLOAT_WORD(hy,y);
+	ix = hx&0x7fffffff;		/* |x| */
+	iy = hy&0x7fffffff;		/* |y| */
+
+	if((ix>0x7f800000) ||   /* x is nan */
+	   (iy>0x7f800000))     /* y is nan */
+	   return x+y;
+	if(x==y) return y;		/* x=y, return y */
+	if(ix==0) {				/* x == 0 */
+	    SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
+	    t = x*x;
+	    if(t==x) return t; else return x;	/* raise underflow flag */
+	}
+	if(hx>=0) {				/* x > 0 */
+	    if(hx>hy) {				/* x > y, x -= ulp */
+		hx -= 1;
+	    } else {				/* x < y, x += ulp */
+		hx += 1;
+	    }
+	} else {				/* x < 0 */
+	    if(hy>=0||hx>hy){			/* x < y, x -= ulp */
+		hx -= 1;
+	    } else {				/* x > y, x += ulp */
+		hx += 1;
+	    }
+	}
+	hy = hx&0x7f800000;
+	if(hy>=0x7f800000) return x+x;	/* overflow  */
+	if(hy<0x00800000) {		/* underflow */
+	    t = x*x;
+	    if(t!=x) {		/* raise underflow flag */
+	        SET_FLOAT_WORD(y,hx);
+		return y;
+	    }
+	}
+	SET_FLOAT_WORD(x,hx);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_nextafterl.c
===================================================================
--- /trunk/libc/src/msun/src/s_nextafterl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_nextafterl.c	(revision 2448)
@@ -0,0 +1,83 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_nextafterl.c,v 1.1 2005/03/07 04:56:46 das Exp $";
+#endif
+
+/* IEEE functions
+ *	nextafter(x,y)
+ *	return the next machine floating-point number of x in the
+ *	direction toward y.
+ *   Special cases:
+ */
+
+#include <sys/cdefs.h>
+#include <float.h>
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+
+#if LDBL_MAX_EXP != 0x4000
+#error "Unsupported long double format"
+#endif
+
+long double
+_STD(nextafterl)(long double x, long double y)
+{
+	volatile long double t;
+	union IEEEl2bits ux, uy;
+
+	ux.e = x;
+	uy.e = y;
+
+	if ((ux.bits.exp == 0x7fff &&
+	     ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl) != 0) ||
+	    (uy.bits.exp == 0x7fff &&
+	     ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
+	   return x+y;	/* x or y is nan */
+	if(x==y) return y;		/* x=y, return y */
+	if(x==0.0) {
+	    ux.bits.manh = 0;			/* return +-minsubnormal */
+	    ux.bits.manl = 1;
+	    ux.bits.sign = uy.bits.sign;
+	    t = ux.e*ux.e;
+	    if(t==ux.e) return t; else return ux.e; /* raise underflow flag */
+	}
+	if(x>0.0 ^ x<y) {			/* x -= ulp */
+	    if(ux.bits.manl==0) {
+		if ((ux.bits.manh&~LDBL_NBIT)==0)
+		    ux.bits.exp -= 1;
+		ux.bits.manh = (ux.bits.manh - 1) | (ux.bits.manh & LDBL_NBIT);
+	    }
+	    ux.bits.manl -= 1;
+	} else {				/* x += ulp */
+	    ux.bits.manl += 1;
+	    if(ux.bits.manl==0) {
+		ux.bits.manh = (ux.bits.manh + 1) | (ux.bits.manh & LDBL_NBIT);
+		if ((ux.bits.manh&~LDBL_NBIT)==0)
+		    ux.bits.exp += 1;
+	    }
+	}
+	if(ux.bits.exp==0x7fff) return x+x;	/* overflow  */
+	if(ux.bits.exp==0) {			/* underflow */
+	    mask_nbit_l(ux);
+	    t = ux.e * ux.e;
+	    if(t!=ux.e)			/* raise underflow flag */
+		return ux.e;
+	}
+	return ux.e;
+}
+
+__strong_reference(_std_nextafterl, _std_nexttowardl);
Index: /trunk/libc/src/msun/src/s_nexttoward.c
===================================================================
--- /trunk/libc/src/msun/src/s_nexttoward.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_nexttoward.c	(revision 2448)
@@ -0,0 +1,74 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_nexttoward.c,v 1.1 2005/03/07 04:56:46 das Exp $";
+#endif
+
+/*
+ * We assume that a long double has a 15-bit exponent.  On systems
+ * where long double is the same as double, nexttoward() is an alias
+ * for nextafter(), so we don't use this routine.
+ */
+
+#include <float.h>
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+
+#if LDBL_MAX_EXP != 0x4000
+#error "Unsupported long double format"
+#endif
+
+double
+nexttoward(double x, long double y)
+{
+	union IEEEl2bits uy;
+	volatile double t;
+	int32_t hx,ix;
+	u_int32_t lx;
+
+	EXTRACT_WORDS(hx,lx,x);
+	ix = hx&0x7fffffff;		/* |x| */
+	uy.e = y;
+
+	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||
+	    (uy.bits.exp == 0x7fff &&
+	     ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
+	   return x+y;	/* x or y is nan */
+	if(x==y) return (double)y;		/* x=y, return y */
+	if(x==0.0) {
+	    INSERT_WORDS(x,uy.bits.sign<<31,1);	/* return +-minsubnormal */
+	    t = x*x;
+	    if(t==x) return t; else return x;	/* raise underflow flag */
+	}
+	if(hx>0.0 ^ x < y) {			/* x -= ulp */
+	    if(lx==0) hx -= 1;
+	    lx -= 1;
+	} else {				/* x += ulp */
+	    lx += 1;
+	    if(lx==0) hx += 1;
+	}
+	ix = hx&0x7ff00000;
+	if(ix>=0x7ff00000) return x+x;	/* overflow  */
+	if(ix<0x00100000) {		/* underflow */
+	    t = x*x;
+	    if(t!=x) {		/* raise underflow flag */
+	        INSERT_WORDS(y,hx,lx);
+		return y;
+	    }
+	}
+	INSERT_WORDS(x,hx,lx);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_nexttowardf.c
===================================================================
--- /trunk/libc/src/msun/src/s_nexttowardf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_nexttowardf.c	(revision 2448)
@@ -0,0 +1,61 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_nexttowardf.c,v 1.1 2005/03/07 04:57:38 das Exp $";
+#endif
+
+#include <float.h>
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+
+#define	LDBL_INFNAN_EXP	(LDBL_MAX_EXP * 2 - 1)
+
+float
+nexttowardf(float x, long double y)
+{
+	union IEEEl2bits uy;
+	volatile float t;
+	int32_t hx,ix;
+
+	GET_FLOAT_WORD(hx,x);
+	ix = hx&0x7fffffff;		/* |x| */
+	uy.e = y;
+
+	if((ix>0x7f800000) ||
+	   (uy.bits.exp == LDBL_INFNAN_EXP &&
+	    ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
+	   return x+y;	/* x or y is nan */
+	if(x==y) return (float)y;		/* x=y, return y */
+	if(ix==0) {				/* x == 0 */
+	    SET_FLOAT_WORD(x,(uy.bits.sign<<31)|1);/* return +-minsubnormal */
+	    t = x*x;
+	    if(t==x) return t; else return x;	/* raise underflow flag */
+	}
+	if(hx>=0 ^ x < y)			/* x -= ulp */
+	    hx -= 1;
+	else					/* x += ulp */
+	    hx += 1;
+	ix = hx&0x7f800000;
+	if(ix>=0x7f800000) return x+x;	/* overflow  */
+	if(ix<0x00800000) {		/* underflow */
+	    t = x*x;
+	    if(t!=x) {		/* raise underflow flag */
+	        SET_FLOAT_WORD(y,hx);
+		return y;
+	    }
+	}
+	SET_FLOAT_WORD(x,hx);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_remquo.c
===================================================================
--- /trunk/libc/src/msun/src/s_remquo.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_remquo.c	(revision 2448)
@@ -0,0 +1,153 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_remquo.c,v 1.1 2005/03/25 04:40:44 das Exp $");
+
+#include "math.h"
+#include "math_private.h"
+
+static const double Zero[] = {0.0, -0.0,};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer.  We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method.  In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ */
+double
+remquo(double x, double y, int *quo)
+{
+	int32_t n,hx,hy,hz,ix,iy,sx,i;
+	u_int32_t lx,ly,lz,q,sxy;
+
+	EXTRACT_WORDS(hx,lx,x);
+	EXTRACT_WORDS(hy,ly,y);
+	sxy = (hx ^ hy) & 0x80000000;
+	sx = hx&0x80000000;		/* sign of x */
+	hx ^=sx;		/* |x| */
+	hy &= 0x7fffffff;	/* |y| */
+
+    /* purge off exception values */
+	if((hy|ly)==0||(hx>=0x7ff00000)||	/* y=0,or x not finite */
+	  ((hy|((ly|-ly)>>31))>0x7ff00000))	/* or y is NaN */
+	    return (x*y)/(x*y);
+	if(hx<=hy) {
+	    if((hx<hy)||(lx<ly)) {
+		q = 0;
+		goto fixup;	/* |x|<|y| return x or x-y */
+	    }
+	    if(lx==ly) {
+		*quo = 1;
+		return Zero[(u_int32_t)sx>>31];	/* |x|=|y| return x*0*/
+	    }
+	}
+
+    /* determine ix = ilogb(x) */
+	if(hx<0x00100000) {	/* subnormal x */
+	    if(hx==0) {
+		for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+	    } else {
+		for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+	    }
+	} else ix = (hx>>20)-1023;
+
+    /* determine iy = ilogb(y) */
+	if(hy<0x00100000) {	/* subnormal y */
+	    if(hy==0) {
+		for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+	    } else {
+		for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+	    }
+	} else iy = (hy>>20)-1023;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+	if(ix >= -1022)
+	    hx = 0x00100000|(0x000fffff&hx);
+	else {		/* subnormal x, shift x to normal */
+	    n = -1022-ix;
+	    if(n<=31) {
+	        hx = (hx<<n)|(lx>>(32-n));
+	        lx <<= n;
+	    } else {
+		hx = lx<<(n-32);
+		lx = 0;
+	    }
+	}
+	if(iy >= -1022)
+	    hy = 0x00100000|(0x000fffff&hy);
+	else {		/* subnormal y, shift y to normal */
+	    n = -1022-iy;
+	    if(n<=31) {
+	        hy = (hy<<n)|(ly>>(32-n));
+	        ly <<= n;
+	    } else {
+		hy = ly<<(n-32);
+		ly = 0;
+	    }
+	}
+
+    /* fix point fmod */
+	n = ix - iy;
+	q = 0;
+	while(n--) {
+	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	    if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
+	    else {hx = hz+hz+(lz>>31); lx = lz+lz; q++;}
+	    q <<= 1;
+	}
+	hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+	if(hz>=0) {hx=hz;lx=lz;q++;}
+
+    /* convert back to floating value and restore the sign */
+	if((hx|lx)==0) {			/* return sign(x)*0 */
+	    *quo = (sxy ? -q : q);
+	    return Zero[(u_int32_t)sx>>31];
+	}
+	while(hx<0x00100000) {		/* normalize x */
+	    hx = hx+hx+(lx>>31); lx = lx+lx;
+	    iy -= 1;
+	}
+	if(iy>= -1022) {	/* normalize output */
+	    hx = ((hx-0x00100000)|((iy+1023)<<20));
+	} else {		/* subnormal output */
+	    n = -1022 - iy;
+	    if(n<=20) {
+		lx = (lx>>n)|((u_int32_t)hx<<(32-n));
+		hx >>= n;
+	    } else if (n<=31) {
+		lx = (hx<<(32-n))|(lx>>n); hx = sx;
+	    } else {
+		lx = hx>>(n-32); hx = sx;
+	    }
+	}
+fixup:
+	INSERT_WORDS(x,hx,lx);
+	y = fabs(y);
+	if (y < 0x1p-1021) {
+	    if (x+x>y || (x+x==y && (q & 1))) {
+		q++;
+		x-=y;
+	    }
+	} else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+	    q++;
+	    x-=y;
+	}
+	GET_HIGH_WORD(hx,x);
+	SET_HIGH_WORD(x,hx^sx);
+	q &= 0x7fffffff;
+	*quo = (sxy ? -q : q);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_remquof.c
===================================================================
--- /trunk/libc/src/msun/src/s_remquof.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_remquof.c	(revision 2448)
@@ -0,0 +1,122 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_remquof.c,v 1.1 2005/03/25 04:40:44 das Exp $");
+
+#include "math.h"
+#include "math_private.h"
+
+static const float Zero[] = {0.0, -0.0,};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer.  We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method.  In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ */
+float
+remquof(float x, float y, int *quo)
+{
+	int32_t n,hx,hy,hz,ix,iy,sx,i;
+	u_int32_t q,sxy;
+
+	GET_FLOAT_WORD(hx,x);
+	GET_FLOAT_WORD(hy,y);
+	sxy = (hx ^ hy) & 0x80000000;
+	sx = hx&0x80000000;		/* sign of x */
+	hx ^=sx;		/* |x| */
+	hy &= 0x7fffffff;	/* |y| */
+
+    /* purge off exception values */
+	if(hy==0||hx>=0x7f800000||hy>0x7f800000) /* y=0,NaN;or x not finite */
+	    return (x*y)/(x*y);
+	if(hx<hy) {
+	    q = 0;
+	    goto fixup;	/* |x|<|y| return x or x-y */
+	} else if(hx==hy) {
+	    *quo = 1;
+	    return Zero[(u_int32_t)sx>>31];	/* |x|=|y| return x*0*/
+	}
+
+    /* determine ix = ilogb(x) */
+	if(hx<0x00800000) {	/* subnormal x */
+	    for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
+	} else ix = (hx>>23)-127;
+
+    /* determine iy = ilogb(y) */
+	if(hy<0x00800000) {	/* subnormal y */
+	    for (iy = -126,i=(hy<<8); i>0; i<<=1) iy -=1;
+	} else iy = (hy>>23)-127;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+	if(ix >= -126)
+	    hx = 0x00800000|(0x007fffff&hx);
+	else {		/* subnormal x, shift x to normal */
+	    n = -126-ix;
+	    hx <<= n;
+	}
+	if(iy >= -126)
+	    hy = 0x00800000|(0x007fffff&hy);
+	else {		/* subnormal y, shift y to normal */
+	    n = -126-iy;
+	    hy <<= n;
+	}
+
+    /* fix point fmod */
+	n = ix - iy;
+	q = 0;
+	while(n--) {
+	    hz=hx-hy;
+	    if(hz<0) hx = hx << 1;
+	    else {hx = hz << 1; q++;}
+	    q <<= 1;
+	}
+	hz=hx-hy;
+	if(hz>=0) {hx=hz;q++;}
+
+    /* convert back to floating value and restore the sign */
+	if(hx==0) {				/* return sign(x)*0 */
+	    *quo = (sxy ? -q : q);
+	    return Zero[(u_int32_t)sx>>31];
+	}
+	while(hx<0x00800000) {		/* normalize x */
+	    hx <<= 1;
+	    iy -= 1;
+	}
+	if(iy>= -126) {		/* normalize output */
+	    hx = ((hx-0x00800000)|((iy+127)<<23));
+	} else {		/* subnormal output */
+	    n = -126 - iy;
+	    hx >>= n;
+	}
+fixup:
+	SET_FLOAT_WORD(x,hx);
+	y = fabsf(y);
+	if (y < 0x1p-125f) {
+	    if (x+x>y || (x+x==y && (q & 1))) {
+		q++;
+		x-=y;
+	    }
+	} else if (x>0.5f*y || (x==0.5f*y && (q & 1))) {
+	    q++;
+	    x-=y;
+	}
+	GET_FLOAT_WORD(hx,x);
+	SET_FLOAT_WORD(x,hx^sx);
+	q &= 0x7fffffff;
+	*quo = (sxy ? -q : q);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_rint.c
===================================================================
--- /trunk/libc/src/msun/src/s_rint.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_rint.c	(revision 2448)
@@ -0,0 +1,85 @@
+/* @(#)s_rint.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_rint.c,v 1.11 2005/03/07 20:28:26 stefanf Exp $";
+#endif
+
+/*
+ * rint(x)
+ * Return x rounded to integral value according to the prevailing
+ * rounding mode.
+ * Method:
+ *	Using floating addition.
+ * Exception:
+ *	Inexact flag raised if x not equal to rint(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+/*
+ * TWO23 is long double instead of double to avoid a bug in gcc.  Without
+ * this, gcc thinks that TWO23[sx]+x and w-TWO23[sx] already have double
+ * precision and doesn't clip them to double precision when they are
+ * assigned and returned.
+ */
+static const long double
+TWO52[2]={
+  4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+};
+
+double
+rint(double x)
+{
+	int32_t i0,j0,sx;
+	u_int32_t i,i1;
+	double w,t;
+	EXTRACT_WORDS(i0,i1,x);
+	sx = (i0>>31)&1;
+	j0 = ((i0>>20)&0x7ff)-0x3ff;
+	if(j0<20) {
+	    if(j0<0) {
+		if(((i0&0x7fffffff)|i1)==0) return x;
+		i1 |= (i0&0x0fffff);
+		i0 &= 0xfffe0000;
+		i0 |= ((i1|-i1)>>12)&0x80000;
+		SET_HIGH_WORD(x,i0);
+	        w = TWO52[sx]+x;
+	        t =  w-TWO52[sx];
+		GET_HIGH_WORD(i0,t);
+		SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
+	        return t;
+	    } else {
+		i = (0x000fffff)>>j0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		i>>=1;
+		if(((i0&i)|i1)!=0) {
+		    if(j0==19) i1 = 0x40000000; else
+		    i0 = (i0&(~i))|((0x20000)>>j0);
+		}
+	    }
+	} else if (j0>51) {
+	    if(j0==0x400) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    i>>=1;
+	    if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
+	}
+	INSERT_WORDS(x,i0,i1);
+	w = TWO52[sx]+x;
+	return w-TWO52[sx];
+}
Index: /trunk/libc/src/msun/src/s_rintf.c
===================================================================
--- /trunk/libc/src/msun/src/s_rintf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_rintf.c	(revision 2448)
@@ -0,0 +1,51 @@
+/* s_rintf.c -- float version of s_rint.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_rintf.c,v 1.9 2004/06/09 21:24:52 das Exp $";
+#endif
+
+#include <sys/types.h>
+#include "math.h"
+#include "math_private.h"
+
+static const float
+TWO23[2]={
+  8.3886080000e+06, /* 0x4b000000 */
+ -8.3886080000e+06, /* 0xcb000000 */
+};
+
+float
+rintf(float x)
+{
+	int32_t i0,j0,sx;
+	volatile float w,t;	/* volatile works around gcc bug */
+	GET_FLOAT_WORD(i0,x);
+	sx = (i0>>31)&1;
+	j0 = ((i0>>23)&0xff)-0x7f;
+	if(j0<23) {
+	    if(j0<0) {
+		if((i0&0x7fffffff)==0) return x;
+	        w = TWO23[sx]+x;
+	        t =  w-TWO23[sx];
+	        return t;
+	    }
+	    w = TWO23[sx]+x;
+	    return w-TWO23[sx];
+	}
+	if(j0==0x80) return x+x;	/* inf or NaN */
+	else return x;			/* x is integral */
+}
Index: /trunk/libc/src/msun/src/s_round.c
===================================================================
--- /trunk/libc/src/msun/src/s_round.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_round.c	(revision 2448)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2003, Steven G. Kargl
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_round.c,v 1.3 2005/01/13 15:43:41 das Exp $");
+
+#include <math.h>
+
+double
+round(double x)
+{
+	double t;
+
+	if (!isfinite(x))
+		return (x);
+
+	if (x >= 0.0) {
+		t = ceil(x);
+		if (t - x > 0.5)
+			t -= 1.0;
+		return (t);
+	} else {
+		t = ceil(-x);
+		if (t + x > 0.5)
+			t -= 1.0;
+		return (-t);
+	}
+}
Index: /trunk/libc/src/msun/src/s_roundf.c
===================================================================
--- /trunk/libc/src/msun/src/s_roundf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_roundf.c	(revision 2448)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2003, Steven G. Kargl
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_roundf.c,v 1.3 2005/01/13 15:43:41 das Exp $");
+
+#include <math.h>
+
+float
+roundf(float x)
+{
+	float t;
+
+	if (!isfinite(x))
+		return (x);
+
+	if (x >= 0.0) {
+		t = ceilf(x);
+		if (t - x > 0.5)
+			t -= 1.0;
+		return (t);
+	} else {
+		t = ceilf(-x);
+		if (t + x > 0.5)
+			t -= 1.0;
+		return (-t);
+	}
+}
Index: /trunk/libc/src/msun/src/s_roundl.c
===================================================================
--- /trunk/libc/src/msun/src/s_roundl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_roundl.c	(revision 2448)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2003, Steven G. Kargl
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_roundl.c,v 1.1 2005/04/08 01:24:08 das Exp $");
+
+#include <math.h>
+
+long double
+roundl(long double x)
+{
+	long double t;
+
+	if (!isfinite(x))
+		return (x);
+
+	if (x >= 0.0) {
+		t = ceill(x);
+		if (t - x > 0.5)
+			t -= 1.0;
+		return (t);
+	} else {
+		t = ceill(-x);
+		if (t + x > 0.5)
+			t -= 1.0;
+		return (-t);
+	}
+}
Index: /trunk/libc/src/msun/src/s_scalbln.c
===================================================================
--- /trunk/libc/src/msun/src/s_scalbln.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_scalbln.c	(revision 2448)
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_scalbln.c,v 1.2 2005/03/07 04:57:50 das Exp $");
+
+#include <limits.h>
+#include <math.h>
+
+double
+scalbln (double x, long n)
+{
+	int in;
+
+	in = (int)n;
+	if (in != n) {
+		if (n > 0)
+			in = INT_MAX;
+		else
+			in = INT_MIN;
+	}
+	return (scalbn(x, in));
+}
+
+float
+scalblnf (float x, long n)
+{
+	int in;
+
+	in = (int)n;
+	if (in != n) {
+		if (n > 0)
+			in = INT_MAX;
+		else
+			in = INT_MIN;
+	}
+	return (scalbnf(x, in));
+}
+
+long double
+scalblnl (long double x, long n)
+{
+	int in;
+
+	in = (int)n;
+	if (in != n) {
+		if (n > 0)
+			in = INT_MAX;
+		else
+			in = INT_MIN;
+	}
+	return (scalbnl(x, (int)n));
+}
Index: /trunk/libc/src/msun/src/s_scalbn.c
===================================================================
--- /trunk/libc/src/msun/src/s_scalbn.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_scalbn.c	(revision 2448)
@@ -0,0 +1,67 @@
+/* @(#)s_scalbn.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_scalbn.c,v 1.11 2005/03/07 21:27:37 das Exp $";
+#endif
+
+/*
+ * scalbn (double x, int n)
+ * scalbn(x,n) returns x* 2**n  computed by  exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+#include <sys/cdefs.h>
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+
+static const double
+two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+huge   = 1.0e+300,
+tiny   = 1.0e-300;
+
+double
+scalbn (double x, int n)
+{
+	int32_t k,hx,lx;
+	EXTRACT_WORDS(hx,lx,x);
+        k = (hx&0x7ff00000)>>20;		/* extract exponent */
+        if (k==0) {				/* 0 or subnormal x */
+            if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
+	    x *= two54;
+	    GET_HIGH_WORD(hx,x);
+	    k = ((hx&0x7ff00000)>>20) - 54;
+            if (n< -50000) return tiny*x; 	/*underflow*/
+	    }
+        if (k==0x7ff) return x+x;		/* NaN or Inf */
+        k = k+n;
+        if (k >  0x7fe) return huge*copysign(huge,x); /* overflow  */
+        if (k > 0) 				/* normal result */
+	    {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
+        if (k <= -54)
+            if (n > 50000) 	/* in case integer overflow in n+k */
+		return huge*copysign(huge,x);	/*overflow*/
+	    else return tiny*copysign(tiny,x); 	/*underflow*/
+        k += 54;				/* subnormal result */
+	SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
+        return x*twom54;
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(scalbn, ldexpl);
+__weak_reference(scalbn, scalbnl);
+#endif
Index: /trunk/libc/src/msun/src/s_scalbnf.c
===================================================================
--- /trunk/libc/src/msun/src/s_scalbnf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_scalbnf.c	(revision 2448)
@@ -0,0 +1,59 @@
+/* s_scalbnf.c -- float version of s_scalbn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_scalbnf.c,v 1.8 2005/03/07 04:52:43 das Exp $";
+#endif
+
+#include <sys/cdefs.h>
+
+#include "math.h"
+#include "math_private.h"
+
+static const float
+two25   =  3.355443200e+07,	/* 0x4c000000 */
+twom25  =  2.9802322388e-08,	/* 0x33000000 */
+huge   = 1.0e+30,
+tiny   = 1.0e-30;
+
+float
+_STD(scalbnf) (float x, int n)
+{
+	int32_t k,ix;
+	GET_FLOAT_WORD(ix,x);
+        k = (ix&0x7f800000)>>23;		/* extract exponent */
+        if (k==0) {				/* 0 or subnormal x */
+            if ((ix&0x7fffffff)==0) return x; /* +-0 */
+	    x *= two25;
+	    GET_FLOAT_WORD(ix,x);
+	    k = ((ix&0x7f800000)>>23) - 25;
+            if (n< -50000) return tiny*x; 	/*underflow*/
+	    }
+        if (k==0xff) return x+x;		/* NaN or Inf */
+        k = k+n;
+        if (k >  0xfe) return huge*copysignf(huge,x); /* overflow  */
+        if (k > 0) 				/* normal result */
+	    {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
+        if (k <= -25)
+            if (n > 50000) 	/* in case integer overflow in n+k */
+		return huge*copysignf(huge,x);	/*overflow*/
+	    else return tiny*copysignf(tiny,x);	/*underflow*/
+        k += 25;				/* subnormal result */
+	SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
+        return x*twom25;
+}
+
+__strong_reference(_std_scalbnf, _std_ldexpf);
Index: /trunk/libc/src/msun/src/s_scalbnl.c
===================================================================
--- /trunk/libc/src/msun/src/s_scalbnl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_scalbnl.c	(revision 2448)
@@ -0,0 +1,72 @@
+/* @(#)s_scalbn.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_scalbnl.c,v 1.1 2005/03/07 04:52:58 das Exp $";
+#endif
+
+/*
+ * scalbnl (long double x, int n)
+ * scalbnl(x,n) returns x* 2**n  computed by  exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+/*
+ * We assume that a long double has a 15-bit exponent.  On systems
+ * where long double is the same as double, scalbnl() is an alias
+ * for scalbn(), so we don't use this routine.
+ */
+
+#include <sys/cdefs.h>
+#include <float.h>
+#include <math.h>
+
+#include "fpmath.h"
+
+#if LDBL_MAX_EXP != 0x4000
+#error "Unsupported long double format"
+#endif
+
+static const long double
+huge = 0x1p16000L,
+tiny = 0x1p-16000L;
+
+long double
+_STD(scalbnl) (long double x, int n)
+{
+	union IEEEl2bits u;
+	int k;
+	u.e = x;
+        k = u.bits.exp;				/* extract exponent */
+        if (k==0) {				/* 0 or subnormal x */
+            if ((u.bits.manh|u.bits.manl)==0) return x;	/* +-0 */
+	    u.e *= 0x1p+128;
+	    k = u.bits.exp - 128;
+            if (n< -50000) return tiny*x; 	/*underflow*/
+	    }
+        if (k==0x7fff) return x+x;		/* NaN or Inf */
+        k = k+n;
+        if (k >= 0x7fff) return huge*copysignl(huge,x); /* overflow  */
+        if (k > 0) 				/* normal result */
+	    {u.bits.exp = k; return u.e;}
+        if (k <= -128)
+            if (n > 50000) 	/* in case integer overflow in n+k */
+		return huge*copysign(huge,x);	/*overflow*/
+	    else return tiny*copysign(tiny,x); 	/*underflow*/
+        k += 128;				/* subnormal result */
+	u.bits.exp = k;
+        return u.e*0x1p-128;
+}
+
+__strong_reference(_std_scalbnl, _std_ldexpl);
Index: /trunk/libc/src/msun/src/s_signbit.c
===================================================================
--- /trunk/libc/src/msun/src/s_signbit.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_signbit.c	(revision 2448)
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/lib/msun/src/s_signbit.c,v 1.1 2004/07/19 08:16:10 das Exp $
+ */
+
+#include "namespace.h"
+#include <math.h>
+
+#include "fpmath.h"
+
+int
+__signbit(double d)
+{
+	union IEEEd2bits u;
+
+	u.d = d;
+	return (u.bits.sign);
+}
+
+int
+__signbitf(float f)
+{
+	union IEEEf2bits u;
+
+	u.f = f;
+	return (u.bits.sign);
+}
+
+int
+__signbitl(long double e)
+{
+	union IEEEl2bits u;
+
+	u.e = e;
+	return (u.bits.sign);
+}
Index: /trunk/libc/src/msun/src/s_signgam.c
===================================================================
--- /trunk/libc/src/msun/src/s_signgam.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_signgam.c	(revision 2448)
@@ -0,0 +1,4 @@
+#include "namespace.h"
+#include "math.h"
+#include "math_private.h"
+int signgam = 0;
Index: /trunk/libc/src/msun/src/s_significand.c
===================================================================
--- /trunk/libc/src/msun/src/s_significand.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_significand.c	(revision 2448)
@@ -0,0 +1,31 @@
+/* @(#)s_signif.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_significand.c,v 1.9 2003/07/23 04:53:47 peter Exp $";
+#endif
+
+/*
+ * significand(x) computes just
+ * 	scalb(x, (double) -ilogb(x)),
+ * for exercising the fraction-part(F) IEEE 754-1985 test vector.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+significand(double x)
+{
+	return __ieee754_scalb(x,(double) -ilogb(x));
+}
Index: /trunk/libc/src/msun/src/s_significandf.c
===================================================================
--- /trunk/libc/src/msun/src/s_significandf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_significandf.c	(revision 2448)
@@ -0,0 +1,28 @@
+/* s_significandf.c -- float version of s_significand.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_significandf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+float
+significandf(float x)
+{
+	return __ieee754_scalbf(x,(float) -ilogbf(x));
+}
Index: /trunk/libc/src/msun/src/s_sin.c
===================================================================
--- /trunk/libc/src/msun/src/s_sin.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_sin.c	(revision 2448)
@@ -0,0 +1,79 @@
+/* @(#)s_sin.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_sin.c,v 1.9 2003/07/23 04:53:47 peter Exp $";
+#endif
+
+/* sin(x)
+ * Return sine function of x.
+ *
+ * kernel function:
+ *	__kernel_sin		... sine function on [-pi/4,pi/4]
+ *	__kernel_cos		... cose function on [-pi/4,pi/4]
+ *	__ieee754_rem_pio2	... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *	in [-pi/4 , +pi/4], and let n = k mod 4.
+ *	We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *	    0	       S	   C		 T
+ *	    1	       C	  -S		-1/T
+ *	    2	      -S	  -C		 T
+ *	    3	      -C	   S		-1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *	TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+sin(double x)
+{
+	double y[2],z=0.0;
+	int32_t n, ix;
+
+    /* High word of x. */
+	GET_HIGH_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+	ix &= 0x7fffffff;
+	if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
+
+    /* sin(Inf or NaN) is NaN */
+	else if (ix>=0x7ff00000) return x-x;
+
+    /* argument reduction needed */
+	else {
+	    n = __ieee754_rem_pio2(x,y);
+	    switch(n&3) {
+		case 0: return  __kernel_sin(y[0],y[1],1);
+		case 1: return  __kernel_cos(y[0],y[1]);
+		case 2: return -__kernel_sin(y[0],y[1],1);
+		default:
+			return -__kernel_cos(y[0],y[1]);
+	    }
+	}
+}
Index: /trunk/libc/src/msun/src/s_sinf.c
===================================================================
--- /trunk/libc/src/msun/src/s_sinf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_sinf.c	(revision 2448)
@@ -0,0 +1,50 @@
+/* s_sinf.c -- float version of s_sin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_sinf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+float
+sinf(float x)
+{
+	float y[2],z=0.0;
+	int32_t n, ix;
+
+	GET_FLOAT_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+	ix &= 0x7fffffff;
+	if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0);
+
+    /* sin(Inf or NaN) is NaN */
+	else if (ix>=0x7f800000) return x-x;
+
+    /* argument reduction needed */
+	else {
+	    n = __ieee754_rem_pio2f(x,y);
+	    switch(n&3) {
+		case 0: return  __kernel_sinf(y[0],y[1],1);
+		case 1: return  __kernel_cosf(y[0],y[1]);
+		case 2: return -__kernel_sinf(y[0],y[1],1);
+		default:
+			return -__kernel_cosf(y[0],y[1]);
+	    }
+	}
+}
Index: /trunk/libc/src/msun/src/s_tan.c
===================================================================
--- /trunk/libc/src/msun/src/s_tan.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_tan.c	(revision 2448)
@@ -0,0 +1,73 @@
+/* @(#)s_tan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_tan.c,v 1.9 2003/07/23 04:53:47 peter Exp $";
+#endif
+
+/* tan(x)
+ * Return tangent function of x.
+ *
+ * kernel function:
+ *	__kernel_tan		... tangent function on [-pi/4,pi/4]
+ *	__ieee754_rem_pio2	... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *	in [-pi/4 , +pi/4], and let n = k mod 4.
+ *	We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *	    0	       S	   C		 T
+ *	    1	       C	  -S		-1/T
+ *	    2	      -S	  -C		 T
+ *	    3	      -C	   S		-1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *	TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+tan(double x)
+{
+	double y[2],z=0.0;
+	int32_t n, ix;
+
+    /* High word of x. */
+	GET_HIGH_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+	ix &= 0x7fffffff;
+	if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1);
+
+    /* tan(Inf or NaN) is NaN */
+	else if (ix>=0x7ff00000) return x-x;		/* NaN */
+
+    /* argument reduction needed */
+	else {
+	    n = __ieee754_rem_pio2(x,y);
+	    return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
+							-1 -- n odd */
+	}
+}
Index: /trunk/libc/src/msun/src/s_tanf.c
===================================================================
--- /trunk/libc/src/msun/src/s_tanf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_tanf.c	(revision 2448)
@@ -0,0 +1,45 @@
+/* s_tanf.c -- float version of s_tan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_tanf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+float
+tanf(float x)
+{
+	float y[2],z=0.0;
+	int32_t n, ix;
+
+	GET_FLOAT_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+	ix &= 0x7fffffff;
+	if(ix <= 0x3f490fda) return __kernel_tanf(x,z,1);
+
+    /* tan(Inf or NaN) is NaN */
+	else if (ix>=0x7f800000) return x-x;		/* NaN */
+
+    /* argument reduction needed */
+	else {
+	    n = __ieee754_rem_pio2f(x,y);
+	    return __kernel_tanf(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
+							      -1 -- n odd */
+	}
+}
Index: /trunk/libc/src/msun/src/s_tanh.c
===================================================================
--- /trunk/libc/src/msun/src/s_tanh.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_tanh.c	(revision 2448)
@@ -0,0 +1,79 @@
+/* @(#)s_tanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_tanh.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+/* Tanh(x)
+ * Return the Hyperbolic Tangent of x
+ *
+ * Method :
+ *				       x    -x
+ *				      e  - e
+ *	0. tanh(x) is defined to be -----------
+ *				       x    -x
+ *				      e  + e
+ *	1. reduce x to non-negative by tanh(-x) = -tanh(x).
+ *	2.  0      <= x <= 2**-55 : tanh(x) := x*(one+x)
+ *					        -t
+ *	    2**-55 <  x <=  1     : tanh(x) := -----; t = expm1(-2x)
+ *					       t + 2
+ *						     2
+ *	    1      <= x <=  22.0  : tanh(x) := 1-  ----- ; t=expm1(2x)
+ *						   t + 2
+ *	    22.0   <  x <= INF    : tanh(x) := 1.
+ *
+ * Special cases:
+ *	tanh(NaN) is NaN;
+ *	only tanh(0)=0 is exact for finite argument.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double one=1.0, two=2.0, tiny = 1.0e-300;
+
+double
+tanh(double x)
+{
+	double t,z;
+	int32_t jx,ix;
+
+    /* High word of |x|. */
+	GET_HIGH_WORD(jx,x);
+	ix = jx&0x7fffffff;
+
+    /* x is INF or NaN */
+	if(ix>=0x7ff00000) {
+	    if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
+	    else       return one/x-one;    /* tanh(NaN) = NaN */
+	}
+
+    /* |x| < 22 */
+	if (ix < 0x40360000) {		/* |x|<22 */
+	    if (ix<0x3c800000) 		/* |x|<2**-55 */
+		return x*(one+x);    	/* tanh(small) = small */
+	    if (ix>=0x3ff00000) {	/* |x|>=1  */
+		t = expm1(two*fabs(x));
+		z = one - two/(t+two);
+	    } else {
+	        t = expm1(-two*fabs(x));
+	        z= -t/(t+two);
+	    }
+    /* |x| > 22, return +-1 */
+	} else {
+	    z = one - tiny;		/* raised inexact flag */
+	}
+	return (jx>=0)? z: -z;
+}
Index: /trunk/libc/src/msun/src/s_tanhf.c
===================================================================
--- /trunk/libc/src/msun/src/s_tanhf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_tanhf.c	(revision 2448)
@@ -0,0 +1,57 @@
+/* s_tanhf.c -- float version of s_tanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_tanhf.c,v 1.7 2002/05/28 18:15:04 alfred Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+static const float one=1.0, two=2.0, tiny = 1.0e-30;
+
+float
+tanhf(float x)
+{
+	float t,z;
+	int32_t jx,ix;
+
+	GET_FLOAT_WORD(jx,x);
+	ix = jx&0x7fffffff;
+
+    /* x is INF or NaN */
+	if(ix>=0x7f800000) {
+	    if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
+	    else       return one/x-one;    /* tanh(NaN) = NaN */
+	}
+
+    /* |x| < 22 */
+	if (ix < 0x41b00000) {		/* |x|<22 */
+	    if (ix<0x24000000) 		/* |x|<2**-55 */
+		return x*(one+x);    	/* tanh(small) = small */
+	    if (ix>=0x3f800000) {	/* |x|>=1  */
+		t = expm1f(two*fabsf(x));
+		z = one - two/(t+two);
+	    } else {
+	        t = expm1f(-two*fabsf(x));
+	        z= -t/(t+two);
+	    }
+    /* |x| > 22, return +-1 */
+	} else {
+	    z = one - tiny;		/* raised inexact flag */
+	}
+	return (jx>=0)? z: -z;
+}
Index: /trunk/libc/src/msun/src/s_trunc.c
===================================================================
--- /trunk/libc/src/msun/src/s_trunc.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_trunc.c	(revision 2448)
@@ -0,0 +1,62 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_trunc.c,v 1.1 2004/06/20 09:25:43 das Exp $");
+
+/*
+ * trunc(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to trunc(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+double
+trunc(double x)
+{
+	int32_t i0,i1,j0;
+	u_int32_t i,j;
+	EXTRACT_WORDS(i0,i1,x);
+	j0 = ((i0>>20)&0x7ff)-0x3ff;
+	if(j0<20) {
+	    if(j0<0) { 	/* raise inexact if x != 0 */
+		if(huge+x>0.0) {/* |x|<1, so return 0*sign(x) */
+		    i0 &= 0x80000000U;
+		    i1 = 0;
+		}
+	    } else {
+		i = (0x000fffff)>>j0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		if(huge+x>0.0) {	/* raise inexact flag */
+		    i0 &= (~i); i1=0;
+		}
+	    }
+	} else if (j0>51) {
+	    if(j0==0x400) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    if(huge+x>0.0)		/* raise inexact flag */
+		i1 &= (~i);
+	}
+	INSERT_WORDS(x,i0,i1);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_truncf.c
===================================================================
--- /trunk/libc/src/msun/src/s_truncf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_truncf.c	(revision 2448)
@@ -0,0 +1,54 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/msun/src/s_truncf.c,v 1.1 2004/06/20 09:25:43 das Exp $");
+
+/*
+ * truncf(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to truncf(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+static const float huge = 1.0e30F;
+
+float
+truncf(float x)
+{
+	int32_t i0,j0;
+	u_int32_t i;
+	GET_FLOAT_WORD(i0,x);
+	j0 = ((i0>>23)&0xff)-0x7f;
+	if(j0<23) {
+	    if(j0<0) { 	/* raise inexact if x != 0 */
+		if(huge+x>0.0F)		/* |x|<1, so return 0*sign(x) */
+		    i0 &= 0x80000000;
+	    } else {
+		i = (0x007fffff)>>j0;
+		if((i0&i)==0) return x; /* x is integral */
+		if(huge+x>0.0F)		/* raise inexact flag */
+		    i0 &= (~i);
+	    }
+	} else {
+	    if(j0==0x80) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	}
+	SET_FLOAT_WORD(x,i0);
+	return x;
+}
Index: /trunk/libc/src/msun/src/s_truncl.c
===================================================================
--- /trunk/libc/src/msun/src/s_truncl.c	(revision 2448)
+++ /trunk/libc/src/msun/src/s_truncl.c	(revision 2448)
@@ -0,0 +1,69 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ */
+
+#include "namespace.h"
+#ifndef lint
+static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_truncl.c,v 1.3 2005/04/22 09:57:55 stefanf Exp $";
+#endif
+
+/*
+ * truncl(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to truncl(x).
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define	MANH_SIZE	(LDBL_MANH_SIZE + 1)
+#else
+#define	MANH_SIZE	LDBL_MANH_SIZE
+#endif
+
+static const double huge = 1.0e300;
+
+long double
+truncl(long double x)
+{
+	union IEEEl2bits u = { .e = x };
+	int e = u.bits.exp - LDBL_MAX_EXP + 1;
+
+	if (e < MANH_SIZE - 1) {
+		if (e < 0) {			/* raise inexact if x != 0 */
+			if (huge + (double)x > 0.0)
+				u.e = 0.0;
+		} else {
+			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+			if (((u.bits.manh & m) | u.bits.manl) == 0)
+				return (x);	/* x is integral */
+			if (huge + (double)x > 0.0) {	/* raise inexact flag */
+				u.bits.manh &= ~m;
+				u.bits.manl = 0;
+			}
+		}
+	} else if (e < LDBL_MANT_DIG - 1) {
+		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+		if ((u.bits.manl & m) == 0)
+			return (x);	/* x is integral */
+		if (huge + (double)x > 0.0)	/* raise inexact flag */
+			u.bits.manl &= ~m;
+	}
+	return (u.e);
+}
Index: /trunk/libc/src/msun/src/w_cabs.c
===================================================================
--- /trunk/libc/src/msun/src/w_cabs.c	(revision 2448)
+++ /trunk/libc/src/msun/src/w_cabs.c	(revision 2448)
@@ -0,0 +1,29 @@
+/*
+ * cabs() wrapper for hypot().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include "namespace.h"
+#ifndef lint
+static const char rcsid[] =
+  "$FreeBSD: src/lib/msun/src/w_cabs.c,v 1.4 2001/06/13 15:16:30 ru Exp $";
+#endif /* not lint */
+
+#include <complex.h>
+#include <math.h>
+
+double
+cabs(z)
+	double complex z;
+{
+	return hypot(creal(z), cimag(z));
+}
+
+double
+z_abs(z)
+	double complex *z;
+{
+	return hypot(creal(*z), cimag(*z));
+}
Index: /trunk/libc/src/msun/src/w_cabsf.c
===================================================================
--- /trunk/libc/src/msun/src/w_cabsf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/w_cabsf.c	(revision 2448)
@@ -0,0 +1,24 @@
+/*
+ * cabsf() wrapper for hypotf().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include "namespace.h"
+#ifndef lint
+static const char rcsid[] =
+  "$FreeBSD: src/lib/msun/src/w_cabsf.c,v 1.3 2001/06/13 15:16:30 ru Exp $";
+#endif /* not lint */
+
+#include <complex.h>
+#include <math.h>
+#include "math_private.h"
+
+float
+cabsf(z)
+	float complex z;
+{
+
+	return hypotf(crealf(z), cimagf(z));
+}
Index: /trunk/libc/src/msun/src/w_drem.c
===================================================================
--- /trunk/libc/src/msun/src/w_drem.c	(revision 2448)
+++ /trunk/libc/src/msun/src/w_drem.c	(revision 2448)
@@ -0,0 +1,16 @@
+/*
+ * drem() wrapper for remainder().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include "namespace.h"
+#include <math.h>
+
+double
+drem(x, y)
+	double x, y;
+{
+	return remainder(x, y);
+}
Index: /trunk/libc/src/msun/src/w_dremf.c
===================================================================
--- /trunk/libc/src/msun/src/w_dremf.c	(revision 2448)
+++ /trunk/libc/src/msun/src/w_dremf.c	(revision 2448)
@@ -0,0 +1,17 @@
+/*
+ * dremf() wrapper for remainderf().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+/* $FreeBSD: src/lib/msun/src/w_dremf.c,v 1.3 2004/07/28 05:53:18 kan Exp $ */
+
+#include "namespace.h"
+#include "math.h"
+#include "math_private.h"
+
+float
+dremf(float x, float y)
+{
+	return remainderf(x, y);
+}
Index: /trunk/libc/src/msun/std-complex.c
===================================================================
--- /trunk/libc/src/msun/std-complex.c	(revision 2448)
+++ /trunk/libc/src/msun/std-complex.c	(revision 2448)
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2001 The FreeBSD Project.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/include/complex.h,v 1.6 2004/08/14 18:03:21 stefanf Exp $
+ */
+
+/**
+ * FreeBSD 5.3
+ */
+
+#ifndef _COMPLEX_H
+#define	_COMPLEX_H
+
+#ifdef __GNUC__
+#if __STDC_VERSION__ < 199901
+#define	_Complex	__complex__
+#endif
+#define	_Complex_I	1.0fi
+#endif
+
+#define	complex		_Complex
+#define	I		_Complex_I
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+double		_STD(cabs)(double complex);
+float		_STD(cabsf)(float complex);
+double		_STD(cimag)(double complex);
+float		_STD(cimagf)(float complex);
+long double	_STD(cimagl)(long double complex);
+double complex	_STD(conj)(double complex);
+float complex	_STD(conjf)(float complex);
+long double complex
+		_STD(conjl)(long double complex);
+double		_STD(creal)(double complex);
+float		_STD(crealf)(float complex);
+long double	_STD(creall)(long double complex);
+
+/* bird: */
+long double          _STD(cabsl)(long double complex);
+double complex       _STD(cacos)(double complex);
+float complex        _STD(cacosf)(float complex);
+double complex       _STD(cacosh)(double complex);
+float complex        _STD(cacoshf)(float complex);
+long double complex  _STD(cacoshl)(long double complex);
+long double complex  _STD(cacosl)(long double complex);
+double               _STD(carg)(double complex);
+float                _STD(cargf)(float complex);
+long double          _STD(cargl)(long double complex);
+double complex       _STD(casin)(double complex);
+float complex        _STD(casinf)(float complex);
+double complex       _STD(casinh)(double complex);
+float complex        _STD(casinhf)(float complex);
+long double complex  _STD(casinhl)(long double complex);
+long double complex  _STD(casinl)(long double complex);
+double complex       _STD(catan)(double complex);
+float complex        _STD(catanf)(float complex);
+double complex       _STD(catanh)(double complex);
+float complex        _STD(catanhf)(float complex);
+long double complex  _STD(catanhl)(long double complex);
+long double complex  _STD(catanl)(long double complex);
+double complex       _STD(ccos)(double complex);
+float complex        _STD(ccosf)(float complex);
+double complex       _STD(ccosh)(double complex);
+float complex        _STD(ccoshf)(float complex);
+long double complex  _STD(ccoshl)(long double complex);
+long double complex  _STD(ccosl)(long double complex);
+double complex       _STD(cexp)(double complex);
+float complex        _STD(cexpf)(float complex);
+long double complex  _STD(cexpl)(long double complex);
+double complex       _STD(clog)(double complex);
+float complex        _STD(clogf)(float complex);
+long double complex  _STD(clogl)(long double complex);
+double complex       _STD(cpow)(double complex, double complex);
+float complex        _STD(cpowf)(float complex, float complex);
+long double complex  _STD(cpowl)(long double complex, long double complex);
+double complex       _STD(cproj)(double complex);
+float complex        _STD(cprojf)(float complex);
+long double complex  _STD(cprojl)(long double complex);
+double complex       _STD(csin)(double complex);
+float complex        _STD(csinf)(float complex);
+double complex       _STD(csinh)(double complex);
+float complex        _STD(csinhf)(float complex);
+long double complex  _STD(csinhl)(long double complex);
+long double complex  _STD(csinl)(long double complex);
+double complex       _STD(csqrt)(double complex);
+float complex        _STD(csqrtf)(float complex);
+long double complex  _STD(csqrtl)(long double complex);
+double complex       _STD(ctan)(double complex);
+float complex        _STD(ctanf)(float complex);
+double complex       _STD(ctanh)(double complex);
+float complex        _STD(ctanhf)(float complex);
+long double complex  _STD(ctanhl)(long double complex);
+long double complex  _STD(ctanl)(long double complex);
+
+double complex       _STD(clog10)(double complex);
+float complex        _STD(clog10f)(float complex);
+long double complex  _STD(clog10l)(long double complex);
+
+__END_DECLS
+
+#endif /* _COMPLEX_H */
+
Index: /trunk/libc/src/msun/std-math.c
===================================================================
--- /trunk/libc/src/msun/std-math.c	(revision 2448)
+++ /trunk/libc/src/msun/std-math.c	(revision 2448)
@@ -0,0 +1,504 @@
+/*
+ * MODIFIED math.h adding _STD() to all the functions which requires this,
+ * this saves a lot of annoying source changes!
+ * This is not mentv for compiling!
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $FreeBSD: src/lib/msun/src/math.h,v 1.61 2005/04/16 21:12:47 das Exp $
+ */
+
+#ifndef _MATH_H_
+#define	_MATH_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+#include <machine/_limits.h>
+
+/*
+ * ANSI/POSIX
+ */
+extern const union __infinity_un {
+	unsigned char	__uc[8];
+	double		__ud;
+} __infinity;
+
+extern const union __nan_un {
+	unsigned char	__uc[sizeof(float)];
+	float		__uf;
+} __nan;
+
+#if __GNUC_PREREQ__(3, 3) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
+#define	__MATH_BUILTIN_CONSTANTS
+#endif
+
+#if __GNUC_PREREQ__(3, 0) && !defined(__INTEL_COMPILER)
+#define	__MATH_BUILTIN_RELOPS
+#endif
+
+#ifdef __MATH_BUILTIN_CONSTANTS
+#define	HUGE_VAL	__builtin_huge_val()
+#else
+#define	HUGE_VAL	(__infinity.__ud)
+#endif
+
+#if __ISO_C_VISIBLE >= 1999
+#define	FP_ILOGB0	(-__INT_MAX)
+#define	FP_ILOGBNAN	__INT_MAX
+
+#ifdef __MATH_BUILTIN_CONSTANTS
+#define	HUGE_VALF	__builtin_huge_valf()
+#define	HUGE_VALL	__builtin_huge_vall()
+#define	INFINITY	__builtin_inf()
+#define	NAN		__builtin_nan("")
+#else
+#define	HUGE_VALF	(float)HUGE_VAL
+#define	HUGE_VALL	(long double)HUGE_VAL
+#define	INFINITY	HUGE_VALF
+#define	NAN		(__nan.__uf)
+#endif /* __MATH_BUILTIN_CONSTANTS */
+
+#define	MATH_ERRNO	1
+#define	MATH_ERREXCEPT	2
+#define	math_errhandling	MATH_ERREXCEPT
+
+/* XXX We need a <machine/math.h>. */
+#if defined(__ia64__) || defined(__sparc64__)
+#define	FP_FAST_FMA
+#endif
+#ifdef __ia64__
+#define	FP_FAST_FMAL
+#endif
+#define	FP_FAST_FMAF
+
+/* Symbolic constants to classify floating point numbers. */
+#define	FP_INFINITE	0x01
+#define	FP_NAN		0x02
+#define	FP_NORMAL	0x04
+#define	FP_SUBNORMAL	0x08
+#define	FP_ZERO		0x10
+#define	fpclassify(x) \
+    ((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) \
+    : (sizeof (x) == sizeof (double)) ? __fpclassifyd(x) \
+    : __fpclassifyl(x))
+
+#define	isfinite(x)					\
+    ((sizeof (x) == sizeof (float)) ? __isfinitef(x)	\
+    : (sizeof (x) == sizeof (double)) ? __isfinite(x)	\
+    : __isfinitel(x))
+#define	isinf(x)					\
+    ((sizeof (x) == sizeof (float)) ? __isinff(x)	\
+    : (sizeof (x) == sizeof (double)) ? isinf(x)	\
+    : __isinfl(x))
+#define	isnan(x)					\
+    ((sizeof (x) == sizeof (float)) ? isnanf(x)		\
+    : (sizeof (x) == sizeof (double)) ? isnan(x)	\
+    : __isnanl(x))
+#define	isnormal(x)					\
+    ((sizeof (x) == sizeof (float)) ? __isnormalf(x)	\
+    : (sizeof (x) == sizeof (double)) ? __isnormal(x)	\
+    : __isnormall(x))
+
+#ifdef __MATH_BUILTIN_RELOPS
+#define	isgreater(x, y)		__builtin_isgreater((x), (y))
+#define	isgreaterequal(x, y)	__builtin_isgreaterequal((x), (y))
+#define	isless(x, y)		__builtin_isless((x), (y))
+#define	islessequal(x, y)	__builtin_islessequal((x), (y))
+#define	islessgreater(x, y)	__builtin_islessgreater((x), (y))
+#define	isunordered(x, y)	__builtin_isunordered((x), (y))
+#else
+#define	isgreater(x, y)		(!isunordered((x), (y)) && (x) > (y))
+#define	isgreaterequal(x, y)	(!isunordered((x), (y)) && (x) >= (y))
+#define	isless(x, y)		(!isunordered((x), (y)) && (x) < (y))
+#define	islessequal(x, y)	(!isunordered((x), (y)) && (x) <= (y))
+#define	islessgreater(x, y)	(!isunordered((x), (y)) && \
+					((x) > (y) || (y) > (x)))
+#define	isunordered(x, y)	(isnan(x) || isnan(y))
+#endif /* __MATH_BUILTIN_RELOPS */
+
+#define	signbit(x)					\
+    ((sizeof (x) == sizeof (float)) ? __signbitf(x)	\
+    : (sizeof (x) == sizeof (double)) ? __signbit(x)	\
+    : __signbitl(x))
+
+typedef	__double_t	double_t;
+typedef	__float_t	float_t;
+#endif /* __ISO_C_VISIBLE >= 1999 */
+
+/*
+ * XOPEN/SVID
+ */
+#if __BSD_VISIBLE || __XSI_VISIBLE
+#define	M_E		2.7182818284590452354	/* e */
+#define	M_LOG2E		1.4426950408889634074	/* log 2e */
+#define	M_LOG10E	0.43429448190325182765	/* log 10e */
+#define	M_LN2		0.69314718055994530942	/* log e2 */
+#define	M_LN10		2.30258509299404568402	/* log e10 */
+#define	M_PI		3.14159265358979323846	/* pi */
+#define	M_PI_2		1.57079632679489661923	/* pi/2 */
+#define	M_PI_4		0.78539816339744830962	/* pi/4 */
+#define	M_1_PI		0.31830988618379067154	/* 1/pi */
+#define	M_2_PI		0.63661977236758134308	/* 2/pi */
+#define	M_2_SQRTPI	1.12837916709551257390	/* 2/sqrt(pi) */
+#define	M_SQRT2		1.41421356237309504880	/* sqrt(2) */
+#define	M_SQRT1_2	0.70710678118654752440	/* 1/sqrt(2) */
+
+#define	MAXFLOAT	((float)3.40282346638528860e+38)
+extern int _STD(signgam);
+#endif /* __BSD_VISIBLE || __XSI_VISIBLE */
+
+#if __BSD_VISIBLE
+#if 0
+/* Old value from 4.4BSD-Lite math.h; this is probably better. */
+#define	HUGE		HUGE_VAL
+#else
+#define	HUGE		MAXFLOAT
+#endif
+#endif /* __BSD_VISIBLE */
+
+/*
+ * Most of these functions depend on the rounding mode and have the side
+ * effect of raising floating-point exceptions, so they are not declared
+ * as __pure2.  In C99, FENV_ACCESS affects the purity of these functions.
+ */
+__BEGIN_DECLS
+/*
+ * ANSI/POSIX
+ */
+int	__fpclassifyd(double) __pure2;
+int	__fpclassifyf(float) __pure2;
+int	__fpclassifyl(long double) __pure2;
+int	__isfinitef(float) __pure2;
+int	__isfinite(double) __pure2;
+int	__isfinitel(long double) __pure2;
+int	__isinff(float) __pure2;
+int	__isinfl(long double) __pure2;
+int	__isnanl(long double) __pure2;
+int	__isnormalf(float) __pure2;
+int	__isnormal(double) __pure2;
+int	__isnormall(long double) __pure2;
+int	__signbit(double) __pure2;
+int	__signbitf(float) __pure2;
+int	__signbitl(long double) __pure2;
+
+double	_STD(acos)(double);
+double	_STD(asin)(double);
+double	_STD(atan)(double);
+double	_STD(atan2)(double, double);
+double	_STD(cos)(double);
+double	_STD(sin)(double);
+double	_STD(tan)(double);
+
+double	_STD(cosh)(double);
+double	_STD(sinh)(double);
+double	_STD(tanh)(double);
+
+double	_STD(exp)(double);
+double	_STD(frexp)(double, int *);	/* fundamentally !__pure2 */
+double	_STD(ldexp)(double, int);
+double	_STD(log)(double);
+double	_STD(log10)(double);
+double	_STD(modf)(double, double *);	/* fundamentally !__pure2 */
+
+double	_STD(pow)(double, double);
+double	_STD(sqrt)(double);
+
+double	_STD(ceil)(double);
+double	_STD(fabs)(double) __pure2;
+double	_STD(floor)(double);
+double	_STD(fmod)(double, double);
+
+/*
+ * These functions are not in C90.
+ */
+#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE
+double	_STD(acosh)(double);
+double	_STD(asinh)(double);
+double	_STD(atanh)(double);
+double	_STD(cbrt)(double);
+double	_STD(erf)(double);
+double	_STD(erfc)(double);
+double	_STD(exp2)(double);
+double	_STD(expm1)(double);
+double	_STD(fma)(double, double, double);
+double	_STD(hypot)(double, double);
+int	_STD(ilogb)(double) __pure2;
+int	_STD(isinf)(double) __pure2;
+int	_STD(isnan)(double) __pure2;
+double	_STD(lgamma)(double);
+long long _STD(llrint)(double);
+long long _STD(llround)(double);
+double	_STD(log1p)(double);
+double	_STD(logb)(double);
+long	_STD(lrint)(double);
+long	_STD(lround)(double);
+double	_STD(nextafter)(double, double);
+double	_STD(remainder)(double, double);
+double	_STD(remquo)(double, double, int *);
+double	_STD(rint)(double);
+#endif /* __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE */
+
+#if __BSD_VISIBLE || __XSI_VISIBLE
+double	_STD(j0)(double);
+double	_STD(j1)(double);
+double	_STD(jn)(int, double);
+double	_STD(scalb)(double, double);
+double	_STD(y0)(double);
+double	_STD(y1)(double);
+double	_STD(yn)(int, double);
+
+#if __XSI_VISIBLE <= 500 || __BSD_VISIBLE
+double	_STD(gamma)(double);
+#endif
+#endif /* __BSD_VISIBLE || __XSI_VISIBLE */
+
+#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999
+double	_STD(copysign)(double, double) __pure2;
+double	_STD(fdim)(double, double);
+double	_STD(fmax)(double, double) __pure2;
+double	_STD(fmin)(double, double) __pure2;
+double	_STD(nearbyint)(double);
+double	_STD(round)(double);
+double	_STD(scalbln)(double, long);
+double	_STD(scalbn)(double, int);
+double	_STD(tgamma)(double);
+double	_STD(trunc)(double);
+#endif
+
+/*
+ * BSD math library entry points
+ */
+#if __BSD_VISIBLE
+double _STD(drem)(double, double);
+int	_STD(finite)(double) __pure2;
+int	_STD(isnanf)(float) __pure2;
+
+/*
+ * Reentrant version of gamma & lgamma; passes signgam back by reference
+ * as the second argument; user must allocate space for signgam.
+ */
+double	_STD(gamma_r)(double, int *);
+double	_STD(lgamma_r)(double, int *);
+
+/*
+ * IEEE Test Vector
+ */
+double	_STD(significand)(double);
+#endif /* __BSD_VISIBLE */
+
+/* float versions of ANSI/POSIX functions */
+#if __ISO_C_VISIBLE >= 1999
+float	_STD(acosf)(float);
+float	_STD(asinf)(float);
+float	_STD(atanf)(float);
+float	_STD(atan2f)(float, float);
+float	_STD(cosf)(float);
+float	_STD(sinf)(float);
+float	_STD(tanf)(float);
+
+float	_STD(coshf)(float);
+float	_STD(sinhf)(float);
+float	_STD(tanhf)(float);
+
+float	_STD(exp2f)(float);
+float	_STD(expf)(float);
+float	_STD(expm1f)(float);
+float	_STD(frexpf)(float, int *);	/* fundamentally !__pure2 */
+int	_STD(ilogbf)(float) __pure2;
+float	_STD(ldexpf)(float, int);
+float	_STD(log10f)(float);
+float	_STD(log1pf)(float);
+float	_STD(logf)(float);
+float	_STD(modff)(float, float *);	/* fundamentally !__pure2 */
+
+float	_STD(powf)(float, float);
+float	_STD(sqrtf)(float);
+
+float	_STD(ceilf)(float);
+float	_STD(fabsf)(float) __pure2;
+float	_STD(floorf)(float);
+float	_STD(fmodf)(float, float);
+float	_STD(roundf)(float);
+
+float	_STD(erff)(float);
+float	_STD(erfcf)(float);
+float	_STD(hypotf)(float, float);
+float	_STD(lgammaf)(float);
+
+float	_STD(acoshf)(float);
+float	_STD(asinhf)(float);
+float	_STD(atanhf)(float);
+float	_STD(cbrtf)(float);
+float	_STD(logbf)(float);
+float	_STD(copysignf)(float, float) __pure2;
+long long _STD(llrintf)(float);
+long long _STD(llroundf)(float);
+long	_STD(lrintf)(float);
+long	_STD(lroundf)(float);
+float	_STD(nearbyintf)(float);
+float	_STD(nextafterf)(float, float);
+float	_STD(remainderf)(float, float);
+float	_STD(remquof)(float, float, int *);
+float	_STD(rintf)(float);
+float	_STD(scalblnf)(float, long);
+float	_STD(scalbnf)(float, int);
+float	_STD(truncf)(float);
+
+float	_STD(fdimf)(float, float);
+float	_STD(fmaf)(float, float, float);
+float	_STD(fmaxf)(float, float) __pure2;
+float	_STD(fminf)(float, float) __pure2;
+#endif
+
+/*
+ * float versions of BSD math library entry points
+ */
+#if __BSD_VISIBLE
+float	_STD(dremf)(float, float);
+int	_STD(finitef)(float) __pure2;
+float	_STD(gammaf)(float);
+float	_STD(j0f)(float);
+float	_STD(j1f)(float);
+float	_STD(jnf)(int, float);
+float	_STD(scalbf)(float, float);
+float	_STD(y0f)(float);
+float	_STD(y1f)(float);
+float	_STD(ynf)(int, float);
+
+/*
+ * Float versions of reentrant version of gamma & lgamma; passes
+ * signgam back by reference as the second argument; user must
+ * allocate space for signgam.
+ */
+float	_STD(gammaf_r)(float, int *);
+float	_STD(lgammaf_r)(float, int *);
+
+/*
+ * float version of IEEE Test Vector
+ */
+float	_STD(significandf)(float);
+#endif	/* __BSD_VISIBLE */
+
+/*
+ * long double versions of ISO/POSIX math functions
+ */
+#if __ISO_C_VISIBLE >= 1999
+#if 0
+long double	_STD(acoshl)(long double);
+long double	_STD(acosl)(long double);
+long double	_STD(asinhl)(long double);
+long double	_STD(asinl)(long double);
+long double	_STD(atan2l)(long double, long double);
+long double	_STD(atanhl)(long double);
+long double	_STD(atanl)(long double);
+long double	_STD(cbrtl)(long double);
+#endif
+long double	_STD(ceill)(long double);
+long double	_STD(copysignl)(long double, long double) __pure2;
+#if 0
+long double	_STD(coshl)(long double);
+long double	_STD(cosl)(long double);
+long double	_STD(erfcl)(long double);
+long double	_STD(erfl)(long double);
+long double	_STD(exp2l)(long double);
+long double	_STD(expl)(long double);
+long double	_STD(expm1l)(long double);
+#endif
+long double	_STD(fabsl)(long double) __pure2;
+long double	_STD(fdiml)(long double, long double);
+long double	_STD(floorl)(long double);
+long double	_STD(fmal)(long double, long double, long double);
+long double	_STD(fmaxl)(long double, long double) __pure2;
+long double	_STD(fminl)(long double, long double) __pure2;
+#if 0
+long double	_STD(fmodl)(long double, long double);
+#endif
+long double	_STD(frexpl)(long double value, int *); /* fundamentally !__pure2 */
+#if 0
+long double	_STD(hypotl)(long double, long double);
+#endif
+int		_STD(ilogbl)(long double) __pure2;
+long double	_STD(ldexpl)(long double, int);
+#if 0
+long double	_STD(lgammal)(long double);
+long long	_STD(llrintl)(long double);
+#endif
+long long	_STD(llroundl)(long double);
+#if 0
+long double	_STD(log10l)(long double);
+long double	_STD(log1pl)(long double);
+long double	_STD(log2l)(long double);
+long double	_STD(logbl)(long double);
+long double	_STD(logl)(long double);
+long		_STD(lrintl)(long double);
+#endif
+long		_STD(lroundl)(long double);
+#if 0
+long double	_STD(modfl)(long double, long double *); /* fundamentally !__pure2 */
+long double	nanl(const char *) __pure2; /* gcc intrinsic */
+long double	_STD(nearbyintl)(long double);
+#endif
+long double	_STD(nextafterl)(long double, long double);
+double		_STD(nexttoward)(double, long double);
+float		_STD(nexttowardf)(float, long double);
+long double	_STD(nexttowardl)(long double, long double);
+#if 0
+long double	_STD(powl)(long double, long double);
+long double	_STD(remainderl)(long double, long double);
+long double	_STD(remquol)(long double, long double, int *);
+long double	_STD(rintl)(long double);
+#endif
+long double	_STD(roundl)(long double);
+long double	_STD(scalblnl)(long double, long);
+long double	_STD(scalbnl)(long double, int);
+#if 0
+long double	_STD(sinhl)(long double);
+long double	_STD(sinl)(long double);
+long double	_STD(sqrtl)(long double);
+long double	_STD(tanhl)(long double);
+long double	_STD(tanl)(long double);
+long double	_STD(tgammal)(long double);
+#endif
+long double	_STD(truncl)(long double);
+
+#endif /* __ISO_C_VISIBLE >= 1999 */
+
+#ifdef __USE_GNU
+void _STD(sincos)(double, double *, double *);
+void _STD(sincosf)(float, float *, float *);
+void _STD(sincosl)(long double, long double *, long double *);
+float _STD(exp10f)(float);
+double _STD(exp10)(double);
+long double _STD(exp10l)(long double);
+float _STD(log2f)(float);
+double _STD(log2)(double);
+long double _STD(log2l)(long double);
+float _STD(tgammaf)(float);
+long double _STD(significandl)(long double);
+long double _STD(j0l)(long double);
+long double _STD(j1l)(long double);
+long double _STD(jnl)(int, long double);
+long double _STD(scalbl)(long double, long double);
+long double _STD(y0l)(long double);
+long double _STD(y1l)(long double);
+long double _STD(ynl)(int, long double);
+long double _STD(gammal)(long double);
+long double _STD(gammal_r)(long double,int *);
+long double _STD(lgammal_r)(long double,int *);
+
+#endif
+__END_DECLS
+
+#endif /* !_MATH_H_ */
