OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/trunk/newlib-1.10.0/newlib/libc/stdlib
    from Rev 1010 to Rev 1765
    Reverse comparison

Rev 1010 → Rev 1765

/Makefile.in
0,0 → 1,580
# Makefile.in generated automatically by automake 1.4 from Makefile.am
 
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
 
 
 
SHELL = @SHELL@
 
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
 
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
 
DESTDIR =
 
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
 
top_builddir = ..
 
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
 
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
 
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
AR = @AR@
AS = @AS@
CC = @CC@
CPP = @CPP@
CRT0 = @CRT0@
DLLTOOL = @DLLTOOL@
EXEEXT = @EXEEXT@
LDFLAGS = @LDFLAGS@
LIBC_MACHINE_LIB = @LIBC_MACHINE_LIB@
LIBC_POSIX_LIB = @LIBC_POSIX_LIB@
LIBC_SIGNAL_DEF = @LIBC_SIGNAL_DEF@
LIBC_SIGNAL_LIB = @LIBC_SIGNAL_LIB@
LIBC_SYSCALL_LIB = @LIBC_SYSCALL_LIB@
LIBC_SYS_LIB = @LIBC_SYS_LIB@
LIBC_UNIX_LIB = @LIBC_UNIX_LIB@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
aext = @aext@
libm_machine_dir = @libm_machine_dir@
machine_dir = @machine_dir@
newlib_basedir = @newlib_basedir@
oext = @oext@
sys_dir = @sys_dir@
 
AUTOMAKE_OPTIONS = cygnus
 
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
 
LIB_SOURCES = \
__adjust.c \
__exp10.c \
__ten_mu.c \
abort.c \
abs.c \
assert.c \
atexit.c \
atof.c \
atoff.c \
atoi.c \
atol.c \
bsearch.c \
calloc.c \
div.c \
drand48.c \
dtoa.c \
dtoastub.c \
ecvtbuf.c \
efgcvt.c \
environ.c \
envlock.c \
eprintf.c \
erand48.c \
exit.c \
getenv.c \
getenv_r.c \
getopt.c \
jrand48.c \
labs.c \
lcong48.c \
ldiv.c \
ldtoa.c \
lrand48.c \
malign.c \
malloc.c \
mblen.c \
mblen_r.c \
mbstowcs.c \
mbstowcs_r.c \
mbtowc.c \
mbtowc_r.c \
mlock.c \
mprec.c \
mrand48.c \
msize.c \
mstats.c \
mtrim.c \
nrand48.c \
putenv.c \
putenv_r.c \
qsort.c \
rand.c \
rand48.c \
rand_r.c \
realloc.c \
seed48.c \
setenv.c \
setenv_r.c \
srand48.c \
strdup.c \
strdup_r.c \
strtod.c \
strtol.c \
strtoll.c \
strtoll_r.c \
strtoul.c \
strtoull.c \
strtoull_r.c \
system.c \
valloc.c \
wcstombs.c \
wcstombs_r.c \
wctomb.c \
wctomb_r.c
 
 
# Because of how libtool moves objects around, mallocr must be built last.
LIBADD_OBJS = freer.$(oext) reallocr.$(oext) callocr.$(oext) cfreer.$(oext) malignr.$(oext) \
vallocr.$(oext) pvallocr.$(oext) mallinfor.$(oext) mallstatsr.$(oext) msizer.$(oext) malloptr.$(oext) mallocr.$(oext)
 
 
libstdlib_la_LDFLAGS = -Xcompiler -nostdlib
 
@USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = @USE_LIBTOOL_TRUE@libstdlib.la
@USE_LIBTOOL_TRUE@libstdlib_la_SOURCES = @USE_LIBTOOL_TRUE@$(LIB_SOURCES)
@USE_LIBTOOL_TRUE@libstdlib_la_LIBADD = @USE_LIBTOOL_TRUE@$(LIBADD_OBJS)
@USE_LIBTOOL_TRUE@LIB_COMPILE = @USE_LIBTOOL_TRUE@$(LTCOMPILE)
@USE_LIBTOOL_FALSE@LIB_COMPILE = @USE_LIBTOOL_FALSE@$(COMPILE)
@USE_LIBTOOL_TRUE@noinst_DATA = @USE_LIBTOOL_TRUE@objectlist.awk.in
@USE_LIBTOOL_FALSE@noinst_DATA =
@USE_LIBTOOL_FALSE@noinst_LIBRARIES = @USE_LIBTOOL_FALSE@lib.a
@USE_LIBTOOL_FALSE@lib_a_SOURCES = @USE_LIBTOOL_FALSE@$(LIB_SOURCES)
@USE_LIBTOOL_FALSE@lib_a_LIBADD = @USE_LIBTOOL_FALSE@$(LIBADD_OBJS)
 
MALLOC_COMPILE = $(LIB_COMPILE) -DINTERNAL_NEWLIB
 
CHEWOUT_FILES = \
abort.def \
abs.def \
assert.def \
atexit.def \
atof.def \
ecvtbuf.def \
atoi.def \
bsearch.def \
calloc.def \
div.def \
efgcvt.def \
envlock.def \
exit.def \
getenv.def \
labs.def \
ldiv.def \
malloc.def \
mallocr.def \
mblen.def \
mbstowcs.def \
mbtowc.def \
mlock.def \
mstats.def \
qsort.def \
rand.def \
rand48.def \
strtod.def \
strtol.def \
strtoll.def \
strtoul.def \
strtoull.def \
system.def \
wcstombs.def \
wctomb.def
 
 
SUFFIXES = .def
 
CHEW = ../../doc/makedoc -f $(srcdir)/../../doc/doc.str
 
TARGETDOC = ../tmp.texi
 
CLEANFILES = $(CHEWOUT_FILES) *.ref
mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
 
 
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LIBS = @LIBS@
@USE_LIBTOOL_FALSE@lib_a_DEPENDENCIES = freer.$(oext) reallocr.$(oext) \
@USE_LIBTOOL_FALSE@callocr.$(oext) cfreer.$(oext) malignr.$(oext) \
@USE_LIBTOOL_FALSE@vallocr.$(oext) pvallocr.$(oext) mallinfor.$(oext) \
@USE_LIBTOOL_FALSE@mallstatsr.$(oext) msizer.$(oext) malloptr.$(oext) \
@USE_LIBTOOL_FALSE@mallocr.$(oext)
@USE_LIBTOOL_FALSE@lib_a_OBJECTS = __adjust.o __exp10.o __ten_mu.o \
@USE_LIBTOOL_FALSE@abort.o abs.o assert.o atexit.o atof.o atoff.o \
@USE_LIBTOOL_FALSE@atoi.o atol.o bsearch.o calloc.o div.o drand48.o \
@USE_LIBTOOL_FALSE@dtoa.o dtoastub.o ecvtbuf.o efgcvt.o environ.o \
@USE_LIBTOOL_FALSE@envlock.o eprintf.o erand48.o exit.o getenv.o \
@USE_LIBTOOL_FALSE@getenv_r.o getopt.o jrand48.o labs.o lcong48.o \
@USE_LIBTOOL_FALSE@ldiv.o ldtoa.o lrand48.o malign.o malloc.o mblen.o \
@USE_LIBTOOL_FALSE@mblen_r.o mbstowcs.o mbstowcs_r.o mbtowc.o \
@USE_LIBTOOL_FALSE@mbtowc_r.o mlock.o mprec.o mrand48.o msize.o \
@USE_LIBTOOL_FALSE@mstats.o mtrim.o nrand48.o putenv.o putenv_r.o \
@USE_LIBTOOL_FALSE@qsort.o rand.o rand48.o rand_r.o realloc.o seed48.o \
@USE_LIBTOOL_FALSE@setenv.o setenv_r.o srand48.o strdup.o strdup_r.o \
@USE_LIBTOOL_FALSE@strtod.o strtol.o strtoll.o strtoll_r.o strtoul.o \
@USE_LIBTOOL_FALSE@strtoull.o strtoull_r.o system.o valloc.o wcstombs.o \
@USE_LIBTOOL_FALSE@wcstombs_r.o wctomb.o wctomb_r.o
LTLIBRARIES = $(noinst_LTLIBRARIES)
 
@USE_LIBTOOL_TRUE@libstdlib_la_DEPENDENCIES = freer.$(oext) \
@USE_LIBTOOL_TRUE@reallocr.$(oext) callocr.$(oext) cfreer.$(oext) \
@USE_LIBTOOL_TRUE@malignr.$(oext) vallocr.$(oext) pvallocr.$(oext) \
@USE_LIBTOOL_TRUE@mallinfor.$(oext) mallstatsr.$(oext) msizer.$(oext) \
@USE_LIBTOOL_TRUE@malloptr.$(oext) mallocr.$(oext)
@USE_LIBTOOL_TRUE@libstdlib_la_OBJECTS = __adjust.lo __exp10.lo \
@USE_LIBTOOL_TRUE@__ten_mu.lo abort.lo abs.lo assert.lo atexit.lo \
@USE_LIBTOOL_TRUE@atof.lo atoff.lo atoi.lo atol.lo bsearch.lo calloc.lo \
@USE_LIBTOOL_TRUE@div.lo drand48.lo dtoa.lo dtoastub.lo ecvtbuf.lo \
@USE_LIBTOOL_TRUE@efgcvt.lo environ.lo envlock.lo eprintf.lo erand48.lo \
@USE_LIBTOOL_TRUE@exit.lo getenv.lo getenv_r.lo getopt.lo jrand48.lo \
@USE_LIBTOOL_TRUE@labs.lo lcong48.lo ldiv.lo ldtoa.lo lrand48.lo \
@USE_LIBTOOL_TRUE@malign.lo malloc.lo mblen.lo mblen_r.lo mbstowcs.lo \
@USE_LIBTOOL_TRUE@mbstowcs_r.lo mbtowc.lo mbtowc_r.lo mlock.lo mprec.lo \
@USE_LIBTOOL_TRUE@mrand48.lo msize.lo mstats.lo mtrim.lo nrand48.lo \
@USE_LIBTOOL_TRUE@putenv.lo putenv_r.lo qsort.lo rand.lo rand48.lo \
@USE_LIBTOOL_TRUE@rand_r.lo realloc.lo seed48.lo setenv.lo setenv_r.lo \
@USE_LIBTOOL_TRUE@srand48.lo strdup.lo strdup_r.lo strtod.lo strtol.lo \
@USE_LIBTOOL_TRUE@strtoll.lo strtoll_r.lo strtoul.lo strtoull.lo \
@USE_LIBTOOL_TRUE@strtoull_r.lo system.lo valloc.lo wcstombs.lo \
@USE_LIBTOOL_TRUE@wcstombs_r.lo wctomb.lo wctomb_r.lo
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DATA = $(noinst_DATA)
 
DIST_COMMON = Makefile.am Makefile.in
 
 
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
TAR = gtar
GZIP_ENV = --best
SOURCES = $(lib_a_SOURCES) $(libstdlib_la_SOURCES)
OBJECTS = $(lib_a_OBJECTS) $(libstdlib_la_OBJECTS)
 
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .def .lo .o .s
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(srcdir)/../../Makefile.shared
cd $(top_srcdir) && $(AUTOMAKE) --cygnus stdlib/Makefile
 
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
 
 
mostlyclean-noinstLIBRARIES:
 
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
 
distclean-noinstLIBRARIES:
 
maintainer-clean-noinstLIBRARIES:
 
.c.o:
$(COMPILE) -c $<
 
.s.o:
$(COMPILE) -c $<
 
.S.o:
$(COMPILE) -c $<
 
mostlyclean-compile:
-rm -f *.o core *.core
 
clean-compile:
 
distclean-compile:
-rm -f *.tab.c
 
maintainer-clean-compile:
 
.c.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
 
.s.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
 
.S.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
 
mostlyclean-libtool:
-rm -f *.lo
 
clean-libtool:
-rm -rf .libs _libs
 
distclean-libtool:
 
maintainer-clean-libtool:
 
lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES)
-rm -f lib.a
$(AR) cru lib.a $(lib_a_OBJECTS) $(lib_a_LIBADD)
$(RANLIB) lib.a
 
mostlyclean-noinstLTLIBRARIES:
 
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
 
distclean-noinstLTLIBRARIES:
 
maintainer-clean-noinstLTLIBRARIES:
 
libstdlib.la: $(libstdlib_la_OBJECTS) $(libstdlib_la_DEPENDENCIES)
$(LINK) $(libstdlib_la_LDFLAGS) $(libstdlib_la_OBJECTS) $(libstdlib_la_LIBADD) $(LIBS)
 
tags: TAGS
 
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
 
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
 
mostlyclean-tags:
 
clean-tags:
 
distclean-tags:
-rm -f TAGS ID
 
maintainer-clean-tags:
 
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
 
subdir = stdlib
 
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am:
check: check-am
installcheck-am:
installcheck: installcheck-am
install-info-am:
install-info: install-info-am
install-exec-am:
install-exec: install-exec-am
 
install-data-am:
install-data: install-data-am
 
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(DATA)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
 
 
mostlyclean-generic:
 
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
 
maintainer-clean-generic:
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-libtool mostlyclean-noinstLTLIBRARIES \
mostlyclean-tags mostlyclean-generic
 
mostlyclean: mostlyclean-am
 
clean-am: clean-noinstLIBRARIES clean-compile clean-libtool \
clean-noinstLTLIBRARIES clean-tags clean-generic \
mostlyclean-am
 
clean: clean-am
 
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-libtool distclean-noinstLTLIBRARIES \
distclean-tags distclean-generic clean-am
-rm -f libtool
 
distclean: distclean-am
 
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-libtool \
maintainer-clean-noinstLTLIBRARIES \
maintainer-clean-tags maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
 
maintainer-clean: maintainer-clean-am
 
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
clean-libtool maintainer-clean-libtool mostlyclean-noinstLTLIBRARIES \
distclean-noinstLTLIBRARIES clean-noinstLTLIBRARIES \
maintainer-clean-noinstLTLIBRARIES tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
check-am installcheck-am installcheck install-info-am install-info \
install-exec-am install-exec install-data-am install-data install-am \
install uninstall-am uninstall all-redirect all-am all installdirs \
mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
 
 
objectlist.awk.in: $(noinst_LTLIBRARIES)
-rm -f objectlist.awk.in
for i in `ls *.lo` ; \
do \
echo $$i `pwd`/$$i >> objectlist.awk.in ; \
done
 
mallocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/mallocr.c -o $@
 
freer.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/mallocr.c -o $@
 
reallocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/mallocr.c -o $@
 
callocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/mallocr.c -o $@
 
cfreer.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_CFREE -c $(srcdir)/mallocr.c -o $@
 
malignr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/mallocr.c -o $@
 
vallocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_VALLOC -c $(srcdir)/mallocr.c -o $@
 
pvallocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_PVALLOC -c $(srcdir)/mallocr.c -o $@
 
mallinfor.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLINFO -c $(srcdir)/mallocr.c -o $@
 
mallstatsr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLOC_STATS -c $(srcdir)/mallocr.c -o $@
 
msizer.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLOC_USABLE_SIZE -c $(srcdir)/mallocr.c -o $@
 
malloptr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/mallocr.c -o $@
 
.c.def:
$(CHEW) < $< > $*.def 2> $*.ref
touch stmp-def
 
doc: $(CHEWOUT_FILES)
cat $(srcdir)/stdlib.tex >> $(TARGETDOC)
 
dtoa.$(oext): dtoa.c mprec.h
ldtoa.$(oext): ldtoa.c mprec.h
ecvtbuf.$(oext): ecvtbuf.c mprec.h
mbtowc_r.$(oext): mbtowc_r.c mbctype.h
$(LIB_COMPILE) -c -fshort-enums $(srcdir)/mbtowc_r.c -o $@
 
mprec.$(oext): mprec.c mprec.h
strtod.$(oext): strtod.c mprec.h
wctomb_r.$(oext): wctomb_r.c mbctype.h
drand48.$(oext): drand48.c rand48.h
erand48.$(oext): erand48.c rand48.h
jrand48.$(oext): jrand48.c rand48.h
lcong48.$(oext): lcong48.c rand48.h
lrand48.$(oext): lrand48.c rand48.h
mrand48.$(oext): mrand48.c rand48.h
nrand48.$(oext): nrand48.c rand48.h
rand48.$(oext): rand48.c rand48.h
seed48.$(oext): seed48.c rand48.h
srand48.$(oext): srand48.c rand48.h
 
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
/drand48.c
0,0 → 1,29
/*
* 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 "rand48.h"
 
double
_DEFUN (_drand48_r, (r),
struct _reent *r)
{
return _erand48_r(r, __rand48_seed);
}
 
#ifndef _REENT_ONLY
double
_DEFUN_VOID (drand48)
{
return _drand48_r (_REENT);
}
#endif /* !_REENT_ONLY */
/setenv.c
0,0 → 1,54
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#ifndef _REENT_ONLY
 
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
 
extern void _unsetenv_r _PARAMS ((struct _reent *, const char *));
 
/*
* setenv --
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
 
int
_DEFUN (setenv, (name, value, rewrite),
_CONST char *name _AND
_CONST char *value _AND
int rewrite)
{
return _setenv_r (_REENT, name, value, rewrite);
}
 
/*
* unsetenv(name) --
* Delete environmental variable "name".
*/
void
_DEFUN (unsetenv, (name),
_CONST char *name)
{
_unsetenv_r (_REENT, name);
}
 
#endif /* !_REENT_ONLY */
/mlock.c
0,0 → 1,50
/*
FUNCTION
<<__malloc_lock>>, <<__malloc_unlock>>--lock malloc pool
 
INDEX
__malloc_lock
INDEX
__malloc_unlock
 
ANSI_SYNOPSIS
#include <malloc.h>
void __malloc_lock (struct _reent *<[reent]>);
void __malloc_unlock (struct _reent *<[reent]>);
 
TRAD_SYNOPSIS
void __malloc_lock(<[reent]>)
struct _reent *<[reent]>;
 
void __malloc_unlock(<[reent]>)
struct _reent *<[reent]>;
 
DESCRIPTION
The <<malloc>> family of routines call these functions when they need
to lock the memory pool. The version of these routines supplied in
the library does not do anything. If multiple threads of execution
can call <<malloc>>, or if <<malloc>> can be called reentrantly, then
you need to define your own versions of these functions in order to
safely lock the memory pool during a call. If you do not, the memory
pool may become corrupted.
 
A call to <<malloc>> may call <<__malloc_lock>> recursively; that is,
the sequence of calls may go <<__malloc_lock>>, <<__malloc_lock>>,
<<__malloc_unlock>>, <<__malloc_unlock>>. Any implementation of these
routines must be careful to avoid causing a thread to wait for a lock
that it already holds.
*/
 
#include <malloc.h>
 
void
__malloc_lock (ptr)
struct _reent *ptr;
{
}
 
void
__malloc_unlock (ptr)
struct _reent *ptr;
{
}
/abs.c
0,0 → 1,43
/*
FUNCTION
<<abs>>---integer absolute value (magnitude)
 
INDEX
abs
 
ANSI_SYNOPSIS
#include <stdlib.h>
int abs(int <[i]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int abs(<[i]>)
int <[i]>;
 
DESCRIPTION
<<abs>> returns
@tex
$|x|$,
@end tex
the absolute value of <[i]> (also called the magnitude
of <[i]>). That is, if <[i]> is negative, the result is the opposite
of <[i]>, but if <[i]> is nonnegative the result is <[i]>.
 
The similar function <<labs>> uses and returns <<long>> rather than <<int>> values.
 
RETURNS
The result is a nonnegative integer.
 
PORTABILITY
<<abs>> is ANSI.
 
No supporting OS subroutines are required.
*/
 
#include <stdlib.h>
 
int
_DEFUN (abs, (i), int i)
{
return (i < 0) ? -i : i;
}
/erand48.c
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 "rand48.h"
 
double
_DEFUN (_erand48_r, (r, xseed),
struct _reent *r _AND
unsigned short xseed[3])
{
__dorand48(r, xseed);
return ldexp((double) xseed[0], -48) +
ldexp((double) xseed[1], -32) +
ldexp((double) xseed[2], -16);
}
 
#ifndef _REENT_ONLY
double
_DEFUN (erand48, (xseed),
unsigned short xseed[3])
{
return _erand48_r (_REENT, xseed);
}
#endif /* !_REENT_ONLY */
/malign.c
0,0 → 1,18
/* malign.c -- a wrapper for memalign_r. */
 
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
 
#ifndef _REENT_ONLY
 
_PTR
_DEFUN (memalign, (align, nbytes),
size_t align _AND
size_t nbytes)
{
return _memalign_r (_REENT, align, nbytes);
}
 
#endif
/mbctype.h
0,0 → 1,20
#ifndef _MBCTYPE_H_
 
#define _MBCTYPE_H_
 
/* escape character used for JIS encoding */
#define ESC_CHAR 0x1b
 
/* functions used to support SHIFT_JIS, EUC-JP, and JIS multibyte encodings */
 
int _EXFUN(_issjis1, (int c));
int _EXFUN(_issjis2, (int c));
int _EXFUN(_iseucjp, (int c));
int _EXFUN(_isjis, (int c));
 
#define _issjis1(c) (((c) >= 0x81 && (c) <= 0x9f) || ((c) >= 0xe0 && (c) <= 0xef))
#define _issjis2(c) (((c) >= 0x40 && (c) <= 0x7e) || ((c) >= 0x80 && (c) <= 0xfc))
#define _iseucjp(c) ((c) >= 0xa1 && (c) <= 0xfe)
#define _isjis(c) ((c) >= 0x21 && (c) <= 0x7e)
 
#endif /* _MBCTYPE_H_ */
/exit.c
0,0 → 1,73
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* %sccs.include.redist.c%
*/
 
/*
FUNCTION
<<exit>>---end program execution
 
INDEX
exit
 
ANSI_SYNOPSIS
#include <stdlib.h>
void exit(int <[code]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
void exit(<[code]>)
int <[code]>;
 
DESCRIPTION
Use <<exit>> to return control from a program to the host operating
environment. Use the argument <[code]> to pass an exit status to the
operating environment: two particular values, <<EXIT_SUCCESS>> and
<<EXIT_FAILURE>>, are defined in `<<stdlib.h>>' to indicate success or
failure in a portable fashion.
 
<<exit>> does two kinds of cleanup before ending execution of your
program. First, it calls all application-defined cleanup functions
you have enrolled with <<atexit>>. Second, files and streams are
cleaned up: any pending output is delivered to the host system, each
open file or stream is closed, and files created by <<tmpfile>> are
deleted.
 
RETURNS
<<exit>> does not return to its caller.
 
PORTABILITY
ANSI C requires <<exit>>, and specifies that <<EXIT_SUCCESS>> and
<<EXIT_FAILURE>> must be defined.
 
Supporting OS subroutines required: <<_exit>>.
*/
 
#include <stdlib.h>
#include <unistd.h> /* for _exit() declaration */
#include <reent.h>
 
#ifndef _REENT_ONLY
 
/*
* Exit, flushing stdio buffers if necessary.
*/
 
void
_DEFUN (exit, (code),
int code)
{
register struct _atexit *p;
register int n;
 
for (p = _REENT->_atexit; p; p = p->_next)
for (n = p->_ind; --n >= 0;)
(*p->_fns[n]) ();
if (_REENT->__cleanup)
(*_REENT->__cleanup) (_REENT);
_exit (code);
}
 
#endif
/strtoull_r.c
0,0 → 1,120
/*
This code is based on strtoul.c which has the following copyright.
It is used to convert a string into an unsigned long long.
long long _strtoull_r (struct _reent *rptr, const char *s,
char **ptr, int base);
 
*/
 
/*
* Copyright (c) 1990 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.
*/
 
#ifdef __GNUC__
 
#define _GNU_SOURCE
#include <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
 
/*
* Convert a string to an unsigned long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long long
_DEFUN (_strtoull_r, (rptr, nptr, endptr, base),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr _AND
int base)
{
register const char *s = nptr;
register unsigned long long acc;
register int c;
register unsigned long long cutoff;
register int neg = 0, any, cutlim;
 
/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else 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;
cutoff = (unsigned long long)ULONG_LONG_MAX / (unsigned long long)base;
cutlim = (unsigned long long)ULONG_LONG_MAX % (unsigned long long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : '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_LONG_MAX;
rptr->_errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
 
#endif /* __GNUC__ */
/jrand48.c
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.
*/
 
#include "rand48.h"
 
long
_DEFUN (_jrand48_r, (r, xseed),
struct _reent *r _AND
unsigned short xseed[3])
{
__dorand48(r, xseed);
return ((long) xseed[2] << 16) + (long) xseed[1];
}
 
#ifndef _REENT_ONLY
long
_DEFUN (jrand48, (xseed),
unsigned short xseed[3])
{
return _jrand48_r (_REENT, xseed);
}
#endif /* !_REENT_ONLY */
/mbtowc_r.c
0,0 → 1,208
#include <stdlib.h>
#include <locale.h>
#include "mbctype.h"
 
#ifdef MB_CAPABLE
typedef enum { ESCAPE, DOLLAR, BRACKET, AT, B, J,
NUL, JIS_CHAR, OTHER, JIS_C_NUM } JIS_CHAR_TYPE;
typedef enum { ASCII, A_ESC, A_ESC_DL, JIS, JIS_1, JIS_2, J_ESC, J_ESC_BR,
J2_ESC, J2_ESC_BR, DONE, INV, JIS_S_NUM } JIS_STATE;
typedef enum { COPY_A, COPY_J, COPY_J2, MAKE_A, MAKE_J, NOOP, EMPTY, ERROR } JIS_ACTION;
 
/**************************************************************************************
* state/action tables for processing JIS encoding
* Where possible, switches to JIS are grouped with proceding JIS characters and switches
* to ASCII are grouped with preceding JIS characters. Thus, maximum returned length
* is 2 (switch to JIS) + 2 (JIS characters) + 2 (switch back to ASCII) = 6.
*************************************************************************************/
 
static JIS_STATE JIS_state_table[JIS_S_NUM][JIS_C_NUM] = {
/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTHER */
/* ASCII */ { A_ESC, DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE },
/* A_ESC */ { DONE, A_ESC_DL, DONE, DONE, DONE, DONE, DONE, DONE, DONE },
/* A_ESC_DL */{ DONE, DONE, DONE, JIS, JIS, DONE, DONE, DONE, DONE },
/* JIS */ { J_ESC, JIS_1, JIS_1, JIS_1, JIS_1, JIS_1, INV, JIS_1, INV },
/* JIS_1 */ { INV, JIS_2, JIS_2, JIS_2, JIS_2, JIS_2, INV, JIS_2, INV },
/* JIS_2 */ { J2_ESC, DONE, DONE, DONE, DONE, DONE, INV, DONE, DONE },
/* J_ESC */ { INV, INV, J_ESC_BR, INV, INV, INV, INV, INV, INV },
/* J_ESC_BR */{ INV, INV, INV, INV, ASCII, ASCII, INV, INV, INV },
/* J2_ESC */ { INV, INV, J2_ESC_BR,INV, INV, INV, INV, INV, INV },
/* J2_ESC_BR*/{ INV, INV, INV, INV, DONE, DONE, INV, INV, INV },
};
 
static JIS_ACTION JIS_action_table[JIS_S_NUM][JIS_C_NUM] = {
/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTHER */
/* ASCII */ { NOOP, COPY_A, COPY_A, COPY_A, COPY_A, COPY_A, EMPTY, COPY_A, COPY_A},
/* A_ESC */ { COPY_A, NOOP, COPY_A, COPY_A, COPY_A, COPY_A, COPY_A, COPY_A, COPY_A},
/* A_ESC_DL */{ COPY_A, COPY_A, COPY_A, MAKE_J, MAKE_J, COPY_A, COPY_A, COPY_A, COPY_A},
/* JIS */ { NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, ERROR, NOOP, ERROR },
/* JIS_1 */ { ERROR, NOOP, NOOP, NOOP, NOOP, NOOP, ERROR, NOOP, ERROR },
/* JIS_2 */ { NOOP, COPY_J2, COPY_J2, COPY_J2, COPY_J2, COPY_J2, ERROR, COPY_J2, COPY_J2},
/* J_ESC */ { ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR },
/* J_ESC_BR */{ ERROR, ERROR, ERROR, ERROR, NOOP, NOOP, ERROR, ERROR, ERROR },
/* J2_ESC */ { ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR },
/* J2_ESC_BR*/{ ERROR, ERROR, ERROR, ERROR, COPY_J, COPY_J, ERROR, ERROR, ERROR },
};
#endif /* MB_CAPABLE */
 
int
_DEFUN (_mbtowc_r, (r, pwc, s, n, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
int *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
 
if (pwc == NULL)
pwc = &dummy;
 
if (s != NULL && n == 0)
return -1;
 
#ifdef MB_CAPABLE
if (r->_current_locale == NULL ||
(strlen (r->_current_locale) <= 1))
{ /* fall-through */ }
else if (!strcmp (r->_current_locale, "C-SJIS"))
{
int char1;
if (s == NULL)
return 0; /* not state-dependent */
char1 = *t;
if (_issjis1 (char1))
{
int char2 = t[1];
if (n <= 1)
return -1;
if (_issjis2 (char2))
{
*pwc = (((wchar_t)*t) << 8) + (wchar_t)(*(t+1));
return 2;
}
else
return -1;
}
}
else if (!strcmp (r->_current_locale, "C-EUCJP"))
{
int char1;
if (s == NULL)
return 0; /* not state-dependent */
char1 = *t;
if (_iseucjp (char1))
{
int char2 = t[1];
if (n <= 1)
return -1;
if (_iseucjp (char2))
{
*pwc = (((wchar_t)*t) << 8) + (wchar_t)(*(t+1));
return 2;
}
else
return -1;
}
}
else if (!strcmp (r->_current_locale, "C-JIS"))
{
JIS_STATE curr_state;
JIS_ACTION action;
JIS_CHAR_TYPE ch;
unsigned char *ptr;
int i, curr_ch;
if (s == NULL)
{
*state = 0;
return 1; /* state-dependent */
}
 
curr_state = (*state == 0 ? ASCII : JIS);
ptr = t;
 
for (i = 0; i < n; ++i)
{
curr_ch = t[i];
switch (curr_ch)
{
case ESC_CHAR:
ch = ESCAPE;
break;
case '$':
ch = DOLLAR;
break;
case '@':
ch = AT;
break;
case '(':
ch = BRACKET;
break;
case 'B':
ch = B;
break;
case 'J':
ch = J;
break;
case '\0':
ch = NUL;
break;
default:
if (_isjis (curr_ch))
ch = JIS_CHAR;
else
ch = OTHER;
}
 
action = JIS_action_table[curr_state][ch];
curr_state = JIS_state_table[curr_state][ch];
switch (action)
{
case NOOP:
break;
case EMPTY:
*state = 0;
*pwc = (wchar_t)0;
return i;
case COPY_A:
*state = 0;
*pwc = (wchar_t)*ptr;
return (i + 1);
case COPY_J:
*state = 0;
*pwc = (((wchar_t)*ptr) << 8) + (wchar_t)(*(ptr+1));
return (i + 1);
case COPY_J2:
*state = 1;
*pwc = (((wchar_t)*ptr) << 8) + (wchar_t)(*(ptr+1));
return (ptr - t) + 2;
case MAKE_A:
case MAKE_J:
ptr = (char *)(t + i + 1);
break;
case ERROR:
default:
return -1;
}
 
}
 
return -1; /* n < bytes needed */
}
#endif /* MB_CAPABLE */
 
/* otherwise this must be the "C" locale or unknown locale */
if (s == NULL)
return 0; /* not state-dependent */
 
*pwc = (wchar_t)*t;
if (*t == '\0')
return 0;
 
return 1;
}
 
/lrand48.c
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 "rand48.h"
 
long
_DEFUN (_lrand48_r, (r),
struct _reent *r)
{
__dorand48(r, __rand48_seed);
return (long)((unsigned long) __rand48_seed[2] << 15) +
((unsigned long) __rand48_seed[1] >> 1);
}
 
#ifndef _REENT_ONLY
long
_DEFUN_VOID (lrand48)
{
return _lrand48_r (_REENT);
}
#endif /* !_REENT_ONLY */
/wctomb_r.c
0,0 → 1,111
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include "mbctype.h"
 
int
_DEFUN (_wctomb_r, (r, s, wchar, state),
struct _reent *r _AND
char *s _AND
wchar_t wchar _AND
int *state)
{
if (strlen (r->_current_locale) <= 1)
{ /* fall-through */ }
else if (!strcmp (r->_current_locale, "C-SJIS"))
{
unsigned char char2 = (unsigned char)wchar;
unsigned char char1 = (unsigned char)(wchar >> 8);
 
if (s == NULL)
return 0; /* not state-dependent */
 
if (char1 != 0x00)
{
/* first byte is non-zero..validate multi-byte char */
if (_issjis1(char1) && _issjis2(char2))
{
*s++ = (char)char1;
*s = (char)char2;
return 2;
}
else
return -1;
}
}
else if (!strcmp (r->_current_locale, "C-EUCJP"))
{
unsigned char char2 = (unsigned char)wchar;
unsigned char char1 = (unsigned char)(wchar >> 8);
 
if (s == NULL)
return 0; /* not state-dependent */
 
if (char1 != 0x00)
{
/* first byte is non-zero..validate multi-byte char */
if (_iseucjp (char1) && _iseucjp (char2))
{
*s++ = (char)char1;
*s = (char)char2;
return 2;
}
else
return -1;
}
}
else if (!strcmp (r->_current_locale, "C-JIS"))
{
int cnt = 0;
unsigned char char2 = (unsigned char)wchar;
unsigned char char1 = (unsigned char)(wchar >> 8);
 
if (s == NULL)
return 1; /* state-dependent */
 
if (char1 != 0x00)
{
/* first byte is non-zero..validate multi-byte char */
if (_isjis (char1) && _isjis (char2))
{
if (*state == 0)
{
/* must switch from ASCII to JIS state */
*state = 1;
*s++ = ESC_CHAR;
*s++ = '$';
*s++ = 'B';
cnt = 3;
}
*s++ = (char)char1;
*s = (char)char2;
return cnt + 2;
}
else
return -1;
}
else
{
if (*state != 0)
{
/* must switch from JIS to ASCII state */
*state = 0;
*s++ = ESC_CHAR;
*s++ = '(';
*s++ = 'B';
cnt = 3;
}
*s = (char)char2;
return cnt + 1;
}
}
 
if (s == NULL)
return 0;
/* otherwise we are dealing with a single byte character */
*s = (char) wchar;
return 1;
}
 
/mrand48.c
0,0 → 1,30
/*
* 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 "rand48.h"
 
long
_DEFUN (_mrand48_r, (r),
struct _reent *r)
{
__dorand48(r, __rand48_seed);
return ((long) __rand48_seed[2] << 16) + (long) __rand48_seed[1];
}
 
#ifndef _REENT_ONLY
long
_DEFUN_VOID (mrand48)
{
return _mrand48_r (_REENT);
}
#endif /* !_REENT_ONLY */
/nrand48.c
0,0 → 1,33
/*
* 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 "rand48.h"
 
long
_DEFUN (_nrand48_r, (r, xseed),
struct _reent *r _AND
unsigned short xseed[3])
{
__dorand48 (r, xseed);
return (long)((unsigned long) xseed[2] << 15) +
((unsigned long) xseed[1] >> 1);
}
 
#ifndef _REENT_ONLY
long
_DEFUN (nrand48, (xseed),
unsigned short xseed[3])
{
return _nrand48_r (_REENT, xseed);
}
#endif /* !_REENT_ONLY */
/wcstombs_r.c
0,0 → 1,32
#include <stdlib.h>
 
size_t
_DEFUN (_wcstombs_r, (reent, s, pwcs, n, state),
struct _reent *r _AND
char *s _AND
const wchar_t *pwcs _AND
size_t n _AND
int *state)
{
char *ptr = s;
size_t max = n;
char buff[8];
int i, num_to_copy;
 
while (n > 0)
{
int bytes = _wctomb_r (r, buff, *pwcs, state);
if (bytes == -1)
return -1;
num_to_copy = (n > bytes ? bytes : (int)n);
for (i = 0; i < num_to_copy; ++i)
*ptr++ = buff[i];
if (*pwcs == 0x00)
return ptr - s - (n >= bytes);
++pwcs;
n -= num_to_copy;
}
 
return max;
}
/srand48.c
0,0 → 1,37
/*
* 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 "rand48.h"
 
_VOID
_DEFUN (_srand48_r, (r, seed),
struct _reent *r _AND
long seed)
{
__rand48_seed[0] = _RAND48_SEED_0;
__rand48_seed[1] = (unsigned short) seed;
__rand48_seed[2] = (unsigned short) ((unsigned long)seed >> 16);
__rand48_mult[0] = _RAND48_MULT_0;
__rand48_mult[1] = _RAND48_MULT_1;
__rand48_mult[2] = _RAND48_MULT_2;
__rand48_add = _RAND48_ADD;
}
 
#ifndef _REENT_ONLY
_VOID
_DEFUN (srand48, (seed),
long seed)
{
_srand48_r (_REENT, seed);
}
#endif /* !_REENT_ONLY */
/__ten_mu.c
0,0 → 1,23
/*
* [atw] multiply 64 bit accumulator by 10 and add digit.
* The KA/CA way to do this should be to use
* a 64-bit integer internally and use "adjust" to
* convert it to float at the end of processing.
*/
 
#include <_ansi.h>
 
int
_DEFUN (__ten_mul, (acc, digit),
double *acc _AND
int digit)
{
/*
* [atw] Crude, but effective (at least on a KB)...
*/
 
*acc *= 10;
*acc += digit;
 
return 0; /* no overflow */
}
/msize.c
0,0 → 1,17
/* msize.c -- a wrapper for malloc_usable_size. */
 
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
 
#ifndef _REENT_ONLY
 
size_t
_DEFUN (malloc_usable_size, (ptr),
_PTR ptr)
{
return _malloc_usable_size_r (_REENT, ptr);
}
 
#endif
/mbtowc.c
0,0 → 1,81
/*
FUNCTION
<<mbtowc>>---minimal multibyte to wide char converter
 
INDEX
mbtowc
 
ANSI_SYNOPSIS
#include <stdlib.h>
int mbtowc(wchar_t *<[pwc]>, const char *<[s]>, size_t <[n]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int mbtowc(<[pwc]>, <[s]>, <[n]>)
wchar_t *<[pwc]>;
const char *<[s]>;
size_t <[n]>;
 
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<mbtowc>>. In this case,
only ``multi-byte character sequences'' recognized are single bytes,
and they are ``converted'' to themselves.
Each call to <<mbtowc>> copies one character from <<*<[s]>>> to
<<*<[pwc]>>>, unless <[s]> is a null pointer. The argument n
is ignored.
 
When MB_CAPABLE is defined, this routine calls <<_mbtowc_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
 
RETURNS
This implementation of <<mbtowc>> returns <<0>> if
<[s]> is <<NULL>> or is the empty string;
it returns <<1>> if not MB_CAPABLE or
the character is a single-byte character; it returns <<-1>>
if n is <<0>> or the multi-byte character is invalid;
otherwise it returns the number of bytes in the multibyte character.
If the return value is -1, no changes are made to the <<pwc>>
output string. If the input is the empty string, a wchar_t nul
is placed in the output string and 0 is returned. If the input
has a length of 0, no changes are made to the <<pwc>> output string.
 
PORTABILITY
<<mbtowc>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
 
<<mbtowc>> requires no supporting OS subroutines.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
 
int
_DEFUN (mbtowc, (pwc, s, n),
wchar_t *pwc _AND
const char *s _AND
size_t n)
{
#ifdef MB_CAPABLE
static int state;
 
return _mbtowc_r (_REENT, pwc, s, n, &state);
#else /* not MB_CAPABLE */
if (s == NULL)
return 0;
if (n == 0)
return -1;
if (pwc)
*pwc = (wchar_t) *s;
return (*s != '\0');
#endif /* not MB_CAPABLE */
}
 
#endif /* !_REENT_ONLY */
 
 
 
 
/wctomb.c
0,0 → 1,69
/*
FUNCTION
<<wctomb>>---minimal wide char to multibyte converter
 
INDEX
wctomb
 
ANSI_SYNOPSIS
#include <stdlib.h>
int wctomb(char *<[s]>, wchar_t <[wchar]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int wctomb(<[s]>, <[wchar]>)
char *<[s]>;
wchar_t <[wchar]>;
 
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<wctomb>>. The
only ``wide characters'' recognized are single bytes,
and they are ``converted'' to themselves.
 
When MB_CAPABLE is defined, this routine calls <<_wctomb_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
 
Each call to <<wctomb>> modifies <<*<[s]>>> unless <[s]> is a null
pointer or MB_CAPABLE is defined and <[wchar]> is invalid.
 
RETURNS
This implementation of <<wctomb>> returns <<0>> if
<[s]> is <<NULL>>; it returns <<-1>> if MB_CAPABLE is enabled
and the wchar is not a valid multi-byte character, it returns <<1>>
if MB_CAPABLE is not defined or the wchar is in reality a single
byte character, otherwise it returns the number of bytes in the
multi-byte character.
 
PORTABILITY
<<wctomb>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
 
<<wctomb>> requires no supporting OS subroutines.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
 
int
_DEFUN (wctomb, (s, wchar),
char *s _AND
wchar_t wchar)
{
#ifdef MB_CAPABLE
static int state;
 
return _wctomb_r (_REENT, s, wchar, &state);
#else /* not MB_CAPABLE */
if (s == NULL)
return 0;
 
*s = (char) wchar;
return 1;
#endif /* not MB_CAPABLE */
}
 
#endif /* !_REENT_ONLY */
/local.h
0,0 → 1,8
/* Misc. local definitions for libc/stdlib */
 
#ifndef _LOCAL_H_
#define _LOCAL_H_
 
char * _EXFUN(_gcvt,(struct _reent *, double , int , char *, char, int));
 
#endif
/std.h
0,0 → 1,33
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <math.h>
#ifndef CYGNUS_NEC
#include <ctype.h>
#endif
 
#define Ise(c) ((c == 'e') || (c == 'E') || (c == 'd') || (c == 'D'))
#define Isdigit(c) ((c <= '9') && (c >= '0'))
#define Isspace(c) ((c == ' ') || (c == '\t') || (c=='\n') || (c=='\v') \
|| (c == '\r') || (c == '\f'))
#define Issign(c) ((c == '-') || (c == '+'))
#define Val(c) ((c - '0'))
 
#define MAXE 308
#define MINE (-308)
 
/* flags */
#define SIGN 0x01
#define ESIGN 0x02
#define DECP 0x04
 
#ifdef _HAVE_STDC
int __ten_mul(double *acc, int digit);
double __adjust(struct _reent *ptr, double *acc, int dexp, int sign);
const double __exp10(unsigned x);
#else
int __ten_mul();
double __adjust();
double __exp10();
#endif
/rand48.c
0,0 → 1,178
/*
* 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.
*/
 
/*
FUNCTION
<<rand48>>, <<drand48>>, <<erand48>>, <<lrand48>>, <<nrand48>>, <<mrand48>>, <<jrand48>>, <<srand48>>, <<seed48>>, <<lcong48>> ---pseudo random number generators and initialization routines
 
INDEX
rand48
INDEX
drand48
INDEX
erand48
INDEX
lrand48
INDEX
nrand48
INDEX
mrand48
INDEX
jrand48
INDEX
srand48
INDEX
seed48
INDEX
lcong48
 
ANSI_SYNOPSIS
#include <stdlib.h>
double drand48(void);
double erand48(unsigned short <[xseed]>[3]);
long lrand48(void);
long nrand48(unsigned short <[xseed]>[3]);
long mrand48(void);
long jrand48(unsigned short <[xseed]>[3]);
void srand48(long <[seed]>);
unsigned short *seed48(unsigned short <[xseed]>[3]);
void lcong48(unsigned short <[p]>[7]);
 
TRAD_SYNOPSIS
#include <stdlib.h>
double drand48();
 
double erand48(<[xseed]>)
unsigned short <[xseed]>[3];
 
long lrand48();
 
long nrand48(<[xseed]>)
unsigned short <[xseed]>[3];
 
long mrand48();
 
long jrand48(<[xseed]>)
unsigned short <[xseed]>[3];
 
void srand48(<[seed]>)
long <[seed]>;
 
unsigned short *seed48(<[xseed]>)
unsigned short <[xseed]>[3];
 
void lcong48(<[p]>)
unsigned short <[p]>[7];
 
DESCRIPTION
The <<rand48>> family of functions generates pseudo-random numbers
using a linear congruential algorithm working on integers 48 bits in size.
The particular formula employed is
r(n+1) = (a * r(n) + c) mod m
where the default values are
for the multiplicand a = 0xfdeece66d = 25214903917 and
the addend c = 0xb = 11. The modulo is always fixed at m = 2 ** 48.
r(n) is called the seed of the random number generator.
 
For all the six generator routines described next, the first
computational step is to perform a single iteration of the algorithm.
 
<<drand48>> and <<erand48>>
return values of type double. The full 48 bits of r(n+1) are
loaded into the mantissa of the returned value, with the exponent set
such that the values produced lie in the interval [0.0, 1.0].
 
<<lrand48>> and <<nrand48>>
return values of type long in the range
[0, 2**31-1]. The high-order (31) bits of
r(n+1) are loaded into the lower bits of the returned value, with
the topmost (sign) bit set to zero.
 
<<mrand48>> and <<jrand48>>
return values of type long in the range
[-2**31, 2**31-1]. The high-order (32) bits of
r(n+1) are loaded into the returned value.
 
<<drand48>>, <<lrand48>>, and <<mrand48>>
use an internal buffer to store r(n). For these functions
the initial value of r(0) = 0x1234abcd330e = 20017429951246.
 
On the other hand, <<erand48>>, <<nrand48>>, and <<jrand48>>
use a user-supplied buffer to store the seed r(n),
which consists of an array of 3 shorts, where the zeroth member
holds the least significant bits.
 
All functions share the same multiplicand and addend.
 
<<srand48>> is used to initialize the internal buffer r(n) of
<<drand48>>, <<lrand48>>, and <<mrand48>>
such that the 32 bits of the seed value are copied into the upper 32 bits
of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e.
Additionally, the constant multiplicand and addend of the algorithm are
reset to the default values given above.
 
<<seed48>> also initializes the internal buffer r(n) of
<<drand48>>, <<lrand48>>, and <<mrand48>>,
but here all 48 bits of the seed can be specified in an array of 3 shorts,
where the zeroth member specifies the lowest bits. Again,
the constant multiplicand and addend of the algorithm are
reset to the default values given above.
<<seed48>> returns a pointer to an array of 3 shorts which contains
the old seed.
This array is statically allocated, thus its contents are lost after
each new call to <<seed48>>.
 
Finally, <<lcong48>> allows full control over the multiplicand and
addend used in <<drand48>>, <<erand48>>, <<lrand48>>, <<nrand48>>,
<<mrand48>>, and <<jrand48>>,
and the seed used in <<drand48>>, <<lrand48>>, and <<mrand48>>.
An array of 7 shorts is passed as parameter; the first three shorts are
used to initialize the seed; the second three are used to initialize the
multiplicand; and the last short is used to initialize the addend.
It is thus not possible to use values greater than 0xffff as the addend.
 
Note that all three methods of seeding the random number generator
always also set the multiplicand and addend for any of the six
generator calls.
 
For a more powerful random number generator, see <<random>>.
 
PORTABILITY
SUS requires these functions.
 
No supporting OS subroutines are required.
*/
 
#include "rand48.h"
 
void
_DEFUN (__dorand48, (r, xseed),
struct _reent *r _AND
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;
}
/assert.c
0,0 → 1,62
/*
FUNCTION
<<assert>>---Macro for Debugging Diagnostics
 
INDEX
assert
 
ANSI_SYNOPSIS
#include <assert.h>
void assert(int <[expression]>);
 
TRAD_SYNOPSIS
#include <assert.h>
assert(<[expression]>)
int <[expression]>;
 
DESCRIPTION
Use this macro to embed debuggging diagnostic statements in
your programs. The argument <[expression]> should be an
expression which evaluates to true (nonzero) when your program
is working as you intended.
 
When <[expression]> evaluates to false (zero), <<assert>>
calls <<abort>>, after first printing a message showing what
failed and where:
 
. Assertion failed: <[expression]>, file <[filename]>, line <[lineno]>
 
The macro is defined to permit you to turn off all uses of
<<assert>> at compile time by defining <<NDEBUG>> as a
preprocessor variable. If you do this, the <<assert>> macro
expands to
 
. (void(0))
 
RETURNS
<<assert>> does not return a value.
 
PORTABILITY
The <<assert>> macro is required by ANSI, as is the behavior
when <<NDEBUG>> is defined.
 
Supporting OS subroutines required (only if enabled): <<close>>, <<fstat>>,
<<getpid>>, <<isatty>>, <<kill>>, <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
 
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
 
void
_DEFUN (__assert, (file, line, failedexpr),
const char *file _AND
int line _AND
const char *failedexpr)
{
(void)fiprintf(stderr,
"assertion \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
abort();
/* NOTREACHED */
}
/wcstombs.c
0,0 → 1,80
/*
FUNCTION
<<wcstombs>>---minimal wide char string to multibyte string converter
 
INDEX
wcstombs
 
ANSI_SYNOPSIS
#include <stdlib.h>
int wcstombs(const char *<[s]>, wchar_t *<[pwc]>, size_t <[n]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int wcstombs(<[s]>, <[pwc]>, <[n]>)
const char *<[s]>;
wchar_t *<[pwc]>;
size_t <[n]>;
 
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<wcstombs>>. In this case,
all wide-characters are expected to represent single bytes and so
are converted simply by casting to char.
 
When MB_CAPABLE is defined, this routine calls <<_wcstombs_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
 
RETURNS
This implementation of <<wcstombs>> returns <<0>> if
<[s]> is <<NULL>> or is the empty string;
it returns <<-1>> if MB_CAPABLE and one of the
wide-char characters does not represent a valid multi-byte character;
otherwise it returns the minimum of: <<n>> or the
number of bytes that are transferred to <<s>>, not including the
nul terminator.
 
If the return value is -1, the state of the <<pwc>> string is
indeterminate. If the input has a length of 0, the output
string will be modified to contain a wchar_t nul terminator if
<<n>> > 0.
 
PORTABILITY
<<wcstombs>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
 
<<wcstombs>> requires no supporting OS subroutines.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
 
size_t
_DEFUN (wcstombs, (s, pwcs, n),
char *s _AND
const wchar_t *pwcs _AND
size_t n)
{
#ifdef MB_CAPABLE
int state = 0;
 
return _wcstombs_r (_REENT, s, pwcs, n, &state);
#else /* not MB_CAPABLE */
int count = 0;
 
if (n != 0) {
do {
if ((*s++ = (char) *pwcs++) == 0)
break;
count++;
} while (--n != 0);
}
 
return count;
#endif /* not MB_CAPABLE */
}
 
#endif /* !_REENT_ONLY */
/strdup_r.c
0,0 → 1,17
#include <reent.h>
#include <stdlib.h>
#include <string.h>
 
char *
_DEFUN (_strdup_r, (reent_ptr, str),
struct _reent *reent_ptr _AND
_CONST char *str)
{
size_t len = strlen (str) + 1;
char *copy = _malloc_r (reent_ptr, len);
if (copy)
{
memcpy (copy, str, len);
}
return copy;
}
/rand_r.c
0,0 → 1,37
#include <stdlib.h>
 
/* Pseudo-random generator based on Minimal Standard by
Lewis, Goodman, and Miller in 1969.
I[j+1] = a*I[j] (mod m)
 
where a = 16807
m = 2147483647
 
Using Schrage's algorithm, a*I[j] (mod m) can be rewritten as:
a*(I[j] mod q) - r*{I[j]/q} if >= 0
a*(I[j] mod q) - r*{I[j]/q} + m otherwise
 
where: {} denotes integer division
q = {m/a} = 127773
r = m (mod a) = 2836
 
note that the seed value of 0 cannot be used in the calculation as
it results in 0 itself
*/
int
_DEFUN (rand_r, (seed), unsigned int *seed)
{
long k;
long s = (long)(*seed);
if (s == 0)
s = 0x12345987;
k = s / 127773;
s = 16807 * (s - k * 127773) - 2836 * k;
if (s < 0)
s += 2147483647;
(*seed) = (unsigned int)s;
return (int)(s & RAND_MAX);
}
/rand48.h
0,0 → 1,36
/*
* 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.
*/
 
#ifndef _RAND48_H_
#define _RAND48_H_
 
#include <math.h>
#include <stdlib.h>
 
extern void _EXFUN(__dorand48,(struct _reent *r, unsigned short[3]));
#define __rand48_seed (r->_new._reent._r48._seed)
#define __rand48_mult (r->_new._reent._r48._mult)
#define __rand48_add (r->_new._reent._r48._add)
 
#if 0
/* following values are defined in <sys/reent.h> */
#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
 
#endif /* _RAND48_H_ */
/abort.c
0,0 → 1,67
/* NetWare can not use this implementation of abort. It provides its
own version of abort in clib.nlm. If we can not use clib.nlm, then
we must write abort in sys/netware. */
 
#ifdef ABORT_PROVIDED
 
int _dummy_abort = 1;
 
#else
 
/*
FUNCTION
<<abort>>---abnormal termination of a program
 
INDEX
abort
 
ANSI_SYNOPSIS
#include <stdlib.h>
void abort(void);
 
TRAD_SYNOPSIS
#include <stdlib.h>
void abort();
 
DESCRIPTION
Use <<abort>> to signal that your program has detected a condition it
cannot deal with. Normally, <<abort>> ends your program's execution.
 
Before terminating your program, <<abort>> raises the exception <<SIGABRT>>
(using `<<raise(SIGABRT)>>'). If you have used <<signal>> to register
an exception handler for this condition, that handler has the
opportunity to retain control, thereby avoiding program termination.
 
In this implementation, <<abort>> does not perform any stream- or
file-related cleanup (the host environment may do so; if not, you can
arrange for your program to do its own cleanup with a <<SIGABRT>>
exception handler).
 
RETURNS
<<abort>> does not return to its caller.
 
PORTABILITY
ANSI C requires <<abort>>.
 
Supporting OS subroutines required: <<_exit>> and optionally, <<write>>.
*/
 
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
 
_VOID
_DEFUN_VOID (abort)
{
#ifdef ABORT_MESSAGE
write (2, "Abort called\n", sizeof ("Abort called\n")-1);
#endif
 
while (1)
{
raise (SIGABRT);
_exit (1);
}
}
 
#endif
/getenv_r.c
0,0 → 1,133
/*
FUNCTION
<<_getenv_r>>---look up environment variable
 
INDEX
_getenv_r
INDEX
environ
 
ANSI_SYNOPSIS
#include <stdlib.h>
char *_getenv_r(struct _reent *<[reent_ptr]>, const char *<[name]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
char *_getenv_r(<[reent_ptr]>, <[name]>)
struct _reent *<[reent_ptr]>;
char *<[name]>;
 
DESCRIPTION
<<_getenv_r>> searches the list of environment variable names and values
(using the global pointer ``<<char **environ>>'') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<_getenv_r>> returns a pointer to the associated value.
 
RETURNS
A pointer to the (string) value of the environment variable, or
<<NULL>> if there is no such environment variable.
 
PORTABILITY
<<_getenv_r>> is not ANSI; the rules for properly forming names of environment
variables vary from one system to another.
 
<<_getenv_r>> requires a global pointer <<environ>>.
*/
 
/* This file may have been modified by DJ Delorie (Jan 1991). If so,
** these modifications are Copyright (C) 1991 DJ Delorie
*/
 
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "envlock.h"
 
extern char **environ;
 
/* Only deal with a pointer to environ, to work around subtle bugs with shared
libraries and/or small data systems where the user declares his own
'environ'. */
static char ***p_environ = &environ;
 
/*
* _findenv --
* Returns pointer to value associated with name, if any, else NULL.
* Sets offset to be the offset of the name/value combination in the
* environmental array, for use by setenv(3) and unsetenv(3).
* Explicitly removes '=' in argument name.
*
* This routine *should* be a static; don't use it.
*/
 
char *
_DEFUN (_findenv_r, (reent_ptr, name, offset),
struct _reent *reent_ptr _AND
register _CONST char *name _AND
int *offset)
{
register int len;
register char **p;
_CONST char *c;
 
ENV_LOCK;
 
/* In some embedded systems, this does not get set. This protects
newlib from dereferencing a bad pointer. */
if (!*p_environ)
return NULL;
 
c = name;
len = 0;
while (*c && *c != '=')
{
c++;
len++;
}
 
for (p = *p_environ; *p; ++p)
if (!strncmp (*p, name, len))
if (*(c = *p + len) == '=')
{
*offset = p - *p_environ;
ENV_UNLOCK;
return (char *) (++c);
}
ENV_UNLOCK;
return NULL;
}
 
/*
* _getenv_r --
* Returns ptr to value associated with name, if any, else NULL.
*/
 
char *
_DEFUN (_getenv_r, (reent_ptr, name),
struct _reent *reent_ptr _AND
_CONST char *name)
{
int offset;
char *_findenv_r ();
 
return _findenv_r (reent_ptr, name, &offset);
}
/mblen_r.c
0,0 → 1,66
/*
FUNCTION
<<_mblen_r>>---reentrant minimal multibyte length function
 
INDEX
_mblen_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
int _mblen_r(struct _reent *<[r]>, const char *<[s]>, size_t <[n]>, int *<[state]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int _mblen_r(<[r]>, <[s]>, <[n]>, <[state]>)
struct _reent *<[r]>;
const char *<[s]>;
size_t <[n]>;
int *<[state]>;
 
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<_mblen_r>>. In this case, the
only ``multi-byte character sequences'' recognized are single bytes,
and thus <<1>> is returned unless <[s]> is the null pointer or
has a length of 0 or is the empty string.
 
When MB_CAPABLE is defined, this routine calls <<_mbtowc_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
 
RETURNS
This implementation of <<_mblen_r>> returns <<0>> if
<[s]> is <<NULL>> or the empty string; it returns <<1>> if not MB_CAPABLE or
the character is a single-byte character; it returns <<-1>>
if the multi-byte character is invalid; otherwise it returns
the number of bytes in the multibyte character.
 
PORTABILITY
<<_mblen>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
 
<<_mblen_r>> requires no supporting OS subroutines.
*/
 
#include <stdlib.h>
 
int
_DEFUN (_mblen_r, (r, s, n, state),
struct _reent *r _AND
const char *s _AND
size_t n _AND
int *state)
{
#ifdef MB_CAPABLE
 
return _mbtowc_r (r, NULL, s, n, state);
#else /* not MB_CAPABLE */
if (s == NULL || *s == '\0')
return 0;
if (n == 0)
return -1;
return 1;
#endif /* not MB_CAPABLE */
}
 
/valloc.c
0,0 → 1,24
/* valloc.c -- a wrapper for valloc_r and pvalloc_r. */
 
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
 
#ifndef _REENT_ONLY
 
_PTR
_DEFUN (valloc, (nbytes),
size_t nbytes)
{
return _valloc_r (_REENT, nbytes);
}
 
_PTR
_DEFUN (pvalloc, (nbytes),
size_t nbytes)
{
return _pvalloc_r (_REENT, nbytes);
}
 
#endif
/realloc.c
0,0 → 1,22
#ifdef MALLOC_PROVIDED
int _dummy_calloc = 1;
#else
/* realloc.c -- a wrapper for realloc_r. */
 
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
 
#ifndef _REENT_ONLY
 
_PTR
_DEFUN (realloc, (ap, nbytes),
_PTR ap _AND
size_t nbytes)
{
return _realloc_r (_REENT, ap, nbytes);
}
 
#endif
#endif /* MALLOC_PROVIDED */
/strdup.c
0,0 → 1,13
#ifndef _REENT_ONLY
 
#include <reent.h>
#include <stdlib.h>
#include <string.h>
 
char *
_DEFUN (strdup, (str), _CONST char *str)
{
return _strdup_r (_REENT, str);
}
 
#endif /* !_REENT_ONLY */
/mbstowcs_r.c
0,0 → 1,29
#include <stdlib.h>
 
size_t
_DEFUN (_mbstowcs_r, (reent, pwcs, s, n, state),
struct _reent *r _AND
wchar_t *pwcs _AND
const char *s _AND
size_t n _AND
int *state)
{
wchar_t *ptr = pwcs;
size_t max = n;
char *t = (char *)s;
int bytes;
 
while (n > 0)
{
bytes = _mbtowc_r (r, ptr, t, MB_CUR_MAX, state);
if (bytes == -1)
return -1;
else if (bytes == 0)
return ptr - pwcs;
t += bytes;
++ptr;
--n;
}
 
return max;
}
/setenv_r.c
0,0 → 1,143
/* This file may have been modified by DJ Delorie (Jan 1991). If so,
** these modifications are Copyright (C) 1991 DJ Delorie
*/
 
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#include <reent.h>
 
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "envlock.h"
 
extern char **environ;
 
/* Only deal with a pointer to environ, to work around subtle bugs with shared
libraries and/or small data systems where the user declares his own
'environ'. */
static char ***p_environ = &environ;
 
/* _findenv_r is defined in getenv_r.c. */
extern char *_findenv_r _PARAMS ((struct _reent *, const char *, int *));
 
/*
* _setenv_r --
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
 
int
_DEFUN (_setenv_r, (reent_ptr, name, value, rewrite),
struct _reent *reent_ptr _AND
_CONST char *name _AND
_CONST char *value _AND
int rewrite)
{
static int alloced; /* if allocated space before */
register char *C;
int l_value, offset;
 
ENV_LOCK;
 
if (*value == '=') /* no `=' in value */
++value;
l_value = strlen (value);
if ((C = _findenv_r (reent_ptr, name, &offset)))
{ /* find if already exists */
if (!rewrite)
{
ENV_UNLOCK;
return 0;
}
if (strlen (C) >= l_value)
{ /* old larger; copy over */
while ((*C++ = *value++) != 0);
ENV_UNLOCK;
return 0;
}
}
else
{ /* create new slot */
register int cnt;
register char **P;
 
for (P = *p_environ, cnt = 0; *P; ++P, ++cnt);
if (alloced)
{ /* just increase size */
*p_environ = (char **) _realloc_r (reent_ptr, (char *) environ,
(size_t) (sizeof (char *) * (cnt + 2)));
if (!*p_environ)
{
ENV_UNLOCK;
return -1;
}
}
else
{ /* get new space */
alloced = 1; /* copy old entries into it */
P = (char **) _malloc_r (reent_ptr, (size_t) (sizeof (char *) * (cnt + 2)));
if (!P)
{
ENV_UNLOCK;
return (-1);
}
bcopy ((char *) *p_environ, (char *) P, cnt * sizeof (char *));
*p_environ = P;
}
(*p_environ)[cnt + 1] = NULL;
offset = cnt;
}
for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
if (!((*p_environ)[offset] = /* name + `=' + value */
_malloc_r (reent_ptr, (size_t) ((int) (C - name) + l_value + 2))))
{
ENV_UNLOCK;
return -1;
}
for (C = (*p_environ)[offset]; (*C = *name++) && *C != '='; ++C);
for (*C++ = '='; (*C++ = *value++) != 0;);
 
ENV_UNLOCK;
 
return 0;
}
 
/*
* _unsetenv_r(name) --
* Delete environmental variable "name".
*/
void
_DEFUN (_unsetenv_r, (reent_ptr, name),
struct _reent *reent_ptr _AND
_CONST char *name)
{
register char **P;
int offset;
 
ENV_LOCK;
 
while (_findenv_r (reent_ptr, name, &offset)) /* if set multiple times */
for (P = &(*p_environ)[offset];; ++P)
if (!(*P = *(P + 1)))
break;
 
ENV_UNLOCK;
}
/__adjust.c
0,0 → 1,44
/*
* return (*acc) scaled by 10**dexp.
*/
 
#include <_ansi.h>
#include <reent.h>
#include "std.h"
 
#define abs(x) (((x) < 0) ? -(x) : (x))
 
double
_DEFUN (__adjust, (ptr, acc, dexp, sign),
struct _reent *ptr _AND
double *acc _AND
int dexp _AND
int sign)
/* *acc the 64 bit accumulator */
/* dexp decimal exponent */
/* sign sign flag */
{
double r;
 
if (dexp > MAXE)
{
ptr->_errno = ERANGE;
return (sign) ? -HUGE_VAL : HUGE_VAL;
}
else if (dexp < MINE)
{
ptr->_errno = ERANGE;
return 0.0;
}
 
r = *acc;
if (sign)
r = -r;
if (dexp == 0)
return r;
 
if (dexp < 0)
return r / __exp10 (abs (dexp));
else
return r * __exp10 (dexp);
}
/mallocr.c
0,0 → 1,3651
#ifdef MALLOC_PROVIDED
int _dummy_mallocr = 1;
#else
/* ---------- To make a malloc.h, start cutting here ------------ */
 
/*
A version of malloc/free/realloc written by Doug Lea and released to the
public domain. Send questions/comments/complaints/performance data
to dl@cs.oswego.edu
 
* VERSION 2.6.4 Thu Nov 28 07:54:55 1996 Doug Lea (dl at gee)
Note: There may be an updated version of this malloc obtainable at
ftp://g.oswego.edu/pub/misc/malloc.c
Check before installing!
 
* Why use this malloc?
 
This is not the fastest, most space-conserving, most portable, or
most tunable malloc ever written. However it is among the fastest
while also being among the most space-conserving, portable and tunable.
Consistent balance across these factors results in a good general-purpose
allocator. For a high-level description, see
http://g.oswego.edu/dl/html/malloc.html
 
* Synopsis of public routines
 
(Much fuller descriptions are contained in the program documentation below.)
 
malloc(size_t n);
Return a pointer to a newly allocated chunk of at least n bytes, or null
if no space is available.
free(Void_t* p);
Release the chunk of memory pointed to by p, or no effect if p is null.
realloc(Void_t* p, size_t n);
Return a pointer to a chunk of size n that contains the same data
as does chunk p up to the minimum of (n, p's size) bytes, or null
if no space is available. The returned pointer may or may not be
the same as p. If p is null, equivalent to malloc. Unless the
#define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
size argument of zero (re)allocates a minimum-sized chunk.
memalign(size_t alignment, size_t n);
Return a pointer to a newly allocated chunk of n bytes, aligned
in accord with the alignment argument, which must be a power of
two.
valloc(size_t n);
Equivalent to memalign(pagesize, n), where pagesize is the page
size of the system (or as near to this as can be figured out from
all the includes/defines below.)
pvalloc(size_t n);
Equivalent to valloc(minimum-page-that-holds(n)), that is,
round up n to nearest pagesize.
calloc(size_t unit, size_t quantity);
Returns a pointer to quantity * unit bytes, with all locations
set to zero.
cfree(Void_t* p);
Equivalent to free(p).
malloc_trim(size_t pad);
Release all but pad bytes of freed top-most memory back
to the system. Return 1 if successful, else 0.
malloc_usable_size(Void_t* p);
Report the number usable allocated bytes associated with allocated
chunk p. This may or may not report more bytes than were requested,
due to alignment and minimum size constraints.
malloc_stats();
Prints brief summary statistics on stderr.
mallinfo()
Returns (by copy) a struct containing various summary statistics.
mallopt(int parameter_number, int parameter_value)
Changes one of the tunable parameters described below. Returns
1 if successful in changing the parameter, else 0.
 
* Vital statistics:
 
Alignment: 8-byte
8 byte alignment is currently hardwired into the design. This
seems to suffice for all current machines and C compilers.
 
Assumed pointer representation: 4 or 8 bytes
Code for 8-byte pointers is untested by me but has worked
reliably by Wolfram Gloger, who contributed most of the
changes supporting this.
 
Assumed size_t representation: 4 or 8 bytes
Note that size_t is allowed to be 4 bytes even if pointers are 8.
 
Minimum overhead per allocated chunk: 4 or 8 bytes
Each malloced chunk has a hidden overhead of 4 bytes holding size
and status information.
 
Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead)
8-byte ptrs: 24/32 bytes (including, 4/8 overhead)
When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
needed; 4 (8) for a trailing size field
and 8 (16) bytes for free list pointers. Thus, the minimum
allocatable size is 16/24/32 bytes.
 
Even a request for zero bytes (i.e., malloc(0)) returns a
pointer to something of the minimum allocatable size.
 
Maximum allocated size: 4-byte size_t: 2^31 - 8 bytes
8-byte size_t: 2^63 - 16 bytes
 
It is assumed that (possibly signed) size_t bit values suffice to
represent chunk sizes. `Possibly signed' is due to the fact
that `size_t' may be defined on a system as either a signed or
an unsigned type. To be conservative, values that would appear
as negative numbers are avoided.
Requests for sizes with a negative sign bit will return a
minimum-sized chunk.
 
Maximum overhead wastage per allocated chunk: normally 15 bytes
 
Alignnment demands, plus the minimum allocatable size restriction
make the normal worst-case wastage 15 bytes (i.e., up to 15
more bytes will be allocated than were requested in malloc), with
two exceptions:
1. Because requests for zero bytes allocate non-zero space,
the worst case wastage for a request of zero bytes is 24 bytes.
2. For requests >= mmap_threshold that are serviced via
mmap(), the worst case wastage is 8 bytes plus the remainder
from a system page (the minimal mmap unit); typically 4096 bytes.
 
* Limitations
 
Here are some features that are NOT currently supported
 
* No user-definable hooks for callbacks and the like.
* No automated mechanism for fully checking that all accesses
to malloced memory stay within their bounds.
* No support for compaction.
 
* Synopsis of compile-time options:
 
People have reported using previous versions of this malloc on all
versions of Unix, sometimes by tweaking some of the defines
below. It has been tested most extensively on Solaris and
Linux. It is also reported to work on WIN32 platforms.
People have also reported adapting this malloc for use in
stand-alone embedded systems.
 
The implementation is in straight, hand-tuned ANSI C. Among other
consequences, it uses a lot of macros. Because of this, to be at
all usable, this code should be compiled using an optimizing compiler
(for example gcc -O2) that can simplify expressions and control
paths.
 
__STD_C (default: derived from C compiler defines)
Nonzero if using ANSI-standard C compiler, a C++ compiler, or
a C compiler sufficiently close to ANSI to get away with it.
DEBUG (default: NOT defined)
Define to enable debugging. Adds fairly extensive assertion-based
checking to help track down memory errors, but noticeably slows down
execution.
SEPARATE_OBJECTS (default: NOT defined)
Define this to compile into separate .o files. You must then
compile malloc.c several times, defining a DEFINE_* macro each
time. The list of DEFINE_* macros appears below.
MALLOC_LOCK (default: NOT defined)
MALLOC_UNLOCK (default: NOT defined)
Define these to C expressions which are run to lock and unlock
the malloc data structures. Calls may be nested; that is,
MALLOC_LOCK may be called more than once before the corresponding
MALLOC_UNLOCK calls. MALLOC_LOCK must avoid waiting for a lock
that it already holds.
MALLOC_ALIGNMENT (default: NOT defined)
Define this to 16 if you need 16 byte alignment instead of 8 byte alignment
which is the normal default.
SIZE_T_SMALLER_THAN_LONG (default: NOT defined)
Define this when the platform you are compiling has sizeof(long) > sizeof(size_t).
The option causes some extra code to be generated to handle operations
that use size_t operands and have long results.
REALLOC_ZERO_BYTES_FREES (default: NOT defined)
Define this if you think that realloc(p, 0) should be equivalent
to free(p). Otherwise, since malloc returns a unique pointer for
malloc(0), so does realloc(p, 0).
HAVE_MEMCPY (default: defined)
Define if you are not otherwise using ANSI STD C, but still
have memcpy and memset in your C library and want to use them.
Otherwise, simple internal versions are supplied.
USE_MEMCPY (default: 1 if HAVE_MEMCPY is defined, 0 otherwise)
Define as 1 if you want the C library versions of memset and
memcpy called in realloc and calloc (otherwise macro versions are used).
At least on some platforms, the simple macro versions usually
outperform libc versions.
HAVE_MMAP (default: defined as 1)
Define to non-zero to optionally make malloc() use mmap() to
allocate very large blocks.
HAVE_MREMAP (default: defined as 0 unless Linux libc set)
Define to non-zero to optionally make realloc() use mremap() to
reallocate very large blocks.
malloc_getpagesize (default: derived from system #includes)
Either a constant or routine call returning the system page size.
HAVE_USR_INCLUDE_MALLOC_H (default: NOT defined)
Optionally define if you are on a system with a /usr/include/malloc.h
that declares struct mallinfo. It is not at all necessary to
define this even if you do, but will ensure consistency.
INTERNAL_SIZE_T (default: size_t)
Define to a 32-bit type (probably `unsigned int') if you are on a
64-bit machine, yet do not want or need to allow malloc requests of
greater than 2^31 to be handled. This saves space, especially for
very small chunks.
INTERNAL_LINUX_C_LIB (default: NOT defined)
Defined only when compiled as part of Linux libc.
Also note that there is some odd internal name-mangling via defines
(for example, internally, `malloc' is named `mALLOc') needed
when compiling in this case. These look funny but don't otherwise
affect anything.
INTERNAL_NEWLIB (default: NOT defined)
Defined only when compiled as part of the Cygnus newlib
distribution.
WIN32 (default: undefined)
Define this on MS win (95, nt) platforms to compile in sbrk emulation.
LACKS_UNISTD_H (default: undefined)
Define this if your system does not have a <unistd.h>.
MORECORE (default: sbrk)
The name of the routine to call to obtain more memory from the system.
MORECORE_FAILURE (default: -1)
The value returned upon failure of MORECORE.
MORECORE_CLEARS (default 1)
True (1) if the routine mapped to MORECORE zeroes out memory (which
holds for sbrk).
DEFAULT_TRIM_THRESHOLD
DEFAULT_TOP_PAD
DEFAULT_MMAP_THRESHOLD
DEFAULT_MMAP_MAX
Default values of tunable parameters (described in detail below)
controlling interaction with host system routines (sbrk, mmap, etc).
These values may also be changed dynamically via mallopt(). The
preset defaults are those that give best performance for typical
programs/systems.
 
 
*/
 
 
 
/* Preliminaries */
 
#ifndef __STD_C
#ifdef __STDC__
#define __STD_C 1
#else
#if __cplusplus
#define __STD_C 1
#else
#define __STD_C 0
#endif /*__cplusplus*/
#endif /*__STDC__*/
#endif /*__STD_C*/
 
#ifndef Void_t
#if __STD_C
#define Void_t void
#else
#define Void_t char
#endif
#endif /*Void_t*/
 
#if __STD_C
#include <stddef.h> /* for size_t */
#else
#include <sys/types.h>
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include <stdio.h> /* needed for malloc_stats */
 
 
/*
Compile-time options
*/
 
 
/*
 
Special defines for Cygnus newlib distribution.
 
*/
 
#ifdef INTERNAL_NEWLIB
 
#include <sys/config.h>
 
/*
In newlib, all the publically visible routines take a reentrancy
pointer. We don't currently do anything much with it, but we do
pass it to the lock routine.
*/
 
#include <reent.h>
 
#define POINTER_UINT unsigned _POINTER_INT
#define SEPARATE_OBJECTS
#define HAVE_MMAP 0
#define MORECORE(size) _sbrk_r(reent_ptr, (size))
#define MORECORE_CLEARS 0
#define MALLOC_LOCK __malloc_lock(reent_ptr)
#define MALLOC_UNLOCK __malloc_unlock(reent_ptr)
 
#ifdef __CYGWIN__
# undef _WIN32
# undef WIN32
#endif
 
#ifndef _WIN32
#ifdef SMALL_MEMORY
#define malloc_getpagesize (128)
#else
#define malloc_getpagesize (4096)
#endif
#endif
 
#if __STD_C
extern void __malloc_lock(struct _reent *);
extern void __malloc_unlock(struct _reent *);
#else
extern void __malloc_lock();
extern void __malloc_unlock();
#endif
 
#if __STD_C
#define RARG struct _reent *reent_ptr,
#define RONEARG struct _reent *reent_ptr
#else
#define RARG reent_ptr
#define RONEARG reent_ptr
#define RDECL struct _reent *reent_ptr;
#endif
 
#define RCALL reent_ptr,
#define RONECALL reent_ptr
 
#else /* ! INTERNAL_NEWLIB */
 
#define POINTER_UINT unsigned long
#define RARG
#define RONEARG
#define RDECL
#define RCALL
#define RONECALL
 
#endif /* ! INTERNAL_NEWLIB */
 
/*
Debugging:
 
Because freed chunks may be overwritten with link fields, this
malloc will often die when freed memory is overwritten by user
programs. This can be very effective (albeit in an annoying way)
in helping track down dangling pointers.
 
If you compile with -DDEBUG, a number of assertion checks are
enabled that will catch more memory errors. You probably won't be
able to make much sense of the actual assertion errors, but they
should help you locate incorrectly overwritten memory. The
checking is fairly extensive, and will slow down execution
noticeably. Calling malloc_stats or mallinfo with DEBUG set will
attempt to check every non-mmapped allocated and free chunk in the
course of computing the summmaries. (By nature, mmapped regions
cannot be checked very much automatically.)
 
Setting DEBUG may also be helpful if you are trying to modify
this code. The assertions in the check routines spell out in more
detail the assumptions and invariants underlying the algorithms.
 
*/
 
#if DEBUG
#include <assert.h>
#else
#define assert(x) ((void)0)
#endif
 
 
/*
SEPARATE_OBJECTS should be defined if you want each function to go
into a separate .o file. You must then compile malloc.c once per
function, defining the appropriate DEFINE_ macro. See below for the
list of macros.
*/
 
#ifndef SEPARATE_OBJECTS
#define DEFINE_MALLOC
#define DEFINE_FREE
#define DEFINE_REALLOC
#define DEFINE_CALLOC
#define DEFINE_CFREE
#define DEFINE_MEMALIGN
#define DEFINE_VALLOC
#define DEFINE_PVALLOC
#define DEFINE_MALLINFO
#define DEFINE_MALLOC_STATS
#define DEFINE_MALLOC_USABLE_SIZE
#define DEFINE_MALLOPT
 
#define STATIC static
#else
#define STATIC
#endif
 
/*
Define MALLOC_LOCK and MALLOC_UNLOCK to C expressions to run to
lock and unlock the malloc data structures. MALLOC_LOCK may be
called recursively.
*/
 
#ifndef MALLOC_LOCK
#define MALLOC_LOCK
#endif
 
#ifndef MALLOC_UNLOCK
#define MALLOC_UNLOCK
#endif
 
/*
INTERNAL_SIZE_T is the word-size used for internal bookkeeping
of chunk sizes. On a 64-bit machine, you can reduce malloc
overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
at the expense of not being able to handle requests greater than
2^31. This limitation is hardly ever a concern; you are encouraged
to set this. However, the default version is the same as size_t.
*/
 
#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif
 
/*
Following is needed on implementations whereby long > size_t.
The problem is caused because the code performs subtractions of
size_t values and stores the result in long values. In the case
where long > size_t and the first value is actually less than
the second value, the resultant value is positive. For example,
(long)(x - y) where x = 0 and y is 1 ends up being 0x00000000FFFFFFFF
which is 2*31 - 1 instead of 0xFFFFFFFFFFFFFFFF. This is due to the
fact that assignment from unsigned to signed won't sign extend.
*/
 
#ifdef SIZE_T_SMALLER_THAN_LONG
#define long_sub_size_t(x, y) ( (x < y) ? -((long)(y - x)) : (x - y) );
#else
#define long_sub_size_t(x, y) ( (long)(x - y) )
#endif
 
/*
REALLOC_ZERO_BYTES_FREES should be set if a call to
realloc with zero bytes should be the same as a call to free.
Some people think it should. Otherwise, since this malloc
returns a unique pointer for malloc(0), so does realloc(p, 0).
*/
 
 
/* #define REALLOC_ZERO_BYTES_FREES */
 
 
/*
WIN32 causes an emulation of sbrk to be compiled in
mmap-based options are not currently supported in WIN32.
*/
 
/* #define WIN32 */
#ifdef WIN32
#define MORECORE wsbrk
#define HAVE_MMAP 0
#endif
 
 
/*
HAVE_MEMCPY should be defined if you are not otherwise using
ANSI STD C, but still have memcpy and memset in your C library
and want to use them in calloc and realloc. Otherwise simple
macro versions are defined here.
 
USE_MEMCPY should be defined as 1 if you actually want to
have memset and memcpy called. People report that the macro
versions are often enough faster than libc versions on many
systems that it is better to use them.
 
*/
 
#define HAVE_MEMCPY
 
#ifndef USE_MEMCPY
#ifdef HAVE_MEMCPY
#define USE_MEMCPY 1
#else
#define USE_MEMCPY 0
#endif
#endif
 
#if (__STD_C || defined(HAVE_MEMCPY))
 
#if __STD_C
void* memset(void*, int, size_t);
void* memcpy(void*, const void*, size_t);
#else
Void_t* memset();
Void_t* memcpy();
#endif
#endif
 
#if USE_MEMCPY
 
/* The following macros are only invoked with (2n+1)-multiples of
INTERNAL_SIZE_T units, with a positive integer n. This is exploited
for fast inline execution when n is small. */
 
#define MALLOC_ZERO(charp, nbytes) \
do { \
INTERNAL_SIZE_T mzsz = (nbytes); \
if(mzsz <= 9*sizeof(mzsz)) { \
INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp); \
if(mzsz >= 5*sizeof(mzsz)) { *mz++ = 0; \
*mz++ = 0; \
if(mzsz >= 7*sizeof(mzsz)) { *mz++ = 0; \
*mz++ = 0; \
if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0; \
*mz++ = 0; }}} \
*mz++ = 0; \
*mz++ = 0; \
*mz = 0; \
} else memset((charp), 0, mzsz); \
} while(0)
 
#define MALLOC_COPY(dest,src,nbytes) \
do { \
INTERNAL_SIZE_T mcsz = (nbytes); \
if(mcsz <= 9*sizeof(mcsz)) { \
INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src); \
INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest); \
if(mcsz >= 5*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
*mcdst++ = *mcsrc++; \
if(mcsz >= 7*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
*mcdst++ = *mcsrc++; \
if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
*mcdst++ = *mcsrc++; }}} \
*mcdst++ = *mcsrc++; \
*mcdst++ = *mcsrc++; \
*mcdst = *mcsrc ; \
} else memcpy(dest, src, mcsz); \
} while(0)
 
#else /* !USE_MEMCPY */
 
/* Use Duff's device for good zeroing/copying performance. */
 
#define MALLOC_ZERO(charp, nbytes) \
do { \
INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp); \
long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \
if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \
switch (mctmp) { \
case 0: for(;;) { *mzp++ = 0; \
case 7: *mzp++ = 0; \
case 6: *mzp++ = 0; \
case 5: *mzp++ = 0; \
case 4: *mzp++ = 0; \
case 3: *mzp++ = 0; \
case 2: *mzp++ = 0; \
case 1: *mzp++ = 0; if(mcn <= 0) break; mcn--; } \
} \
} while(0)
 
#define MALLOC_COPY(dest,src,nbytes) \
do { \
INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src; \
INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest; \
long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \
if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \
switch (mctmp) { \
case 0: for(;;) { *mcdst++ = *mcsrc++; \
case 7: *mcdst++ = *mcsrc++; \
case 6: *mcdst++ = *mcsrc++; \
case 5: *mcdst++ = *mcsrc++; \
case 4: *mcdst++ = *mcsrc++; \
case 3: *mcdst++ = *mcsrc++; \
case 2: *mcdst++ = *mcsrc++; \
case 1: *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; } \
} \
} while(0)
 
#endif
 
 
/*
Define HAVE_MMAP to optionally make malloc() use mmap() to
allocate very large blocks. These will be returned to the
operating system immediately after a free().
*/
 
#ifndef HAVE_MMAP
#define HAVE_MMAP 1
#endif
 
/*
Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
large blocks. This is currently only possible on Linux with
kernel versions newer than 1.3.77.
*/
 
#ifndef HAVE_MREMAP
#ifdef INTERNAL_LINUX_C_LIB
#define HAVE_MREMAP 1
#else
#define HAVE_MREMAP 0
#endif
#endif
 
#if HAVE_MMAP
 
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
 
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif
 
#endif /* HAVE_MMAP */
 
/*
Access to system page size. To the extent possible, this malloc
manages memory from the system in page-size units.
The following mechanics for getpagesize were adapted from
bsd/gnu getpagesize.h
*/
 
#ifndef LACKS_UNISTD_H
# include <unistd.h>
#endif
 
#ifndef malloc_getpagesize
# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
# ifndef _SC_PAGE_SIZE
# define _SC_PAGE_SIZE _SC_PAGESIZE
# endif
# endif
# ifdef _SC_PAGE_SIZE
# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
# else
# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
extern size_t getpagesize();
# define malloc_getpagesize getpagesize()
# else
# include <sys/param.h>
# ifdef EXEC_PAGESIZE
# define malloc_getpagesize EXEC_PAGESIZE
# else
# ifdef NBPG
# ifndef CLSIZE
# define malloc_getpagesize NBPG
# else
# define malloc_getpagesize (NBPG * CLSIZE)
# endif
# else
# ifdef NBPC
# define malloc_getpagesize NBPC
# else
# ifdef PAGESIZE
# define malloc_getpagesize PAGESIZE
# else
# define malloc_getpagesize (4096) /* just guess */
# endif
# endif
# endif
# endif
# endif
# endif
#endif
 
 
 
/*
 
This version of malloc supports the standard SVID/XPG mallinfo
routine that returns a struct containing the same kind of
information you can get from malloc_stats. It should work on
any SVID/XPG compliant system that has a /usr/include/malloc.h
defining struct mallinfo. (If you'd like to install such a thing
yourself, cut out the preliminary declarations as described above
and below and save them in a malloc.h file. But there's no
compelling reason to bother to do this.)
 
The main declaration needed is the mallinfo struct that is returned
(by-copy) by mallinfo(). The SVID/XPG malloinfo struct contains a
bunch of fields, most of which are not even meaningful in this
version of malloc. Some of these fields are are instead filled by
mallinfo() with other numbers that might possibly be of interest.
 
HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
/usr/include/malloc.h file that includes a declaration of struct
mallinfo. If so, it is included; else an SVID2/XPG2 compliant
version is declared below. These must be precisely the same for
mallinfo() to work.
 
*/
 
/* #define HAVE_USR_INCLUDE_MALLOC_H */
 
#if HAVE_USR_INCLUDE_MALLOC_H
#include "/usr/include/malloc.h"
#else
 
/* SVID2/XPG mallinfo structure */
 
struct mallinfo {
int arena; /* total space allocated from system */
int ordblks; /* number of non-inuse chunks */
int smblks; /* unused -- always zero */
int hblks; /* number of mmapped regions */
int hblkhd; /* total space in mmapped regions */
int usmblks; /* unused -- always zero */
int fsmblks; /* unused -- always zero */
int uordblks; /* total allocated space */
int fordblks; /* total non-inuse space */
int keepcost; /* top-most, releasable (via malloc_trim) space */
};
 
/* SVID2/XPG mallopt options */
 
#define M_MXFAST 1 /* UNUSED in this malloc */
#define M_NLBLKS 2 /* UNUSED in this malloc */
#define M_GRAIN 3 /* UNUSED in this malloc */
#define M_KEEP 4 /* UNUSED in this malloc */
 
#endif
 
/* mallopt options that actually do something */
 
#define M_TRIM_THRESHOLD -1
#define M_TOP_PAD -2
#define M_MMAP_THRESHOLD -3
#define M_MMAP_MAX -4
 
 
 
#ifndef DEFAULT_TRIM_THRESHOLD
#define DEFAULT_TRIM_THRESHOLD (128L * 1024L)
#endif
 
/*
M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
to keep before releasing via malloc_trim in free().
 
Automatic trimming is mainly useful in long-lived programs.
Because trimming via sbrk can be slow on some systems, and can
sometimes be wasteful (in cases where programs immediately
afterward allocate more large chunks) the value should be high
enough so that your overall system performance would improve by
releasing.
 
The trim threshold and the mmap control parameters (see below)
can be traded off with one another. Trimming and mmapping are
two different ways of releasing unused memory back to the
system. Between these two, it is often possible to keep
system-level demands of a long-lived program down to a bare
minimum. For example, in one test suite of sessions measuring
the XF86 X server on Linux, using a trim threshold of 128K and a
mmap threshold of 192K led to near-minimal long term resource
consumption.
 
If you are using this malloc in a long-lived program, it should
pay to experiment with these values. As a rough guide, you
might set to a value close to the average size of a process
(program) running on your system. Releasing this much memory
would allow such a process to run in memory. Generally, it's
worth it to tune for trimming rather tham memory mapping when a
program undergoes phases where several large chunks are
allocated and released in ways that can reuse each other's
storage, perhaps mixed with phases where there are no such
chunks at all. And in well-behaved long-lived programs,
controlling release of large blocks via trimming versus mapping
is usually faster.
 
However, in most programs, these parameters serve mainly as
protection against the system-level effects of carrying around
massive amounts of unneeded memory. Since frequent calls to
sbrk, mmap, and munmap otherwise degrade performance, the default
parameters are set to relatively high values that serve only as
safeguards.
 
The default trim value is high enough to cause trimming only in
fairly extreme (by current memory consumption standards) cases.
It must be greater than page size to have any useful effect. To
disable trimming completely, you can set to (unsigned long)(-1);
 
 
*/
 
 
#ifndef DEFAULT_TOP_PAD
#define DEFAULT_TOP_PAD (0)
#endif
 
/*
M_TOP_PAD is the amount of extra `padding' space to allocate or
retain whenever sbrk is called. It is used in two ways internally:
 
* When sbrk is called to extend the top of the arena to satisfy
a new malloc request, this much padding is added to the sbrk
request.
 
* When malloc_trim is called automatically from free(),
it is used as the `pad' argument.
 
In both cases, the actual amount of padding is rounded
so that the end of the arena is always a system page boundary.
 
The main reason for using padding is to avoid calling sbrk so
often. Having even a small pad greatly reduces the likelihood
that nearly every malloc request during program start-up (or
after trimming) will invoke sbrk, which needlessly wastes
time.
 
Automatic rounding-up to page-size units is normally sufficient
to avoid measurable overhead, so the default is 0. However, in
systems where sbrk is relatively slow, it can pay to increase
this value, at the expense of carrying around more memory than
the program needs.
 
*/
 
 
#ifndef DEFAULT_MMAP_THRESHOLD
#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
#endif
 
/*
 
M_MMAP_THRESHOLD is the request size threshold for using mmap()
to service a request. Requests of at least this size that cannot
be allocated using already-existing space will be serviced via mmap.
(If enough normal freed space already exists it is used instead.)
 
Using mmap segregates relatively large chunks of memory so that
they can be individually obtained and released from the host
system. A request serviced through mmap is never reused by any
other request (at least not directly; the system may just so
happen to remap successive requests to the same locations).
 
Segregating space in this way has the benefit that mmapped space
can ALWAYS be individually released back to the system, which
helps keep the system level memory demands of a long-lived
program low. Mapped memory can never become `locked' between
other chunks, as can happen with normally allocated chunks, which
menas that even trimming via malloc_trim would not release them.
 
However, it has the disadvantages that:
 
1. The space cannot be reclaimed, consolidated, and then
used to service later requests, as happens with normal chunks.
2. It can lead to more wastage because of mmap page alignment
requirements
3. It causes malloc performance to be more dependent on host
system memory management support routines which may vary in
implementation quality and may impose arbitrary
limitations. Generally, servicing a request via normal
malloc steps is faster than going through a system's mmap.
 
All together, these considerations should lead you to use mmap
only for relatively large requests.
 
 
*/
 
 
 
#ifndef DEFAULT_MMAP_MAX
#if HAVE_MMAP
#define DEFAULT_MMAP_MAX (64)
#else
#define DEFAULT_MMAP_MAX (0)
#endif
#endif
 
/*
M_MMAP_MAX is the maximum number of requests to simultaneously
service using mmap. This parameter exists because:
 
1. Some systems have a limited number of internal tables for
use by mmap.
2. In most systems, overreliance on mmap can degrade overall
performance.
3. If a program allocates many large regions, it is probably
better off using normal sbrk-based allocation routines that
can reclaim and reallocate normal heap memory. Using a
small value allows transition into this mode after the
first few allocations.
 
Setting to 0 disables all use of mmap. If HAVE_MMAP is not set,
the default value is 0, and attempts to set it to non-zero values
in mallopt will fail.
*/
 
 
 
 
/*
 
Special defines for linux libc
 
Except when compiled using these special defines for Linux libc
using weak aliases, this malloc is NOT designed to work in
multithreaded applications. No semaphores or other concurrency
control are provided to ensure that multiple malloc or free calls
don't run at the same time, which could be disasterous. A single
semaphore could be used across malloc, realloc, and free (which is
essentially the effect of the linux weak alias approach). It would
be hard to obtain finer granularity.
 
*/
 
 
#ifdef INTERNAL_LINUX_C_LIB
 
#if __STD_C
 
Void_t * __default_morecore_init (ptrdiff_t);
Void_t *(*__morecore)(ptrdiff_t) = __default_morecore_init;
 
#else
 
Void_t * __default_morecore_init ();
Void_t *(*__morecore)() = __default_morecore_init;
 
#endif
 
#define MORECORE (*__morecore)
#define MORECORE_FAILURE 0
#define MORECORE_CLEARS 1
 
#else /* INTERNAL_LINUX_C_LIB */
 
#ifndef INTERNAL_NEWLIB
#if __STD_C
extern Void_t* sbrk(ptrdiff_t);
#else
extern Void_t* sbrk();
#endif
#endif
 
#ifndef MORECORE
#define MORECORE sbrk
#endif
 
#ifndef MORECORE_FAILURE
#define MORECORE_FAILURE -1
#endif
 
#ifndef MORECORE_CLEARS
#define MORECORE_CLEARS 1
#endif
 
#endif /* INTERNAL_LINUX_C_LIB */
 
#if defined(INTERNAL_LINUX_C_LIB) && defined(__ELF__)
 
#define cALLOc __libc_calloc
#define fREe __libc_free
#define mALLOc __libc_malloc
#define mEMALIGn __libc_memalign
#define rEALLOc __libc_realloc
#define vALLOc __libc_valloc
#define pvALLOc __libc_pvalloc
#define mALLINFo __libc_mallinfo
#define mALLOPt __libc_mallopt
 
#pragma weak calloc = __libc_calloc
#pragma weak free = __libc_free
#pragma weak cfree = __libc_free
#pragma weak malloc = __libc_malloc
#pragma weak memalign = __libc_memalign
#pragma weak realloc = __libc_realloc
#pragma weak valloc = __libc_valloc
#pragma weak pvalloc = __libc_pvalloc
#pragma weak mallinfo = __libc_mallinfo
#pragma weak mallopt = __libc_mallopt
 
#else
 
#ifdef INTERNAL_NEWLIB
 
#define cALLOc _calloc_r
#define fREe _free_r
#define mALLOc _malloc_r
#define mEMALIGn _memalign_r
#define rEALLOc _realloc_r
#define vALLOc _valloc_r
#define pvALLOc _pvalloc_r
#define mALLINFo _mallinfo_r
#define mALLOPt _mallopt_r
 
#define malloc_stats _malloc_stats_r
#define malloc_trim _malloc_trim_r
#define malloc_usable_size _malloc_usable_size_r
 
#define malloc_update_mallinfo __malloc_update_mallinfo
 
#define malloc_av_ __malloc_av_
#define malloc_current_mallinfo __malloc_current_mallinfo
#define malloc_max_sbrked_mem __malloc_max_sbrked_mem
#define malloc_max_total_mem __malloc_max_total_mem
#define malloc_sbrk_base __malloc_sbrk_base
#define malloc_top_pad __malloc_top_pad
#define malloc_trim_threshold __malloc_trim_threshold
 
#else /* ! INTERNAL_NEWLIB */
 
#define cALLOc calloc
#define fREe free
#define mALLOc malloc
#define mEMALIGn memalign
#define rEALLOc realloc
#define vALLOc valloc
#define pvALLOc pvalloc
#define mALLINFo mallinfo
#define mALLOPt mallopt
 
#endif /* ! INTERNAL_NEWLIB */
#endif
 
/* Public routines */
 
#if __STD_C
 
Void_t* mALLOc(RARG size_t);
void fREe(RARG Void_t*);
Void_t* rEALLOc(RARG Void_t*, size_t);
Void_t* mEMALIGn(RARG size_t, size_t);
Void_t* vALLOc(RARG size_t);
Void_t* pvALLOc(RARG size_t);
Void_t* cALLOc(RARG size_t, size_t);
void cfree(Void_t*);
int malloc_trim(RARG size_t);
size_t malloc_usable_size(RARG Void_t*);
void malloc_stats(RONEARG);
int mALLOPt(RARG int, int);
struct mallinfo mALLINFo(RONEARG);
#else
Void_t* mALLOc();
void fREe();
Void_t* rEALLOc();
Void_t* mEMALIGn();
Void_t* vALLOc();
Void_t* pvALLOc();
Void_t* cALLOc();
void cfree();
int malloc_trim();
size_t malloc_usable_size();
void malloc_stats();
int mALLOPt();
struct mallinfo mALLINFo();
#endif
 
 
#ifdef __cplusplus
}; /* end of extern "C" */
#endif
 
/* ---------- To make a malloc.h, end cutting here ------------ */
 
 
/*
Emulation of sbrk for WIN32
All code within the ifdef WIN32 is untested by me.
*/
 
 
#ifdef WIN32
 
#define AlignPage(add) (((add) + (malloc_getpagesize-1)) &
~(malloc_getpagesize-1))
 
/* resrve 64MB to insure large contiguous space */
#define RESERVED_SIZE (1024*1024*64)
#define NEXT_SIZE (2048*1024)
#define TOP_MEMORY ((unsigned long)2*1024*1024*1024)
 
struct GmListElement;
typedef struct GmListElement GmListElement;
 
struct GmListElement
{
GmListElement* next;
void* base;
};
 
static GmListElement* head = 0;
static unsigned int gNextAddress = 0;
static unsigned int gAddressBase = 0;
static unsigned int gAllocatedSize = 0;
 
static
GmListElement* makeGmListElement (void* bas)
{
GmListElement* this;
this = (GmListElement*)(void*)LocalAlloc (0, sizeof (GmListElement));
ASSERT (this);
if (this)
{
this->base = bas;
this->next = head;
head = this;
}
return this;
}
 
void gcleanup ()
{
BOOL rval;
ASSERT ( (head == NULL) || (head->base == (void*)gAddressBase));
if (gAddressBase && (gNextAddress - gAddressBase))
{
rval = VirtualFree ((void*)gAddressBase,
gNextAddress - gAddressBase,
MEM_DECOMMIT);
ASSERT (rval);
}
while (head)
{
GmListElement* next = head->next;
rval = VirtualFree (head->base, 0, MEM_RELEASE);
ASSERT (rval);
LocalFree (head);
head = next;
}
}
static
void* findRegion (void* start_address, unsigned long size)
{
MEMORY_BASIC_INFORMATION info;
while ((unsigned long)start_address < TOP_MEMORY)
{
VirtualQuery (start_address, &info, sizeof (info));
if (info.State != MEM_FREE)
start_address = (char*)info.BaseAddress + info.RegionSize;
else if (info.RegionSize >= size)
return start_address;
else
start_address = (char*)info.BaseAddress + info.RegionSize;
}
return NULL;
}
 
 
void* wsbrk (long size)
{
void* tmp;
if (size > 0)
{
if (gAddressBase == 0)
{
gAllocatedSize = max (RESERVED_SIZE, AlignPage (size));
gNextAddress = gAddressBase =
(unsigned int)VirtualAlloc (NULL, gAllocatedSize,
MEM_RESERVE, PAGE_NOACCESS);
} else if (AlignPage (gNextAddress + size) > (gAddressBase +
gAllocatedSize))
{
long new_size = max (NEXT_SIZE, AlignPage (size));
void* new_address = (void*)(gAddressBase+gAllocatedSize);
do
{
new_address = findRegion (new_address, new_size);
if (new_address == 0)
return (void*)-1;
 
gAddressBase = gNextAddress =
(unsigned int)VirtualAlloc (new_address, new_size,
MEM_RESERVE, PAGE_NOACCESS);
// repeat in case of race condition
// The region that we found has been snagged
// by another thread
}
while (gAddressBase == 0);
 
ASSERT (new_address == (void*)gAddressBase);
 
gAllocatedSize = new_size;
 
if (!makeGmListElement ((void*)gAddressBase))
return (void*)-1;
}
if ((size + gNextAddress) > AlignPage (gNextAddress))
{
void* res;
res = VirtualAlloc ((void*)AlignPage (gNextAddress),
(size + gNextAddress -
AlignPage (gNextAddress)),
MEM_COMMIT, PAGE_READWRITE);
if (res == 0)
return (void*)-1;
}
tmp = (void*)gNextAddress;
gNextAddress = (unsigned int)tmp + size;
return tmp;
}
else if (size < 0)
{
unsigned int alignedGoal = AlignPage (gNextAddress + size);
/* Trim by releasing the virtual memory */
if (alignedGoal >= gAddressBase)
{
VirtualFree ((void*)alignedGoal, gNextAddress - alignedGoal,
MEM_DECOMMIT);
gNextAddress = gNextAddress + size;
return (void*)gNextAddress;
}
else
{
VirtualFree ((void*)gAddressBase, gNextAddress - gAddressBase,
MEM_DECOMMIT);
gNextAddress = gAddressBase;
return (void*)-1;
}
}
else
{
return (void*)gNextAddress;
}
}
 
#endif
 
 
/*
Type declarations
*/
 
 
struct malloc_chunk
{
INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
};
 
typedef struct malloc_chunk* mchunkptr;
 
/*
 
malloc_chunk details:
 
(The following includes lightly edited explanations by Colin Plumb.)
 
Chunks of memory are maintained using a `boundary tag' method as
described in e.g., Knuth or Standish. (See the paper by Paul
Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
survey of such techniques.) Sizes of free chunks are stored both
in the front of each chunk and at the end. This makes
consolidating fragmented chunks into bigger chunks very fast. The
size fields also hold bits representing whether chunks are free or
in use.
 
An allocated chunk looks like this:
 
 
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if allocated | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... .
. .
. (malloc_usable_space() bytes) .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 
Where "chunk" is the front of the chunk for the purpose of most of
the malloc code, but "mem" is the pointer that is returned to the
user. "Nextchunk" is the beginning of the next contiguous chunk.
 
Chunks always begin on even word boundries, so the mem portion
(which is returned to the user) is also on an even word boundary, and
thus double-word aligned.
 
Free chunks are stored in circular doubly-linked lists, and look like this:
 
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:' | Size of chunk, in bytes |P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Forward pointer to next chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Back pointer to previous chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unused space (may be 0 bytes long) .
. .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`foot:' | Size of chunk, in bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
The P (PREV_INUSE) bit, stored in the unused low-order bit of the
chunk size (which is always a multiple of two words), is an in-use
bit for the *previous* chunk. If that bit is *clear*, then the
word before the current chunk size contains the previous chunk
size, and can be used to find the front of the previous chunk.
(The very first chunk allocated always has this bit set,
preventing access to non-existent (or non-owned) memory.)
 
Note that the `foot' of the current chunk is actually represented
as the prev_size of the NEXT chunk. (This makes it easier to
deal with alignments etc).
 
The two exceptions to all this are
 
1. The special chunk `top', which doesn't bother using the
trailing size field since there is no
next contiguous chunk that would have to index off it. (After
initialization, `top' is forced to always exist. If it would
become less than MINSIZE bytes long, it is replenished via
malloc_extend_top.)
 
2. Chunks allocated via mmap, which have the second-lowest-order
bit (IS_MMAPPED) set in their size fields. Because they are
never merged or traversed from any other chunk, they have no
foot size or inuse information.
 
Available chunks are kept in any of several places (all declared below):
 
* `av': An array of chunks serving as bin headers for consolidated
chunks. Each bin is doubly linked. The bins are approximately
proportionally (log) spaced. There are a lot of these bins
(128). This may look excessive, but works very well in
practice. All procedures maintain the invariant that no
consolidated chunk physically borders another one. Chunks in
bins are kept in size order, with ties going to the
approximately least recently used chunk.
 
The chunks in each bin are maintained in decreasing sorted order by
size. This is irrelevant for the small bins, which all contain
the same-sized chunks, but facilitates best-fit allocation for
larger chunks. (These lists are just sequential. Keeping them in
order almost never requires enough traversal to warrant using
fancier ordered data structures.) Chunks of the same size are
linked with the most recently freed at the front, and allocations
are taken from the back. This results in LRU or FIFO allocation
order, which tends to give each chunk an equal opportunity to be
consolidated with adjacent freed chunks, resulting in larger free
chunks and less fragmentation.
 
* `top': The top-most available chunk (i.e., the one bordering the
end of available memory) is treated specially. It is never
included in any bin, is used only if no other chunk is
available, and is released back to the system if it is very
large (see M_TRIM_THRESHOLD).
 
* `last_remainder': A bin holding only the remainder of the
most recently split (non-top) chunk. This bin is checked
before other non-fitting chunks, so as to provide better
locality for runs of sequentially allocated chunks.
 
* Implicitly, through the host system's memory mapping tables.
If supported, requests greater than a threshold are usually
serviced via calls to mmap, and then later released via munmap.
 
*/
 
 
 
 
 
/* sizes, alignments */
 
#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))
#ifndef MALLOC_ALIGNMENT
#define MALLOC_ALIGN 8
#define MALLOC_ALIGNMENT (SIZE_SZ < 4 ? 8 : (SIZE_SZ + SIZE_SZ))
#else
#define MALLOC_ALIGN MALLOC_ALIGNMENT
#endif
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
#define MINSIZE (sizeof(struct malloc_chunk))
 
/* conversion from malloc headers to user pointers, and back */
 
#define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ))
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
 
/* pad request bytes into a usable size */
 
#define request2size(req) \
(((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \
(long)(MINSIZE + MALLOC_ALIGN_MASK)) ? ((MINSIZE + MALLOC_ALIGN_MASK) & ~(MALLOC_ALIGN_MASK)) : \
(((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK)))
 
/* Check if m has acceptable alignment */
 
#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
 
 
 
/*
Physical chunk operations
*/
 
 
/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
 
#define PREV_INUSE 0x1
 
/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
 
#define IS_MMAPPED 0x2
 
/* Bits to mask off when extracting size */
 
#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
 
 
/* Ptr to next physical malloc_chunk. */
 
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
 
/* Ptr to previous physical malloc_chunk */
 
#define prev_chunk(p)\
((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
 
 
/* Treat space at ptr + offset as a chunk */
 
#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
 
 
 
/*
Dealing with use bits
*/
 
/* extract p's inuse bit */
 
#define inuse(p)\
((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
 
/* extract inuse bit of previous chunk */
 
#define prev_inuse(p) ((p)->size & PREV_INUSE)
 
/* check for mmap()'ed chunk */
 
#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
 
/* set/clear chunk as in use without otherwise disturbing */
 
#define set_inuse(p)\
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
 
#define clear_inuse(p)\
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
 
/* check/set/clear inuse bits in known places */
 
#define inuse_bit_at_offset(p, s)\
(((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
 
#define set_inuse_bit_at_offset(p, s)\
(((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
 
#define clear_inuse_bit_at_offset(p, s)\
(((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
 
 
 
/*
Dealing with size fields
*/
 
/* Get size, ignoring use bits */
 
#define chunksize(p) ((p)->size & ~(SIZE_BITS))
 
/* Set size at head, without disturbing its use bit */
 
#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))
 
/* Set size/use ignoring previous bits in header */
 
#define set_head(p, s) ((p)->size = (s))
 
/* Set size at footer (only when chunk is not in use) */
 
#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
 
 
 
 
/*
Bins
 
The bins, `av_' are an array of pairs of pointers serving as the
heads of (initially empty) doubly-linked lists of chunks, laid out
in a way so that each pair can be treated as if it were in a
malloc_chunk. (This way, the fd/bk offsets for linking bin heads
and chunks are the same).
 
Bins for sizes < 512 bytes contain chunks of all the same size, spaced
8 bytes apart. Larger bins are approximately logarithmically
spaced. (See the table below.) The `av_' array is never mentioned
directly in the code, but instead via bin access macros.
 
Bin layout:
 
64 bins of size 8
32 bins of size 64
16 bins of size 512
8 bins of size 4096
4 bins of size 32768
2 bins of size 262144
1 bin of size what's left
 
There is actually a little bit of slop in the numbers in bin_index
for the sake of speed. This makes no difference elsewhere.
 
The special chunks `top' and `last_remainder' get their own bins,
(this is implemented via yet more trickery with the av_ array),
although `top' is never properly linked to its bin since it is
always handled specially.
 
*/
 
#ifdef SEPARATE_OBJECTS
#define av_ malloc_av_
#endif
 
#define NAV 128 /* number of bins */
 
typedef struct malloc_chunk* mbinptr;
 
/* access macros */
 
#define bin_at(i) ((mbinptr)((char*)&(av_[2*(i) + 2]) - 2*SIZE_SZ))
#define next_bin(b) ((mbinptr)((char*)(b) + 2 * sizeof(mbinptr)))
#define prev_bin(b) ((mbinptr)((char*)(b) - 2 * sizeof(mbinptr)))
 
/*
The first 2 bins are never indexed. The corresponding av_ cells are instead
used for bookkeeping. This is not to save space, but to simplify
indexing, maintain locality, and avoid some initialization tests.
*/
 
#define top (bin_at(0)->fd) /* The topmost chunk */
#define last_remainder (bin_at(1)) /* remainder from last split */
 
 
/*
Because top initially points to its own bin with initial
zero size, thus forcing extension on the first malloc request,
we avoid having any special code in malloc to check whether
it even exists yet. But we still need to in malloc_extend_top.
*/
 
#define initial_top ((mchunkptr)(bin_at(0)))
 
/* Helper macro to initialize bins */
 
#define IAV(i) bin_at(i), bin_at(i)
 
#ifdef DEFINE_MALLOC
STATIC mbinptr av_[NAV * 2 + 2] = {
0, 0,
IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5), IAV(6), IAV(7),
IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13), IAV(14), IAV(15),
IAV(16), IAV(17), IAV(18), IAV(19), IAV(20), IAV(21), IAV(22), IAV(23),
IAV(24), IAV(25), IAV(26), IAV(27), IAV(28), IAV(29), IAV(30), IAV(31),
IAV(32), IAV(33), IAV(34), IAV(35), IAV(36), IAV(37), IAV(38), IAV(39),
IAV(40), IAV(41), IAV(42), IAV(43), IAV(44), IAV(45), IAV(46), IAV(47),
IAV(48), IAV(49), IAV(50), IAV(51), IAV(52), IAV(53), IAV(54), IAV(55),
IAV(56), IAV(57), IAV(58), IAV(59), IAV(60), IAV(61), IAV(62), IAV(63),
IAV(64), IAV(65), IAV(66), IAV(67), IAV(68), IAV(69), IAV(70), IAV(71),
IAV(72), IAV(73), IAV(74), IAV(75), IAV(76), IAV(77), IAV(78), IAV(79),
IAV(80), IAV(81), IAV(82), IAV(83), IAV(84), IAV(85), IAV(86), IAV(87),
IAV(88), IAV(89), IAV(90), IAV(91), IAV(92), IAV(93), IAV(94), IAV(95),
IAV(96), IAV(97), IAV(98), IAV(99), IAV(100), IAV(101), IAV(102), IAV(103),
IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111),
IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127)
};
#else
extern mbinptr av_[NAV * 2 + 2];
#endif
 
 
/* field-extraction macros */
 
#define first(b) ((b)->fd)
#define last(b) ((b)->bk)
 
/*
Indexing into bins
*/
 
#define bin_index(sz) \
(((((unsigned long)(sz)) >> 9) == 0) ? (((unsigned long)(sz)) >> 3): \
((((unsigned long)(sz)) >> 9) <= 4) ? 56 + (((unsigned long)(sz)) >> 6): \
((((unsigned long)(sz)) >> 9) <= 20) ? 91 + (((unsigned long)(sz)) >> 9): \
((((unsigned long)(sz)) >> 9) <= 84) ? 110 + (((unsigned long)(sz)) >> 12): \
((((unsigned long)(sz)) >> 9) <= 340) ? 119 + (((unsigned long)(sz)) >> 15): \
((((unsigned long)(sz)) >> 9) <= 1364) ? 124 + (((unsigned long)(sz)) >> 18): \
126)
/*
bins for chunks < 512 are all spaced SMALLBIN_WIDTH bytes apart, and hold
identically sized chunks. This is exploited in malloc.
*/
 
#define MAX_SMALLBIN_SIZE 512
#define SMALLBIN_WIDTH 8
#define SMALLBIN_WIDTH_BITS 3
#define MAX_SMALLBIN (MAX_SMALLBIN_SIZE / SMALLBIN_WIDTH) - 1
 
#define smallbin_index(sz) (((unsigned long)(sz)) >> SMALLBIN_WIDTH_BITS)
 
/*
Requests are `small' if both the corresponding and the next bin are small
*/
 
#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH)
 
 
/*
To help compensate for the large number of bins, a one-level index
structure is used for bin-by-bin searching. `binblocks' is a
one-word bitvector recording whether groups of BINBLOCKWIDTH bins
have any (possibly) non-empty bins, so they can be skipped over
all at once during during traversals. The bits are NOT always
cleared as soon as all bins in a block are empty, but instead only
when all are noticed to be empty during traversal in malloc.
*/
 
#define BINBLOCKWIDTH 4 /* bins per block */
 
#define binblocks (bin_at(0)->size) /* bitvector of nonempty blocks */
 
/* bin<->block macros */
 
#define idx2binblock(ix) ((unsigned long)1 << (ix / BINBLOCKWIDTH))
#define mark_binblock(ii) (binblocks |= idx2binblock(ii))
#define clear_binblock(ii) (binblocks &= ~(idx2binblock(ii)))
 
 
 
 
/* Other static bookkeeping data */
 
#ifdef SEPARATE_OBJECTS
#define trim_threshold malloc_trim_threshold
#define top_pad malloc_top_pad
#define n_mmaps_max malloc_n_mmaps_max
#define mmap_threshold malloc_mmap_threshold
#define sbrk_base malloc_sbrk_base
#define max_sbrked_mem malloc_max_sbrked_mem
#define max_total_mem malloc_max_total_mem
#define current_mallinfo malloc_current_mallinfo
#define n_mmaps malloc_n_mmaps
#define max_n_mmaps malloc_max_n_mmaps
#define mmapped_mem malloc_mmapped_mem
#define max_mmapped_mem malloc_max_mmapped_mem
#endif
 
/* variables holding tunable values */
 
#ifdef DEFINE_MALLOC
 
STATIC unsigned long trim_threshold = DEFAULT_TRIM_THRESHOLD;
STATIC unsigned long top_pad = DEFAULT_TOP_PAD;
#if HAVE_MMAP
STATIC unsigned int n_mmaps_max = DEFAULT_MMAP_MAX;
STATIC unsigned long mmap_threshold = DEFAULT_MMAP_THRESHOLD;
#endif
 
/* The first value returned from sbrk */
STATIC char* sbrk_base = (char*)(-1);
 
/* The maximum memory obtained from system via sbrk */
STATIC unsigned long max_sbrked_mem = 0;
 
/* The maximum via either sbrk or mmap */
STATIC unsigned long max_total_mem = 0;
 
/* internal working copy of mallinfo */
STATIC struct mallinfo current_mallinfo = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
#if HAVE_MMAP
 
/* Tracking mmaps */
 
STATIC unsigned int n_mmaps = 0;
STATIC unsigned int max_n_mmaps = 0;
STATIC unsigned long mmapped_mem = 0;
STATIC unsigned long max_mmapped_mem = 0;
 
#endif
 
#else /* ! DEFINE_MALLOC */
 
extern unsigned long trim_threshold;
extern unsigned long top_pad;
#if HAVE_MMAP
extern unsigned int n_mmaps_max;
extern unsigned long mmap_threshold;
#endif
extern char* sbrk_base;
extern unsigned long max_sbrked_mem;
extern unsigned long max_total_mem;
extern struct mallinfo current_mallinfo;
#if HAVE_MMAP
extern unsigned int n_mmaps;
extern unsigned int max_n_mmaps;
extern unsigned long mmapped_mem;
extern unsigned long max_mmapped_mem;
#endif
 
#endif /* ! DEFINE_MALLOC */
 
/* The total memory obtained from system via sbrk */
#define sbrked_mem (current_mallinfo.arena)
 
 
/*
Debugging support
*/
 
#if DEBUG
 
 
/*
These routines make a number of assertions about the states
of data structures that should be true at all times. If any
are not true, it's very likely that a user program has somehow
trashed memory. (It's also possible that there is a coding error
in malloc. In which case, please report it!)
*/
 
#if __STD_C
static void do_check_chunk(mchunkptr p)
#else
static void do_check_chunk(p) mchunkptr p;
#endif
{
INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
 
/* No checkable chunk is mmapped */
assert(!chunk_is_mmapped(p));
 
/* Check for legal address ... */
assert((char*)p >= sbrk_base);
if (p != top)
assert((char*)p + sz <= (char*)top);
else
assert((char*)p + sz <= sbrk_base + sbrked_mem);
 
}
 
 
#if __STD_C
static void do_check_free_chunk(mchunkptr p)
#else
static void do_check_free_chunk(p) mchunkptr p;
#endif
{
INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
mchunkptr next = chunk_at_offset(p, sz);
 
do_check_chunk(p);
 
/* Check whether it claims to be free ... */
assert(!inuse(p));
 
/* Unless a special marker, must have OK fields */
if ((long)sz >= (long)MINSIZE)
{
assert((sz & MALLOC_ALIGN_MASK) == 0);
assert(aligned_OK(chunk2mem(p)));
/* ... matching footer field */
assert(next->prev_size == sz);
/* ... and is fully consolidated */
assert(prev_inuse(p));
assert (next == top || inuse(next));
/* ... and has minimally sane links */
assert(p->fd->bk == p);
assert(p->bk->fd == p);
}
else /* markers are always of size SIZE_SZ */
assert(sz == SIZE_SZ);
}
 
#if __STD_C
static void do_check_inuse_chunk(mchunkptr p)
#else
static void do_check_inuse_chunk(p) mchunkptr p;
#endif
{
mchunkptr next = next_chunk(p);
do_check_chunk(p);
 
/* Check whether it claims to be in use ... */
assert(inuse(p));
 
/* ... and is surrounded by OK chunks.
Since more things can be checked with free chunks than inuse ones,
if an inuse chunk borders them and debug is on, it's worth doing them.
*/
if (!prev_inuse(p))
{
mchunkptr prv = prev_chunk(p);
assert(next_chunk(prv) == p);
do_check_free_chunk(prv);
}
if (next == top)
{
assert(prev_inuse(next));
assert(chunksize(next) >= MINSIZE);
}
else if (!inuse(next))
do_check_free_chunk(next);
 
}
 
#if __STD_C
static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
#else
static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
#endif
{
INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
long room = long_sub_size_t(sz, s);
 
do_check_inuse_chunk(p);
 
/* Legal size ... */
assert((long)sz >= (long)MINSIZE);
assert((sz & MALLOC_ALIGN_MASK) == 0);
assert(room >= 0);
assert(room < (long)MINSIZE);
 
/* ... and alignment */
assert(aligned_OK(chunk2mem(p)));
 
 
/* ... and was allocated at front of an available chunk */
assert(prev_inuse(p));
 
}
 
 
#define check_free_chunk(P) do_check_free_chunk(P)
#define check_inuse_chunk(P) do_check_inuse_chunk(P)
#define check_chunk(P) do_check_chunk(P)
#define check_malloced_chunk(P,N) do_check_malloced_chunk(P,N)
#else
#define check_free_chunk(P)
#define check_inuse_chunk(P)
#define check_chunk(P)
#define check_malloced_chunk(P,N)
#endif
 
 
/*
Macro-based internal utilities
*/
 
 
/*
Linking chunks in bin lists.
Call these only with variables, not arbitrary expressions, as arguments.
*/
 
/*
Place chunk p of size s in its bin, in size order,
putting it ahead of others of same size.
*/
 
 
#define frontlink(P, S, IDX, BK, FD) \
{ \
if (S < MAX_SMALLBIN_SIZE) \
{ \
IDX = smallbin_index(S); \
mark_binblock(IDX); \
BK = bin_at(IDX); \
FD = BK->fd; \
P->bk = BK; \
P->fd = FD; \
FD->bk = BK->fd = P; \
} \
else \
{ \
IDX = bin_index(S); \
BK = bin_at(IDX); \
FD = BK->fd; \
if (FD == BK) mark_binblock(IDX); \
else \
{ \
while (FD != BK && S < chunksize(FD)) FD = FD->fd; \
BK = FD->bk; \
} \
P->bk = BK; \
P->fd = FD; \
FD->bk = BK->fd = P; \
} \
}
 
 
/* take a chunk off a list */
 
#define unlink(P, BK, FD) \
{ \
BK = P->bk; \
FD = P->fd; \
FD->bk = BK; \
BK->fd = FD; \
} \
 
/* Place p as the last remainder */
 
#define link_last_remainder(P) \
{ \
last_remainder->fd = last_remainder->bk = P; \
P->fd = P->bk = last_remainder; \
}
 
/* Clear the last_remainder bin */
 
#define clear_last_remainder \
(last_remainder->fd = last_remainder->bk = last_remainder)
 
 
 
 
 
/* Routines dealing with mmap(). */
 
#if HAVE_MMAP
 
#ifdef DEFINE_MALLOC
 
#if __STD_C
static mchunkptr mmap_chunk(size_t size)
#else
static mchunkptr mmap_chunk(size) size_t size;
#endif
{
size_t page_mask = malloc_getpagesize - 1;
mchunkptr p;
 
#ifndef MAP_ANONYMOUS
static int fd = -1;
#endif
 
if(n_mmaps >= n_mmaps_max) return 0; /* too many regions */
 
/* For mmapped chunks, the overhead is one SIZE_SZ unit larger, because
* there is no following chunk whose prev_size field could be used.
*/
size = (size + SIZE_SZ + page_mask) & ~page_mask;
 
#ifdef MAP_ANONYMOUS
p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
#else /* !MAP_ANONYMOUS */
if (fd < 0)
{
fd = open("/dev/zero", O_RDWR);
if(fd < 0) return 0;
}
p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
#endif
 
if(p == (mchunkptr)-1) return 0;
 
n_mmaps++;
if (n_mmaps > max_n_mmaps) max_n_mmaps = n_mmaps;
/* We demand that eight bytes into a page must be 8-byte aligned. */
assert(aligned_OK(chunk2mem(p)));
 
/* The offset to the start of the mmapped region is stored
* in the prev_size field of the chunk; normally it is zero,
* but that can be changed in memalign().
*/
p->prev_size = 0;
set_head(p, size|IS_MMAPPED);
mmapped_mem += size;
if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)
max_mmapped_mem = mmapped_mem;
if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
max_total_mem = mmapped_mem + sbrked_mem;
return p;
}
 
#endif /* DEFINE_MALLOC */
 
#ifdef SEPARATE_OBJECTS
#define munmap_chunk malloc_munmap_chunk
#endif
 
#ifdef DEFINE_FREE
 
#if __STD_C
STATIC void munmap_chunk(mchunkptr p)
#else
STATIC void munmap_chunk(p) mchunkptr p;
#endif
{
INTERNAL_SIZE_T size = chunksize(p);
int ret;
 
assert (chunk_is_mmapped(p));
assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
assert((n_mmaps > 0));
assert(((p->prev_size + size) & (malloc_getpagesize-1)) == 0);
 
n_mmaps--;
mmapped_mem -= (size + p->prev_size);
 
ret = munmap((char *)p - p->prev_size, size + p->prev_size);
 
/* munmap returns non-zero on failure */
assert(ret == 0);
}
 
#else /* ! DEFINE_FREE */
 
#if __STD_C
extern void munmap_chunk(mchunkptr);
#else
extern void munmap_chunk();
#endif
 
#endif /* ! DEFINE_FREE */
 
#if HAVE_MREMAP
 
#ifdef DEFINE_REALLOC
 
#if __STD_C
static mchunkptr mremap_chunk(mchunkptr p, size_t new_size)
#else
static mchunkptr mremap_chunk(p, new_size) mchunkptr p; size_t new_size;
#endif
{
size_t page_mask = malloc_getpagesize - 1;
INTERNAL_SIZE_T offset = p->prev_size;
INTERNAL_SIZE_T size = chunksize(p);
char *cp;
 
assert (chunk_is_mmapped(p));
assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
assert((n_mmaps > 0));
assert(((size + offset) & (malloc_getpagesize-1)) == 0);
 
/* Note the extra SIZE_SZ overhead as in mmap_chunk(). */
new_size = (new_size + offset + SIZE_SZ + page_mask) & ~page_mask;
 
cp = (char *)mremap((char *)p - offset, size + offset, new_size, 1);
 
if (cp == (char *)-1) return 0;
 
p = (mchunkptr)(cp + offset);
 
assert(aligned_OK(chunk2mem(p)));
 
assert((p->prev_size == offset));
set_head(p, (new_size - offset)|IS_MMAPPED);
 
mmapped_mem -= size + offset;
mmapped_mem += new_size;
if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)
max_mmapped_mem = mmapped_mem;
if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
max_total_mem = mmapped_mem + sbrked_mem;
return p;
}
 
#endif /* DEFINE_REALLOC */
 
#endif /* HAVE_MREMAP */
 
#endif /* HAVE_MMAP */
 
 
 
#ifdef DEFINE_MALLOC
 
/*
Extend the top-most chunk by obtaining memory from system.
Main interface to sbrk (but see also malloc_trim).
*/
 
#if __STD_C
static void malloc_extend_top(RARG INTERNAL_SIZE_T nb)
#else
static void malloc_extend_top(RARG nb) RDECL INTERNAL_SIZE_T nb;
#endif
{
char* brk; /* return value from sbrk */
INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */
INTERNAL_SIZE_T correction; /* bytes for 2nd sbrk call */
char* new_brk; /* return of 2nd sbrk call */
INTERNAL_SIZE_T top_size; /* new size of top chunk */
 
mchunkptr old_top = top; /* Record state of old top */
INTERNAL_SIZE_T old_top_size = chunksize(old_top);
char* old_end = (char*)(chunk_at_offset(old_top, old_top_size));
 
/* Pad request with top_pad plus minimal overhead */
INTERNAL_SIZE_T sbrk_size = nb + top_pad + MINSIZE;
unsigned long pagesz = malloc_getpagesize;
 
/* If not the first time through, round to preserve page boundary */
/* Otherwise, we need to correct to a page size below anyway. */
/* (We also correct below if an intervening foreign sbrk call.) */
 
if (sbrk_base != (char*)(-1))
sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1);
 
brk = (char*)(MORECORE (sbrk_size));
 
/* Fail if sbrk failed or if a foreign sbrk call killed our space */
if (brk == (char*)(MORECORE_FAILURE) ||
(brk < old_end && old_top != initial_top))
return;
 
sbrked_mem += sbrk_size;
 
if (brk == old_end) /* can just add bytes to current top */
{
top_size = sbrk_size + old_top_size;
set_head(top, top_size | PREV_INUSE);
}
else
{
if (sbrk_base == (char*)(-1)) /* First time through. Record base */
sbrk_base = brk;
else /* Someone else called sbrk(). Count those bytes as sbrked_mem. */
sbrked_mem += brk - (char*)old_end;
 
/* Guarantee alignment of first new chunk made from this space */
front_misalign = (POINTER_UINT)chunk2mem(brk) & MALLOC_ALIGN_MASK;
if (front_misalign > 0)
{
correction = (MALLOC_ALIGNMENT) - front_misalign;
brk += correction;
}
else
correction = 0;
 
/* Guarantee the next brk will be at a page boundary */
correction += pagesz - ((POINTER_UINT)(brk + sbrk_size) & (pagesz - 1));
 
/* Allocate correction */
new_brk = (char*)(MORECORE (correction));
if (new_brk == (char*)(MORECORE_FAILURE)) return;
 
sbrked_mem += correction;
 
top = (mchunkptr)brk;
top_size = new_brk - brk + correction;
set_head(top, top_size | PREV_INUSE);
 
if (old_top != initial_top)
{
 
/* There must have been an intervening foreign sbrk call. */
/* A double fencepost is necessary to prevent consolidation */
 
/* If not enough space to do this, then user did something very wrong */
if (old_top_size < MINSIZE)
{
set_head(top, PREV_INUSE); /* will force null return from malloc */
return;
}
 
/* Also keep size a multiple of MALLOC_ALIGNMENT */
old_top_size = (old_top_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;
set_head_size(old_top, old_top_size);
chunk_at_offset(old_top, old_top_size )->size =
SIZE_SZ|PREV_INUSE;
chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size =
SIZE_SZ|PREV_INUSE;
/* If possible, release the rest. */
if (old_top_size >= MINSIZE)
fREe(RCALL chunk2mem(old_top));
}
}
 
if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem)
max_sbrked_mem = sbrked_mem;
#if HAVE_MMAP
if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
max_total_mem = mmapped_mem + sbrked_mem;
#else
if ((unsigned long)(sbrked_mem) > (unsigned long)max_total_mem)
max_total_mem = sbrked_mem;
#endif
 
/* We always land on a page boundary */
assert(((unsigned long)((char*)top + top_size) & (pagesz - 1)) == 0);
}
 
#endif /* DEFINE_MALLOC */
 
/* Main public routines */
 
#ifdef DEFINE_MALLOC
 
/*
Malloc Algorthim:
 
The requested size is first converted into a usable form, `nb'.
This currently means to add 4 bytes overhead plus possibly more to
obtain 8-byte alignment and/or to obtain a size of at least
MINSIZE (currently 16 bytes), the smallest allocatable size.
(All fits are considered `exact' if they are within MINSIZE bytes.)
 
From there, the first successful of the following steps is taken:
 
1. The bin corresponding to the request size is scanned, and if
a chunk of exactly the right size is found, it is taken.
 
2. The most recently remaindered chunk is used if it is big
enough. This is a form of (roving) first fit, used only in
the absence of exact fits. Runs of consecutive requests use
the remainder of the chunk used for the previous such request
whenever possible. This limited use of a first-fit style
allocation strategy tends to give contiguous chunks
coextensive lifetimes, which improves locality and can reduce
fragmentation in the long run.
 
3. Other bins are scanned in increasing size order, using a
chunk big enough to fulfill the request, and splitting off
any remainder. This search is strictly by best-fit; i.e.,
the smallest (with ties going to approximately the least
recently used) chunk that fits is selected.
 
4. If large enough, the chunk bordering the end of memory
(`top') is split off. (This use of `top' is in accord with
the best-fit search rule. In effect, `top' is treated as
larger (and thus less well fitting) than any other available
chunk since it can be extended to be as large as necessary
(up to system limitations).
 
5. If the request size meets the mmap threshold and the
system supports mmap, and there are few enough currently
allocated mmapped regions, and a call to mmap succeeds,
the request is allocated via direct memory mapping.
 
6. Otherwise, the top of memory is extended by
obtaining more space from the system (normally using sbrk,
but definable to anything else via the MORECORE macro).
Memory is gathered from the system (in system page-sized
units) in a way that allows chunks obtained across different
sbrk calls to be consolidated, but does not require
contiguous memory. Thus, it should be safe to intersperse
mallocs with other sbrk calls.
 
 
All allocations are made from the the `lowest' part of any found
chunk. (The implementation invariant is that prev_inuse is
always true of any allocated chunk; i.e., that each allocated
chunk borders either a previously allocated and still in-use chunk,
or the base of its memory arena.)
 
*/
 
#if __STD_C
Void_t* mALLOc(RARG size_t bytes)
#else
Void_t* mALLOc(RARG bytes) RDECL size_t bytes;
#endif
{
#ifdef MALLOC_PROVIDED
 
malloc (bytes);
 
#else
 
mchunkptr victim; /* inspected/selected chunk */
INTERNAL_SIZE_T victim_size; /* its size */
int idx; /* index for bin traversal */
mbinptr bin; /* associated bin */
mchunkptr remainder; /* remainder from a split */
long remainder_size; /* its size */
int remainder_index; /* its bin index */
unsigned long block; /* block traverser bit */
int startidx; /* first bin of a traversed block */
mchunkptr fwd; /* misc temp for linking */
mchunkptr bck; /* misc temp for linking */
mbinptr q; /* misc temp */
 
INTERNAL_SIZE_T nb = request2size(bytes); /* padded request size; */
 
MALLOC_LOCK;
 
/* Check for exact match in a bin */
 
if (is_small_request(nb)) /* Faster version for small requests */
{
idx = smallbin_index(nb);
 
/* No traversal or size check necessary for small bins. */
 
q = bin_at(idx);
victim = last(q);
 
#if MALLOC_ALIGN != 16
/* Also scan the next one, since it would have a remainder < MINSIZE */
if (victim == q)
{
q = next_bin(q);
victim = last(q);
}
#endif
if (victim != q)
{
victim_size = chunksize(victim);
unlink(victim, bck, fwd);
set_inuse_bit_at_offset(victim, victim_size);
check_malloced_chunk(victim, nb);
MALLOC_UNLOCK;
return chunk2mem(victim);
}
 
idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */
 
}
else
{
idx = bin_index(nb);
bin = bin_at(idx);
 
for (victim = last(bin); victim != bin; victim = victim->bk)
{
victim_size = chunksize(victim);
remainder_size = long_sub_size_t(victim_size, nb);
if (remainder_size >= (long)MINSIZE) /* too big */
{
--idx; /* adjust to rescan below after checking last remainder */
break;
}
 
else if (remainder_size >= 0) /* exact fit */
{
unlink(victim, bck, fwd);
set_inuse_bit_at_offset(victim, victim_size);
check_malloced_chunk(victim, nb);
MALLOC_UNLOCK;
return chunk2mem(victim);
}
}
 
++idx;
 
}
 
/* Try to use the last split-off remainder */
 
if ( (victim = last_remainder->fd) != last_remainder)
{
victim_size = chunksize(victim);
remainder_size = long_sub_size_t(victim_size, nb);
 
if (remainder_size >= (long)MINSIZE) /* re-split */
{
remainder = chunk_at_offset(victim, nb);
set_head(victim, nb | PREV_INUSE);
link_last_remainder(remainder);
set_head(remainder, remainder_size | PREV_INUSE);
set_foot(remainder, remainder_size);
check_malloced_chunk(victim, nb);
MALLOC_UNLOCK;
return chunk2mem(victim);
}
 
clear_last_remainder;
 
if (remainder_size >= 0) /* exhaust */
{
set_inuse_bit_at_offset(victim, victim_size);
check_malloced_chunk(victim, nb);
MALLOC_UNLOCK;
return chunk2mem(victim);
}
 
/* Else place in bin */
 
frontlink(victim, victim_size, remainder_index, bck, fwd);
}
 
/*
If there are any possibly nonempty big-enough blocks,
search for best fitting chunk by scanning bins in blockwidth units.
*/
 
if ( (block = idx2binblock(idx)) <= binblocks)
{
 
/* Get to the first marked block */
 
if ( (block & binblocks) == 0)
{
/* force to an even block boundary */
idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH;
block <<= 1;
while ((block & binblocks) == 0)
{
idx += BINBLOCKWIDTH;
block <<= 1;
}
}
/* For each possibly nonempty block ... */
for (;;)
{
startidx = idx; /* (track incomplete blocks) */
q = bin = bin_at(idx);
 
/* For each bin in this block ... */
do
{
/* Find and use first big enough chunk ... */
 
for (victim = last(bin); victim != bin; victim = victim->bk)
{
victim_size = chunksize(victim);
remainder_size = long_sub_size_t(victim_size, nb);
 
if (remainder_size >= (long)MINSIZE) /* split */
{
remainder = chunk_at_offset(victim, nb);
set_head(victim, nb | PREV_INUSE);
unlink(victim, bck, fwd);
link_last_remainder(remainder);
set_head(remainder, remainder_size | PREV_INUSE);
set_foot(remainder, remainder_size);
check_malloced_chunk(victim, nb);
MALLOC_UNLOCK;
return chunk2mem(victim);
}
 
else if (remainder_size >= 0) /* take */
{
set_inuse_bit_at_offset(victim, victim_size);
unlink(victim, bck, fwd);
check_malloced_chunk(victim, nb);
MALLOC_UNLOCK;
return chunk2mem(victim);
}
 
}
 
bin = next_bin(bin);
 
#if MALLOC_ALIGN == 16
if (idx < MAX_SMALLBIN)
{
bin = next_bin(bin);
++idx;
}
#endif
} while ((++idx & (BINBLOCKWIDTH - 1)) != 0);
 
/* Clear out the block bit. */
 
do /* Possibly backtrack to try to clear a partial block */
{
if ((startidx & (BINBLOCKWIDTH - 1)) == 0)
{
binblocks &= ~block;
break;
}
--startidx;
q = prev_bin(q);
} while (first(q) == q);
 
/* Get to the next possibly nonempty block */
 
if ( (block <<= 1) <= binblocks && (block != 0) )
{
while ((block & binblocks) == 0)
{
idx += BINBLOCKWIDTH;
block <<= 1;
}
}
else
break;
}
}
 
 
/* Try to use top chunk */
 
/* Require that there be a remainder, ensuring top always exists */
remainder_size = long_sub_size_t(chunksize(top), nb);
if (chunksize(top) < nb || remainder_size < (long)MINSIZE)
{
 
#if HAVE_MMAP
/* If big and would otherwise need to extend, try to use mmap instead */
if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
(victim = mmap_chunk(nb)) != 0)
{
MALLOC_UNLOCK;
return chunk2mem(victim);
}
#endif
 
/* Try to extend */
malloc_extend_top(RCALL nb);
remainder_size = long_sub_size_t(chunksize(top), nb);
if (chunksize(top) < nb || remainder_size < (long)MINSIZE)
{
MALLOC_UNLOCK;
return 0; /* propagate failure */
}
}
 
victim = top;
set_head(victim, nb | PREV_INUSE);
top = chunk_at_offset(victim, nb);
set_head(top, remainder_size | PREV_INUSE);
check_malloced_chunk(victim, nb);
MALLOC_UNLOCK;
return chunk2mem(victim);
 
#endif /* MALLOC_PROVIDED */
}
 
#endif /* DEFINE_MALLOC */
#ifdef DEFINE_FREE
 
/*
 
free() algorithm :
 
cases:
 
1. free(0) has no effect.
 
2. If the chunk was allocated via mmap, it is release via munmap().
 
3. If a returned chunk borders the current high end of memory,
it is consolidated into the top, and if the total unused
topmost memory exceeds the trim threshold, malloc_trim is
called.
 
4. Other chunks are consolidated as they arrive, and
placed in corresponding bins. (This includes the case of
consolidating with the current `last_remainder').
 
*/
 
 
#if __STD_C
void fREe(RARG Void_t* mem)
#else
void fREe(RARG mem) RDECL Void_t* mem;
#endif
{
#ifdef MALLOC_PROVIDED
 
free (mem);
 
#else
 
mchunkptr p; /* chunk corresponding to mem */
INTERNAL_SIZE_T hd; /* its head field */
INTERNAL_SIZE_T sz; /* its size */
int idx; /* its bin index */
mchunkptr next; /* next contiguous chunk */
INTERNAL_SIZE_T nextsz; /* its size */
INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */
mchunkptr bck; /* misc temp for linking */
mchunkptr fwd; /* misc temp for linking */
int islr; /* track whether merging with last_remainder */
 
if (mem == 0) /* free(0) has no effect */
return;
 
MALLOC_LOCK;
 
p = mem2chunk(mem);
hd = p->size;
 
#if HAVE_MMAP
if (hd & IS_MMAPPED) /* release mmapped memory. */
{
munmap_chunk(p);
MALLOC_UNLOCK;
return;
}
#endif
check_inuse_chunk(p);
sz = hd & ~PREV_INUSE;
next = chunk_at_offset(p, sz);
nextsz = chunksize(next);
if (next == top) /* merge with top */
{
sz += nextsz;
 
if (!(hd & PREV_INUSE)) /* consolidate backward */
{
prevsz = p->prev_size;
p = chunk_at_offset(p, -prevsz);
sz += prevsz;
unlink(p, bck, fwd);
}
 
set_head(p, sz | PREV_INUSE);
top = p;
if ((unsigned long)(sz) >= (unsigned long)trim_threshold)
malloc_trim(RCALL top_pad);
MALLOC_UNLOCK;
return;
}
 
set_head(next, nextsz); /* clear inuse bit */
 
islr = 0;
 
if (!(hd & PREV_INUSE)) /* consolidate backward */
{
prevsz = p->prev_size;
p = chunk_at_offset(p, -prevsz);
sz += prevsz;
if (p->fd == last_remainder) /* keep as last_remainder */
islr = 1;
else
unlink(p, bck, fwd);
}
if (!(inuse_bit_at_offset(next, nextsz))) /* consolidate forward */
{
sz += nextsz;
if (!islr && next->fd == last_remainder) /* re-insert last_remainder */
{
islr = 1;
link_last_remainder(p);
}
else
unlink(next, bck, fwd);
}
 
 
set_head(p, sz | PREV_INUSE);
set_foot(p, sz);
if (!islr)
frontlink(p, sz, idx, bck, fwd);
 
MALLOC_UNLOCK;
 
#endif /* MALLOC_PROVIDED */
}
 
#endif /* DEFINE_FREE */
#ifdef DEFINE_REALLOC
 
/*
 
Realloc algorithm:
 
Chunks that were obtained via mmap cannot be extended or shrunk
unless HAVE_MREMAP is defined, in which case mremap is used.
Otherwise, if their reallocation is for additional space, they are
copied. If for less, they are just left alone.
 
Otherwise, if the reallocation is for additional space, and the
chunk can be extended, it is, else a malloc-copy-free sequence is
taken. There are several different ways that a chunk could be
extended. All are tried:
 
* Extending forward into following adjacent free chunk.
* Shifting backwards, joining preceding adjacent space
* Both shifting backwards and extending forward.
* Extending into newly sbrked space
 
Unless the #define REALLOC_ZERO_BYTES_FREES is set, realloc with a
size argument of zero (re)allocates a minimum-sized chunk.
 
If the reallocation is for less space, and the new request is for
a `small' (<512 bytes) size, then the newly unused space is lopped
off and freed.
 
The old unix realloc convention of allowing the last-free'd chunk
to be used as an argument to realloc is no longer supported.
I don't know of any programs still relying on this feature,
and allowing it would also allow too many other incorrect
usages of realloc to be sensible.
 
 
*/
 
 
#if __STD_C
Void_t* rEALLOc(RARG Void_t* oldmem, size_t bytes)
#else
Void_t* rEALLOc(RARG oldmem, bytes) RDECL Void_t* oldmem; size_t bytes;
#endif
{
#ifdef MALLOC_PROVIDED
 
realloc (oldmem, bytes);
 
#else
 
INTERNAL_SIZE_T nb; /* padded request size */
 
mchunkptr oldp; /* chunk corresponding to oldmem */
INTERNAL_SIZE_T oldsize; /* its size */
 
mchunkptr newp; /* chunk to return */
INTERNAL_SIZE_T newsize; /* its size */
Void_t* newmem; /* corresponding user mem */
 
mchunkptr next; /* next contiguous chunk after oldp */
INTERNAL_SIZE_T nextsize; /* its size */
 
mchunkptr prev; /* previous contiguous chunk before oldp */
INTERNAL_SIZE_T prevsize; /* its size */
 
mchunkptr remainder; /* holds split off extra space from newp */
INTERNAL_SIZE_T remainder_size; /* its size */
 
mchunkptr bck; /* misc temp for linking */
mchunkptr fwd; /* misc temp for linking */
 
#ifdef REALLOC_ZERO_BYTES_FREES
if (bytes == 0) { fREe(RCALL oldmem); return 0; }
#endif
 
 
/* realloc of null is supposed to be same as malloc */
if (oldmem == 0) return mALLOc(RCALL bytes);
 
MALLOC_LOCK;
 
newp = oldp = mem2chunk(oldmem);
newsize = oldsize = chunksize(oldp);
 
 
nb = request2size(bytes);
 
#if HAVE_MMAP
if (chunk_is_mmapped(oldp))
{
#if HAVE_MREMAP
newp = mremap_chunk(oldp, nb);
if(newp)
{
MALLOC_UNLOCK;
return chunk2mem(newp);
}
#endif
/* Note the extra SIZE_SZ overhead. */
if(oldsize - SIZE_SZ >= nb)
{
MALLOC_UNLOCK;
return oldmem; /* do nothing */
}
/* Must alloc, copy, free. */
newmem = mALLOc(RCALL bytes);
if (newmem == 0)
{
MALLOC_UNLOCK;
return 0; /* propagate failure */
}
MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
munmap_chunk(oldp);
MALLOC_UNLOCK;
return newmem;
}
#endif
 
check_inuse_chunk(oldp);
 
if ((long)(oldsize) < (long)(nb))
{
 
/* Try expanding forward */
 
next = chunk_at_offset(oldp, oldsize);
if (next == top || !inuse(next))
{
nextsize = chunksize(next);
 
/* Forward into top only if a remainder */
if (next == top)
{
if ((long)(nextsize + newsize) >= (long)(nb + MINSIZE))
{
newsize += nextsize;
top = chunk_at_offset(oldp, nb);
set_head(top, (newsize - nb) | PREV_INUSE);
set_head_size(oldp, nb);
MALLOC_UNLOCK;
return chunk2mem(oldp);
}
}
 
/* Forward into next chunk */
else if (((long)(nextsize + newsize) >= (long)(nb)))
{
unlink(next, bck, fwd);
newsize += nextsize;
goto split;
}
}
else
{
next = 0;
nextsize = 0;
}
 
/* Try shifting backwards. */
 
if (!prev_inuse(oldp))
{
prev = prev_chunk(oldp);
prevsize = chunksize(prev);
 
/* try forward + backward first to save a later consolidation */
 
if (next != 0)
{
/* into top */
if (next == top)
{
if ((long)(nextsize + prevsize + newsize) >= (long)(nb + MINSIZE))
{
unlink(prev, bck, fwd);
newp = prev;
newsize += prevsize + nextsize;
newmem = chunk2mem(newp);
MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
top = chunk_at_offset(newp, nb);
set_head(top, (newsize - nb) | PREV_INUSE);
set_head_size(newp, nb);
MALLOC_UNLOCK;
return newmem;
}
}
 
/* into next chunk */
else if (((long)(nextsize + prevsize + newsize) >= (long)(nb)))
{
unlink(next, bck, fwd);
unlink(prev, bck, fwd);
newp = prev;
newsize += nextsize + prevsize;
newmem = chunk2mem(newp);
MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
goto split;
}
}
/* backward only */
if (prev != 0 && (long)(prevsize + newsize) >= (long)nb)
{
unlink(prev, bck, fwd);
newp = prev;
newsize += prevsize;
newmem = chunk2mem(newp);
MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
goto split;
}
}
 
/* Must allocate */
 
newmem = mALLOc (RCALL bytes);
 
if (newmem == 0) /* propagate failure */
{
MALLOC_UNLOCK;
return 0;
}
 
/* Avoid copy if newp is next chunk after oldp. */
/* (This can only happen when new chunk is sbrk'ed.) */
 
if ( (newp = mem2chunk(newmem)) == next_chunk(oldp))
{
newsize += chunksize(newp);
newp = oldp;
goto split;
}
 
/* Otherwise copy, free, and exit */
MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
fREe(RCALL oldmem);
MALLOC_UNLOCK;
return newmem;
}
 
 
split: /* split off extra room in old or expanded chunk */
 
remainder_size = long_sub_size_t(newsize, nb);
 
if (remainder_size >= (long)MINSIZE) /* split off remainder */
{
remainder = chunk_at_offset(newp, nb);
set_head_size(newp, nb);
set_head(remainder, remainder_size | PREV_INUSE);
set_inuse_bit_at_offset(remainder, remainder_size);
fREe(RCALL chunk2mem(remainder)); /* let free() deal with it */
}
else
{
set_head_size(newp, newsize);
set_inuse_bit_at_offset(newp, newsize);
}
 
check_inuse_chunk(newp);
MALLOC_UNLOCK;
return chunk2mem(newp);
 
#endif /* MALLOC_PROVIDED */
}
 
#endif /* DEFINE_REALLOC */
#ifdef DEFINE_MEMALIGN
 
/*
 
memalign algorithm:
 
memalign requests more than enough space from malloc, finds a spot
within that chunk that meets the alignment request, and then
possibly frees the leading and trailing space.
 
The alignment argument must be a power of two. This property is not
checked by memalign, so misuse may result in random runtime errors.
 
8-byte alignment is guaranteed by normal malloc calls, so don't
bother calling memalign with an argument of 8 or less.
 
Overreliance on memalign is a sure way to fragment space.
 
*/
 
 
#if __STD_C
Void_t* mEMALIGn(RARG size_t alignment, size_t bytes)
#else
Void_t* mEMALIGn(RARG alignment, bytes) RDECL size_t alignment; size_t bytes;
#endif
{
INTERNAL_SIZE_T nb; /* padded request size */
char* m; /* memory returned by malloc call */
mchunkptr p; /* corresponding chunk */
char* brk; /* alignment point within p */
mchunkptr newp; /* chunk to return */
INTERNAL_SIZE_T newsize; /* its size */
INTERNAL_SIZE_T leadsize; /* leading space befor alignment point */
mchunkptr remainder; /* spare room at end to split off */
long remainder_size; /* its size */
 
/* If need less alignment than we give anyway, just relay to malloc */
 
if (alignment <= MALLOC_ALIGNMENT) return mALLOc(RCALL bytes);
 
/* Otherwise, ensure that it is at least a minimum chunk size */
if (alignment < MINSIZE) alignment = MINSIZE;
 
/* Call malloc with worst case padding to hit alignment. */
 
nb = request2size(bytes);
m = (char*)(mALLOc(RCALL nb + alignment + MINSIZE));
 
if (m == 0) return 0; /* propagate failure */
 
MALLOC_LOCK;
 
p = mem2chunk(m);
 
if ((((unsigned long)(m)) % alignment) == 0) /* aligned */
{
#if HAVE_MMAP
if(chunk_is_mmapped(p))
{
MALLOC_UNLOCK;
return chunk2mem(p); /* nothing more to do */
}
#endif
}
else /* misaligned */
{
/*
Find an aligned spot inside chunk.
Since we need to give back leading space in a chunk of at
least MINSIZE, if the first calculation places us at
a spot with less than MINSIZE leader, we can move to the
next aligned spot -- we've allocated enough total room so that
this is always possible.
*/
 
brk = (char*)mem2chunk(((unsigned long)(m + alignment - 1)) & -alignment);
if ((long)(brk - (char*)(p)) < (long)MINSIZE) brk = brk + alignment;
 
newp = (mchunkptr)brk;
leadsize = brk - (char*)(p);
newsize = chunksize(p) - leadsize;
 
#if HAVE_MMAP
if(chunk_is_mmapped(p))
{
newp->prev_size = p->prev_size + leadsize;
set_head(newp, newsize|IS_MMAPPED);
MALLOC_UNLOCK;
return chunk2mem(newp);
}
#endif
 
/* give back leader, use the rest */
 
set_head(newp, newsize | PREV_INUSE);
set_inuse_bit_at_offset(newp, newsize);
set_head_size(p, leadsize);
fREe(RCALL chunk2mem(p));
p = newp;
 
assert (newsize >= nb && (((unsigned long)(chunk2mem(p))) % alignment) == 0);
}
 
/* Also give back spare room at the end */
 
remainder_size = long_sub_size_t(chunksize(p), nb);
 
if (remainder_size >= (long)MINSIZE)
{
remainder = chunk_at_offset(p, nb);
set_head(remainder, remainder_size | PREV_INUSE);
set_head_size(p, nb);
fREe(RCALL chunk2mem(remainder));
}
 
check_inuse_chunk(p);
MALLOC_UNLOCK;
return chunk2mem(p);
 
}
 
#endif /* DEFINE_MEMALIGN */
#ifdef DEFINE_VALLOC
 
/*
valloc just invokes memalign with alignment argument equal
to the page size of the system (or as near to this as can
be figured out from all the includes/defines above.)
*/
 
#if __STD_C
Void_t* vALLOc(RARG size_t bytes)
#else
Void_t* vALLOc(RARG bytes) RDECL size_t bytes;
#endif
{
return mEMALIGn (RCALL malloc_getpagesize, bytes);
}
 
#endif /* DEFINE_VALLOC */
 
#ifdef DEFINE_PVALLOC
 
/*
pvalloc just invokes valloc for the nearest pagesize
that will accommodate request
*/
 
 
#if __STD_C
Void_t* pvALLOc(RARG size_t bytes)
#else
Void_t* pvALLOc(RARG bytes) RDECL size_t bytes;
#endif
{
size_t pagesize = malloc_getpagesize;
return mEMALIGn (RCALL pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
}
 
#endif /* DEFINE_PVALLOC */
 
#ifdef DEFINE_CALLOC
 
/*
 
calloc calls malloc, then zeroes out the allocated chunk.
 
*/
 
#if __STD_C
Void_t* cALLOc(RARG size_t n, size_t elem_size)
#else
Void_t* cALLOc(RARG n, elem_size) RDECL size_t n; size_t elem_size;
#endif
{
mchunkptr p;
INTERNAL_SIZE_T csz;
 
INTERNAL_SIZE_T sz = n * elem_size;
 
#if MORECORE_CLEARS
mchunkptr oldtop;
INTERNAL_SIZE_T oldtopsize;
#endif
Void_t* mem;
 
/* check if expand_top called, in which case don't need to clear */
#if MORECORE_CLEARS
MALLOC_LOCK;
oldtop = top;
oldtopsize = chunksize(top);
#endif
 
mem = mALLOc (RCALL sz);
 
if (mem == 0)
{
#if MORECORE_CLEARS
MALLOC_UNLOCK;
#endif
return 0;
}
else
{
p = mem2chunk(mem);
 
/* Two optional cases in which clearing not necessary */
 
 
#if HAVE_MMAP
if (chunk_is_mmapped(p))
{
#if MORECORE_CLEARS
MALLOC_UNLOCK;
#endif
return mem;
}
#endif
 
csz = chunksize(p);
 
#if MORECORE_CLEARS
if (p == oldtop && csz > oldtopsize)
{
/* clear only the bytes from non-freshly-sbrked memory */
csz = oldtopsize;
}
MALLOC_UNLOCK;
#endif
 
MALLOC_ZERO(mem, csz - SIZE_SZ);
return mem;
}
}
 
#endif /* DEFINE_CALLOC */
 
#if defined(DEFINE_CFREE) && !defined(__CYGWIN__)
 
/*
cfree just calls free. It is needed/defined on some systems
that pair it with calloc, presumably for odd historical reasons.
 
*/
 
#if !defined(INTERNAL_LINUX_C_LIB) || !defined(__ELF__)
#if !defined(INTERNAL_NEWLIB) || !defined(_REENT_ONLY)
#if __STD_C
void cfree(Void_t *mem)
#else
void cfree(mem) Void_t *mem;
#endif
{
#ifdef INTERNAL_NEWLIB
fREe(_REENT, mem);
#else
fREe(mem);
#endif
}
#endif
#endif
 
#endif /* DEFINE_CFREE */
#ifdef DEFINE_FREE
 
/*
 
Malloc_trim gives memory back to the system (via negative
arguments to sbrk) if there is unused memory at the `high' end of
the malloc pool. You can call this after freeing large blocks of
memory to potentially reduce the system-level memory requirements
of a program. However, it cannot guarantee to reduce memory. Under
some allocation patterns, some large free blocks of memory will be
locked between two used chunks, so they cannot be given back to
the system.
 
The `pad' argument to malloc_trim represents the amount of free
trailing space to leave untrimmed. If this argument is zero,
only the minimum amount of memory to maintain internal data
structures will be left (one page or less). Non-zero arguments
can be supplied to maintain enough trailing space to service
future expected allocations without having to re-obtain memory
from the system.
 
Malloc_trim returns 1 if it actually released any memory, else 0.
 
*/
 
#if __STD_C
int malloc_trim(RARG size_t pad)
#else
int malloc_trim(RARG pad) RDECL size_t pad;
#endif
{
long top_size; /* Amount of top-most memory */
long extra; /* Amount to release */
char* current_brk; /* address returned by pre-check sbrk call */
char* new_brk; /* address returned by negative sbrk call */
 
unsigned long pagesz = malloc_getpagesize;
 
MALLOC_LOCK;
 
top_size = chunksize(top);
extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
 
if (extra < (long)pagesz) /* Not enough memory to release */
{
MALLOC_UNLOCK;
return 0;
}
 
else
{
/* Test to make sure no one else called sbrk */
current_brk = (char*)(MORECORE (0));
if (current_brk != (char*)(top) + top_size)
{
MALLOC_UNLOCK;
return 0; /* Apparently we don't own memory; must fail */
}
 
else
{
new_brk = (char*)(MORECORE (-extra));
if (new_brk == (char*)(MORECORE_FAILURE)) /* sbrk failed? */
{
/* Try to figure out what we have */
current_brk = (char*)(MORECORE (0));
top_size = current_brk - (char*)top;
if (top_size >= (long)MINSIZE) /* if not, we are very very dead! */
{
sbrked_mem = current_brk - sbrk_base;
set_head(top, top_size | PREV_INUSE);
}
check_chunk(top);
MALLOC_UNLOCK;
return 0;
}
 
else
{
/* Success. Adjust top accordingly. */
set_head(top, (top_size - extra) | PREV_INUSE);
sbrked_mem -= extra;
check_chunk(top);
MALLOC_UNLOCK;
return 1;
}
}
}
}
 
#endif /* DEFINE_FREE */
#ifdef DEFINE_MALLOC_USABLE_SIZE
 
/*
malloc_usable_size:
 
This routine tells you how many bytes you can actually use in an
allocated chunk, which may be more than you requested (although
often not). You can use this many bytes without worrying about
overwriting other allocated objects. Not a particularly great
programming practice, but still sometimes useful.
 
*/
 
#if __STD_C
size_t malloc_usable_size(RARG Void_t* mem)
#else
size_t malloc_usable_size(RARG mem) RDECL Void_t* mem;
#endif
{
mchunkptr p;
if (mem == 0)
return 0;
else
{
p = mem2chunk(mem);
if(!chunk_is_mmapped(p))
{
if (!inuse(p)) return 0;
#if DEBUG
MALLOC_LOCK;
check_inuse_chunk(p);
MALLOC_UNLOCK;
#endif
return chunksize(p) - SIZE_SZ;
}
return chunksize(p) - 2*SIZE_SZ;
}
}
 
#endif /* DEFINE_MALLOC_USABLE_SIZE */
#ifdef DEFINE_MALLINFO
 
/* Utility to update current_mallinfo for malloc_stats and mallinfo() */
 
STATIC void malloc_update_mallinfo()
{
int i;
mbinptr b;
mchunkptr p;
#if DEBUG
mchunkptr q;
#endif
 
INTERNAL_SIZE_T avail = chunksize(top);
int navail = ((long)(avail) >= (long)MINSIZE)? 1 : 0;
 
for (i = 1; i < NAV; ++i)
{
b = bin_at(i);
for (p = last(b); p != b; p = p->bk)
{
#if DEBUG
check_free_chunk(p);
for (q = next_chunk(p);
q < top && inuse(q) && (long)(chunksize(q)) >= (long)MINSIZE;
q = next_chunk(q))
check_inuse_chunk(q);
#endif
avail += chunksize(p);
navail++;
}
}
 
current_mallinfo.ordblks = navail;
current_mallinfo.uordblks = sbrked_mem - avail;
current_mallinfo.fordblks = avail;
#if HAVE_MMAP
current_mallinfo.hblks = n_mmaps;
current_mallinfo.hblkhd = mmapped_mem;
#endif
current_mallinfo.keepcost = chunksize(top);
 
}
 
#else /* ! DEFINE_MALLINFO */
 
#if __STD_C
extern void malloc_update_mallinfo(void);
#else
extern void malloc_update_mallinfo();
#endif
 
#endif /* ! DEFINE_MALLINFO */
#ifdef DEFINE_MALLOC_STATS
 
/*
 
malloc_stats:
 
Prints on stderr the amount of space obtain from the system (both
via sbrk and mmap), the maximum amount (which may be more than
current if malloc_trim and/or munmap got called), the maximum
number of simultaneous mmap regions used, and the current number
of bytes allocated via malloc (or realloc, etc) but not yet
freed. (Note that this is the number of bytes allocated, not the
number requested. It will be larger than the number requested
because of alignment and bookkeeping overhead.)
 
*/
 
#if __STD_C
void malloc_stats(RONEARG)
#else
void malloc_stats(RONEARG) RDECL
#endif
{
unsigned long local_max_total_mem;
int local_sbrked_mem;
struct mallinfo local_mallinfo;
#if HAVE_MMAP
unsigned long local_mmapped_mem, local_max_n_mmaps;
#endif
FILE *fp;
 
MALLOC_LOCK;
malloc_update_mallinfo();
local_max_total_mem = max_total_mem;
local_sbrked_mem = sbrked_mem;
local_mallinfo = current_mallinfo;
#if HAVE_MMAP
local_mmapped_mem = mmapped_mem;
local_max_n_mmaps = max_n_mmaps;
#endif
MALLOC_UNLOCK;
 
#ifdef INTERNAL_NEWLIB
fp = _stderr_r(reent_ptr);
#define fprintf fiprintf
#else
fp = stderr;
#endif
 
fprintf(fp, "max system bytes = %10u\n",
(unsigned int)(local_max_total_mem));
#if HAVE_MMAP
fprintf(fp, "system bytes = %10u\n",
(unsigned int)(local_sbrked_mem + local_mmapped_mem));
fprintf(fp, "in use bytes = %10u\n",
(unsigned int)(local_mallinfo.uordblks + local_mmapped_mem));
#else
fprintf(fp, "system bytes = %10u\n",
(unsigned int)local_sbrked_mem);
fprintf(fp, "in use bytes = %10u\n",
(unsigned int)local_mallinfo.uordblks);
#endif
#if HAVE_MMAP
fprintf(fp, "max mmap regions = %10u\n",
(unsigned int)local_max_n_mmaps);
#endif
}
 
#endif /* DEFINE_MALLOC_STATS */
 
#ifdef DEFINE_MALLINFO
 
/*
mallinfo returns a copy of updated current mallinfo.
*/
 
#if __STD_C
struct mallinfo mALLINFo(RONEARG)
#else
struct mallinfo mALLINFo(RONEARG) RDECL
#endif
{
struct mallinfo ret;
 
MALLOC_LOCK;
malloc_update_mallinfo();
ret = current_mallinfo;
MALLOC_UNLOCK;
return ret;
}
 
#endif /* DEFINE_MALLINFO */
#ifdef DEFINE_MALLOPT
 
/*
mallopt:
 
mallopt is the general SVID/XPG interface to tunable parameters.
The format is to provide a (parameter-number, parameter-value) pair.
mallopt then sets the corresponding parameter to the argument
value if it can (i.e., so long as the value is meaningful),
and returns 1 if successful else 0.
 
See descriptions of tunable parameters above.
 
*/
 
#if __STD_C
int mALLOPt(RARG int param_number, int value)
#else
int mALLOPt(RARG param_number, value) RDECL int param_number; int value;
#endif
{
MALLOC_LOCK;
switch(param_number)
{
case M_TRIM_THRESHOLD:
trim_threshold = value; MALLOC_UNLOCK; return 1;
case M_TOP_PAD:
top_pad = value; MALLOC_UNLOCK; return 1;
case M_MMAP_THRESHOLD:
#if HAVE_MMAP
mmap_threshold = value;
#endif
MALLOC_UNLOCK;
return 1;
case M_MMAP_MAX:
#if HAVE_MMAP
n_mmaps_max = value; MALLOC_UNLOCK; return 1;
#else
MALLOC_UNLOCK; return value == 0;
#endif
 
default:
MALLOC_UNLOCK;
return 0;
}
}
 
#endif /* DEFINE_MALLOPT */
 
/*
 
History:
 
V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
* Added pvalloc, as recommended by H.J. Liu
* Added 64bit pointer support mainly from Wolfram Gloger
* Added anonymously donated WIN32 sbrk emulation
* Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
* malloc_extend_top: fix mask error that caused wastage after
foreign sbrks
* Add linux mremap support code from HJ Liu
V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
* Integrated most documentation with the code.
* Add support for mmap, with help from
Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
* Use last_remainder in more cases.
* Pack bins using idea from colin@nyx10.cs.du.edu
* Use ordered bins instead of best-fit threshhold
* Eliminate block-local decls to simplify tracing and debugging.
* Support another case of realloc via move into top
* Fix error occuring when initial sbrk_base not word-aligned.
* Rely on page size for units instead of SBRK_UNIT to
avoid surprises about sbrk alignment conventions.
* Add mallinfo, mallopt. Thanks to Raymond Nijssen
(raymond@es.ele.tue.nl) for the suggestion.
* Add `pad' argument to malloc_trim and top_pad mallopt parameter.
* More precautions for cases where other routines call sbrk,
courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
* Added macros etc., allowing use in linux libc from
H.J. Lu (hjl@gnu.ai.mit.edu)
* Inverted this history list
 
V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
* Re-tuned and fixed to behave more nicely with V2.6.0 changes.
* Removed all preallocation code since under current scheme
the work required to undo bad preallocations exceeds
the work saved in good cases for most test programs.
* No longer use return list or unconsolidated bins since
no scheme using them consistently outperforms those that don't
given above changes.
* Use best fit for very large chunks to prevent some worst-cases.
* Added some support for debugging
 
V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
* Removed footers when chunks are in use. Thanks to
Paul Wilson (wilson@cs.texas.edu) for the suggestion.
 
V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
* Added malloc_trim, with help from Wolfram Gloger
(wmglo@Dent.MED.Uni-Muenchen.DE).
 
V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
 
V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
* realloc: try to expand in both directions
* malloc: swap order of clean-bin strategy;
* realloc: only conditionally expand backwards
* Try not to scavenge used bins
* Use bin counts as a guide to preallocation
* Occasionally bin return list chunks in first scan
* Add a few optimizations from colin@nyx10.cs.du.edu
 
V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
* faster bin computation & slightly different binning
* merged all consolidations to one part of malloc proper
(eliminating old malloc_find_space & malloc_clean_bin)
* Scan 2 returns chunks (not just 1)
* Propagate failure in realloc if malloc returns 0
* Add stuff to allow compilation on non-ANSI compilers
from kpv@research.att.com
V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
* removed potential for odd address access in prev_chunk
* removed dependency on getpagesize.h
* misc cosmetics and a bit more internal documentation
* anticosmetics: mangled names in macros to evade debugger strangeness
* tested on sparc, hp-700, dec-mips, rs6000
with gcc & native cc (hp, dec only) allowing
Detlefs & Zorn comparison study (in SIGPLAN Notices.)
 
Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
* Based loosely on libg++-1.2X malloc. (It retains some of the overall
structure of old version, but most details differ.)
 
*/
#endif
/atof.c
0,0 → 1,72
/*
FUNCTION
<<atof>>, <<atoff>>---string to double or float
 
INDEX
atof
INDEX
atoff
 
ANSI_SYNOPSIS
#include <stdlib.h>
double atof(const char *<[s]>);
float atoff(const char *<[s]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
double atof(<[s]>)
char *<[s]>;
 
float atoff(<[s]>)
char *<[s]>;
 
DESCRIPTION
<<atof>> converts the initial portion of a string to a <<double>>.
<<atoff>> converts the initial portion of a string to a <<float>>.
 
The functions parse the character string <[s]>,
locating a substring which can be converted to a floating point
value. The substring must match the format:
. [+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>]
The substring converted is the longest initial
fragment of <[s]> that has the expected format, beginning with
the first non-whitespace character. The substring
is empty if <<str>> is empty, consists entirely
of whitespace, or if the first non-whitespace character is
something other than <<+>>, <<->>, <<.>>, or a digit.
 
<<atof(<[s]>)>> is implemented as <<strtod(<[s]>, NULL)>>.
<<atoff(<[s]>)>> is implemented as <<strtodf(<[s]>, NULL)>>.
 
RETURNS
<<atof>> returns the converted substring value, if any, as a
<<double>>; or <<0.0>>, if no conversion could be performed.
If the correct value is out of the range of representable values, plus
or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is stored in
<<errno>>.
If the correct value would cause underflow, <<0.0>> is returned
and <<ERANGE>> is stored in <<errno>>.
 
<<atoff>> obeys the same rules as <<atof>>, except that it
returns a <<float>>.
 
PORTABILITY
<<atof>> is ANSI C. <<atof>>, <<atoi>>, and <<atol>> are subsumed by <<strod>>
and <<strol>>, but are used extensively in existing code. These functions are
less reliable, but may be faster if the argument is verified to be in a valid
range.
 
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
 
 
#include <stdlib.h>
#include <_ansi.h>
 
double
_DEFUN (atof, (s),
_CONST char *s)
{
return strtod (s, NULL);
}
/mblen.c
0,0 → 1,66
/*
FUNCTION
<<mblen>>---minimal multibyte length function
 
INDEX
mblen
 
ANSI_SYNOPSIS
#include <stdlib.h>
int mblen(const char *<[s]>, size_t <[n]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int mblen(<[s]>, <[n]>)
const char *<[s]>;
size_t <[n]>;
 
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<mblen>>. In this case, the
only ``multi-byte character sequences'' recognized are single bytes,
and thus <<1>> is returned unless <[s]> is the null pointer or
has a length of 0 or is the empty string.
 
When MB_CAPABLE is defined, this routine calls <<_mbtowc_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
 
RETURNS
This implementation of <<mblen>> returns <<0>> if
<[s]> is <<NULL>> or the empty string; it returns <<1>> if not MB_CAPABLE or
the character is a single-byte character; it returns <<-1>>
if the multi-byte character is invalid; otherwise it returns
the number of bytes in the multibyte character.
 
PORTABILITY
<<mblen>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
 
<<mblen>> requires no supporting OS subroutines.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
 
int
_DEFUN (mblen, (s, n),
const char *s _AND
size_t n)
{
#ifdef MB_CAPABLE
static int state;
 
return _mbtowc_r (_REENT, NULL, s, n, &state);
#else /* not MB_CAPABLE */
if (s == NULL || *s == '\0')
return 0;
if (n == 0)
return -1;
return 1;
#endif /* not MB_CAPABLE */
}
 
#endif /* !_REENT_ONLY */
/atexit.c
0,0 → 1,80
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* %sccs.include.redist.c%
*/
 
/*
FUNCTION
<<atexit>>---request execution of functions at program exit
 
INDEX
atexit
 
ANSI_SYNOPSIS
#include <stdlib.h>
int atexit (void (*<[function]>)(void));
 
TRAD_SYNOPSIS
#include <stdlib.h>
int atexit ((<[function]>)
void (*<[function]>)();
 
DESCRIPTION
You can use <<atexit>> to enroll functions in a list of functions that
will be called when your program terminates normally. The argument is
a pointer to a user-defined function (which must not require arguments and
must not return a result).
 
The functions are kept in a LIFO stack; that is, the last function
enrolled by <<atexit>> will be the first to execute when your program
exits.
 
There is no built-in limit to the number of functions you can enroll
in this list; however, after every group of 32 functions is enrolled,
<<atexit>> will call <<malloc>> to get space for the next part of the
list. The initial list of 32 functions is statically allocated, so
you can always count on at least that many slots available.
 
RETURNS
<<atexit>> returns <<0>> if it succeeds in enrolling your function,
<<-1>> if it fails (possible only if no space was available for
<<malloc>> to extend the list of functions).
 
PORTABILITY
<<atexit>> is required by the ANSI standard, which also specifies that
implementations must support enrolling at least 32 functions.
 
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
 
#include <stddef.h>
#include <stdlib.h>
#include <reent.h>
 
/*
* Register a function to be performed at exit.
*/
 
int
_DEFUN (atexit,
(fn),
_VOID _EXFUN ((*fn), (_VOID)))
{
register struct _atexit *p;
 
if ((p = _REENT->_atexit) == NULL)
_REENT->_atexit = p = &_REENT->_atexit0;
if (p->_ind >= _ATEXIT_SIZE)
{
if ((p = (struct _atexit *) malloc (sizeof *p)) == NULL)
return -1;
p->_ind = 0;
p->_next = _REENT->_atexit;
_REENT->_atexit = p;
}
p->_fns[p->_ind++] = fn;
return 0;
}
/ecvtbuf.c
0,0 → 1,469
/*
FUNCTION
<<ecvtbuf>>, <<fcvtbuf>>---double or float to string
 
INDEX
ecvtbuf
INDEX
fcvtbuf
 
ANSI_SYNOPSIS
#include <stdio.h>
 
char *ecvtbuf(double <[val]>, int <[chars]>, int *<[decpt]>,
int *<[sgn]>, char *<[buf]>);
 
char *fcvtbuf(double <[val]>, int <[decimals]>, int *<[decpt]>,
int *<[sgn]>, char *<[buf]>);
 
TRAD_SYNOPSIS
#include <stdio.h>
 
char *ecvtbuf(<[val]>, <[chars]>, <[decpt]>, <[sgn]>, <[buf]>);
double <[val]>;
int <[chars]>;
int *<[decpt]>;
int *<[sgn]>;
char *<[buf]>;
 
char *fcvtbuf(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>, <[buf]>);
double <[val]>;
int <[decimals]>;
int *<[decpt]>;
int *<[sgn]>;
char *<[buf]>;
 
DESCRIPTION
<<ecvtbuf>> and <<fcvtbuf>> produce (null-terminated) strings
of digits representating the <<double>> number <[val]>.
 
The only difference between <<ecvtbuf>> and <<fcvtbuf>> is the
interpretation of the second argument (<[chars]> or
<[decimals]>). For <<ecvtbuf>>, the second argument <[chars]>
specifies the total number of characters to write (which is
also the number of significant digits in the formatted string,
since these two functions write only digits). For <<fcvtbuf>>,
the second argument <[decimals]> specifies the number of
characters to write after the decimal point; all digits for
the integer part of <[val]> are always included.
 
Since <<ecvtbuf>> and <<fcvtbuf>> write only digits in the
output string, they record the location of the decimal point
in <<*<[decpt]>>>, and the sign of the number in <<*<[sgn]>>>.
After formatting a number, <<*<[decpt]>>> contains the number
of digits to the left of the decimal point. <<*<[sgn]>>>
contains <<0>> if the number is positive, and <<1>> if it is
negative. For both functions, you supply a pointer <[buf]> to
an area of memory to hold the converted string.
 
RETURNS
Both functions return a pointer to <[buf]>, the string
containing a character representation of <[val]>.
 
PORTABILITY
Neither function is ANSI C.
 
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
 
#include <_ansi.h>
#include <stdlib.h>
#include <string.h>
#include <reent.h>
#include "mprec.h"
#include "local.h"
 
static void
_DEFUN (print_f, (ptr, buf, invalue, ndigit, type, dot, mode),
struct _reent *ptr _AND
char *buf _AND
double invalue _AND
int ndigit _AND
char type _AND
int dot _AND
int mode)
{
int decpt;
int sign;
char *p, *start, *end;
 
start = p = _dtoa_r (ptr, invalue, mode, ndigit, &decpt, &sign, &end);
 
if (decpt == 9999)
{
strcpy (buf, p);
return;
}
while (*p && decpt > 0)
{
*buf++ = *p++;
decpt--;
}
/* Even if not in buffer */
while (decpt > 0)
{
*buf++ = '0';
decpt--;
}
 
if (dot || *p)
{
if (p == start)
*buf++ = '0';
*buf++ = '.';
while (decpt < 0 && ndigit > 0)
{
*buf++ = '0';
decpt++;
ndigit--;
}
 
/* Print rest of stuff */
while (*p && ndigit > 0)
{
*buf++ = *p++;
ndigit--;
}
/* And trailing zeros */
while (ndigit > 0)
{
*buf++ = '0';
ndigit--;
}
}
*buf++ = 0;
}
 
/* Print number in e format with width chars after.
 
TYPE is one of 'e' or 'E'. It may also be one of 'g' or 'G' indicating
that _gcvt is calling us and we should remove trailing zeroes.
 
WIDTH is the number of digits of precision after the decimal point. */
 
static void
_DEFUN (print_e, (ptr, buf, invalue, width, type, dot),
struct _reent *ptr _AND
char *buf _AND
double invalue _AND
int width _AND
char type _AND
int dot)
{
int sign;
char *end;
char *p;
int decpt;
int top;
int ndigit = width;
 
p = _dtoa_r (ptr, invalue, 2, width + 1, &decpt, &sign, &end);
 
if (decpt == 9999)
{
strcpy (buf, p);
return;
}
 
*buf++ = *p++;
if (dot || ndigit != 0)
*buf++ = '.';
 
while (*p && ndigit > 0)
{
*buf++ = *p++;
ndigit--;
}
 
/* Add trailing zeroes to fill out to ndigits unless this is 'g' format.
Also, convert g/G to e/E. */
 
if (type == 'g')
type = 'e';
else if (type == 'G')
type = 'E';
else
{
while (ndigit > 0)
{
*buf++ = '0';
ndigit--;
}
}
 
/* Add the exponent. */
 
*buf++ = type;
decpt--;
if (decpt < 0)
{
*buf++ = '-';
decpt = -decpt;
}
else
{
*buf++ = '+';
}
if (decpt > 99)
{
int top = decpt / 100;
*buf++ = top + '0';
decpt -= top * 100;
}
top = decpt / 10;
*buf++ = top + '0';
decpt -= top * 10;
*buf++ = decpt + '0';
 
*buf++ = 0;
}
 
#ifndef _REENT_ONLY
 
/* Undocumented behaviour: when given NULL as a buffer, return a
pointer to static space in the rent structure. This is only to
support ecvt and fcvt, which aren't ANSI anyway. */
 
char *
_DEFUN (fcvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
double invalue _AND
int ndigit _AND
int *decpt _AND
int *sign _AND
char *fcvt_buf)
{
char *save;
char *p;
char *end;
int done = 0;
 
if (fcvt_buf == NULL)
{
if (_REENT->_cvtlen <= ndigit + 35)
{
if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
ndigit + 36)) == NULL)
return NULL;
_REENT->_cvtlen = ndigit + 36;
_REENT->_cvtbuf = fcvt_buf;
}
 
fcvt_buf = _REENT->_cvtbuf ;
}
 
save = fcvt_buf;
 
if (invalue < 1.0 && invalue > -1.0)
{
p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
}
else
{
p = _dtoa_r (_REENT, invalue, 3, ndigit, decpt, sign, &end);
}
 
/* Now copy */
 
done = -*decpt;
while (p < end)
{
*fcvt_buf++ = *p++;
done++;
}
/* And unsuppress the trailing zeroes */
while (done < ndigit)
{
*fcvt_buf++ = '0';
done++;
}
*fcvt_buf++ = 0;
return save;
}
 
char *
_DEFUN (ecvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
double invalue _AND
int ndigit _AND
int *decpt _AND
int *sign _AND
char *fcvt_buf)
{
char *save;
char *p;
char *end;
int done = 0;
 
if (fcvt_buf == NULL)
{
if (_REENT->_cvtlen <= ndigit)
{
if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
ndigit + 1)) == NULL)
return NULL;
_REENT->_cvtlen = ndigit + 1;
_REENT->_cvtbuf = fcvt_buf;
}
 
fcvt_buf = _REENT->_cvtbuf ;
}
 
save = fcvt_buf;
 
p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
 
/* Now copy */
 
while (p < end)
{
*fcvt_buf++ = *p++;
done++;
}
/* And unsuppress the trailing zeroes */
while (done < ndigit)
{
*fcvt_buf++ = '0';
done++;
}
*fcvt_buf++ = 0;
return save;
}
 
#endif
 
char *
_DEFUN (_gcvt, (ptr, invalue, ndigit, buf, type, dot),
struct _reent *ptr _AND
double invalue _AND
int ndigit _AND
char *buf _AND
char type _AND
int dot)
{
char *save = buf;
 
if (invalue < 0)
{
invalue = -invalue;
}
 
if (invalue == 0)
{
*buf++ = '0';
*buf = '\0';
}
else
/* Which one to print ?
ANSI says that anything with more that 4 zeros after the . or more
than precision digits before is printed in e with the qualification
that trailing zeroes are removed from the fraction portion. */
 
if (0.0001 >= invalue || invalue >= _mprec_log10 (ndigit))
{
/* We subtract 1 from ndigit because in the 'e' format the precision is
the number of digits after the . but in 'g' format it is the number
of significant digits.
 
We defer changing type to e/E so that print_e() can know it's us
calling and thus should remove trailing zeroes. */
 
print_e (ptr, buf, invalue, ndigit - 1, type, dot);
}
else
{
int decpt;
int sign;
char *end;
char *p;
 
if (invalue < 1.0)
{
/* what we want is ndigits after the point */
p = _dtoa_r (ptr, invalue, 3, ndigit, &decpt, &sign, &end);
}
else
{
p = _dtoa_r (ptr, invalue, 2, ndigit, &decpt, &sign, &end);
}
 
if (decpt == 9999)
{
strcpy (buf, p);
return save;
}
while (*p && decpt > 0)
{
*buf++ = *p++;
decpt--;
ndigit--;
}
/* Even if not in buffer */
while (decpt > 0 && ndigit > 0)
{
*buf++ = '0';
decpt--;
ndigit--;
}
 
if (dot || *p)
{
if (buf == save)
*buf++ = '0';
*buf++ = '.';
while (decpt < 0 && ndigit > 0)
{
*buf++ = '0';
decpt++;
ndigit--;
}
 
/* Print rest of stuff */
while (*p && ndigit > 0)
{
*buf++ = *p++;
ndigit--;
}
/* And trailing zeros */
if (dot)
{
while (ndigit > 0)
{
*buf++ = '0';
ndigit--;
}
}
}
*buf++ = 0;
}
 
return save;
}
 
char *
_DEFUN (_dcvt, (ptr, buffer, invalue, precision, width, type, dot),
struct _reent *ptr _AND
char *buffer _AND
double invalue _AND
int precision _AND
int width _AND
char type _AND
int dot)
{
switch (type)
{
case 'f':
case 'F':
print_f (ptr, buffer, invalue, precision, type, precision == 0 ? dot : 1, 3);
break;
case 'g':
case 'G':
if (precision == 0)
precision = 1;
_gcvt (ptr, invalue, precision, buffer, type, dot);
break;
case 'e':
case 'E':
print_e (ptr, buffer, invalue, precision, type, dot);
}
return buffer;
}
/atol.c
0,0 → 1,12
/*
* Andy Wilson, 2-Oct-89.
*/
 
#include <stdlib.h>
#include <_ansi.h>
 
long
_DEFUN (atol, (s), _CONST char *s)
{
return strtol (s, NULL, 10);
}
/mbstowcs.c
0,0 → 1,80
/*
FUNCTION
<<mbstowcs>>---minimal multibyte string to wide char converter
 
INDEX
mbstowcs
 
ANSI_SYNOPSIS
#include <stdlib.h>
int mbstowcs(wchar_t *<[pwc]>, const char *<[s]>, size_t <[n]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int mbstowcs(<[pwc]>, <[s]>, <[n]>)
wchar_t *<[pwc]>;
const char *<[s]>;
size_t <[n]>;
 
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<mbstowcs>>. In this case, the
only ``multi-byte character sequences'' recognized are single bytes,
and they are ``converted'' to wide-char versions simply by byte
extension.
 
When MB_CAPABLE is defined, this routine calls <<_mbstowcs_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
 
RETURNS
This implementation of <<mbstowcs>> returns <<0>> if
<[s]> is <<NULL>> or is the empty string;
it returns <<-1>> if MB_CAPABLE and one of the
multi-byte characters is invalid or incomplete;
otherwise it returns the minimum of: <<n>> or the
number of multi-byte characters in <<s>> plus 1 (to
compensate for the nul character).
If the return value is -1, the state of the <<pwc>> string is
indeterminate. If the input has a length of 0, the output
string will be modified to contain a wchar_t nul terminator.
 
PORTABILITY
<<mbstowcs>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
 
<<mbstowcs>> requires no supporting OS subroutines.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
 
size_t
_DEFUN (mbstowcs, (pwcs, s, n),
wchar_t *pwcs _AND
const char *s _AND
size_t n)
{
#ifdef MB_CAPABLE
int state = 0;
 
return _mbstowcs_r (_REENT, pwcs, s, n, &state);
#else /* not MB_CAPABLE */
 
int count = 0;
 
if (n != 0) {
do {
if ((*pwcs++ = (wchar_t) *s++) == 0)
break;
count++;
} while (--n != 0);
}
 
return count;
#endif /* not MB_CAPABLE */
}
 
#endif /* !_REENT_ONLY */
/getopt.c
0,0 → 1,117
/*
* Copyright (c) 1987, 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[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */
static char *rcsid = "$Id: getopt.c,v 1.1 2002-08-23 22:31:29 ivang Exp $";
#endif /* LIBC_SCCS and not lint */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
 
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
 
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
 
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-') { /* found "--" */
++optind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", nargv[0], optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
nargv[0], optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
}
/ldtoa.c
0,0 → 1,3720
 
/* Extended precision arithmetic functions for long double I/O.
* This program has been placed in the public domain.
*/
 
#include <_ansi.h>
#include <reent.h>
#include <string.h>
#include <stdlib.h>
#include "mprec.h"
 
/* These are the externally visible entries. */
/* linux name: long double _IO_strtold (char *, char **); */
long double _strtold (char *, char **);
char * _ldtoa_r (struct _reent *, long double, int, int, int *, int *, char **);
int _ldcheck (long double *);
#if 0
void _IO_ldtostr(long double *, char *, int, int, char);
#endif
 
/* Number of 16 bit words in external x type format */
#define NE 10
 
/* Number of 16 bit words in internal format */
#define NI (NE+3)
 
/* Array offset to exponent */
#define E 1
 
/* Array offset to high guard word */
#define M 2
 
/* Number of bits of precision */
#define NBITS ((NI-4)*16)
 
/* Maximum number of decimal digits in ASCII conversion
* = NBITS*log10(2)
*/
#define NDEC (NBITS*8/27)
 
/* The exponent of 1.0 */
#define EXONE (0x3fff)
 
/* Control structure for long doublue conversion including rounding precision values.
* rndprc can be set to 80 (if NE=6), 64, 56, 53, or 24 bits.
*/
typedef struct
{
int rlast;
int rndprc;
int rw;
int re;
int outexpon;
unsigned short rmsk;
unsigned short rmbit;
unsigned short rebit;
unsigned short rbit[NI];
unsigned short equot[NI];
} LDPARMS;
 
static void esub(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static void emul(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static void ediv(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static int ecmp(short unsigned int *a, short unsigned int *b);
static int enormlz(short unsigned int *x);
static int eshift(short unsigned int *x, int sc);
static void eshup1(register short unsigned int *x);
static void eshup8(register short unsigned int *x);
static void eshup6(register short unsigned int *x);
static void eshdn1(register short unsigned int *x);
static void eshdn8(register short unsigned int *x);
static void eshdn6(register short unsigned int *x);
static void eneg(short unsigned int *x);
static void emov(register short unsigned int *a, register short unsigned int *b);
static void eclear(register short unsigned int *x);
static void einfin(register short unsigned int *x, register LDPARMS *ldp);
static void efloor(short unsigned int *x, short unsigned int *y, LDPARMS *ldp);
static void etoasc(short unsigned int *x, char *string, int ndigs, int outformat, LDPARMS *ldp);
 
#if LDBL_MANT_DIG == 24
static void e24toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
#elif LDBL_MANT_DIG == 53
static void e53toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
#elif LDBL_MANT_DIG == 64
static void e64toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
#else
static void e113toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
#endif
 
/* econst.c */
/* e type constants used by high precision check routines */
 
#if NE == 10
/* 0.0 */
static unsigned short ezero[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
 
/* 1.0E0 */
static unsigned short eone[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
 
#else
 
/* 0.0 */
static unsigned short ezero[NE] = {
0, 0000000,0000000,0000000,0000000,0000000,};
/* 1.0E0 */
static unsigned short eone[NE] = {
0, 0000000,0000000,0000000,0100000,0x3fff,};
 
#endif
 
/* Debugging routine for displaying errors */
#ifdef DEBUG
/* Notice: the order of appearance of the following
* messages is bound to the error codes defined
* in mconf.h.
*/
static char *ermsg[7] = {
"unknown", /* error code 0 */
"domain", /* error code 1 */
"singularity", /* et seq. */
"overflow",
"underflow",
"total loss of precision",
"partial loss of precision"
};
#define mtherr(name, code) printf( "\n%s %s error\n", name, ermsg[code] );
#else
#define mtherr(name, code)
#endif
 
/* ieee.c
*
* Extended precision IEEE binary floating point arithmetic routines
*
* Numbers are stored in C language as arrays of 16-bit unsigned
* short integers. The arguments of the routines are pointers to
* the arrays.
*
*
* External e type data structure, simulates Intel 8087 chip
* temporary real format but possibly with a larger significand:
*
* NE-1 significand words (least significant word first,
* most significant bit is normally set)
* exponent (value = EXONE for 1.0,
* top bit is the sign)
*
*
* Internal data structure of a number (a "word" is 16 bits):
*
* ei[0] sign word (0 for positive, 0xffff for negative)
* ei[1] biased exponent (value = EXONE for the number 1.0)
* ei[2] high guard word (always zero after normalization)
* ei[3]
* to ei[NI-2] significand (NI-4 significand words,
* most significant word first,
* most significant bit is set)
* ei[NI-1] low guard word (0x8000 bit is rounding place)
*
*
*
* Routines for external format numbers
*
* asctoe( string, e ) ASCII string to extended double e type
* asctoe64( string, &d ) ASCII string to long double
* asctoe53( string, &d ) ASCII string to double
* asctoe24( string, &f ) ASCII string to single
* asctoeg( string, e, prec, ldp ) ASCII string to specified precision
* e24toe( &f, e, ldp ) IEEE single precision to e type
* e53toe( &d, e, ldp ) IEEE double precision to e type
* e64toe( &d, e, ldp ) IEEE long double precision to e type
* e113toe( &d, e, ldp ) IEEE long double precision to e type
* eabs(e) absolute value
* eadd( a, b, c ) c = b + a
* eclear(e) e = 0
* ecmp (a, b) Returns 1 if a > b, 0 if a == b,
* -1 if a < b, -2 if either a or b is a NaN.
* ediv( a, b, c, ldp ) c = b / a
* efloor( a, b, ldp ) truncate to integer, toward -infinity
* efrexp( a, exp, s ) extract exponent and significand
* eifrac( e, &l, frac ) e to long integer and e type fraction
* euifrac( e, &l, frac ) e to unsigned long integer and e type fraction
* einfin( e, ldp ) set e to infinity, leaving its sign alone
* eldexp( a, n, b ) multiply by 2**n
* emov( a, b ) b = a
* emul( a, b, c, ldp ) c = b * a
* eneg(e) e = -e
* eround( a, b ) b = nearest integer value to a
* esub( a, b, c, ldp ) c = b - a
* e24toasc( &f, str, n ) single to ASCII string, n digits after decimal
* e53toasc( &d, str, n ) double to ASCII string, n digits after decimal
* e64toasc( &d, str, n ) long double to ASCII string
* etoasc(e,str,n,fmt,ldp)e to ASCII string, n digits after decimal
* etoe24( e, &f ) convert e type to IEEE single precision
* etoe53( e, &d ) convert e type to IEEE double precision
* etoe64( e, &d ) convert e type to IEEE long double precision
* ltoe( &l, e ) long (32 bit) integer to e type
* ultoe( &l, e ) unsigned long (32 bit) integer to e type
* eisneg( e ) 1 if sign bit of e != 0, else 0
* eisinf( e ) 1 if e has maximum exponent (non-IEEE)
* or is infinite (IEEE)
* eisnan( e ) 1 if e is a NaN
* esqrt( a, b ) b = square root of a
*
*
* Routines for internal format numbers
*
* eaddm( ai, bi ) add significands, bi = bi + ai
* ecleaz(ei) ei = 0
* ecleazs(ei) set ei = 0 but leave its sign alone
* ecmpm( ai, bi ) compare significands, return 1, 0, or -1
* edivm( ai, bi, ldp ) divide significands, bi = bi / ai
* emdnorm(ai,l,s,exp,ldp) normalize and round off
* emovi( a, ai ) convert external a to internal ai
* emovo( ai, a, ldp ) convert internal ai to external a
* emovz( ai, bi ) bi = ai, low guard word of bi = 0
* emulm( ai, bi, ldp ) multiply significands, bi = bi * ai
* enormlz(ei) left-justify the significand
* eshdn1( ai ) shift significand and guards down 1 bit
* eshdn8( ai ) shift down 8 bits
* eshdn6( ai ) shift down 16 bits
* eshift( ai, n ) shift ai n bits up (or down if n < 0)
* eshup1( ai ) shift significand and guards up 1 bit
* eshup8( ai ) shift up 8 bits
* eshup6( ai ) shift up 16 bits
* esubm( ai, bi ) subtract significands, bi = bi - ai
*
*
* The result is always normalized and rounded to NI-4 word precision
* after each arithmetic operation.
*
* Exception flags are NOT fully supported.
*
* Define INFINITY in mconf.h for support of infinity; otherwise a
* saturation arithmetic is implemented.
*
* Define NANS for support of Not-a-Number items; otherwise the
* arithmetic will never produce a NaN output, and might be confused
* by a NaN input.
* If NaN's are supported, the output of ecmp(a,b) is -2 if
* either a or b is a NaN. This means asking if(ecmp(a,b) < 0)
* may not be legitimate. Use if(ecmp(a,b) == -1) for less-than
* if in doubt.
* Signaling NaN's are NOT supported; they are treated the same
* as quiet NaN's.
*
* Denormals are always supported here where appropriate (e.g., not
* for conversion to DEC numbers).
*/
 
/*
* Revision history:
*
* 5 Jan 84 PDP-11 assembly language version
* 6 Dec 86 C language version
* 30 Aug 88 100 digit version, improved rounding
* 15 May 92 80-bit long double support
* 22 Nov 00 Revised to fit into newlib by Jeff Johnston <jjohnstn@redhat.com>
*
* Author: S. L. Moshier.
*
* Copyright (c) 1984,2000 S.L. Moshier
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION
* OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
* SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
*/
 
#include <stdio.h>
/* #include "\usr\include\stdio.h" */
/*#include "ehead.h"*/
/*#include "mconf.h"*/
/* mconf.h
*
* Common include file for math routines
*
*
*
* SYNOPSIS:
*
* #include "mconf.h"
*
*
*
* DESCRIPTION:
*
* This file contains definitions for error codes that are
* passed to the common error handling routine mtherr()
* (which see).
*
* The file also includes a conditional assembly definition
* for the type of computer arithmetic (IEEE, DEC, Motorola
* IEEE, or UNKnown).
*
* For Digital Equipment PDP-11 and VAX computers, certain
* IBM systems, and others that use numbers with a 56-bit
* significand, the symbol DEC should be defined. In this
* mode, most floating point constants are given as arrays
* of octal integers to eliminate decimal to binary conversion
* errors that might be introduced by the compiler.
*
* For computers, such as IBM PC, that follow the IEEE
* Standard for Binary Floating Point Arithmetic (ANSI/IEEE
* Std 754-1985), the symbol IBMPC should be defined. These
* numbers have 53-bit significands. In this mode, constants
* are provided as arrays of hexadecimal 16 bit integers.
*
* To accommodate other types of computer arithmetic, all
* constants are also provided in a normal decimal radix
* which one can hope are correctly converted to a suitable
* format by the available C language compiler. To invoke
* this mode, the symbol UNK is defined.
*
* An important difference among these modes is a predefined
* set of machine arithmetic constants for each. The numbers
* MACHEP (the machine roundoff error), MAXNUM (largest number
* represented), and several other parameters are preset by
* the configuration symbol. Check the file const.c to
* ensure that these values are correct for your computer.
*
* For ANSI C compatibility, define ANSIC equal to 1. Currently
* this affects only the atan2() function and others that use it.
*/
 
/* Constant definitions for math error conditions
*/
 
#define DOMAIN 1 /* argument domain error */
#define SING 2 /* argument singularity */
#define OVERFLOW 3 /* overflow range error */
#define UNDERFLOW 4 /* underflow range error */
#define TLOSS 5 /* total loss of precision */
#define PLOSS 6 /* partial loss of precision */
 
#define EDOM 33
#define ERANGE 34
 
typedef struct
{
double r;
double i;
}cmplx;
 
/* Type of computer arithmetic */
 
#ifndef DEC
#ifdef __IEEE_LITTLE_ENDIAN
#define IBMPC 1
#else /* !__IEEE_LITTLE_ENDIAN */
#define MIEEE 1
#endif /* !__IEEE_LITTLE_ENDIAN */
#endif /* !DEC */
 
/* Define 1 for ANSI C atan2() function
* See atan.c and clog.c.
*/
#define ANSIC 1
 
/*define VOLATILE volatile*/
#define VOLATILE
 
#define NANS
#define INFINITY
 
/* NaN's require infinity support. */
#ifdef NANS
#ifndef INFINITY
#define INFINITY
#endif
#endif
 
/* This handles 64-bit long ints. */
#define LONGBITS (8 * sizeof(long))
 
 
static void eaddm(short unsigned int *x, short unsigned int *y);
static void esubm(short unsigned int *x, short unsigned int *y);
static void emdnorm(short unsigned int *s, int lost, int subflg, long int exp, int rcntrl, LDPARMS *ldp);
static int asctoeg(char *ss, short unsigned int *y, int oprec, LDPARMS *ldp);
static void enan(short unsigned int *nan, int size);
#if LDBL_MANT_DIG == 24
static void toe24(short unsigned int *x, short unsigned int *y);
#elif LDBL_MANT_DIG == 53
static void toe53(short unsigned int *x, short unsigned int *y);
#elif LDBL_MANT_DIG == 64
static void toe64(short unsigned int *a, short unsigned int *b);
#else
static void toe113(short unsigned int *a, short unsigned int *b);
#endif
static void eiremain(short unsigned int *den, short unsigned int *num, LDPARMS *ldp);
static int ecmpm(register short unsigned int *a, register short unsigned int *b);
static int edivm(short unsigned int *den, short unsigned int *num, LDPARMS *ldp);
static int emulm(short unsigned int *a, short unsigned int *b, LDPARMS *ldp);
static int eisneg(short unsigned int *x);
static int eisinf(short unsigned int *x);
static void emovi(short unsigned int *a, short unsigned int *b);
static void emovo(short unsigned int *a, short unsigned int *b, LDPARMS *ldp);
static void emovz(register short unsigned int *a, register short unsigned int *b);
static void ecleaz(register short unsigned int *xi);
static void eadd1(short unsigned int *a, short unsigned int *b, short unsigned int *c, int subflg, LDPARMS *ldp);
static int eisnan(short unsigned int *x);
static int eiisnan(short unsigned int *x);
 
#ifdef DEC
static void etodec(), todec(), dectoe();
#endif
 
/*
; Clear out entire external format number.
;
; unsigned short x[];
; eclear( x );
*/
 
static void eclear(register short unsigned int *x)
{
register int i;
 
for( i=0; i<NE; i++ )
*x++ = 0;
}
 
 
 
/* Move external format number from a to b.
*
* emov( a, b );
*/
 
static void emov(register short unsigned int *a, register short unsigned int *b)
{
register int i;
 
for( i=0; i<NE; i++ )
*b++ = *a++;
}
 
 
/*
; Negate external format number
;
; unsigned short x[NE];
; eneg( x );
*/
 
static void eneg(short unsigned int *x)
{
 
#ifdef NANS
if( eisnan(x) )
return;
#endif
x[NE-1] ^= 0x8000; /* Toggle the sign bit */
}
 
 
 
/* Return 1 if external format number is negative,
* else return zero.
*/
static int eisneg(short unsigned int *x)
{
 
#ifdef NANS
if( eisnan(x) )
return( 0 );
#endif
if( x[NE-1] & 0x8000 )
return( 1 );
else
return( 0 );
}
 
 
/* Return 1 if external format number has maximum possible exponent,
* else return zero.
*/
static int eisinf(short unsigned int *x)
{
 
if( (x[NE-1] & 0x7fff) == 0x7fff )
{
#ifdef NANS
if( eisnan(x) )
return( 0 );
#endif
return( 1 );
}
else
return( 0 );
}
 
/* Check if e-type number is not a number.
*/
static int eisnan(short unsigned int *x)
{
 
#ifdef NANS
int i;
/* NaN has maximum exponent */
if( (x[NE-1] & 0x7fff) != 0x7fff )
return (0);
/* ... and non-zero significand field. */
for( i=0; i<NE-1; i++ )
{
if( *x++ != 0 )
return (1);
}
#endif
return (0);
}
 
/*
; Fill entire number, including exponent and significand, with
; largest possible number. These programs implement a saturation
; value that is an ordinary, legal number. A special value
; "infinity" may also be implemented; this would require tests
; for that value and implementation of special rules for arithmetic
; operations involving inifinity.
*/
 
static void einfin(register short unsigned int *x, register LDPARMS *ldp)
{
register int i;
 
#ifdef INFINITY
for( i=0; i<NE-1; i++ )
*x++ = 0;
*x |= 32767;
ldp = ldp;
#else
for( i=0; i<NE-1; i++ )
*x++ = 0xffff;
*x |= 32766;
if( ldp->rndprc < NBITS )
{
if (ldp->rndprc == 113)
{
*(x - 9) = 0;
*(x - 8) = 0;
}
if( ldp->rndprc == 64 )
{
*(x-5) = 0;
}
if( ldp->rndprc == 53 )
{
*(x-4) = 0xf800;
}
else
{
*(x-4) = 0;
*(x-3) = 0;
*(x-2) = 0xff00;
}
}
#endif
}
 
/* Move in external format number,
* converting it to internal format.
*/
static void emovi(short unsigned int *a, short unsigned int *b)
{
register unsigned short *p, *q;
int i;
 
q = b;
p = a + (NE-1); /* point to last word of external number */
/* get the sign bit */
if( *p & 0x8000 )
*q++ = 0xffff;
else
*q++ = 0;
/* get the exponent */
*q = *p--;
*q++ &= 0x7fff; /* delete the sign bit */
#ifdef INFINITY
if( (*(q-1) & 0x7fff) == 0x7fff )
{
#ifdef NANS
if( eisnan(a) )
{
*q++ = 0;
for( i=3; i<NI; i++ )
*q++ = *p--;
return;
}
#endif
for( i=2; i<NI; i++ )
*q++ = 0;
return;
}
#endif
/* clear high guard word */
*q++ = 0;
/* move in the significand */
for( i=0; i<NE-1; i++ )
*q++ = *p--;
/* clear low guard word */
*q = 0;
}
 
 
/* Move internal format number out,
* converting it to external format.
*/
static void emovo(short unsigned int *a, short unsigned int *b, LDPARMS *ldp)
{
register unsigned short *p, *q;
unsigned short i;
 
p = a;
q = b + (NE-1); /* point to output exponent */
/* combine sign and exponent */
i = *p++;
if( i )
*q-- = *p++ | 0x8000;
else
*q-- = *p++;
#ifdef INFINITY
if( *(p-1) == 0x7fff )
{
#ifdef NANS
if( eiisnan(a) )
{
enan( b, NBITS );
return;
}
#endif
einfin(b, ldp);
return;
}
#endif
/* skip over guard word */
++p;
/* move the significand */
for( i=0; i<NE-1; i++ )
*q-- = *p++;
}
 
 
/* Clear out internal format number.
*/
 
static void ecleaz(register short unsigned int *xi)
{
register int i;
 
for( i=0; i<NI; i++ )
*xi++ = 0;
}
 
/* same, but don't touch the sign. */
 
static void ecleazs(register short unsigned int *xi)
{
register int i;
 
++xi;
for(i=0; i<NI-1; i++)
*xi++ = 0;
}
 
 
 
 
/* Move internal format number from a to b.
*/
static void emovz(register short unsigned int *a, register short unsigned int *b)
{
register int i;
 
for( i=0; i<NI-1; i++ )
*b++ = *a++;
/* clear low guard word */
*b = 0;
}
 
/* Return nonzero if internal format number is a NaN.
*/
 
static int eiisnan (short unsigned int *x)
{
int i;
 
if( (x[E] & 0x7fff) == 0x7fff )
{
for( i=M+1; i<NI; i++ )
{
if( x[i] != 0 )
return(1);
}
}
return(0);
}
 
#if LDBL_MANT_DIG == 64
 
/* Return nonzero if internal format number is infinite. */
static int
eiisinf (x)
unsigned short x[];
{
 
#ifdef NANS
if (eiisnan (x))
return (0);
#endif
if ((x[E] & 0x7fff) == 0x7fff)
return (1);
return (0);
}
#endif /* LDBL_MANT_DIG == 64 */
 
/*
; Compare significands of numbers in internal format.
; Guard words are included in the comparison.
;
; unsigned short a[NI], b[NI];
; cmpm( a, b );
;
; for the significands:
; returns +1 if a > b
; 0 if a == b
; -1 if a < b
*/
static int ecmpm(register short unsigned int *a, register short unsigned int *b)
{
int i;
 
a += M; /* skip up to significand area */
b += M;
for( i=M; i<NI; i++ )
{
if( *a++ != *b++ )
goto difrnt;
}
return(0);
 
difrnt:
if( *(--a) > *(--b) )
return(1);
else
return(-1);
}
 
 
/*
; Shift significand down by 1 bit
*/
 
static void eshdn1(register short unsigned int *x)
{
register unsigned short bits;
int i;
 
x += M; /* point to significand area */
 
bits = 0;
for( i=M; i<NI; i++ )
{
if( *x & 1 )
bits |= 1;
*x >>= 1;
if( bits & 2 )
*x |= 0x8000;
bits <<= 1;
++x;
}
}
 
 
 
/*
; Shift significand up by 1 bit
*/
 
static void eshup1(register short unsigned int *x)
{
register unsigned short bits;
int i;
 
x += NI-1;
bits = 0;
 
for( i=M; i<NI; i++ )
{
if( *x & 0x8000 )
bits |= 1;
*x <<= 1;
if( bits & 2 )
*x |= 1;
bits <<= 1;
--x;
}
}
 
 
 
/*
; Shift significand down by 8 bits
*/
 
static void eshdn8(register short unsigned int *x)
{
register unsigned short newbyt, oldbyt;
int i;
 
x += M;
oldbyt = 0;
for( i=M; i<NI; i++ )
{
newbyt = *x << 8;
*x >>= 8;
*x |= oldbyt;
oldbyt = newbyt;
++x;
}
}
 
/*
; Shift significand up by 8 bits
*/
 
static void eshup8(register short unsigned int *x)
{
int i;
register unsigned short newbyt, oldbyt;
 
x += NI-1;
oldbyt = 0;
 
for( i=M; i<NI; i++ )
{
newbyt = *x >> 8;
*x <<= 8;
*x |= oldbyt;
oldbyt = newbyt;
--x;
}
}
 
/*
; Shift significand up by 16 bits
*/
 
static void eshup6(register short unsigned int *x)
{
int i;
register unsigned short *p;
 
p = x + M;
x += M + 1;
 
for( i=M; i<NI-1; i++ )
*p++ = *x++;
 
*p = 0;
}
 
/*
; Shift significand down by 16 bits
*/
 
static void eshdn6(register short unsigned int *x)
{
int i;
register unsigned short *p;
 
x += NI-1;
p = x + 1;
 
for( i=M; i<NI-1; i++ )
*(--p) = *(--x);
 
*(--p) = 0;
}
/*
; Add significands
; x + y replaces y
*/
 
static void eaddm(short unsigned int *x, short unsigned int *y)
{
register unsigned long a;
int i;
unsigned int carry;
 
x += NI-1;
y += NI-1;
carry = 0;
for( i=M; i<NI; i++ )
{
a = (unsigned long )(*x) + (unsigned long )(*y) + carry;
if( a & 0x10000 )
carry = 1;
else
carry = 0;
*y = (unsigned short )a;
--x;
--y;
}
}
 
/*
; Subtract significands
; y - x replaces y
*/
 
static void esubm(short unsigned int *x, short unsigned int *y)
{
unsigned long a;
int i;
unsigned int carry;
 
x += NI-1;
y += NI-1;
carry = 0;
for( i=M; i<NI; i++ )
{
a = (unsigned long )(*y) - (unsigned long )(*x) - carry;
if( a & 0x10000 )
carry = 1;
else
carry = 0;
*y = (unsigned short )a;
--x;
--y;
}
}
 
 
/* Divide significands */
 
 
/* Multiply significand of e-type number b
by 16-bit quantity a, e-type result to c. */
 
static void m16m(short unsigned int a, short unsigned int *b, short unsigned int *c)
{
register unsigned short *pp;
register unsigned long carry;
unsigned short *ps;
unsigned short p[NI];
unsigned long aa, m;
int i;
 
aa = a;
pp = &p[NI-2];
*pp++ = 0;
*pp = 0;
ps = &b[NI-1];
 
for( i=M+1; i<NI; i++ )
{
if( *ps == 0 )
{
--ps;
--pp;
*(pp-1) = 0;
}
else
{
m = (unsigned long) aa * *ps--;
carry = (m & 0xffff) + *pp;
*pp-- = (unsigned short )carry;
carry = (carry >> 16) + (m >> 16) + *pp;
*pp = (unsigned short )carry;
*(pp-1) = carry >> 16;
}
}
for( i=M; i<NI; i++ )
c[i] = p[i];
}
 
 
/* Divide significands. Neither the numerator nor the denominator
is permitted to have its high guard word nonzero. */
 
 
static int edivm(short unsigned int *den, short unsigned int *num, LDPARMS *ldp)
{
int i;
register unsigned short *p;
unsigned long tnum;
unsigned short j, tdenm, tquot;
unsigned short tprod[NI+1];
unsigned short *equot = ldp->equot;
 
p = &equot[0];
*p++ = num[0];
*p++ = num[1];
 
for( i=M; i<NI; i++ )
{
*p++ = 0;
}
eshdn1( num );
tdenm = den[M+1];
for( i=M; i<NI; i++ )
{
/* Find trial quotient digit (the radix is 65536). */
tnum = (((unsigned long) num[M]) << 16) + num[M+1];
 
/* Do not execute the divide instruction if it will overflow. */
if( (tdenm * 0xffffUL) < tnum )
tquot = 0xffff;
else
tquot = tnum / tdenm;
 
/* Prove that the divide worked. */
/*
tcheck = (unsigned long )tquot * tdenm;
if( tnum - tcheck > tdenm )
tquot = 0xffff;
*/
/* Multiply denominator by trial quotient digit. */
m16m( tquot, den, tprod );
/* The quotient digit may have been overestimated. */
if( ecmpm( tprod, num ) > 0 )
{
tquot -= 1;
esubm( den, tprod );
if( ecmpm( tprod, num ) > 0 )
{
tquot -= 1;
esubm( den, tprod );
}
}
/*
if( ecmpm( tprod, num ) > 0 )
{
eshow( "tprod", tprod );
eshow( "num ", num );
printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
tnum, den[M+1], tquot );
}
*/
esubm( tprod, num );
/*
if( ecmpm( num, den ) >= 0 )
{
eshow( "num ", num );
eshow( "den ", den );
printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
tnum, den[M+1], tquot );
}
*/
equot[i] = tquot;
eshup6(num);
}
/* test for nonzero remainder after roundoff bit */
p = &num[M];
j = 0;
for( i=M; i<NI; i++ )
{
j |= *p++;
}
if( j )
j = 1;
 
for( i=0; i<NI; i++ )
num[i] = equot[i];
 
return( (int )j );
}
 
 
 
/* Multiply significands */
static int emulm(short unsigned int *a, short unsigned int *b, LDPARMS *ldp)
{
unsigned short *p, *q;
unsigned short pprod[NI];
unsigned short j;
int i;
unsigned short *equot = ldp->equot;
 
equot[0] = b[0];
equot[1] = b[1];
for( i=M; i<NI; i++ )
equot[i] = 0;
 
j = 0;
p = &a[NI-1];
q = &equot[NI-1];
for( i=M+1; i<NI; i++ )
{
if( *p == 0 )
{
--p;
}
else
{
m16m( *p--, b, pprod );
eaddm(pprod, equot);
}
j |= *q;
eshdn6(equot);
}
 
for( i=0; i<NI; i++ )
b[i] = equot[i];
 
/* return flag for lost nonzero bits */
return( (int)j );
}
 
 
/*
static void eshow(str, x)
char *str;
unsigned short *x;
{
int i;
 
printf( "%s ", str );
for( i=0; i<NI; i++ )
printf( "%04x ", *x++ );
printf( "\n" );
}
*/
 
 
/*
* Normalize and round off.
*
* The internal format number to be rounded is "s".
* Input "lost" indicates whether the number is exact.
* This is the so-called sticky bit.
*
* Input "subflg" indicates whether the number was obtained
* by a subtraction operation. In that case if lost is nonzero
* then the number is slightly smaller than indicated.
*
* Input "exp" is the biased exponent, which may be negative.
* the exponent field of "s" is ignored but is replaced by
* "exp" as adjusted by normalization and rounding.
*
* Input "rcntrl" is the rounding control.
*/
 
 
static void emdnorm(short unsigned int *s, int lost, int subflg, long int exp, int rcntrl, LDPARMS *ldp)
{
int i, j;
unsigned short r;
 
/* Normalize */
j = enormlz( s );
 
/* a blank significand could mean either zero or infinity. */
#ifndef INFINITY
if( j > NBITS )
{
ecleazs( s );
return;
}
#endif
exp -= j;
#ifndef INFINITY
if( exp >= 32767L )
goto overf;
#else
if( (j > NBITS) && (exp < 32767L) )
{
ecleazs( s );
return;
}
#endif
if( exp < 0L )
{
if( exp > (long )(-NBITS-1) )
{
j = (int )exp;
i = eshift( s, j );
if( i )
lost = 1;
}
else
{
ecleazs( s );
return;
}
}
/* Round off, unless told not to by rcntrl. */
if( rcntrl == 0 )
goto mdfin;
/* Set up rounding parameters if the control register changed. */
if( ldp->rndprc != ldp->rlast )
{
ecleaz( ldp->rbit );
switch( ldp->rndprc )
{
default:
case NBITS:
ldp->rw = NI-1; /* low guard word */
ldp->rmsk = 0xffff;
ldp->rmbit = 0x8000;
ldp->rebit = 1;
ldp->re = ldp->rw - 1;
break;
case 113:
ldp->rw = 10;
ldp->rmsk = 0x7fff;
ldp->rmbit = 0x4000;
ldp->rebit = 0x8000;
ldp->re = ldp->rw;
break;
case 64:
ldp->rw = 7;
ldp->rmsk = 0xffff;
ldp->rmbit = 0x8000;
ldp->rebit = 1;
ldp->re = ldp->rw-1;
break;
/* For DEC arithmetic */
case 56:
ldp->rw = 6;
ldp->rmsk = 0xff;
ldp->rmbit = 0x80;
ldp->rebit = 0x100;
ldp->re = ldp->rw;
break;
case 53:
ldp->rw = 6;
ldp->rmsk = 0x7ff;
ldp->rmbit = 0x0400;
ldp->rebit = 0x800;
ldp->re = ldp->rw;
break;
case 24:
ldp->rw = 4;
ldp->rmsk = 0xff;
ldp->rmbit = 0x80;
ldp->rebit = 0x100;
ldp->re = ldp->rw;
break;
}
ldp->rbit[ldp->re] = ldp->rebit;
ldp->rlast = ldp->rndprc;
}
 
/* Shift down 1 temporarily if the data structure has an implied
* most significant bit and the number is denormal.
* For rndprc = 64 or NBITS, there is no implied bit.
* But Intel long double denormals lose one bit of significance even so.
*/
#if IBMPC
if( (exp <= 0) && (ldp->rndprc != NBITS) )
#else
if( (exp <= 0) && (ldp->rndprc != 64) && (ldp->rndprc != NBITS) )
#endif
{
lost |= s[NI-1] & 1;
eshdn1(s);
}
/* Clear out all bits below the rounding bit,
* remembering in r if any were nonzero.
*/
r = s[ldp->rw] & ldp->rmsk;
if( ldp->rndprc < NBITS )
{
i = ldp->rw + 1;
while( i < NI )
{
if( s[i] )
r |= 1;
s[i] = 0;
++i;
}
}
s[ldp->rw] &= ~ldp->rmsk;
if( (r & ldp->rmbit) != 0 )
{
if( r == ldp->rmbit )
{
if( lost == 0 )
{ /* round to even */
if( (s[ldp->re] & ldp->rebit) == 0 )
goto mddone;
}
else
{
if( subflg != 0 )
goto mddone;
}
}
eaddm( ldp->rbit, s );
}
mddone:
#if IBMPC
if( (exp <= 0) && (ldp->rndprc != NBITS) )
#else
if( (exp <= 0) && (ldp->rndprc != 64) && (ldp->rndprc != NBITS) )
#endif
{
eshup1(s);
}
if( s[2] != 0 )
{ /* overflow on roundoff */
eshdn1(s);
exp += 1;
}
mdfin:
s[NI-1] = 0;
if( exp >= 32767L )
{
#ifndef INFINITY
overf:
#endif
#ifdef INFINITY
s[1] = 32767;
for( i=2; i<NI-1; i++ )
s[i] = 0;
#else
s[1] = 32766;
s[2] = 0;
for( i=M+1; i<NI-1; i++ )
s[i] = 0xffff;
s[NI-1] = 0;
if( (ldp->rndprc < 64) || (ldp->rndprc == 113) )
{
s[ldp->rw] &= ~ldp->rmsk;
if( ldp->rndprc == 24 )
{
s[5] = 0;
s[6] = 0;
}
}
#endif
return;
}
if( exp < 0 )
s[1] = 0;
else
s[1] = (unsigned short )exp;
}
 
 
 
/*
; Subtract external format numbers.
;
; unsigned short a[NE], b[NE], c[NE];
; LDPARMS *ldp;
; esub( a, b, c, ldp ); c = b - a
*/
 
static void esub(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
{
 
#ifdef NANS
if( eisnan(a) )
{
emov (a, c);
return;
}
if( eisnan(b) )
{
emov(b,c);
return;
}
/* Infinity minus infinity is a NaN.
* Test for subtracting infinities of the same sign.
*/
if( eisinf(a) && eisinf(b) && ((eisneg (a) ^ eisneg (b)) == 0))
{
mtherr( "esub", DOMAIN );
enan( c, NBITS );
return;
}
#endif
eadd1( a, b, c, 1, ldp );
}
 
 
 
static void eadd1(short unsigned int *a, short unsigned int *b, short unsigned int *c, int subflg, LDPARMS *ldp)
{
unsigned short ai[NI], bi[NI], ci[NI];
int i, lost, j, k;
long lt, lta, ltb;
 
#ifdef INFINITY
if( eisinf(a) )
{
emov(a,c);
if( subflg )
eneg(c);
return;
}
if( eisinf(b) )
{
emov(b,c);
return;
}
#endif
emovi( a, ai );
emovi( b, bi );
if( subflg )
ai[0] = ~ai[0];
 
/* compare exponents */
lta = ai[E];
ltb = bi[E];
lt = lta - ltb;
if( lt > 0L )
{ /* put the larger number in bi */
emovz( bi, ci );
emovz( ai, bi );
emovz( ci, ai );
ltb = bi[E];
lt = -lt;
}
lost = 0;
if( lt != 0L )
{
if( lt < (long )(-NBITS-1) )
goto done; /* answer same as larger addend */
k = (int )lt;
lost = eshift( ai, k ); /* shift the smaller number down */
}
else
{
/* exponents were the same, so must compare significands */
i = ecmpm( ai, bi );
if( i == 0 )
{ /* the numbers are identical in magnitude */
/* if different signs, result is zero */
if( ai[0] != bi[0] )
{
eclear(c);
return;
}
/* if same sign, result is double */
/* double denomalized tiny number */
if( (bi[E] == 0) && ((bi[3] & 0x8000) == 0) )
{
eshup1( bi );
goto done;
}
/* add 1 to exponent unless both are zero! */
for( j=1; j<NI-1; j++ )
{
if( bi[j] != 0 )
{
/* This could overflow, but let emovo take care of that. */
ltb += 1;
break;
}
}
bi[E] = (unsigned short )ltb;
goto done;
}
if( i > 0 )
{ /* put the larger number in bi */
emovz( bi, ci );
emovz( ai, bi );
emovz( ci, ai );
}
}
if( ai[0] == bi[0] )
{
eaddm( ai, bi );
subflg = 0;
}
else
{
esubm( ai, bi );
subflg = 1;
}
emdnorm( bi, lost, subflg, ltb, 64, ldp );
 
done:
emovo( bi, c, ldp );
}
 
 
 
/*
; Divide.
;
; unsigned short a[NE], b[NE], c[NE];
; LDPARMS *ldp;
; ediv( a, b, c, ldp ); c = b / a
*/
static void ediv(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
{
unsigned short ai[NI], bi[NI];
int i;
long lt, lta, ltb;
 
#ifdef NANS
/* Return any NaN input. */
if( eisnan(a) )
{
emov(a,c);
return;
}
if( eisnan(b) )
{
emov(b,c);
return;
}
/* Zero over zero, or infinity over infinity, is a NaN. */
if( ((ecmp(a,ezero) == 0) && (ecmp(b,ezero) == 0))
|| (eisinf (a) && eisinf (b)) )
{
mtherr( "ediv", DOMAIN );
enan( c, NBITS );
return;
}
#endif
/* Infinity over anything else is infinity. */
#ifdef INFINITY
if( eisinf(b) )
{
if( eisneg(a) ^ eisneg(b) )
*(c+(NE-1)) = 0x8000;
else
*(c+(NE-1)) = 0;
einfin(c, ldp);
return;
}
if( eisinf(a) )
{
eclear(c);
return;
}
#endif
emovi( a, ai );
emovi( b, bi );
lta = ai[E];
ltb = bi[E];
if( bi[E] == 0 )
{ /* See if numerator is zero. */
for( i=1; i<NI-1; i++ )
{
if( bi[i] != 0 )
{
ltb -= enormlz( bi );
goto dnzro1;
}
}
eclear(c);
return;
}
dnzro1:
 
if( ai[E] == 0 )
{ /* possible divide by zero */
for( i=1; i<NI-1; i++ )
{
if( ai[i] != 0 )
{
lta -= enormlz( ai );
goto dnzro2;
}
}
if( ai[0] == bi[0] )
*(c+(NE-1)) = 0;
else
*(c+(NE-1)) = 0x8000;
einfin(c, ldp);
mtherr( "ediv", SING );
return;
}
dnzro2:
 
i = edivm( ai, bi, ldp );
/* calculate exponent */
lt = ltb - lta + EXONE;
emdnorm( bi, i, 0, lt, 64, ldp );
/* set the sign */
if( ai[0] == bi[0] )
bi[0] = 0;
else
bi[0] = 0Xffff;
emovo( bi, c, ldp );
}
 
 
 
/*
; Multiply.
;
; unsigned short a[NE], b[NE], c[NE];
; LDPARMS *ldp
; emul( a, b, c, ldp ); c = b * a
*/
static void emul(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
{
unsigned short ai[NI], bi[NI];
int i, j;
long lt, lta, ltb;
 
#ifdef NANS
/* NaN times anything is the same NaN. */
if( eisnan(a) )
{
emov(a,c);
return;
}
if( eisnan(b) )
{
emov(b,c);
return;
}
/* Zero times infinity is a NaN. */
if( (eisinf(a) && (ecmp(b,ezero) == 0))
|| (eisinf(b) && (ecmp(a,ezero) == 0)) )
{
mtherr( "emul", DOMAIN );
enan( c, NBITS );
return;
}
#endif
/* Infinity times anything else is infinity. */
#ifdef INFINITY
if( eisinf(a) || eisinf(b) )
{
if( eisneg(a) ^ eisneg(b) )
*(c+(NE-1)) = 0x8000;
else
*(c+(NE-1)) = 0;
einfin(c, ldp);
return;
}
#endif
emovi( a, ai );
emovi( b, bi );
lta = ai[E];
ltb = bi[E];
if( ai[E] == 0 )
{
for( i=1; i<NI-1; i++ )
{
if( ai[i] != 0 )
{
lta -= enormlz( ai );
goto mnzer1;
}
}
eclear(c);
return;
}
mnzer1:
 
if( bi[E] == 0 )
{
for( i=1; i<NI-1; i++ )
{
if( bi[i] != 0 )
{
ltb -= enormlz( bi );
goto mnzer2;
}
}
eclear(c);
return;
}
mnzer2:
 
/* Multiply significands */
j = emulm( ai, bi, ldp );
/* calculate exponent */
lt = lta + ltb - (EXONE - 1);
emdnorm( bi, j, 0, lt, 64, ldp );
/* calculate sign of product */
if( ai[0] == bi[0] )
bi[0] = 0;
else
bi[0] = 0xffff;
emovo( bi, c, ldp );
}
 
 
 
#if LDBL_MANT_DIG > 64
static void e113toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
{
register unsigned short r;
unsigned short *e, *p;
unsigned short yy[NI];
int denorm, i;
 
e = pe;
denorm = 0;
ecleaz(yy);
#ifdef IBMPC
e += 7;
#endif
r = *e;
yy[0] = 0;
if( r & 0x8000 )
yy[0] = 0xffff;
r &= 0x7fff;
#ifdef INFINITY
if( r == 0x7fff )
{
#ifdef NANS
#ifdef IBMPC
for( i=0; i<7; i++ )
{
if( pe[i] != 0 )
{
enan( y, NBITS );
return;
}
}
#else /* !IBMPC */
for( i=1; i<8; i++ )
{
if( pe[i] != 0 )
{
enan( y, NBITS );
return;
}
}
#endif /* !IBMPC */
#endif /* NANS */
eclear( y );
einfin( y, ldp );
if( *e & 0x8000 )
eneg(y);
return;
}
#endif /* INFINITY */
yy[E] = r;
p = &yy[M + 1];
#ifdef IBMPC
for( i=0; i<7; i++ )
*p++ = *(--e);
#else /* IBMPC */
++e;
for( i=0; i<7; i++ )
*p++ = *e++;
#endif /* IBMPC */
/* If denormal, remove the implied bit; else shift down 1. */
if( r == 0 )
{
yy[M] = 0;
}
else
{
yy[M] = 1;
eshift( yy, -1 );
}
emovo(yy,y,ldp);
}
 
/* move out internal format to ieee long double */
static void toe113(short unsigned int *a, short unsigned int *b)
{
register unsigned short *p, *q;
unsigned short i;
 
#ifdef NANS
if( eiisnan(a) )
{
enan( b, 113 );
return;
}
#endif
p = a;
#ifdef MIEEE
q = b;
#else
q = b + 7; /* point to output exponent */
#endif
 
/* If not denormal, delete the implied bit. */
if( a[E] != 0 )
{
eshup1 (a);
}
/* combine sign and exponent */
i = *p++;
#ifdef MIEEE
if( i )
*q++ = *p++ | 0x8000;
else
*q++ = *p++;
#else
if( i )
*q-- = *p++ | 0x8000;
else
*q-- = *p++;
#endif
/* skip over guard word */
++p;
/* move the significand */
#ifdef MIEEE
for (i = 0; i < 7; i++)
*q++ = *p++;
#else
for (i = 0; i < 7; i++)
*q-- = *p++;
#endif
}
#endif /* LDBL_MANT_DIG > 64 */
 
 
#if LDBL_MANT_DIG == 64
static void e64toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
{
unsigned short yy[NI];
unsigned short *p, *q, *e;
int i;
 
e = pe;
p = yy;
 
for( i=0; i<NE-5; i++ )
*p++ = 0;
#ifdef IBMPC
for( i=0; i<5; i++ )
*p++ = *e++;
#endif
#ifdef DEC
for( i=0; i<5; i++ )
*p++ = *e++;
#endif
#ifdef MIEEE
p = &yy[0] + (NE-1);
*p-- = *e++;
++e; /* MIEEE skips over 2nd short */
for( i=0; i<4; i++ )
*p-- = *e++;
#endif
 
#ifdef IBMPC
/* For Intel long double, shift denormal significand up 1
-- but only if the top significand bit is zero. */
if((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
{
unsigned short temp[NI+1];
emovi(yy, temp);
eshup1(temp);
emovo(temp,y,ldp);
return;
}
#endif
#ifdef INFINITY
/* Point to the exponent field. */
p = &yy[NE-1];
if( *p == 0x7fff )
{
#ifdef NANS
#ifdef IBMPC
for( i=0; i<4; i++ )
{
if((i != 3 && pe[i] != 0)
/* Check for Intel long double infinity pattern. */
|| (i == 3 && pe[i] != 0x8000))
{
enan( y, NBITS );
return;
}
}
#endif
#ifdef MIEEE
for( i=2; i<=5; i++ )
{
if( pe[i] != 0 )
{
enan( y, NBITS );
return;
}
}
#endif
#endif /* NANS */
eclear( y );
einfin( y, ldp );
if( *p & 0x8000 )
eneg(y);
return;
}
#endif /* INFINITY */
p = yy;
q = y;
for( i=0; i<NE; i++ )
*q++ = *p++;
}
 
/* move out internal format to ieee long double */
static void toe64(short unsigned int *a, short unsigned int *b)
{
register unsigned short *p, *q;
unsigned short i;
 
#ifdef NANS
if( eiisnan(a) )
{
enan( b, 64 );
return;
}
#endif
#ifdef IBMPC
/* Shift Intel denormal significand down 1. */
if( a[E] == 0 )
eshdn1(a);
#endif
p = a;
#ifdef MIEEE
q = b;
#else
q = b + 4; /* point to output exponent */
/* NOTE: Intel data type is 96 bits wide, clear the last word here. */
*(q+1)= 0;
#endif
 
/* combine sign and exponent */
i = *p++;
#ifdef MIEEE
if( i )
*q++ = *p++ | 0x8000;
else
*q++ = *p++;
*q++ = 0; /* leave 2nd short blank */
#else
if( i )
*q-- = *p++ | 0x8000;
else
*q-- = *p++;
#endif
/* skip over guard word */
++p;
/* move the significand */
#ifdef MIEEE
for( i=0; i<4; i++ )
*q++ = *p++;
#else
#ifdef INFINITY
#ifdef IBMPC
if (eiisinf (a))
{
/* Intel long double infinity. */
*q-- = 0x8000;
*q-- = 0;
*q-- = 0;
*q = 0;
return;
}
#endif /* IBMPC */
#endif /* INFINITY */
for( i=0; i<4; i++ )
*q-- = *p++;
#endif
}
 
#endif /* LDBL_MANT_DIG == 64 */
 
#if LDBL_MANT_DIG == 53
/*
; Convert IEEE double precision to e type
; double d;
; unsigned short x[N+2];
; e53toe( &d, x );
*/
static void e53toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
{
#ifdef DEC
 
dectoe( pe, y ); /* see etodec.c */
 
#else
 
register unsigned short r;
register unsigned short *p, *e;
unsigned short yy[NI];
int denorm, k;
 
e = pe;
denorm = 0; /* flag if denormalized number */
ecleaz(yy);
#ifdef IBMPC
e += 3;
#endif
#ifdef DEC
e += 3;
#endif
r = *e;
yy[0] = 0;
if( r & 0x8000 )
yy[0] = 0xffff;
yy[M] = (r & 0x0f) | 0x10;
r &= ~0x800f; /* strip sign and 4 significand bits */
#ifdef INFINITY
if( r == 0x7ff0 )
{
#ifdef NANS
#ifdef IBMPC
if( ((pe[3] & 0xf) != 0) || (pe[2] != 0)
|| (pe[1] != 0) || (pe[0] != 0) )
{
enan( y, NBITS );
return;
}
#else /* !IBMPC */
if( ((pe[0] & 0xf) != 0) || (pe[1] != 0)
|| (pe[2] != 0) || (pe[3] != 0) )
{
enan( y, NBITS );
return;
}
#endif /* !IBMPC */
#endif /* NANS */
eclear( y );
einfin( y, ldp );
if( yy[0] )
eneg(y);
return;
}
#endif
r >>= 4;
/* If zero exponent, then the significand is denormalized.
* So, take back the understood high significand bit. */
if( r == 0 )
{
denorm = 1;
yy[M] &= ~0x10;
}
r += EXONE - 01777;
yy[E] = r;
p = &yy[M+1];
#ifdef IBMPC
*p++ = *(--e);
*p++ = *(--e);
*p++ = *(--e);
#else /* !IBMPC */
++e;
*p++ = *e++;
*p++ = *e++;
*p++ = *e++;
#endif /* !IBMPC */
(void )eshift( yy, -5 );
if( denorm )
{ /* if zero exponent, then normalize the significand */
if( (k = enormlz(yy)) > NBITS )
ecleazs(yy);
else
yy[E] -= (unsigned short )(k-1);
}
emovo( yy, y, ldp );
#endif /* !DEC */
}
 
/*
; e type to IEEE double precision
; double d;
; unsigned short x[NE];
; etoe53( x, &d );
*/
 
#ifdef DEC
 
static void etoe53( x, e )
unsigned short *x, *e;
{
etodec( x, e ); /* see etodec.c */
}
 
static void toe53( x, y )
unsigned short *x, *y;
{
todec( x, y );
}
 
#else
 
static void toe53(short unsigned int *x, short unsigned int *y)
{
unsigned short i;
unsigned short *p;
 
 
#ifdef NANS
if( eiisnan(x) )
{
enan( y, 53 );
return;
}
#endif
p = &x[0];
#ifdef IBMPC
y += 3;
#endif
#ifdef DEC
y += 3;
#endif
*y = 0; /* output high order */
if( *p++ )
*y = 0x8000; /* output sign bit */
 
i = *p++;
if( i >= (unsigned int )2047 )
{ /* Saturate at largest number less than infinity. */
#ifdef INFINITY
*y |= 0x7ff0;
#ifdef IBMPC
*(--y) = 0;
*(--y) = 0;
*(--y) = 0;
#else /* !IBMPC */
++y;
*y++ = 0;
*y++ = 0;
*y++ = 0;
#endif /* IBMPC */
#else /* !INFINITY */
*y |= (unsigned short )0x7fef;
#ifdef IBMPC
*(--y) = 0xffff;
*(--y) = 0xffff;
*(--y) = 0xffff;
#else /* !IBMPC */
++y;
*y++ = 0xffff;
*y++ = 0xffff;
*y++ = 0xffff;
#endif
#endif /* !INFINITY */
return;
}
if( i == 0 )
{
(void )eshift( x, 4 );
}
else
{
i <<= 4;
(void )eshift( x, 5 );
}
i |= *p++ & (unsigned short )0x0f; /* *p = xi[M] */
*y |= (unsigned short )i; /* high order output already has sign bit set */
#ifdef IBMPC
*(--y) = *p++;
*(--y) = *p++;
*(--y) = *p;
#else /* !IBMPC */
++y;
*y++ = *p++;
*y++ = *p++;
*y++ = *p++;
#endif /* !IBMPC */
}
 
#endif /* not DEC */
#endif /* LDBL_MANT_DIG == 53 */
 
#if LDBL_MANT_DIG == 24
/*
; Convert IEEE single precision to e type
; float d;
; unsigned short x[N+2];
; dtox( &d, x );
*/
void e24toe( short unsigned int *pe, short unsigned int *y, LDPARMS *ldp )
{
register unsigned short r;
register unsigned short *p, *e;
unsigned short yy[NI];
int denorm, k;
 
e = pe;
denorm = 0; /* flag if denormalized number */
ecleaz(yy);
#ifdef IBMPC
e += 1;
#endif
#ifdef DEC
e += 1;
#endif
r = *e;
yy[0] = 0;
if( r & 0x8000 )
yy[0] = 0xffff;
yy[M] = (r & 0x7f) | 0200;
r &= ~0x807f; /* strip sign and 7 significand bits */
#ifdef INFINITY
if( r == 0x7f80 )
{
#ifdef NANS
#ifdef MIEEE
if( ((pe[0] & 0x7f) != 0) || (pe[1] != 0) )
{
enan( y, NBITS );
return;
}
#else /* !MIEEE */
if( ((pe[1] & 0x7f) != 0) || (pe[0] != 0) )
{
enan( y, NBITS );
return;
}
#endif /* !MIEEE */
#endif /* NANS */
eclear( y );
einfin( y, ldp );
if( yy[0] )
eneg(y);
return;
}
#endif
r >>= 7;
/* If zero exponent, then the significand is denormalized.
* So, take back the understood high significand bit. */
if( r == 0 )
{
denorm = 1;
yy[M] &= ~0200;
}
r += EXONE - 0177;
yy[E] = r;
p = &yy[M+1];
#ifdef IBMPC
*p++ = *(--e);
#endif
#ifdef DEC
*p++ = *(--e);
#endif
#ifdef MIEEE
++e;
*p++ = *e++;
#endif
(void )eshift( yy, -8 );
if( denorm )
{ /* if zero exponent, then normalize the significand */
if( (k = enormlz(yy)) > NBITS )
ecleazs(yy);
else
yy[E] -= (unsigned short )(k-1);
}
emovo( yy, y, ldp );
}
 
static void toe24(short unsigned int *x, short unsigned int *y)
{
unsigned short i;
unsigned short *p;
 
#ifdef NANS
if( eiisnan(x) )
{
enan( y, 24 );
return;
}
#endif
p = &x[0];
#ifdef IBMPC
y += 1;
#endif
#ifdef DEC
y += 1;
#endif
*y = 0; /* output high order */
if( *p++ )
*y = 0x8000; /* output sign bit */
 
i = *p++;
if( i >= 255 )
{ /* Saturate at largest number less than infinity. */
#ifdef INFINITY
*y |= (unsigned short )0x7f80;
#ifdef IBMPC
*(--y) = 0;
#endif
#ifdef DEC
*(--y) = 0;
#endif
#ifdef MIEEE
++y;
*y = 0;
#endif
#else /* !INFINITY */
*y |= (unsigned short )0x7f7f;
#ifdef IBMPC
*(--y) = 0xffff;
#endif
#ifdef DEC
*(--y) = 0xffff;
#endif
#ifdef MIEEE
++y;
*y = 0xffff;
#endif
#endif /* !INFINITY */
return;
}
if( i == 0 )
{
(void )eshift( x, 7 );
}
else
{
i <<= 7;
(void )eshift( x, 8 );
}
i |= *p++ & (unsigned short )0x7f; /* *p = xi[M] */
*y |= i; /* high order output already has sign bit set */
#ifdef IBMPC
*(--y) = *p;
#endif
#ifdef DEC
*(--y) = *p;
#endif
#ifdef MIEEE
++y;
*y = *p;
#endif
}
#endif /* LDBL_MANT_DIG == 24 */
 
/* Compare two e type numbers.
*
* unsigned short a[NE], b[NE];
* ecmp( a, b );
*
* returns +1 if a > b
* 0 if a == b
* -1 if a < b
* -2 if either a or b is a NaN.
*/
static int ecmp(short unsigned int *a, short unsigned int *b)
{
unsigned short ai[NI], bi[NI];
register unsigned short *p, *q;
register int i;
int msign;
 
#ifdef NANS
if (eisnan (a) || eisnan (b))
return( -2 );
#endif
emovi( a, ai );
p = ai;
emovi( b, bi );
q = bi;
 
if( *p != *q )
{ /* the signs are different */
/* -0 equals + 0 */
for( i=1; i<NI-1; i++ )
{
if( ai[i] != 0 )
goto nzro;
if( bi[i] != 0 )
goto nzro;
}
return(0);
nzro:
if( *p == 0 )
return( 1 );
else
return( -1 );
}
/* both are the same sign */
if( *p == 0 )
msign = 1;
else
msign = -1;
i = NI-1;
do
{
if( *p++ != *q++ )
{
goto diff;
}
}
while( --i > 0 );
 
return(0); /* equality */
 
 
 
diff:
 
if( *(--p) > *(--q) )
return( msign ); /* p is bigger */
else
return( -msign ); /* p is littler */
}
 
 
/*
; Shift significand
;
; Shifts significand area up or down by the number of bits
; given by the variable sc.
*/
static int eshift(short unsigned int *x, int sc)
{
unsigned short lost;
unsigned short *p;
 
if( sc == 0 )
return( 0 );
 
lost = 0;
p = x + NI-1;
 
if( sc < 0 )
{
sc = -sc;
while( sc >= 16 )
{
lost |= *p; /* remember lost bits */
eshdn6(x);
sc -= 16;
}
 
while( sc >= 8 )
{
lost |= *p & 0xff;
eshdn8(x);
sc -= 8;
}
 
while( sc > 0 )
{
lost |= *p & 1;
eshdn1(x);
sc -= 1;
}
}
else
{
while( sc >= 16 )
{
eshup6(x);
sc -= 16;
}
 
while( sc >= 8 )
{
eshup8(x);
sc -= 8;
}
 
while( sc > 0 )
{
eshup1(x);
sc -= 1;
}
}
if( lost )
lost = 1;
return( (int )lost );
}
 
 
 
/*
; normalize
;
; Shift normalizes the significand area pointed to by argument
; shift count (up = positive) is returned.
*/
static int enormlz(short unsigned int *x)
{
register unsigned short *p;
int sc;
 
sc = 0;
p = &x[M];
if( *p != 0 )
goto normdn;
++p;
if( *p & 0x8000 )
return( 0 ); /* already normalized */
while( *p == 0 )
{
eshup6(x);
sc += 16;
/* With guard word, there are NBITS+16 bits available.
* return true if all are zero.
*/
if( sc > NBITS )
return( sc );
}
/* see if high byte is zero */
while( (*p & 0xff00) == 0 )
{
eshup8(x);
sc += 8;
}
/* now shift 1 bit at a time */
while( (*p & 0x8000) == 0)
{
eshup1(x);
sc += 1;
if( sc > (NBITS+16) )
{
mtherr( "enormlz", UNDERFLOW );
return( sc );
}
}
return( sc );
 
/* Normalize by shifting down out of the high guard word
of the significand */
normdn:
 
if( *p & 0xff00 )
{
eshdn8(x);
sc -= 8;
}
while( *p != 0 )
{
eshdn1(x);
sc -= 1;
 
if( sc < -NBITS )
{
mtherr( "enormlz", OVERFLOW );
return( sc );
}
}
return( sc );
}
 
 
 
 
/* Convert e type number to decimal format ASCII string.
* The constants are for 64 bit precision.
*/
 
#define NTEN 12
#define MAXP 4096
 
#if NE == 10
static unsigned short etens[NTEN + 1][NE] =
{
{0x6576, 0x4a92, 0x804a, 0x153f,
0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */
{0x6a32, 0xce52, 0x329a, 0x28ce,
0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */
{0x526c, 0x50ce, 0xf18b, 0x3d28,
0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
{0x9c66, 0x58f8, 0xbc50, 0x5c54,
0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
{0x851e, 0xeab7, 0x98fe, 0x901b,
0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
{0x0235, 0x0137, 0x36b1, 0x336c,
0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
{0x50f8, 0x25fb, 0xc76b, 0x6b71,
0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
{0x0000, 0x0000, 0x0000, 0x0000,
0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */
};
 
static unsigned short emtens[NTEN + 1][NE] =
{
{0x2030, 0xcffc, 0xa1c3, 0x8123,
0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */
{0x8264, 0xd2cb, 0xf2ea, 0x12d4,
0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */
{0xf53f, 0xf698, 0x6bd3, 0x0158,
0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
{0xe731, 0x04d4, 0xe3f2, 0xd332,
0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
{0xa23e, 0x5308, 0xfefb, 0x1155,
0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
{0xe26d, 0xdbde, 0xd05d, 0xb3f6,
0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
{0x2a20, 0x6224, 0x47b3, 0x98d7,
0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
{0x0b5b, 0x4af2, 0xa581, 0x18ed,
0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
{0xbf71, 0xa9b3, 0x7989, 0xbe68,
0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
{0x3d4d, 0x7c3d, 0x36ba, 0x0d2b,
0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
{0xc155, 0xa4a8, 0x404e, 0x6113,
0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
{0xd70a, 0x70a3, 0x0a3d, 0xa3d7,
0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
{0xcccd, 0xcccc, 0xcccc, 0xcccc,
0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */
};
#else
static unsigned short etens[NTEN+1][NE] = {
{0xc94c,0x979a,0x8a20,0x5202,0xc460,0x7525,},/* 10**4096 */
{0xa74d,0x5de4,0xc53d,0x3b5d,0x9e8b,0x5a92,},/* 10**2048 */
{0x650d,0x0c17,0x8175,0x7586,0xc976,0x4d48,},
{0xcc65,0x91c6,0xa60e,0xa0ae,0xe319,0x46a3,},
{0xddbc,0xde8d,0x9df9,0xebfb,0xaa7e,0x4351,},
{0xc66f,0x8cdf,0x80e9,0x47c9,0x93ba,0x41a8,},
{0x3cbf,0xa6d5,0xffcf,0x1f49,0xc278,0x40d3,},
{0xf020,0xb59d,0x2b70,0xada8,0x9dc5,0x4069,},
{0x0000,0x0000,0x0400,0xc9bf,0x8e1b,0x4034,},
{0x0000,0x0000,0x0000,0x2000,0xbebc,0x4019,},
{0x0000,0x0000,0x0000,0x0000,0x9c40,0x400c,},
{0x0000,0x0000,0x0000,0x0000,0xc800,0x4005,},
{0x0000,0x0000,0x0000,0x0000,0xa000,0x4002,}, /* 10**1 */
};
 
static unsigned short emtens[NTEN+1][NE] = {
{0x2de4,0x9fde,0xd2ce,0x04c8,0xa6dd,0x0ad8,}, /* 10**-4096 */
{0x4925,0x2de4,0x3436,0x534f,0xceae,0x256b,}, /* 10**-2048 */
{0x87a6,0xc0bd,0xda57,0x82a5,0xa2a6,0x32b5,},
{0x7133,0xd21c,0xdb23,0xee32,0x9049,0x395a,},
{0xfa91,0x1939,0x637a,0x4325,0xc031,0x3cac,},
{0xac7d,0xe4a0,0x64bc,0x467c,0xddd0,0x3e55,},
{0x3f24,0xe9a5,0xa539,0xea27,0xa87f,0x3f2a,},
{0x67de,0x94ba,0x4539,0x1ead,0xcfb1,0x3f94,},
{0x4c2f,0xe15b,0xc44d,0x94be,0xe695,0x3fc9,},
{0xfdc2,0xcefc,0x8461,0x7711,0xabcc,0x3fe4,},
{0xd3c3,0x652b,0xe219,0x1758,0xd1b7,0x3ff1,},
{0x3d71,0xd70a,0x70a3,0x0a3d,0xa3d7,0x3ff8,},
{0xcccd,0xcccc,0xcccc,0xcccc,0xcccc,0x3ffb,}, /* 10**-1 */
};
#endif
 
 
 
/* ASCII string outputs for unix */
 
 
#if 0
void _IO_ldtostr(x, string, ndigs, flags, fmt)
long double *x;
char *string;
int ndigs;
int flags;
char fmt;
{
unsigned short w[NI];
char *t, *u;
LDPARMS rnd;
LDPARMS *ldp = &rnd;
 
rnd.rlast = -1;
rnd.rndprc = NBITS;
 
if (sizeof(long double) == 16)
e113toe( (unsigned short *)x, w, ldp );
else
e64toe( (unsigned short *)x, w, ldp );
 
etoasc( w, string, ndigs, -1, ldp );
if( ndigs == 0 && flags == 0 )
{
/* Delete the decimal point unless alternate format. */
t = string;
while( *t != '.' )
++t;
u = t + 1;
while( *t != '\0' )
*t++ = *u++;
}
if (*string == ' ')
{
t = string;
u = t + 1;
while( *t != '\0' )
*t++ = *u++;
}
if (fmt == 'E')
{
t = string;
while( *t != 'e' )
++t;
*t = 'E';
}
}
 
#endif
 
/* This routine will not return more than NDEC+1 digits. */
 
char *
_ldtoa_r (struct _reent *ptr, long double d, int mode, int ndigits, int *decpt,
int *sign, char **rve)
{
unsigned short e[NI];
char *s, *p;
int k;
LDPARMS rnd;
LDPARMS *ldp = &rnd;
char *outstr;
 
rnd.rlast = -1;
rnd.rndprc = NBITS;
 
/* reentrancy addition to use mprec storage pool */
if (ptr->_result)
{
ptr->_result->_k = ptr->_result_k;
ptr->_result->_maxwds = 1 << ptr->_result_k;
Bfree (ptr, ptr->_result);
ptr->_result = 0;
}
 
#if LDBL_MANT_DIG == 24
e24toe( (unsigned short *)&d, e, ldp );
#elif LDBL_MANT_DIG == 53
e53toe( (unsigned short *)&d, e, ldp );
#elif LDBL_MANT_DIG == 64
e64toe( (unsigned short *)&d, e, ldp );
#else
e113toe( (unsigned short *)&d, e, ldp );
#endif
 
if( eisneg(e) )
*sign = 1;
else
*sign = 0;
/* Mode 3 is "f" format. */
if( mode != 3 )
ndigits -= 1;
/* Mode 0 is for %.999 format, which is supposed to give a
minimum length string that will convert back to the same binary value.
For now, just ask for 20 digits which is enough but sometimes too many. */
if( mode == 0 )
ndigits = 20;
/* This sanity limit must agree with the corresponding one in etoasc, to
keep straight the returned value of outexpon. */
if( ndigits > NDEC )
ndigits = NDEC;
 
/* reentrancy addition to use mprec storage pool */
ptr->_result = Balloc (ptr, 3);
ptr->_result_k = 3;
outstr = (char *)ptr->_result;
 
etoasc( e, outstr, ndigits, mode, ldp );
s = outstr;
if( eisinf(e) || eisnan(e) )
{
*decpt = 9999;
goto stripspaces;
}
*decpt = ldp->outexpon + 1;
 
/* Transform the string returned by etoasc into what the caller wants. */
 
/* Look for decimal point and delete it from the string. */
s = outstr;
while( *s != '\0' )
{
if( *s == '.' )
goto yesdecpt;
++s;
}
goto nodecpt;
 
yesdecpt:
 
/* Delete the decimal point. */
while( *s != '\0' )
{
*s = *(s+1);
++s;
}
 
nodecpt:
 
/* Back up over the exponent field. */
while( *s != 'E' && s > outstr)
--s;
*s = '\0';
 
stripspaces:
 
/* Strip leading spaces and sign. */
p = outstr;
while( *p == ' ' || *p == '-')
++p;
 
/* Find new end of string. */
s = outstr;
while( (*s++ = *p++) != '\0' )
;
--s;
 
/* Strip trailing zeros. */
if( mode == 2 )
k = 1;
else if( ndigits > ldp->outexpon )
k = ndigits;
else
k = ldp->outexpon;
 
while( *(s-1) == '0' && ((s - outstr) > k))
*(--s) = '\0';
 
/* In f format, flush small off-scale values to zero.
Rounding has been taken care of by etoasc. */
if( mode == 3 && ((ndigits + ldp->outexpon) < 0))
{
s = outstr;
*s = '\0';
*decpt = 0;
}
 
if( rve )
*rve = s;
return outstr;
}
 
/* Routine used to tell if long double is NaN or Infinity or regular number.
Returns: 0 = regular number
1 = Nan
2 = Infinity
*/
int
_ldcheck (long double *d)
{
unsigned short e[NI];
char *s, *p;
int k;
LDPARMS rnd;
LDPARMS *ldp = &rnd;
char *outstr;
 
rnd.rlast = -1;
rnd.rndprc = NBITS;
 
#if LDBL_MANT_DIG == 24
e24toe( (unsigned short *)d, e, ldp );
#elif LDBL_MANT_DIG == 53
e53toe( (unsigned short *)d, e, ldp );
#elif LDBL_MANT_DIG == 64
e64toe( (unsigned short *)d, e, ldp );
#else
e113toe( (unsigned short *)d, e, ldp );
#endif
 
if( (e[NE-1] & 0x7fff) == 0x7fff )
{
#ifdef NANS
if( eisnan(e) )
return( 1 );
#endif
return( 2 );
}
else
return( 0 );
} /* _ldcheck */
 
static void etoasc(short unsigned int *x, char *string, int ndigits, int outformat, LDPARMS *ldp)
{
long digit;
unsigned short y[NI], t[NI], u[NI], w[NI];
unsigned short *p, *r, *ten;
unsigned short sign;
int i, j, k, expon, rndsav, ndigs;
char *s, *ss;
unsigned short m;
unsigned short *equot = ldp->equot;
 
ndigs = ndigits;
rndsav = ldp->rndprc;
#ifdef NANS
if( eisnan(x) )
{
sprintf( string, " NaN " );
expon = 9999;
goto bxit;
}
#endif
ldp->rndprc = NBITS; /* set to full precision */
emov( x, y ); /* retain external format */
if( y[NE-1] & 0x8000 )
{
sign = 0xffff;
y[NE-1] &= 0x7fff;
}
else
{
sign = 0;
}
expon = 0;
ten = &etens[NTEN][0];
emov( eone, t );
/* Test for zero exponent */
if( y[NE-1] == 0 )
{
for( k=0; k<NE-1; k++ )
{
if( y[k] != 0 )
goto tnzro; /* denormalized number */
}
goto isone; /* legal all zeros */
}
tnzro:
 
/* Test for infinity.
*/
if( y[NE-1] == 0x7fff )
{
if( sign )
sprintf( string, " -Infinity " );
else
sprintf( string, " Infinity " );
expon = 9999;
goto bxit;
}
 
/* Test for exponent nonzero but significand denormalized.
* This is an error condition.
*/
if( (y[NE-1] != 0) && ((y[NE-2] & 0x8000) == 0) )
{
mtherr( "etoasc", DOMAIN );
sprintf( string, "NaN" );
expon = 9999;
goto bxit;
}
 
/* Compare to 1.0 */
i = ecmp( eone, y );
if( i == 0 )
goto isone;
 
if( i < 0 )
{ /* Number is greater than 1 */
/* Convert significand to an integer and strip trailing decimal zeros. */
emov( y, u );
u[NE-1] = EXONE + NBITS - 1;
 
p = &etens[NTEN-4][0];
m = 16;
do
{
ediv( p, u, t, ldp );
efloor( t, w, ldp );
for( j=0; j<NE-1; j++ )
{
if( t[j] != w[j] )
goto noint;
}
emov( t, u );
expon += (int )m;
noint:
p += NE;
m >>= 1;
}
while( m != 0 );
 
/* Rescale from integer significand */
u[NE-1] += y[NE-1] - (unsigned int )(EXONE + NBITS - 1);
emov( u, y );
/* Find power of 10 */
emov( eone, t );
m = MAXP;
p = &etens[0][0];
while( ecmp( ten, u ) <= 0 )
{
if( ecmp( p, u ) <= 0 )
{
ediv( p, u, u, ldp );
emul( p, t, t, ldp );
expon += (int )m;
}
m >>= 1;
if( m == 0 )
break;
p += NE;
}
}
else
{ /* Number is less than 1.0 */
/* Pad significand with trailing decimal zeros. */
if( y[NE-1] == 0 )
{
while( (y[NE-2] & 0x8000) == 0 )
{
emul( ten, y, y, ldp );
expon -= 1;
}
}
else
{
emovi( y, w );
for( i=0; i<NDEC+1; i++ )
{
if( (w[NI-1] & 0x7) != 0 )
break;
/* multiply by 10 */
emovz( w, u );
eshdn1( u );
eshdn1( u );
eaddm( w, u );
u[1] += 3;
while( u[2] != 0 )
{
eshdn1(u);
u[1] += 1;
}
if( u[NI-1] != 0 )
break;
if( eone[NE-1] <= u[1] )
break;
emovz( u, w );
expon -= 1;
}
emovo( w, y, ldp );
}
k = -MAXP;
p = &emtens[0][0];
r = &etens[0][0];
emov( y, w );
emov( eone, t );
while( ecmp( eone, w ) > 0 )
{
if( ecmp( p, w ) >= 0 )
{
emul( r, w, w, ldp );
emul( r, t, t, ldp );
expon += k;
}
k /= 2;
if( k == 0 )
break;
p += NE;
r += NE;
}
ediv( t, eone, t, ldp );
}
isone:
/* Find the first (leading) digit. */
emovi( t, w );
emovz( w, t );
emovi( y, w );
emovz( w, y );
eiremain( t, y, ldp );
digit = equot[NI-1];
while( (digit == 0) && (ecmp(y,ezero) != 0) )
{
eshup1( y );
emovz( y, u );
eshup1( u );
eshup1( u );
eaddm( u, y );
eiremain( t, y, ldp );
digit = equot[NI-1];
expon -= 1;
}
s = string;
if( sign )
*s++ = '-';
else
*s++ = ' ';
/* Examine number of digits requested by caller. */
if( outformat == 3 )
ndigs += expon;
/*
else if( ndigs < 0 )
ndigs = 0;
*/
if( ndigs > NDEC )
ndigs = NDEC;
if( digit == 10 )
{
*s++ = '1';
*s++ = '.';
if( ndigs > 0 )
{
*s++ = '0';
ndigs -= 1;
}
expon += 1;
if( ndigs < 0 )
{
ss = s;
goto doexp;
}
}
else
{
*s++ = (char )digit + '0';
*s++ = '.';
}
/* Generate digits after the decimal point. */
for( k=0; k<=ndigs; k++ )
{
/* multiply current number by 10, without normalizing */
eshup1( y );
emovz( y, u );
eshup1( u );
eshup1( u );
eaddm( u, y );
eiremain( t, y, ldp );
*s++ = (char )equot[NI-1] + '0';
}
digit = equot[NI-1];
--s;
ss = s;
/* round off the ASCII string */
if( digit > 4 )
{
/* Test for critical rounding case in ASCII output. */
if( digit == 5 )
{
emovo( y, t, ldp );
if( ecmp(t,ezero) != 0 )
goto roun; /* round to nearest */
if( (*(s-1) & 1) == 0 )
goto doexp; /* round to even */
}
/* Round up and propagate carry-outs */
roun:
--s;
k = *s & 0x7f;
/* Carry out to most significant digit? */
if( ndigs < 0 )
{
/* This will print like "1E-6". */
*s = '1';
expon += 1;
goto doexp;
}
else if( k == '.' )
{
--s;
k = *s;
k += 1;
*s = (char )k;
/* Most significant digit carries to 10? */
if( k > '9' )
{
expon += 1;
*s = '1';
}
goto doexp;
}
/* Round up and carry out from less significant digits */
k += 1;
*s = (char )k;
if( k > '9' )
{
*s = '0';
goto roun;
}
}
doexp:
#ifdef __GO32__
if( expon >= 0 )
sprintf( ss, "e+%02d", expon );
else
sprintf( ss, "e-%02d", -expon );
#else
sprintf( ss, "E%d", expon );
#endif
bxit:
ldp->rndprc = rndsav;
ldp->outexpon = expon;
}
 
 
 
 
/*
; ASCTOQ
; ASCTOQ.MAC LATEST REV: 11 JAN 84
; SLM, 3 JAN 78
;
; Convert ASCII string to quadruple precision floating point
;
; Numeric input is free field decimal number
; with max of 15 digits with or without
; decimal point entered as ASCII from teletype.
; Entering E after the number followed by a second
; number causes the second number to be interpreted
; as a power of 10 to be multiplied by the first number
; (i.e., "scientific" notation).
;
; Usage:
; asctoq( string, q );
*/
 
long double _strtold (char *s, char **se)
{
long double x;
LDPARMS rnd;
LDPARMS *ldp = &rnd;
int lenldstr;
 
rnd.rlast = -1;
rnd.rndprc = NBITS;
 
lenldstr = asctoeg( s, (unsigned short *)&x, LDBL_MANT_DIG, ldp );
if (se)
*se = s + lenldstr;
return x;
}
 
#define REASONABLE_LEN 200
 
static int
asctoeg(char *ss, short unsigned int *y, int oprec, LDPARMS *ldp)
{
unsigned short yy[NI], xt[NI], tt[NI];
int esign, decflg, sgnflg, nexp, exp, prec, lost;
int k, trail, c, rndsav;
long lexp;
unsigned short nsign, *p;
char *sp, *s, *lstr;
int lenldstr;
int mflag = 0;
char tmpstr[REASONABLE_LEN];
 
/* Copy the input string. */
c = strlen (ss) + 2;
if (c <= REASONABLE_LEN)
lstr = tmpstr;
else
{
lstr = (char *) calloc (c, 1);
mflag = 1;
}
s = ss;
lenldstr = 0;
while( *s == ' ' ) /* skip leading spaces */
{
++s;
++lenldstr;
}
sp = lstr;
for( k=0; k<c; k++ )
{
if( (*sp++ = *s++) == '\0' )
break;
}
*sp = '\0';
s = lstr;
 
rndsav = ldp->rndprc;
ldp->rndprc = NBITS; /* Set to full precision */
lost = 0;
nsign = 0;
decflg = 0;
sgnflg = 0;
nexp = 0;
exp = 0;
prec = 0;
ecleaz( yy );
trail = 0;
 
nxtcom:
k = *s - '0';
if( (k >= 0) && (k <= 9) )
{
/* Ignore leading zeros */
if( (prec == 0) && (decflg == 0) && (k == 0) )
goto donchr;
/* Identify and strip trailing zeros after the decimal point. */
if( (trail == 0) && (decflg != 0) )
{
sp = s;
while( (*sp >= '0') && (*sp <= '9') )
++sp;
/* Check for syntax error */
c = *sp & 0x7f;
if( (c != 'e') && (c != 'E') && (c != '\0')
&& (c != '\n') && (c != '\r') && (c != ' ')
&& (c != ',') )
goto error;
--sp;
while( *sp == '0' )
*sp-- = 'z';
trail = 1;
if( *s == 'z' )
goto donchr;
}
/* If enough digits were given to more than fill up the yy register,
* continuing until overflow into the high guard word yy[2]
* guarantees that there will be a roundoff bit at the top
* of the low guard word after normalization.
*/
if( yy[2] == 0 )
{
if( decflg )
nexp += 1; /* count digits after decimal point */
eshup1( yy ); /* multiply current number by 10 */
emovz( yy, xt );
eshup1( xt );
eshup1( xt );
eaddm( xt, yy );
ecleaz( xt );
xt[NI-2] = (unsigned short )k;
eaddm( xt, yy );
}
else
{
/* Mark any lost non-zero digit. */
lost |= k;
/* Count lost digits before the decimal point. */
if (decflg == 0)
nexp -= 1;
}
prec += 1;
goto donchr;
}
 
switch( *s )
{
case 'z':
break;
case 'E':
case 'e':
goto expnt;
case '.': /* decimal point */
if( decflg )
goto error;
++decflg;
break;
case '-':
nsign = 0xffff;
if( sgnflg )
goto error;
++sgnflg;
break;
case '+':
if( sgnflg )
goto error;
++sgnflg;
break;
case ',':
case ' ':
case '\0':
case '\n':
case '\r':
goto daldone;
case 'i':
case 'I':
goto infinite;
default:
error:
#ifdef NANS
enan( yy, NI*16 );
#else
mtherr( "asctoe", DOMAIN );
ecleaz(yy);
#endif
goto aexit;
}
donchr:
++s;
goto nxtcom;
 
/* Exponent interpretation */
expnt:
 
esign = 1;
exp = 0;
++s;
/* check for + or - */
if( *s == '-' )
{
esign = -1;
++s;
}
if( *s == '+' )
++s;
while( (*s >= '0') && (*s <= '9') )
{
exp *= 10;
exp += *s++ - '0';
if (exp > 4977)
{
if (esign < 0)
goto zero;
else
goto infinite;
}
}
if( esign < 0 )
exp = -exp;
if( exp > 4932 )
{
infinite:
ecleaz(yy);
yy[E] = 0x7fff; /* infinity */
goto aexit;
}
if( exp < -4977 )
{
zero:
ecleaz(yy);
goto aexit;
}
 
daldone:
nexp = exp - nexp;
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
while( (nexp > 0) && (yy[2] == 0) )
{
emovz( yy, xt );
eshup1( xt );
eshup1( xt );
eaddm( yy, xt );
eshup1( xt );
if( xt[2] != 0 )
break;
nexp -= 1;
emovz( xt, yy );
}
if( (k = enormlz(yy)) > NBITS )
{
ecleaz(yy);
goto aexit;
}
lexp = (EXONE - 1 + NBITS) - k;
emdnorm( yy, lost, 0, lexp, 64, ldp );
/* convert to external format */
 
 
/* Multiply by 10**nexp. If precision is 64 bits,
* the maximum relative error incurred in forming 10**n
* for 0 <= n <= 324 is 8.2e-20, at 10**180.
* For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947.
* For 0 >= n >= -999, it is -1.55e-19 at 10**-435.
*/
lexp = yy[E];
if( nexp == 0 )
{
k = 0;
goto expdon;
}
esign = 1;
if( nexp < 0 )
{
nexp = -nexp;
esign = -1;
if( nexp > 4096 )
{ /* Punt. Can't handle this without 2 divides. */
emovi( etens[0], tt );
lexp -= tt[E];
k = edivm( tt, yy, ldp );
lexp += EXONE;
nexp -= 4096;
}
}
p = &etens[NTEN][0];
emov( eone, xt );
exp = 1;
do
{
if( exp & nexp )
emul( p, xt, xt, ldp );
p -= NE;
exp = exp + exp;
}
while( exp <= MAXP );
 
emovi( xt, tt );
if( esign < 0 )
{
lexp -= tt[E];
k = edivm( tt, yy, ldp );
lexp += EXONE;
}
else
{
lexp += tt[E];
k = emulm( tt, yy, ldp );
lexp -= EXONE - 1;
}
 
expdon:
 
/* Round and convert directly to the destination type */
if( oprec == 53 )
lexp -= EXONE - 0x3ff;
else if( oprec == 24 )
lexp -= EXONE - 0177;
#ifdef DEC
else if( oprec == 56 )
lexp -= EXONE - 0201;
#endif
ldp->rndprc = oprec;
emdnorm( yy, k, 0, lexp, 64, ldp );
 
aexit:
 
ldp->rndprc = rndsav;
yy[0] = nsign;
switch( oprec )
{
#ifdef DEC
case 56:
todec( yy, y ); /* see etodec.c */
break;
#endif
#if LDBL_MANT_DIG == 53
case 53:
toe53( yy, y );
break;
#elif LDBL_MANT_DIG == 24
case 24:
toe24( yy, y );
break;
#elif LDBL_MANT_DIG == 64
case 64:
toe64( yy, y );
break;
#elif LDBL_MANT_DIG == 113
case 113:
toe113( yy, y );
break;
#else
case NBITS:
emovo( yy, y, ldp );
break;
#endif
}
lenldstr += s - lstr;
if (mflag)
free (lstr);
return lenldstr;
}
 
 
/* y = largest integer not greater than x
* (truncated toward minus infinity)
*
* unsigned short x[NE], y[NE]
* LDPARMS *ldp
*
* efloor( x, y, ldp );
*/
static unsigned short bmask[] = {
0xffff,
0xfffe,
0xfffc,
0xfff8,
0xfff0,
0xffe0,
0xffc0,
0xff80,
0xff00,
0xfe00,
0xfc00,
0xf800,
0xf000,
0xe000,
0xc000,
0x8000,
0x0000,
};
 
static void efloor(short unsigned int *x, short unsigned int *y, LDPARMS *ldp)
{
register unsigned short *p;
int e, expon, i;
unsigned short f[NE];
 
emov( x, f ); /* leave in external format */
expon = (int )f[NE-1];
e = (expon & 0x7fff) - (EXONE - 1);
if( e <= 0 )
{
eclear(y);
goto isitneg;
}
/* number of bits to clear out */
e = NBITS - e;
emov( f, y );
if( e <= 0 )
return;
 
p = &y[0];
while( e >= 16 )
{
*p++ = 0;
e -= 16;
}
/* clear the remaining bits */
*p &= bmask[e];
/* truncate negatives toward minus infinity */
isitneg:
 
if( (unsigned short )expon & (unsigned short )0x8000 )
{
for( i=0; i<NE-1; i++ )
{
if( f[i] != y[i] )
{
esub( eone, y, y, ldp );
break;
}
}
}
}
 
 
 
static void eiremain(short unsigned int *den, short unsigned int *num, LDPARMS *ldp)
{
long ld, ln;
unsigned short j;
unsigned short *equot = ldp->equot;
 
ld = den[E];
ld -= enormlz( den );
ln = num[E];
ln -= enormlz( num );
ecleaz( equot );
while( ln >= ld )
{
if( ecmpm(den,num) <= 0 )
{
esubm(den, num);
j = 1;
}
else
{
j = 0;
}
eshup1(equot);
equot[NI-1] |= j;
eshup1(num);
ln -= 1;
}
emdnorm( num, 0, 0, ln, 0, ldp );
}
 
/* NaN bit patterns
*/
#ifdef MIEEE
static unsigned short nan113[8] = {
0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
static unsigned short nan64[6] = {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
static unsigned short nan53[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
static unsigned short nan24[2] = {0x7fff, 0xffff};
#else /* !MIEEE */
static unsigned short nan113[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0x7fff};
static unsigned short nan64[6] = {0, 0, 0, 0, 0xc000, 0x7fff};
static unsigned short nan53[4] = {0, 0, 0, 0x7ff8};
static unsigned short nan24[2] = {0, 0x7fc0};
#endif /* !MIEEE */
 
 
static void enan (short unsigned int *nan, int size)
{
int i, n;
unsigned short *p;
 
switch( size )
{
#ifndef DEC
case 113:
n = 8;
p = nan113;
break;
 
case 64:
n = 6;
p = nan64;
break;
 
case 53:
n = 4;
p = nan53;
break;
 
case 24:
n = 2;
p = nan24;
break;
 
case NBITS:
for( i=0; i<NE-2; i++ )
*nan++ = 0;
*nan++ = 0xc000;
*nan++ = 0x7fff;
return;
 
case NI*16:
*nan++ = 0;
*nan++ = 0x7fff;
*nan++ = 0;
*nan++ = 0xc000;
for( i=4; i<NI; i++ )
*nan++ = 0;
return;
#endif
default:
mtherr( "enan", DOMAIN );
return;
}
for (i=0; i < n; i++)
*nan++ = *p++;
}
 
 
 
 
/atexit.h
0,0 → 1,13
/*
* %G% (UofMD) %D%
*/
 
#define ATEXIT_SIZE 32 /* must be at least 32 to guarantee ANSI conformance */
 
struct atexit {
struct atexit *next; /* next in list */
int ind; /* next index in this table */
void (*fns[ATEXIT_SIZE])(); /* the table itself */
};
 
struct atexit *__atexit; /* points to head of LIFO stack */
/mprec.c
0,0 → 1,984
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by AT&T.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
 
/* Please send bug reports to
David M. Gay
AT&T Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-2070
U.S.A.
dmg@research.att.com or research!dmg
*/
 
/* 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 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.
* #define Unsigned_Shifts if >> does treats its left operand as unsigned.
* #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 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.
*/
 
#include <_ansi.h>
#include <stdlib.h>
#include <string.h>
#include <reent.h>
#include "mprec.h"
 
/* reent.c knows this value */
#define _Kmax 15
 
_Bigint *
_DEFUN (Balloc, (ptr, k), struct _reent *ptr _AND int k)
{
int x;
_Bigint *rv ;
 
if (ptr->_freelist == NULL)
{
/* Allocate a list of pointers to the mprec objects */
ptr->_freelist = (struct _Bigint **) _calloc_r (ptr,
sizeof (struct _Bigint *),
_Kmax + 1);
if (ptr->_freelist == NULL)
{
return NULL;
}
}
 
if ((rv = ptr->_freelist[k]) != 0)
{
ptr->_freelist[k] = rv->_next;
}
else
{
x = 1 << k;
/* Allocate an mprec Bigint and stick in in the freelist */
rv = (_Bigint *) _calloc_r (ptr,
1,
sizeof (_Bigint) +
(x-1) * sizeof(rv->_x));
if (rv == NULL) return NULL;
rv->_k = k;
rv->_maxwds = x;
}
rv->_sign = rv->_wds = 0;
return rv;
}
 
void
_DEFUN (Bfree, (ptr, v), struct _reent *ptr _AND _Bigint * v)
{
if (v)
{
v->_next = ptr->_freelist[v->_k];
ptr->_freelist[v->_k] = v;
}
}
 
_Bigint *
_DEFUN (multadd, (ptr, b, m, a),
struct _reent *ptr _AND
_Bigint * b _AND
int m _AND
int a)
{
int i, wds;
__ULong *x, y;
#ifdef Pack_32
__ULong xi, z;
#endif
_Bigint *b1;
 
wds = b->_wds;
x = b->_x;
i = 0;
do
{
#ifdef Pack_32
xi = *x;
y = (xi & 0xffff) * m + a;
z = (xi >> 16) * m + (y >> 16);
a = (int) (z >> 16);
*x++ = (z << 16) + (y & 0xffff);
#else
y = *x * m + a;
a = (int) (y >> 16);
*x++ = y & 0xffff;
#endif
}
while (++i < wds);
if (a)
{
if (wds >= b->_maxwds)
{
b1 = Balloc (ptr, b->_k + 1);
Bcopy (b1, b);
Bfree (ptr, b);
b = b1;
}
b->_x[wds++] = a;
b->_wds = wds;
}
return b;
}
 
_Bigint *
_DEFUN (s2b, (ptr, s, nd0, nd, y9),
struct _reent * ptr _AND
_CONST char *s _AND
int nd0 _AND
int nd _AND
__ULong y9)
{
_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 (ptr, k);
b->_x[0] = y9;
b->_wds = 1;
#else
b = Balloc (ptr, 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 (ptr, b, 10, *s++ - '0');
while (++i < nd0);
s++;
}
else
s += 10;
for (; i < nd; i++)
b = multadd (ptr, b, 10, *s++ - '0');
return b;
}
 
int
_DEFUN (hi0bits,
(x), register __ULong x)
{
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;
}
 
int
_DEFUN (lo0bits, (y), __ULong *y)
{
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 *
_DEFUN (i2b, (ptr, i), struct _reent * ptr _AND int i)
{
_Bigint *b;
 
b = Balloc (ptr, 1);
b->_x[0] = i;
b->_wds = 1;
return b;
}
 
_Bigint *
_DEFUN (mult, (ptr, a, b), struct _reent * ptr _AND _Bigint * a _AND _Bigint * b)
{
_Bigint *c;
int k, wa, wb, wc;
__ULong carry, y, z;
__ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
#ifdef Pack_32
__ULong z2;
#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 (ptr, 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 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++)
{
x = xa;
xc = xc0;
carry = 0;
do
{
z = *x++ * y + *xc + carry;
carry = z >> 16;
*xc++ = z & 0xffff;
}
while (x < xae);
*xc = carry;
}
}
#endif
for (xc0 = c->_x, xc = xc0 + wc; wc > 0 && !*--xc; --wc);
c->_wds = wc;
return c;
}
 
_Bigint *
_DEFUN (pow5mult,
(ptr, b, k), struct _reent * ptr _AND _Bigint * b _AND int k)
{
_Bigint *b1, *p5, *p51;
int i;
static _CONST int p05[3] = {5, 25, 125};
 
if ((i = k & 3) != 0)
b = multadd (ptr, b, p05[i - 1], 0);
 
if (!(k >>= 2))
return b;
if (!(p5 = ptr->_p5s))
{
/* first time */
p5 = ptr->_p5s = i2b (ptr, 625);
p5->_next = 0;
}
for (;;)
{
if (k & 1)
{
b1 = mult (ptr, b, p5);
Bfree (ptr, b);
b = b1;
}
if (!(k >>= 1))
break;
if (!(p51 = p5->_next))
{
p51 = p5->_next = mult (ptr, p5, p5);
p51->_next = 0;
}
p5 = p51;
}
return b;
}
 
_Bigint *
_DEFUN (lshift, (ptr, b, k), struct _reent * ptr _AND _Bigint * b _AND int k)
{
int i, k1, n, n1;
_Bigint *b1;
__ULong *x, *x1, *xe, z;
 
#ifdef Pack_32
n = k >> 5;
#else
n = k >> 4;
#endif
k1 = b->_k;
n1 = n + b->_wds + 1;
for (i = b->_maxwds; n1 > i; i <<= 1)
k1++;
b1 = Balloc (ptr, k1);
x1 = b1->_x;
for (i = 0; i < n; i++)
*x1++ = 0;
x = b->_x;
xe = x + b->_wds;
#ifdef Pack_32
if (k &= 0x1f)
{
k1 = 32 - k;
z = 0;
do
{
*x1++ = *x << k | z;
z = *x++ >> k1;
}
while (x < xe);
if ((*x1 = z) != 0)
++n1;
}
#else
if (k &= 0xf)
{
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 (ptr, b);
return b1;
}
 
int
_DEFUN (cmp, (a, b), _Bigint * a _AND _Bigint * b)
{
__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 *
_DEFUN (diff, (ptr, a, b), struct _reent * ptr _AND
_Bigint * a _AND _Bigint * b)
{
_Bigint *c;
int i, wa, wb;
__Long borrow, y; /* We need signed shifts here. */
__ULong *xa, *xae, *xb, *xbe, *xc;
#ifdef Pack_32
__Long z;
#endif
 
i = cmp (a, b);
if (!i)
{
c = Balloc (ptr, 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 (ptr, 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 Pack_32
do
{
y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
borrow = z >> 16;
Sign_Extend (borrow, z);
Storeinc (xc, z, y);
}
while (xb < xbe);
while (xa < xae)
{
y = (*xa & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
z = (*xa++ >> 16) + borrow;
borrow = z >> 16;
Sign_Extend (borrow, z);
Storeinc (xc, z, y);
}
#else
do
{
y = *xa++ - *xb++ + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
*xc++ = y & 0xffff;
}
while (xb < xbe);
while (xa < xae)
{
y = *xa++ + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
*xc++ = y & 0xffff;
}
#endif
while (!*--xc)
wa--;
c->_wds = wa;
return c;
}
 
double
_DEFUN (ulp, (_x), double _x)
{
union double_union x, a;
register __Long L;
 
x.d = _x;
 
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;
#ifndef _DOUBLE_IS_32BITS
word1 (a) = 0;
#endif
 
#ifndef Sudden_Underflow
}
else
{
L = -L >> Exp_shift;
if (L < Exp_shift)
{
word0 (a) = 0x80000 >> L;
#ifndef _DOUBLE_IS_32BITS
word1 (a) = 0;
#endif
}
else
{
word0 (a) = 0;
L -= Exp_shift;
#ifndef _DOUBLE_IS_32BITS
word1 (a) = L >= 31 ? 1 : 1 << (31 - L);
#endif
}
}
#endif
return a.d;
}
 
double
_DEFUN (b2d, (a, e),
_Bigint * a _AND int *e)
{
__ULong *xa, *xa0, w, y, z;
int k;
union double_union 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;
#ifndef _DOUBLE_IS_32BITS
d1 = y << ((32 - Ebits) + k) | w >> (Ebits - k);
#endif
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
if (k -= Ebits)
{
d0 = Exp_1 | y << k | z >> (32 - k);
y = xa > xa0 ? *--xa : 0;
#ifndef _DOUBLE_IS_32BITS
d1 = z << k | y >> (32 - k);
#endif
}
else
{
d0 = Exp_1 | y;
#ifndef _DOUBLE_IS_32BITS
d1 = z;
#endif
}
#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;
#else
#undef d0
#undef d1
#endif
return d.d;
}
 
_Bigint *
_DEFUN (d2b,
(ptr, _d, e, bits),
struct _reent * ptr _AND
double _d _AND
int *e _AND
int *bits)
 
{
union double_union d;
_Bigint *b;
int de, i, k;
__ULong *x, y, z;
#ifdef VAX
__ULong d0, d1;
#endif
d.d = _d;
#ifdef VAX
d0 = word0 (d) >> 16 | word0 (d) << 16;
d1 = word1 (d) >> 16 | word1 (d) << 16;
#else
#define d0 word0(d)
#define d1 word1(d)
d.d = _d;
#endif
 
#ifdef Pack_32
b = Balloc (ptr, 1);
#else
b = Balloc (ptr, 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
#ifndef _DOUBLE_IS_32BITS
if (d1)
{
y = d1;
k = lo0bits (&y);
if (k)
{
x[0] = y | z << (32 - k);
z >>= k;
}
else
x[0] = y;
i = b->_wds = (x[1] = z) ? 2 : 1;
}
else
#endif
{
#ifdef DEBUG
if (!z)
Bug ("Zero passed to d2b");
#endif
k = lo0bits (&z);
x[0] = z;
i = b->_wds = 1;
#ifndef _DOUBLE_IS_32BITS
k += 32;
#endif
}
#else
if (d1)
{
y = d1;
k = lo0bits (&y);
if (k)
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
 
double
_DEFUN (ratio, (a, b), _Bigint * a _AND _Bigint * b)
 
{
union double_union da, db;
int k, ka, kb;
 
da.d = b2d (a, &ka);
db.d = b2d (b, &kb);
#ifdef Pack_32
k = ka - kb + 32 * (a->_wds - b->_wds);
#else
k = ka - kb + 16 * (a->_wds - b->_wds);
#endif
#ifdef IBM
if (k > 0)
{
word0 (da) += (k >> 2) * Exp_msk1;
if (k &= 3)
da.d *= 1 << k;
}
else
{
k = -k;
word0 (db) += (k >> 2) * Exp_msk1;
if (k &= 3)
db.d *= 1 << k;
}
#else
if (k > 0)
word0 (da) += k * Exp_msk1;
else
{
k = -k;
word0 (db) += k * Exp_msk1;
}
#endif
return da.d / db.d;
}
 
 
_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, 1e23, 1e24
 
};
 
#if !defined(_DOUBLE_IS_32BITS) && !defined(__v800)
_CONST double bigtens[] =
{1e16, 1e32, 1e64, 1e128, 1e256};
 
_CONST double tinytens[] =
{1e-16, 1e-32, 1e-64, 1e-128, 1e-256};
#else
_CONST double bigtens[] =
{1e16, 1e32};
 
_CONST double tinytens[] =
{1e-16, 1e-32};
#endif
 
 
double
_DEFUN (_mprec_log10, (dig),
int dig)
{
double v = 1.0;
if (dig < 24)
return tens[dig];
while (dig > 0)
{
v *= 10;
dig--;
}
return v;
}
/malloc.c
0,0 → 1,206
/* VxWorks provides its own version of malloc, and we can't use this
one because VxWorks does not provide sbrk. So we have a hook to
not compile this code. */
 
/* The routines here are simple cover fns to the routines that do the real
work (the reentrant versions). */
/* FIXME: Does the warning below (see WARNINGS) about non-reentrancy still
apply? A first guess would be "no", but how about reentrancy in the *same*
thread? */
 
#ifdef MALLOC_PROVIDED
 
int _dummy_malloc = 1;
 
#else
 
/*
FUNCTION
<<malloc>>, <<realloc>>, <<free>>---manage memory
 
INDEX
malloc
INDEX
realloc
INDEX
free
INDEX
memalign
INDEX
malloc_usable_size
INDEX
_malloc_r
INDEX
_realloc_r
INDEX
_free_r
INDEX
_memalign_r
INDEX
_malloc_usable_size_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
void *malloc(size_t <[nbytes]>);
void *realloc(void *<[aptr]>, size_t <[nbytes]>);
void free(void *<[aptr]>);
 
void *memalign(size_t <[align]>, size_t <[nbytes]>);
 
size_t malloc_usable_size(void *<[aptr]>);
 
void *_malloc_r(void *<[reent]>, size_t <[nbytes]>);
void *_realloc_r(void *<[reent]>,
void *<[aptr]>, size_t <[nbytes]>);
void _free_r(void *<[reent]>, void *<[aptr]>);
 
void *_memalign_r(void *<[reent]>,
size_t <[align]>, size_t <[nbytes]>);
 
size_t _malloc_usable_size_r(void *<[reent]>, void *<[aptr]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
char *malloc(<[nbytes]>)
size_t <[nbytes]>;
 
char *realloc(<[aptr]>, <[nbytes]>)
char *<[aptr]>;
size_t <[nbytes]>;
 
void free(<[aptr]>)
char *<[aptr]>;
 
char *memalign(<[align]>, <[nbytes]>)
size_t <[align]>;
size_t <[nbytes]>;
 
size_t malloc_usable_size(<[aptr]>)
char *<[aptr]>;
 
char *_malloc_r(<[reent]>,<[nbytes]>)
char *<[reent]>;
size_t <[nbytes]>;
 
char *_realloc_r(<[reent]>, <[aptr]>, <[nbytes]>)
char *<[reent]>;
char *<[aptr]>;
size_t <[nbytes]>;
 
void _free_r(<[reent]>, <[aptr]>)
char *<[reent]>;
char *<[aptr]>;
 
char *_memalign_r(<[reent]>, <[align]>, <[nbytes]>)
char *<[reent]>;
size_t <[align]>;
size_t <[nbytes]>;
 
size_t malloc_usable_size(<[reent]>, <[aptr]>)
char *<[reent]>;
char *<[aptr]>;
 
DESCRIPTION
These functions manage a pool of system memory.
 
Use <<malloc>> to request allocation of an object with at least
<[nbytes]> bytes of storage available. If the space is available,
<<malloc>> returns a pointer to a newly allocated block as its result.
 
If you already have a block of storage allocated by <<malloc>>, but
you no longer need all the space allocated to it, you can make it
smaller by calling <<realloc>> with both the object pointer and the
new desired size as arguments. <<realloc>> guarantees that the
contents of the smaller object match the beginning of the original object.
 
Similarly, if you need more space for an object, use <<realloc>> to
request the larger size; again, <<realloc>> guarantees that the
beginning of the new, larger object matches the contents of the
original object.
 
When you no longer need an object originally allocated by <<malloc>>
or <<realloc>> (or the related function <<calloc>>), return it to the
memory storage pool by calling <<free>> with the address of the object
as the argument. You can also use <<realloc>> for this purpose by
calling it with <<0>> as the <[nbytes]> argument.
 
The <<memalign>> function returns a block of size <[nbytes]> aligned
to a <[align]> boundary. The <[align]> argument must be a power of
two.
 
The <<malloc_usable_size>> function takes a pointer to a block
allocated by <<malloc>>. It returns the amount of space that is
available in the block. This may or may not be more than the size
requested from <<malloc>>, due to alignment or minimum size
constraints.
 
The alternate functions <<_malloc_r>>, <<_realloc_r>>, <<_free_r>>,
<<_memalign_r>>, and <<_malloc_usable_size_r>> are reentrant versions.
The extra argument <[reent]> is a pointer to a reentrancy structure.
 
If you have multiple threads of execution which may call any of these
routines, or if any of these routines may be called reentrantly, then
you must provide implementations of the <<__malloc_lock>> and
<<__malloc_unlock>> functions for your system. See the documentation
for those functions.
 
These functions operate by calling the function <<_sbrk_r>> or
<<sbrk>>, which allocates space. You may need to provide one of these
functions for your system. <<_sbrk_r>> is called with a positive
value to allocate more space, and with a negative value to release
previously allocated space if it is no longer required.
@xref{Stubs}.
 
RETURNS
<<malloc>> returns a pointer to the newly allocated space, if
successful; otherwise it returns <<NULL>>. If your application needs
to generate empty objects, you may use <<malloc(0)>> for this purpose.
 
<<realloc>> returns a pointer to the new block of memory, or <<NULL>>
if a new block could not be allocated. <<NULL>> is also the result
when you use `<<realloc(<[aptr]>,0)>>' (which has the same effect as
`<<free(<[aptr]>)>>'). You should always check the result of
<<realloc>>; successful reallocation is not guaranteed even when
you request a smaller object.
 
<<free>> does not return a result.
 
<<memalign>> returns a pointer to the newly allocated space.
 
<<malloc_usable_size>> returns the usable size.
 
PORTABILITY
<<malloc>>, <<realloc>>, and <<free>> are specified by the ANSI C
standard, but other conforming implementations of <<malloc>> may
behave differently when <[nbytes]> is zero.
 
<<memalign>> is part of SVR4.
 
<<malloc_usable_size>> is not portable.
 
Supporting OS subroutines required: <<sbrk>>. */
 
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
 
#ifndef _REENT_ONLY
 
_PTR
_DEFUN (malloc, (nbytes),
size_t nbytes) /* get a block */
{
return _malloc_r (_REENT, nbytes);
}
 
void
_DEFUN (free, (aptr),
_PTR aptr)
{
_free_r (_REENT, aptr);
}
 
#endif
 
#endif /* ! defined (MALLOC_PROVIDED) */
/bsearch.c
0,0 → 1,100
/*
* bsearch.c
* Original Author: G. Haley
* Rewritten by: G. Noer
*
* Searches an array of nmemb members, the initial member of which is pointed
* to by base, for a member that matches the object pointed to by key. The
* contents of the array shall be in ascending order according to a comparison
* function pointed to by compar. The function shall return an integer less
* than, equal to or greater than zero if the first argument is considered to be
* respectively less than, equal to or greater than the second. Returns a
* pointer to the matching member of the array, or a null pointer if no match
* is found.
*/
 
/*
FUNCTION
<<bsearch>>---binary search
 
INDEX
bsearch
 
ANSI_SYNOPSIS
#include <stdlib.h>
void *bsearch(const void *<[key]>, const void *<[base]>,
size_t <[nmemb]>, size_t <[size]>,
int (*<[compar]>)(const void *, const void *));
 
TRAD_SYNOPSIS
#include <stdlib.h>
char *bsearch(<[key]>, <[base]>, <[nmemb]>, <[size]>, <[compar]>)
char *<[key]>;
char *<[base]>;
size_t <[nmemb]>, <[size]>;
int (*<[compar]>)();
 
DESCRIPTION
<<bsearch>> searches an array beginning at <[base]> for any element
that matches <[key]>, using binary search. <[nmemb]> is the element
count of the array; <[size]> is the size of each element.
 
The array must be sorted in ascending order with respect to the
comparison function <[compar]> (which you supply as the last argument of
<<bsearch>>).
 
You must define the comparison function <<(*<[compar]>)>> to have two
arguments; its result must be negative if the first argument is
less than the second, zero if the two arguments match, and
positive if the first argument is greater than the second (where
``less than'' and ``greater than'' refer to whatever arbitrary
ordering is appropriate).
 
RETURNS
Returns a pointer to an element of <[array]> that matches <[key]>. If
more than one matching element is available, the result may point to
any of them.
 
PORTABILITY
<<bsearch>> is ANSI.
 
No supporting OS subroutines are required.
*/
 
#include <stdlib.h>
 
_PTR
_DEFUN (bsearch, (key, base, nmemb, size, compar),
_CONST _PTR key _AND
_CONST _PTR base _AND
size_t nmemb _AND
size_t size _AND
int _EXFUN ((*compar), (const _PTR, const _PTR)))
{
_PTR current;
size_t lower = 0;
size_t upper = nmemb;
size_t index;
int result;
 
if (nmemb == 0 || size == 0)
return NULL;
 
while (lower < upper)
{
index = (lower + upper) / 2;
current = (_PTR) (((char *) base) + (index * size));
 
result = compar (key, current);
 
if (result < 0)
upper = index;
else if (result > 0)
lower = index + 1;
else
return current;
}
 
return NULL;
}
 
/mstats.c
0,0 → 1,151
/* VxWorks provides its own version of malloc, and we can't use this
one because VxWorks does not provide sbrk. So we have a hook to
not compile this code. */
 
#ifdef MALLOC_PROVIDED
 
int _dummy_mstats = 1;
 
#else
 
/*
FUNCTION
<<mallinfo>>, <<malloc_stats>>, <<mallopt>>--malloc support
 
INDEX
mallinfo
INDEX
malloc_stats
INDEX
mallopt
INDEX
_mallinfo_r
INDEX
_malloc_stats_r
INDEX
_mallopt_r
 
ANSI_SYNOPSIS
#include <malloc.h>
struct mallinfo mallinfo(void);
void malloc_stats(void);
int mallopt(int <[parameter]>, <[value]>);
 
struct mallinfo _mallinfo_r(void *<[reent]>);
void _malloc_stats_r(void *<[reent]>);
int _mallopt_r(void *<[reent]>, int <[parameter]>, <[value]>);
 
TRAD_SYNOPSIS
#include <malloc.h>
struct mallinfo mallinfo();
 
void malloc_stats();
 
int mallopt(<[parameter]>, <[value]>)
int <[parameter]>;
int <[value]>;
 
struct mallinfo _mallinfo_r(<[reent]>);
char *<[reent]>;
 
void _malloc_stats_r(<[reent]>);
char *<[reent]>;
 
int _mallopt_r(<[reent]>, <[parameter]>, <[value]>)
char *<[reent]>;
int <[parameter]>;
int <[value]>;
 
DESCRIPTION
<<mallinfo>> returns a structure describing the current state of
memory allocation. The structure is defined in malloc.h. The
following fields are defined: <<arena>> is the total amount of space
in the heap; <<ordblks>> is the number of chunks which are not in use;
<<uordblks>> is the total amount of space allocated by <<malloc>>;
<<fordblks>> is the total amount of space not in use; <<keepcost>> is
the size of the top most memory block.
 
<<malloc_stats>> print some statistics about memory allocation on
standard error.
 
<<mallopt>> takes a parameter and a value. The parameters are defined
in malloc.h, and may be one of the following: <<M_TRIM_THRESHOLD>>
sets the maximum amount of unused space in the top most block before
releasing it back to the system in <<free>> (the space is released by
calling <<_sbrk_r>> with a negative argument); <<M_TOP_PAD>> is the
amount of padding to allocate whenever <<_sbrk_r>> is called to
allocate more space.
 
The alternate functions <<_mallinfo_r>>, <<_malloc_stats_r>>, and
<<_mallopt_r>> are reentrant versions. The extra argument <[reent]>
is a pointer to a reentrancy structure.
 
RETURNS
<<mallinfo>> returns a mallinfo structure. The structure is defined
in malloc.h.
 
<<malloc_stats>> does not return a result.
 
<<mallopt>> returns zero if the parameter could not be set, or
non-zero if it could be set.
 
PORTABILITY
<<mallinfo>> and <<mallopt>> are provided by SVR4, but <<mallopt>>
takes different parameters on different systems. <<malloc_stats>> is
not portable.
 
*/
 
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
 
#ifndef _REENT_ONLY
 
struct mallinfo
_DEFUN_VOID (mallinfo)
{
return _mallinfo_r (_REENT);
}
 
void
_DEFUN_VOID (malloc_stats)
{
_malloc_stats_r (_REENT);
}
 
int
_DEFUN (mallopt, (p, v),
int p _AND
int v)
{
return _mallopt_r (_REENT, p, v);
}
 
#endif
 
/* mstats is now compatibility code. It used to be real, for a
previous version of the malloc routines. It now just calls
malloc_stats. */
 
void
_DEFUN (_mstats_r, (ptr, s),
struct _reent *ptr _AND
char *s)
{
fiprintf (_stderr_r (ptr), "Memory allocation statistics %s\n", s);
_malloc_stats_r (ptr);
}
 
#ifndef _REENT_ONLY
void
_DEFUN (mstats, (s),
char *s)
{
_mstats_r (_REENT, s);
}
 
#endif
#endif /* ! defined (MALLOC_PROVIDED) */
/mprec.h
0,0 → 1,313
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by AT&T.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
 
/* Please send bug reports to
David M. Gay
AT&T Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-2070
U.S.A.
dmg@research.att.com or research!dmg
*/
 
#include <ieeefp.h>
#include <math.h>
#include <float.h>
#include <errno.h>
#include <sys/config.h>
 
#ifdef __IEEE_LITTLE_ENDIAN
#define IEEE_8087
#endif
 
#ifdef __IEEE_BIG_ENDIAN
#define IEEE_MC68k
#endif
 
#ifdef __Z8000__
#define Just_16
#endif
 
#ifdef DEBUG
#include "stdio.h"
#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
#endif
 
#ifdef Unsigned_Shifts
#define Sign_Extend(a,b) if (b < 0) a |= (__uint32_t)0xffff0000;
#else
#define Sign_Extend(a,b) /*no-op*/
#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
 
/* If we are going to examine or modify specific bits in a double using
the word0 and/or word1 macros, then we must wrap the double inside
a union. This is necessary to avoid undefined behavior according to
the ANSI C spec. */
union double_union
{
double d;
__uint32_t i[2];
};
 
#ifdef IEEE_8087
#define word0(x) (x.i[1])
#define word1(x) (x.i[0])
#else
#define word0(x) (x.i[0])
#define word1(x) (x.i[1])
#endif
 
/* 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_BYTES_LITTLE_ENDIAN) + 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) */
 
#if defined(IEEE_8087) + defined(IEEE_MC68k)
#if defined (_DOUBLE_IS_32BITS)
#define Exp_shift 23
#define Exp_shift1 23
#define Exp_msk1 ((__uint32_t)0x00800000L)
#define Exp_msk11 ((__uint32_t)0x00800000L)
#define Exp_mask ((__uint32_t)0x7f800000L)
#define P 24
#define Bias 127
#if 0
#define IEEE_Arith /* it is, but the code doesn't handle IEEE singles yet */
#endif
#define Emin (-126)
#define Exp_1 ((__uint32_t)0x3f800000L)
#define Exp_11 ((__uint32_t)0x3f800000L)
#define Ebits 8
#define Frac_mask ((__uint32_t)0x007fffffL)
#define Frac_mask1 ((__uint32_t)0x007fffffL)
#define Ten_pmax 10
#define Sign_bit ((__uint32_t)0x80000000L)
#define Ten_pmax 10
#define Bletch 2
#define Bndry_mask ((__uint32_t)0x007fffffL)
#define Bndry_mask1 ((__uint32_t)0x007fffffL)
#define LSB 1
#define Sign_bit ((__uint32_t)0x80000000L)
#define Log2P 1
#define Tiny0 0
#define Tiny1 1
#define Quick_max 5
#define Int_max 6
#define Infinite(x) (word0(x) == ((__uint32_t)0x7f800000L))
#undef word0
#undef word1
 
#define word0(x) (x.i[0])
#define word1(x) 0
#else
 
#define Exp_shift 20
#define Exp_shift1 20
#define Exp_msk1 ((__uint32_t)0x100000L)
#define Exp_msk11 ((__uint32_t)0x100000L)
#define Exp_mask ((__uint32_t)0x7ff00000L)
#define P 53
#define Bias 1023
#define IEEE_Arith
#define Emin (-1022)
#define Exp_1 ((__uint32_t)0x3ff00000L)
#define Exp_11 ((__uint32_t)0x3ff00000L)
#define Ebits 11
#define Frac_mask ((__uint32_t)0xfffffL)
#define Frac_mask1 ((__uint32_t)0xfffffL)
#define Ten_pmax 22
#define Bletch 0x10
#define Bndry_mask ((__uint32_t)0xfffffL)
#define Bndry_mask1 ((__uint32_t)0xfffffL)
#define LSB 1
#define Sign_bit ((__uint32_t)0x80000000L)
#define Log2P 1
#define Tiny0 0
#define Tiny1 1
#define Quick_max 14
#define Int_max 14
#define Infinite(x) (word0(x) == ((__uint32_t)0x7ff00000L)) /* sufficient test for here */
#endif
 
#else
#undef Sudden_Underflow
#define Sudden_Underflow
#ifdef IBM
#define Exp_shift 24
#define Exp_shift1 24
#define Exp_msk1 ((__uint32_t)0x1000000L)
#define Exp_msk11 ((__uint32_t)0x1000000L)
#define Exp_mask ((__uint32_t)0x7f000000L)
#define P 14
#define Bias 65
#define Exp_1 ((__uint32_t)0x41000000L)
#define Exp_11 ((__uint32_t)0x41000000L)
#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
#define Frac_mask ((__uint32_t)0xffffffL)
#define Frac_mask1 ((__uint32_t)0xffffffL)
#define Bletch 4
#define Ten_pmax 22
#define Bndry_mask ((__uint32_t)0xefffffL)
#define Bndry_mask1 ((__uint32_t)0xffffffL)
#define LSB 1
#define Sign_bit ((__uint32_t)0x80000000L)
#define Log2P 4
#define Tiny0 ((__uint32_t)0x100000L)
#define Tiny1 0
#define Quick_max 14
#define Int_max 15
#else /* VAX */
#define Exp_shift 23
#define Exp_shift1 7
#define Exp_msk1 0x80
#define Exp_msk11 ((__uint32_t)0x800000L)
#define Exp_mask ((__uint32_t)0x7f80L)
#define P 56
#define Bias 129
#define Exp_1 ((__uint32_t)0x40800000L)
#define Exp_11 ((__uint32_t)0x4080L)
#define Ebits 8
#define Frac_mask ((__uint32_t)0x7fffffL)
#define Frac_mask1 ((__uint32_t)0xffff007fL)
#define Ten_pmax 24
#define Bletch 2
#define Bndry_mask ((__uint32_t)0xffff007fL)
#define Bndry_mask1 ((__uint32_t)0xffff007fL)
#define LSB ((__uint32_t)0x10000L)
#define Sign_bit ((__uint32_t)0x8000L)
#define Log2P 1
#define Tiny0 0x80
#define Tiny1 0
#define Quick_max 15
#define Int_max 15
#endif
#endif
 
#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 ((__uint32_t)0xffffffffL)
 
#ifndef Just_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.
*/
 
#ifndef Pack_32
#define Pack_32
#endif
#endif
 
 
#ifdef __cplusplus
extern "C" double strtod(const char *s00, char **se);
extern "C" char *dtoa(double d, int mode, int ndigits,
int *decpt, int *sign, char **rve);
#endif
 
 
typedef struct _Bigint _Bigint;
 
#define Balloc _Balloc
#define Bfree _Bfree
#define multadd _multadd
#define s2b _s2b
#define lo0bits _lo0bits
#define hi0bits _hi0bits
#define i2b _i2b
#define mult _multiply
#define pow5mult _pow5mult
#define lshift _lshift
#define cmp __mcmp
#define diff __mdiff
#define ulp _ulp
#define b2d _b2d
#define d2b _d2b
#define ratio _ratio
 
#define tens __mprec_tens
#define bigtens __mprec_bigtens
#define tinytens __mprec_tinytens
 
struct _reent ;
double _EXFUN(ulp,(double x));
double _EXFUN(b2d,(_Bigint *a , int *e));
_Bigint * _EXFUN(Balloc,(struct _reent *p, int k));
void _EXFUN(Bfree,(struct _reent *p, _Bigint *v));
_Bigint * _EXFUN(multadd,(struct _reent *p, _Bigint *, int, int));
_Bigint * _EXFUN(s2b,(struct _reent *, const char*, int, int, __ULong));
_Bigint * _EXFUN(i2b,(struct _reent *,int));
_Bigint * _EXFUN(mult, (struct _reent *, _Bigint *, _Bigint *));
_Bigint * _EXFUN(pow5mult, (struct _reent *, _Bigint *, int k));
int _EXFUN(hi0bits,(__ULong));
int _EXFUN(lo0bits,(__ULong *));
_Bigint * _EXFUN(d2b,(struct _reent *p, double d, int *e, int *bits));
_Bigint * _EXFUN(lshift,(struct _reent *p, _Bigint *b, int k));
_Bigint * _EXFUN(diff,(struct _reent *p, _Bigint *a, _Bigint *b));
int _EXFUN(cmp,(_Bigint *a, _Bigint *b));
 
double _EXFUN(ratio,(_Bigint *a, _Bigint *b));
#define Bcopy(x,y) memcpy((char *)&x->_sign, (char *)&y->_sign, y->_wds*sizeof(__Long) + 2*sizeof(int))
 
#if defined(_DOUBLE_IS_32BITS) && defined(__v800)
#define n_bigtens 2
#else
#define n_bigtens 5
#endif
 
extern _CONST double tinytens[];
extern _CONST double bigtens[];
extern _CONST double tens[];
 
 
double _EXFUN(_mprec_log10,(int));
/strtoul.c
0,0 → 1,206
/*
FUNCTION
<<strtoul>>---string to unsigned long
 
INDEX
strtoul
INDEX
_strtoul_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
unsigned long strtoul(const char *<[s]>, char **<[ptr]>,
int <[base]>);
 
unsigned long _strtoul_r(void *<[reent]>, const char *<[s]>,
char **<[ptr]>, int <[base]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
unsigned long strtoul(<[s]>, <[ptr]>, <[base]>)
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
unsigned long _strtoul_r(<[reent]>, <[s]>, <[ptr]>, <[base]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
DESCRIPTION
The function <<strtoul>> converts the string <<*<[s]>>> to
an <<unsigned long>>. First, it breaks down the string into three parts:
leading whitespace, which is ignored; a subject string consisting
of the digits meaningful in the radix specified by <[base]>
(for example, <<0>> through <<7>> if the value of <[base]> is 8);
and a trailing portion consisting of one or more unparseable characters,
which always includes the terminating null character. Then, it attempts
to convert the subject string into an unsigned long integer, and returns the
result.
 
If the value of <[base]> is zero, the subject string is expected to look
like a normal C integer constant (save that no optional sign is permitted):
a possible <<0x>> indicating hexadecimal radix, and a number.
If <[base]> is between 2 and 36, the expected form of the subject is a
sequence of digits (which may include letters, depending on the
base) representing an integer in the radix specified by <[base]>.
The letters <<a>>--<<z>> (or <<A>>--<<Z>>) are used as digits valued from
10 to 35. If <[base]> is 16, a leading <<0x>> is permitted.
 
The subject sequence is the longest initial sequence of the input
string that has the expected form, starting with the first
non-whitespace character. If the string is empty or consists entirely
of whitespace, or if the first non-whitespace character is not a
permissible digit, the subject string is empty.
 
If the subject string is acceptable, and the value of <[base]> is zero,
<<strtoul>> attempts to determine the radix from the input string. A
string with a leading <<0x>> is treated as a hexadecimal value; a string with
a leading <<0>> and no <<x>> is treated as octal; all other strings are
treated as decimal. If <[base]> is between 2 and 36, it is used as the
conversion radix, as described above. Finally, a pointer to the first
character past the converted subject string is stored in <[ptr]>, if
<[ptr]> is not <<NULL>>.
 
If the subject string is empty (that is, if <<*>><[s]> does not start
with a substring in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
 
The alternate function <<_strtoul_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
 
 
RETURNS
<<strtoul>> returns the converted value, if any. If no conversion was
made, <<0>> is returned.
 
<<strtoul>> returns <<ULONG_MAX>> if the magnitude of the converted
value is too large, and sets <<errno>> to <<ERANGE>>.
 
PORTABILITY
<<strtoul>> is ANSI.
 
<<strtoul>> requires no supporting OS subroutines.
*/
 
/*
* Copyright (c) 1990 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 <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
 
/*
* Convert a string to an unsigned long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long
_DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr _AND
int base)
{
register const char *s = nptr;
register unsigned long acc;
register int c;
register unsigned long cutoff;
register int neg = 0, any, cutlim;
 
/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else 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;
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : '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;
rptr->_errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
 
#ifndef _REENT_ONLY
 
unsigned long
_DEFUN (strtoul, (s, ptr, base),
_CONST char *s _AND
char **ptr _AND
int base)
{
return _strtoul_r (_REENT, s, ptr, base);
}
 
#endif
/efgcvt.c
0,0 → 1,202
/*
FUNCTION
<<ecvt>>,<<ecvtf>>,<<fcvt>>,<<fcvtf>>---double or float to string
 
INDEX
ecvt
INDEX
fcvt
 
ANSI_SYNOPSIS
#include <stdlib.h>
 
char *ecvt(double <[val]>, int <[chars]>, int *<[decpt]>, int *<[sgn]>);
char *ecvtf(float <[val]>, int <[chars]>, int *<[decpt]>, int *<[sgn]>);
 
char *fcvt(double <[val]>, int <[decimals]>,
int *<[decpt]>, int *<[sgn]>);
char *fcvtf(float <[val]>, int <[decimals]>,
int *<[decpt]>, int *<[sgn]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
 
char *ecvt(<[val]>, <[chars]>, <[decpt]>, <[sgn]>);
double <[val]>;
int <[chars]>;
int *<[decpt]>;
int *<[sgn]>;
char *ecvtf(<[val]>, <[chars]>, <[decpt]>, <[sgn]>);
float <[val]>;
int <[chars]>;
int *<[decpt]>;
int *<[sgn]>;
 
char *fcvt(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>);
double <[val]>;
int <[decimals]>;
int *<[decpt]>;
int *<[sgn]>;
char *fcvtf(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>);
float <[val]>;
int <[decimals]>;
int *<[decpt]>;
int *<[sgn]>;
 
DESCRIPTION
<<ecvt>> and <<fcvt>> produce (null-terminated) strings of digits
representating the <<double>> number <[val]>.
<<ecvtf>> and <<fcvtf>> produce the corresponding character
representations of <<float>> numbers.
 
(The <<stdlib>> functions <<ecvtbuf>> and <<fcvtbuf>> are reentrant
versions of <<ecvt>> and <<fcvt>>.)
 
The only difference between <<ecvt>> and <<fcvt>> is the
interpretation of the second argument (<[chars]> or <[decimals]>).
For <<ecvt>>, the second argument <[chars]> specifies the total number
of characters to write (which is also the number of significant digits
in the formatted string, since these two functions write only digits).
For <<fcvt>>, the second argument <[decimals]> specifies the number of
characters to write after the decimal point; all digits for the integer
part of <[val]> are always included.
 
Since <<ecvt>> and <<fcvt>> write only digits in the output string,
they record the location of the decimal point in <<*<[decpt]>>>, and
the sign of the number in <<*<[sgn]>>>. After formatting a number,
<<*<[decpt]>>> contains the number of digits to the left of the
decimal point. <<*<[sgn]>>> contains <<0>> if the number is positive,
and <<1>> if it is negative.
 
RETURNS
All four functions return a pointer to the new string containing a
character representation of <[val]>.
 
PORTABILITY
None of these functions are ANSI C.
 
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
 
NEWPAGE
FUNCTION
<<gvcvt>>, <<gcvtf>>---format double or float as string
 
INDEX
gcvt
INDEX
gcvtf
 
ANSI_SYNOPSIS
#include <stdlib.h>
 
char *gcvt(double <[val]>, int <[precision]>, char *<[buf]>);
char *gcvtf(float <[val]>, int <[precision]>, char *<[buf]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
 
char *gcvt(<[val]>, <[precision]>, <[buf]>);
double <[val]>;
int <[precision]>;
char *<[buf]>;
char *gcvtf(<[val]>, <[precision]>, <[buf]>);
float <[val]>;
int <[precision]>;
char *<[buf]>;
 
DESCRIPTION
<<gcvt>> writes a fully formatted number as a null-terminated
string in the buffer <<*<[buf]>>>. <<gdvtf>> produces corresponding
character representations of <<float>> numbers.
 
<<gcvt>> uses the same rules as the <<printf>> format
`<<%.<[precision]>g>>'---only negative values are signed (with
`<<->>'), and either exponential or ordinary decimal-fraction format
is chosen depending on the number of significant digits (specified by
<[precision]>).
 
RETURNS
The result is a pointer to the formatted representation of <[val]>
(the same as the argument <[buf]>).
 
PORTABILITY
Neither function is ANSI C.
 
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
 
#include <_ansi.h>
#include <reent.h>
#include <stdio.h>
#include <stdlib.h>
#include "local.h"
 
char *
_DEFUN (fcvt, (d, ndigit, decpt, sign),
double d _AND
int ndigit _AND
int *decpt _AND
int *sign)
{
return fcvtbuf (d, ndigit, decpt, sign, NULL);
}
 
char *
_DEFUN (fcvtf, (d, ndigit, decpt, sign),
float d _AND
int ndigit _AND
int *decpt _AND
int *sign)
{
return fcvt ((float) d, ndigit, decpt, sign);
}
 
 
char *
_DEFUN (gcvtf, (d, ndigit, buf),
float d _AND
int ndigit _AND
char *buf)
{
double asd = d;
return gcvt (asd, ndigit, buf);
}
 
 
char *
_DEFUN (ecvt, (d, ndigit, decpt, sign),
double d _AND
int ndigit _AND
int *decpt _AND
int *sign)
{
return ecvtbuf (d, ndigit, decpt, sign, NULL);
}
 
char *
_DEFUN (ecvtf, (d, ndigit, decpt, sign),
float d _AND
int ndigit _AND
int *decpt _AND
int *sign)
{
return ecvt ((double) d, ndigit, decpt, sign);
}
 
 
char *
_DEFUN (gcvt, (d, ndigit, buf),
double d _AND
int ndigit _AND
char *buf)
{
char *tbuf = buf;
if (d < 0) {
*buf = '-';
buf++;
ndigit--;
}
return (_gcvt (_REENT, d, ndigit, buf, 'g', 0) ? tbuf : 0);
}
/environ.c
0,0 → 1,23
/* Copyright (c) 1995, 1996 Cygnus Support.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* at Cygnus Support, Inc. Cygnus Support, Inc. 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 WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
/* Provide a definition of `environ' if crt0.o doesn't. */
 
static char *initial_env[] = { 0 };
 
/* Posix says `environ' is a pointer to a null terminated list of pointers.
Hence `environ' itself is never NULL. */
char **environ = &initial_env[0];
/strtoll_r.c
0,0 → 1,140
/*
This code is based on strtoul.c which has the following copyright.
It is used to convert a string into a signed long long.
 
long long _strtoll_r (struct _reent *rptr, const char *s,
char **ptr, int base);
*/
 
/*-
* Copyright (c) 1990 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.
*/
 
#ifdef __GNUC__
 
#define _GNU_SOURCE
#include <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
 
/*
* Convert a string to a long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long long
_DEFUN (_strtoll_r, (rptr, nptr, endptr, base),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr _AND
int base)
{
register const char *s = nptr;
register unsigned long long acc;
register int c;
register unsigned long long cutoff;
register int neg = 0, 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.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else 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;
 
/*
* 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 longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, 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 ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX;
cutlim = cutoff % (unsigned long long)base;
cutoff /= (unsigned long long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : '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_LONG_MIN : LONG_LONG_MAX;
rptr->_errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
 
#endif /* __GNUC__ */
/system.c
0,0 → 1,186
/*
FUNCTION
<<system>>---execute command string
 
INDEX
system
INDEX
_system_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
int system(char *<[s]>);
 
int _system_r(void *<[reent]>, char *<[s]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int system(<[s]>)
char *<[s]>;
 
int _system_r(<[reent]>, <[s]>)
char *<[reent]>;
char *<[s]>;
 
DESCRIPTION
 
Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
your system, and wait for it to finish executing.
 
Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
available.
 
The alternate function <<_system_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
 
RETURNS
<<system(NULL)>> returns a non-zero value if <</bin/sh>> is available, and
<<0>> if it is not.
 
With a command argument, the result of <<system>> is the exit status
returned by <</bin/sh>>.
 
PORTABILITY
ANSI C requires <<system>>, but leaves the nature and effects of a
command processor undefined. ANSI C does, however, specify that
<<system(NULL)>> return zero or nonzero to report on the existence of
a command processor.
 
POSIX.2 requires <<system>>, and requires that it invoke a <<sh>>.
Where <<sh>> is found is left unspecified.
 
Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>,
<<_wait_r>>.
*/
 
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <_syslist.h>
#include <reent.h>
 
#if defined (unix) || defined (__CYGWIN__)
static int do_system ();
#endif
 
int
_system_r (ptr, s)
struct _reent *ptr;
_CONST char *s;
{
#ifdef NO_EXEC
if (s == NULL)
return 0;
errno = ENOSYS;
return -1;
#else
 
/* ??? How to handle (s == NULL) here is not exactly clear.
If _fork_r fails, that's not really a justification for returning 0.
For now we always return 0 and leave it to each target to explicitly
handle otherwise (this can always be relaxed in the future). */
 
#if defined (unix) || defined (__CYGWIN__)
if (s == NULL)
return 1;
return do_system (ptr, s);
#else
if (s == NULL)
return 0;
errno = ENOSYS;
return -1;
#endif
 
#endif
}
 
#ifndef _REENT_ONLY
 
int
system (s)
_CONST char *s;
{
return _system_r (_REENT, s);
}
 
#endif
#if defined (unix) && !defined (__CYGWIN__) && !defined(__rtems__)
extern char **environ;
 
/* Only deal with a pointer to environ, to work around subtle bugs with shared
libraries and/or small data systems where the user declares his own
'environ'. */
static char ***p_environ = &environ;
 
static int
do_system (ptr, s)
struct _reent *ptr;
_CONST char *s;
{
char *argv[4];
int pid, status;
 
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *) s;
argv[3] = NULL;
 
if ((pid = _fork_r (ptr)) == 0)
{
_execve ("/bin/sh", argv, *p_environ);
exit (100);
}
else if (pid == -1)
return -1;
else
{
int rc = _wait_r (ptr, &status);
if (rc == -1)
return -1;
status = (status >> 8) & 0xff;
return status;
}
}
#endif
 
#if defined (__CYGWIN__)
static int
do_system (ptr, s)
struct _reent *ptr;
_CONST char *s;
{
char *argv[4];
int pid, status;
 
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *) s;
argv[3] = NULL;
 
if ((pid = vfork ()) == 0)
{
/* ??? It's not clear what's the right path to take (pun intended :-).
There won't be an "sh" in any fixed location so we need each user
to be able to say where to find "sh". That suggests using an
environment variable, but after a few more such situations we may
have too many of them. */
char *sh = getenv ("SH_PATH");
if (sh == NULL)
sh = "/bin/sh";
_execve (sh, argv, environ);
exit (100);
}
else if (pid == -1)
return -1;
else
{
int rc = _wait (&status);
if (rc == -1)
return -1;
status = (status >> 8) & 0xff;
return status;
}
}
#endif
/dtoastub.c
0,0 → 1,23
#include <_ansi.h>
#include <stdlib.h>
#include <reent.h>
#include <string.h>
 
/* Nothing in newlib actually *calls* dtoa, they all call _dtoa_r, so this
is a safe way of providing it to the user. */
#ifndef NO_REENT
 
char *
_DEFUN (__dtoa,
(d, mode, ndigits, decpt, sign, rve),
double d _AND
int mode _AND
int ndigits _AND
int *decpt _AND
int *sign _AND
char **rve)
{
return _dtoa_r (_REENT, d, mode, ndigits, decpt, sign, rve);
}
 
#endif
/dtoa.c
0,0 → 1,853
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by AT&T.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
 
/* Please send bug reports to
David M. Gay
AT&T Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-2070
U.S.A.
dmg@research.att.com or research!dmg
*/
 
#include <_ansi.h>
#include <stdlib.h>
#include <reent.h>
#include <string.h>
#include "mprec.h"
 
static int
_DEFUN (quorem,
(b, S),
_Bigint * b _AND _Bigint * S)
{
int n;
__Long borrow, y;
__ULong carry, q, ys;
__ULong *bx, *bxe, *sx, *sxe;
#ifdef Pack_32
__Long z;
__ULong si, zs;
#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 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 >> 16;
Sign_Extend (borrow, y);
z = (*bx >> 16) - (zs & 0xffff) + borrow;
borrow = z >> 16;
Sign_Extend (borrow, z);
Storeinc (bx, z, y);
#else
ys = *sx++ * q + carry;
carry = ys >> 16;
y = *bx - (ys & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
*bx++ = y & 0xffff;
#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 Pack_32
si = *sx++;
ys = (si & 0xffff) + carry;
zs = (si >> 16) + (ys >> 16);
carry = zs >> 16;
y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
z = (*bx >> 16) - (zs & 0xffff) + borrow;
borrow = z >> 16;
Sign_Extend (borrow, z);
Storeinc (bx, z, y);
#else
ys = *sx++ + carry;
carry = ys >> 16;
y = *bx - (ys & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
*bx++ = y & 0xffff;
#endif
}
while (sx <= sxe);
bx = b->_x;
bxe = bx + n;
if (!*bxe)
{
while (--bxe > bx && !*bxe)
--n;
b->_wds = n;
}
}
return q;
}
 
/* 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 *
_DEFUN (_dtoa_r,
(ptr, _d, mode, ndigits, decpt, sign, rve),
struct _reent *ptr _AND
double _d _AND
int mode _AND
int ndigits _AND
int *decpt _AND
int *sign _AND
char **rve)
{
/* 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-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, be, dig, i, ieps, ilim, ilim0, ilim1, j, j1, k, k0,
k_check, leftright, m2, m5, s2, s5, spec_case, try_quick;
union double_union d, d2, eps;
__Long L;
#ifndef Sudden_Underflow
int denorm;
__ULong x;
#endif
_Bigint *b, *b1, *delta, *mlo, *mhi, *S;
double ds;
char *s, *s0;
 
d.d = _d;
 
if (ptr->_result)
{
ptr->_result->_k = ptr->_result_k;
ptr->_result->_maxwds = 1 << ptr->_result_k;
Bfree (ptr, ptr->_result);
ptr->_result = 0;
}
 
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;
s =
#ifdef IEEE_Arith
!word1 (d) && !(word0 (d) & 0xfffff) ? "Infinity" :
#endif
"NaN";
if (rve)
*rve =
#ifdef IEEE_Arith
s[3] ? s + 8 :
#endif
s + 3;
return s;
}
#endif
#ifdef IBM
d.d += 0; /* normalize */
#endif
if (!d.d)
{
*decpt = 1;
s = "0";
if (rve)
*rve = s + 1;
return s;
}
 
b = d2b (ptr, d.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
d2.d = d.d;
word0 (d2) &= Frac_mask1;
word0 (d2) |= Exp_11;
#ifdef IBM
if (j = 11 - hi0bits (word0 (d2) & Frac_mask))
d2.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.)
*/
 
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));
d2.d = x;
word0 (d2) -= 31 * Exp_msk1; /* adjust exponent */
i -= (Bias + (P - 1) - 1) + 1;
denorm = 1;
}
#endif
ds = (d2.d - 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 (d.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;
ilim = ilim1 = -1;
switch (mode)
{
case 0:
case 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;
}
j = sizeof (__ULong);
for (ptr->_result_k = 0; sizeof (_Bigint) - sizeof (__ULong) + j <= i;
j <<= 1)
ptr->_result_k++;
ptr->_result = Balloc (ptr, ptr->_result_k);
s = s0 = (char *) ptr->_result;
 
if (ilim >= 0 && ilim <= Quick_max && try_quick)
{
/* Try to get by with floating-point arithmetic. */
 
i = 0;
d2.d = d.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;
d.d /= bigtens[n_bigtens - 1];
ieps++;
}
for (; j; j >>= 1, i++)
if (j & 1)
{
ieps++;
ds *= bigtens[i];
}
d.d /= ds;
}
else if ((j1 = -k) != 0)
{
d.d *= tens[j1 & 0xf];
for (j = j1 >> 4; j; j >>= 1, i++)
if (j & 1)
{
ieps++;
d.d *= bigtens[i];
}
}
if (k_check && d.d < 1. && ilim > 0)
{
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
d.d *= 10.;
ieps++;
}
eps.d = ieps * d.d + 7.;
word0 (eps) -= (P - 1) * Exp_msk1;
if (ilim == 0)
{
S = mhi = 0;
d.d -= 5.;
if (d.d > eps.d)
goto one_digit;
if (d.d < -eps.d)
goto no_digits;
goto fast_failed;
}
#ifndef No_leftright
if (leftright)
{
/* Use Steele & White method of only
* generating digits needed.
*/
eps.d = 0.5 / tens[ilim - 1] - eps.d;
for (i = 0;;)
{
L = d.d;
d.d -= L;
*s++ = '0' + (int) L;
if (d.d < eps.d)
goto ret1;
if (1. - d.d < eps.d)
goto bump_up;
if (++i >= ilim)
break;
eps.d *= 10.;
d.d *= 10.;
}
}
else
{
#endif
/* Generate ilim digits, then fix them up. */
eps.d *= tens[ilim - 1];
for (i = 1;; i++, d.d *= 10.)
{
L = d.d;
d.d -= L;
*s++ = '0' + (int) L;
if (i == ilim)
{
if (d.d > 0.5 + eps.d)
goto bump_up;
else if (d.d < 0.5 - eps.d)
{
while (*--s == '0');
s++;
goto ret1;
}
break;
}
}
#ifndef No_leftright
}
#endif
fast_failed:
s = s0;
d.d = d2.d;
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 || d.d <= 5 * ds)
goto no_digits;
goto one_digit;
}
for (i = 1;; i++)
{
L = d.d / ds;
d.d -= L * ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (d.d < 0)
{
L--;
d.d += ds;
}
#endif
*s++ = '0' + (int) L;
if (i == ilim)
{
d.d += d.d;
if ((d.d > ds) || ((d.d == ds) && (L & 1)))
{
bump_up:
while (*--s == '9')
if (s == s0)
{
k++;
*s = '0';
break;
}
++*s++;
}
break;
}
if (!(d.d *= 10.))
break;
}
goto ret1;
}
 
m2 = b2;
m5 = b5;
mhi = mlo = 0;
if (leftright)
{
if (mode < 2)
{
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
}
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 (ptr, 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 (ptr, mhi, m5);
b1 = mult (ptr, mhi, b);
Bfree (ptr, b);
b = b1;
}
if ((j = b5 - m5) != 0)
b = pow5mult (ptr, b, j);
}
else
b = pow5mult (ptr, b, b5);
}
S = i2b (ptr, 1);
if (s5 > 0)
S = pow5mult (ptr, S, s5);
 
/* Check for special case that d is a normalized power of 2. */
 
spec_case = 0;
if (mode < 2)
{
if (!word1 (d) && !(word0 (d) & Bndry_mask)
#ifndef Sudden_Underflow
&& word0 (d) & Exp_mask
#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 (ptr, b, b2);
if (s2 > 0)
S = lshift (ptr, S, s2);
if (k_check)
{
if (cmp (b, S) < 0)
{
k--;
b = multadd (ptr, b, 10, 0); /* we botched the k estimate */
if (leftright)
mhi = multadd (ptr, mhi, 10, 0);
ilim = ilim1;
}
}
if (ilim <= 0 && mode > 2)
{
if (ilim < 0 || cmp (b, S = multadd (ptr, 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 (ptr, mhi, m2);
 
/* Compute mlo -- check for special case
* that d is a normalized power of 2.
*/
 
mlo = mhi;
if (spec_case)
{
mhi = Balloc (ptr, mhi->_k);
Bcopy (mhi, mlo);
mhi = lshift (ptr, 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 (ptr, S, mhi);
j1 = delta->_sign ? 1 : cmp (b, delta);
Bfree (ptr, delta);
#ifndef ROUND_BIASED
if (j1 == 0 && !mode && !(word1 (d) & 1))
{
if (dig == '9')
goto round_9_up;
if (j > 0)
dig++;
*s++ = dig;
goto ret;
}
#endif
if ((j < 0) || ((j == 0) && !mode
#ifndef ROUND_BIASED
&& !(word1 (d) & 1)
#endif
))
{
if (j1 > 0)
{
b = lshift (ptr, b, 1);
j1 = cmp (b, S);
if (((j1 > 0) || ((j1 == 0) && (dig & 1)))
&& dig++ == '9')
goto round_9_up;
}
*s++ = dig;
goto ret;
}
if (j1 > 0)
{
if (dig == '9')
{ /* possible if i == 1 */
round_9_up:
*s++ = '9';
goto roundoff;
}
*s++ = dig + 1;
goto ret;
}
*s++ = dig;
if (i == ilim)
break;
b = multadd (ptr, b, 10, 0);
if (mlo == mhi)
mlo = mhi = multadd (ptr, mhi, 10, 0);
else
{
mlo = multadd (ptr, mlo, 10, 0);
mhi = multadd (ptr, mhi, 10, 0);
}
}
}
else
for (i = 1;; i++)
{
*s++ = dig = quorem (b, S) + '0';
if (i >= ilim)
break;
b = multadd (ptr, b, 10, 0);
}
 
/* Round off last digit */
 
b = lshift (ptr, 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
{
while (*--s == '0');
s++;
}
ret:
Bfree (ptr, S);
if (mhi)
{
if (mlo && mlo != mhi)
Bfree (ptr, mlo);
Bfree (ptr, mhi);
}
ret1:
Bfree (ptr, b);
*s = 0;
*decpt = k + 1;
if (rve)
*rve = s;
return s0;
}
/mtrim.c
0,0 → 1,17
/* mtrim.c -- a wrapper for malloc_trim. */
 
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
 
#ifndef _REENT_ONLY
 
int
_DEFUN (malloc_trim, (pad),
size_t pad)
{
return _malloc_trim_r (_REENT, pad);
}
 
#endif
/strtoull.c
0,0 → 1,139
/*
FUNCTION
<<strtoull>>---string to unsigned long long
 
INDEX
strtoull
INDEX
_strtoull_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
unsigned long long strtoull(const char *<[s]>, char **<[ptr]>,
int <[base]>);
 
unsigned long long _strtoull_r(void *<[reent]>, const char *<[s]>,
char **<[ptr]>, int <[base]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
unsigned long long strtoull(<[s]>, <[ptr]>, <[base]>)
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
unsigned long long _strtoull_r(<[reent]>, <[s]>, <[ptr]>, <[base]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
DESCRIPTION
The function <<strtoull>> converts the string <<*<[s]>>> to
an <<unsigned long long>>. First, it breaks down the string into three parts:
leading whitespace, which is ignored; a subject string consisting
of the digits meaningful in the radix specified by <[base]>
(for example, <<0>> through <<7>> if the value of <[base]> is 8);
and a trailing portion consisting of one or more unparseable characters,
which always includes the terminating null character. Then, it attempts
to convert the subject string into an unsigned long long integer, and returns the
result.
 
If the value of <[base]> is zero, the subject string is expected to look
like a normal C integer constant (save that no optional sign is permitted):
a possible <<0x>> indicating hexadecimal radix, and a number.
If <[base]> is between 2 and 36, the expected form of the subject is a
sequence of digits (which may include letters, depending on the
base) representing an integer in the radix specified by <[base]>.
The letters <<a>>--<<z>> (or <<A>>--<<Z>>) are used as digits valued from
10 to 35. If <[base]> is 16, a leading <<0x>> is permitted.
 
The subject sequence is the longest initial sequence of the input
string that has the expected form, starting with the first
non-whitespace character. If the string is empty or consists entirely
of whitespace, or if the first non-whitespace character is not a
permissible digit, the subject string is empty.
 
If the subject string is acceptable, and the value of <[base]> is zero,
<<strtoull>> attempts to determine the radix from the input string. A
string with a leading <<0x>> is treated as a hexadecimal value; a string with
a leading <<0>> and no <<x>> is treated as octal; all other strings are
treated as decimal. If <[base]> is between 2 and 36, it is used as the
conversion radix, as described above. Finally, a pointer to the first
character past the converted subject string is stored in <[ptr]>, if
<[ptr]> is not <<NULL>>.
 
If the subject string is empty (that is, if <<*>><[s]> does not start
with a substring in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
 
The alternate function <<_strtoull_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
 
 
RETURNS
<<strtoull>> returns the converted value, if any. If no conversion was
made, <<0>> is returned.
 
<<strtoull>> returns <<ULONG_LONG_MAX>> if the magnitude of the converted
value is too large, and sets <<errno>> to <<ERANGE>>.
 
PORTABILITY
<<strtoull>> is nonstandard.
 
<<strtoull>> requires no supporting OS subroutines.
*/
 
/*
* Copyright (c) 1990 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 <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
 
#ifndef _REENT_ONLY
 
unsigned long long
_DEFUN (strtoull, (s, ptr, base),
_CONST char *s _AND
char **ptr _AND
int base)
{
return _strtoull_r (_REENT, s, ptr, base);
}
 
#endif
/seed48.c
0,0 → 1,43
/*
* 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 "rand48.h"
 
unsigned short *
_DEFUN (_seed48_r, (r, xseed),
struct _reent *r _AND
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;
}
 
#ifndef _REENT_ONLY
unsigned short *
_DEFUN (seed48, (xseed),
unsigned short xseed[3])
{
return _seed48_r (_REENT, xseed);
}
#endif /* !_REENT_ONLY */
/ldiv.c
0,0 → 1,109
/*
FUNCTION
<<ldiv>>---divide two long integers
 
INDEX
ldiv
 
ANSI_SYNOPSIS
#include <stdlib.h>
ldiv_t ldiv(long <[n]>, long <[d]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
ldiv_t ldiv(<[n]>, <[d]>)
long <[n]>, <[d]>;
 
DESCRIPTION
Divide
@tex
$n/d$,
@end tex
@ifinfo
<[n]>/<[d]>,
@end ifinfo
returning quotient and remainder as two long integers in a structure <<ldiv_t>>.
 
RETURNS
The result is represented with the structure
 
. typedef struct
. {
. long quot;
. long rem;
. } ldiv_t;
 
where the <<quot>> field represents the quotient, and <<rem>> the
remainder. For nonzero <[d]>, if `<<<[r]> = ldiv(<[n]>,<[d]>);>>' then
<[n]> equals `<<<[r]>.rem + <[d]>*<[r]>.quot>>'.
 
To divide <<int>> rather than <<long>> values, use the similar
function <<div>>.
 
PORTABILITY
<<ldiv>> is ANSI.
 
No supporting OS subroutines are required.
*/
 
 
/*
* Copyright (c) 1990 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 <_ansi.h>
#include <stdlib.h> /* ldiv_t */
 
ldiv_t
_DEFUN (ldiv, (num, denom),
long num _AND
long denom)
{
ldiv_t r;
 
/* see div.c for comments */
 
r.quot = num / denom;
r.rem = num % denom;
if (num >= 0 && r.rem < 0) {
++r.quot;
r.rem -= denom;
}
else if (num < 0 && r.rem > 0) {
--r.quot;
r.rem += denom;
}
return (r);
}
/atoff.c
0,0 → 1,9
#include <stdlib.h>
#include <_ansi.h>
 
float
_DEFUN (atoff, (s),
_CONST char *s)
{
return strtodf (s, NULL);
}
/stdlib.tex
0,0 → 1,134
@node Stdlib
@chapter Standard Utility Functions (@file{stdlib.h})
 
This chapter groups utility functions useful in a variety of programs.
The corresponding declarations are in the header file @file{stdlib.h}.
 
@menu
* abort:: Abnormal termination of a program
* abs:: Integer absolute value (magnitude)
* assert:: Macro for Debugging Diagnostics
* atexit:: Request execution of functions at program exit
* atof:: String to double or float
* atoi:: String to integer
* bsearch:: Binary search
* calloc:: Allocate space for arrays
* div:: Divide two integers
* ecvtbuf:: Double or float to string of digits
* ecvt:: Double or float to string of digits (malloc result)
* __env_lock:: Lock environment list for getenv and setenv
* gvcvt:: Format double or float as string
* exit:: End program execution
* getenv:: Look up environment variable
* labs:: Long integer absolute value (magnitude)
* ldiv:: Divide two long integers
* malloc:: Allocate and manage memory (malloc, realloc, free)
* mallinfo:: Get information about allocated memory
* __malloc_lock:: Lock memory pool for malloc and free
* mbstowcs:: Minimal multibyte string to wide string converter
* mblen:: Minimal multibyte length
* mbtowc:: Minimal multibyte to wide character converter
* qsort:: Sort an array
* rand:: Pseudo-random numbers
* rand48:: Uniformaly distributed pseudo-random numbers
* strtod:: String to double or float
* strtol:: String to long
* strtoul:: String to unsigned long
* system:: Execute command string
* wcstombs:: Minimal wide string to multibyte string converter
* wctomb:: Minimal wide character to multibyte converter
@end menu
 
@page
@include stdlib/abort.def
 
@page
@include stdlib/abs.def
 
@page
@include stdlib/assert.def
 
@page
@include stdlib/atexit.def
 
@page
@include stdlib/atof.def
 
@page
@include stdlib/atoi.def
 
@page
@include stdlib/bsearch.def
 
@page
@include stdlib/calloc.def
 
@page
@include stdlib/div.def
 
@page
@include stdlib/efgcvt.def
 
@page
@include stdlib/ecvtbuf.def
 
@page
@include stdlib/envlock.def
 
@page
@include stdlib/exit.def
 
@page
@include stdlib/getenv.def
 
@page
@include stdlib/labs.def
 
@page
@include stdlib/ldiv.def
 
@page
@include stdlib/malloc.def
 
@page
@include stdlib/mstats.def
 
@page
@include stdlib/mlock.def
 
@page
@include stdlib/mblen.def
 
@page
@include stdlib/mbstowcs.def
 
@page
@include stdlib/mbtowc.def
 
@page
@include stdlib/qsort.def
 
@page
@include stdlib/rand.def
 
@page
@include stdlib/rand48.def
 
@page
@include stdlib/strtod.def
 
@page
@include stdlib/strtol.def
 
@page
@include stdlib/strtoul.def
 
@page
@include stdlib/system.def
 
@page
@include stdlib/wcstombs.def
 
@page
@include stdlib/wctomb.def
 
/envlock.c
0,0 → 1,51
/*
FUNCTION
<<__env_lock>>, <<__env_unlock>>--lock environ variable
 
INDEX
__env_lock
INDEX
__env_unlock
 
ANSI_SYNOPSIS
#include "envlock.h"
void __env_lock (struct _reent *<[reent]>);
void __env_unlock (struct _reent *<[reent]>);
 
TRAD_SYNOPSIS
void __env_lock(<[reent]>)
struct _reent *<[reent]>;
 
void __env_unlock(<[reent]>)
struct _reent *<[reent]>;
 
DESCRIPTION
The <<setenv>> family of routines call these functions when they need
to modify the environ variable. The version of these routines supplied
in the library does not do anything. If multiple threads of execution
can call <<setenv>>, or if <<setenv>> can be called reentrantly, then
you need to define your own versions of these functions in order to
safely lock the memory pool during a call. If you do not, the memory
pool may become corrupted.
 
A call to <<setenv>> may call <<__env_lock>> recursively; that is,
the sequence of calls may go <<__env_lock>>, <<__env_lock>>,
<<__env_unlock>>, <<__env_unlock>>. Any implementation of these
routines must be careful to avoid causing a thread to wait for a lock
that it already holds.
*/
 
#include "envlock.h"
 
 
void
__env_lock (ptr)
struct _reent *ptr;
{
}
 
void
__env_unlock (ptr)
struct _reent *ptr;
{
}
/putenv_r.c
0,0 → 1,57
/* This file may have been modified by DJ Delorie (Jan 1991). If so,
** these modifications are Copyright (C) 1991 DJ Delorie
*/
 
/*-
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#include <reent.h>
#include <stdlib.h>
#include <string.h>
 
#include "envlock.h"
 
/* _putenv_r - reentrant version of putenv that either adds
or replaces the environment variable "name"
with "value" which is specified by str as "name=value". */
int
_DEFUN (_putenv_r, (reent_ptr, str),
struct _reent *reent_ptr _AND
_CONST char *str)
{
register char *p, *equal;
int rval;
 
p = _strdup_r (reent_ptr, str);
 
if (!p)
return 1;
 
if (!(equal = index (p, '=')))
{
(void) _free_r (reent_ptr, p);
return 1;
}
 
*equal = '\0';
rval = _setenv_r (reent_ptr, p, equal + 1, 1);
(void) _free_r (reent_ptr, p);
 
return rval;
}
/strtoll.c
0,0 → 1,138
/*
FUNCTION
<<strtoll>>---string to long long
 
INDEX
strtoll
INDEX
_strtoll_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
long long strtoll(const char *<[s]>, char **<[ptr]>,int <[base]>);
 
long long _strtoll_r(void *<[reent]>,
const char *<[s]>, char **<[ptr]>,int <[base]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
long strtoll (<[s]>, <[ptr]>, <[base]>)
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
long _strtoll_r (<[reent]>, <[s]>, <[ptr]>, <[base]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
DESCRIPTION
The function <<strtoll>> converts the string <<*<[s]>>> to
a <<long long>>. First, it breaks down the string into three parts:
leading whitespace, which is ignored; a subject string consisting
of characters resembling an integer in the radix specified by <[base]>;
and a trailing portion consisting of zero or more unparseable characters,
and always including the terminating null character. Then, it attempts
to convert the subject string into a <<long long>> and returns the
result.
 
If the value of <[base]> is 0, the subject string is expected to look
like a normal C integer constant: an optional sign, a possible `<<0x>>'
indicating a hexadecimal base, and a number. If <[base]> is between
2 and 36, the expected form of the subject is a sequence of letters
and digits representing an integer in the radix specified by <[base]>,
with an optional plus or minus sign. The letters <<a>>--<<z>> (or,
equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35;
only letters whose ascribed values are less than <[base]> are
permitted. If <[base]> is 16, a leading <<0x>> is permitted.
 
The subject sequence is the longest initial sequence of the input
string that has the expected form, starting with the first
non-whitespace character. If the string is empty or consists entirely
of whitespace, or if the first non-whitespace character is not a
permissible letter or digit, the subject string is empty.
 
If the subject string is acceptable, and the value of <[base]> is zero,
<<strtoll>> attempts to determine the radix from the input string. A
string with a leading <<0x>> is treated as a hexadecimal value; a string with
a leading 0 and no <<x>> is treated as octal; all other strings are
treated as decimal. If <[base]> is between 2 and 36, it is used as the
conversion radix, as described above. If the subject string begins with
a minus sign, the value is negated. Finally, a pointer to the first
character past the converted subject string is stored in <[ptr]>, if
<[ptr]> is not <<NULL>>.
 
If the subject string is empty (or not in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
 
The alternate function <<_strtoll_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
 
RETURNS
<<strtoll>> returns the converted value, if any. If no conversion was
made, 0 is returned.
 
<<strtoll>> returns <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>> if the magnitude of
the converted value is too large, and sets <<errno>> to <<ERANGE>>.
 
PORTABILITY
<<strtoll>> is nonstandard.
 
No supporting OS subroutines are required.
*/
 
/*-
* Copyright (c) 1990 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 <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
 
#ifndef _REENT_ONLY
 
long long
_DEFUN (strtoll, (s, ptr, base),
_CONST char *s _AND
char **ptr _AND
int base)
{
return _strtoll_r (_REENT, s, ptr, base);
}
 
#endif
/envlock.h
0,0 → 1,15
/* envlock.h -- header file for env routines. */
 
#ifndef _INCLUDE_ENVLOCK_H_
#define _INCLUDE_ENVLOCK_H_
 
#include <_ansi.h>
#include <sys/reent.h>
 
#define ENV_LOCK __env_lock(reent_ptr)
#define ENV_UNLOCK __env_unlock(reent_ptr)
 
void _EXFUN(__env_lock,(struct _reent *reent));
void _EXFUN(__env_unlock,(struct _reent *reent));
 
#endif /* _INCLUDE_ENVLOCK_H_ */
/eprintf.c
0,0 → 1,26
/* This is an implementation of the __eprintf function which is
compatible with the assert.h which is distributed with gcc.
 
This function is provided because in some cases libgcc.a will not
provide __eprintf. This will happen if inhibit_libc is defined,
which is done because at the time that libgcc2.c is compiled, the
correct <stdio.h> may not be available. newlib provides its own
copy of assert.h, which calls __assert, not __eprintf. However, in
some cases you may accidentally wind up compiling with the gcc
assert.h. In such a case, this __eprintf will be used if there
does not happen to be one in libgcc2.c. */
 
#include <stdlib.h>
#include <stdio.h>
 
void
__eprintf (format, file, line, expression)
const char *format;
const char *file;
unsigned int line;
const char *expression;
{
(void) fiprintf (stderr, format, file, line, expression);
abort ();
/*NOTREACHED*/
}
/qsort.c
0,0 → 1,222
/*
FUNCTION
<<qsort>>---sort an array
 
INDEX
qsort
 
ANSI_SYNOPSIS
#include <stdlib.h>
void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
int (*<[compar]>)(const void *, const void *) );
 
TRAD_SYNOPSIS
#include <stdlib.h>
qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> )
char *<[base]>;
size_t <[nmemb]>;
size_t <[size]>;
int (*<[compar]>)();
 
DESCRIPTION
<<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
<[size]> describes the size of each element of the array.
 
You must supply a pointer to a comparison function, using the argument
shown as <[compar]>. (This permits sorting objects of unknown
properties.) Define the comparison function to accept two arguments,
each a pointer to an element of the array starting at <[base]>. The
result of <<(*<[compar]>)>> must be negative if the first argument is
less than the second, zero if the two arguments match, and positive if
the first argument is greater than the second (where ``less than'' and
``greater than'' refer to whatever arbitrary ordering is appropriate).
 
The array is sorted in place; that is, when <<qsort>> returns, the
array elements beginning at <[base]> have been reordered.
 
RETURNS
<<qsort>> does not return a result.
 
PORTABILITY
<<qsort>> is required by ANSI (without specifying the sorting algorithm).
*/
 
/*-
* 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 <_ansi.h>
#include <stdlib.h>
 
#ifndef __GNUC__
#define inline
#endif
 
static inline char *med3 _PARAMS((char *, char *, char *, int (*)()));
static inline void swapfunc _PARAMS((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); \
register TYPE *pi = (TYPE *) (parmi); \
register TYPE *pj = (TYPE *) (parmj); \
do { \
register 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
_DEFUN(swapfunc, (a, b, n, swaptype),
char *a _AND
char *b _AND
int n _AND
int 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)
 
static inline char *
_DEFUN(med3, (a, b, c, cmp),
char *a _AND
char *b _AND
char *c _AND
int (*cmp)())
{
return cmp(a, b) < 0 ?
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
:(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
}
 
void
_DEFUN(qsort, (a, n, es, cmp),
void *a _AND
size_t n _AND
size_t es _AND
int (*cmp)())
{
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(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);
pm = med3(pm - d, pm, pm + d, cmp);
pn = med3(pn - 2 * d, pn - d, pn, cmp);
}
pm = med3(pl, pm, pn, cmp);
}
swap(a, pm);
pa = pb = (char *) a + es;
 
pc = pd = (char *) a + (n - 1) * es;
for (;;) {
while (pb <= pc && (r = cmp(pb, a)) <= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pa, pb);
pa += es;
}
pb += es;
}
while (pb <= pc && (r = cmp(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(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)
qsort(a, r / es, es, cmp);
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);*/
}
/lcong48.c
0,0 → 1,37
/*
* 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 "rand48.h"
 
_VOID
_DEFUN (_lcong48_r, (r, p),
struct _reent *r _AND
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];
}
 
#ifndef _REENT_ONLY
_VOID
_DEFUN (lcong48, (p),
unsigned short p[7])
{
_lcong48_r (_REENT, p);
}
#endif /* !_REENT_ONLY */
/strtod.c
0,0 → 1,731
/*
FUNCTION
<<strtod>>, <<strtodf>>---string to double or float
 
INDEX
strtod
INDEX
_strtod_r
INDEX
strtodf
 
ANSI_SYNOPSIS
#include <stdlib.h>
double strtod(const char *<[str]>, char **<[tail]>);
float strtodf(const char *<[str]>, char **<[tail]>);
 
double _strtod_r(void *<[reent]>,
const char *<[str]>, char **<[tail]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
double strtod(<[str]>,<[tail]>)
char *<[str]>;
char **<[tail]>;
 
float strtodf(<[str]>,<[tail]>)
char *<[str]>;
char **<[tail]>;
 
double _strtod_r(<[reent]>,<[str]>,<[tail]>)
char *<[reent]>;
char *<[str]>;
char **<[tail]>;
 
DESCRIPTION
The function <<strtod>> parses the character string <[str]>,
producing a substring which can be converted to a double
value. The substring converted is the longest initial
subsequence of <[str]>, beginning with the first
non-whitespace character, that has the format:
.[+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>]
The substring contains no characters if <[str]> is empty, consists
entirely of whitespace, or if the first non-whitespace
character is something other than <<+>>, <<->>, <<.>>, or a
digit. If the substring is empty, no conversion is done, and
the value of <[str]> is stored in <<*<[tail]>>>. Otherwise,
the substring is converted, and a pointer to the final string
(which will contain at least the terminating null character of
<[str]>) is stored in <<*<[tail]>>>. If you want no
assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>.
<<strtodf>> is identical to <<strtod>> except for its return type.
 
This implementation returns the nearest machine number to the
input decimal string. Ties are broken by using the IEEE
round-even rule.
 
The alternate function <<_strtod_r>> is a reentrant version.
The extra argument <[reent]> is a pointer to a reentrancy structure.
 
RETURNS
<<strtod>> returns the converted substring value, if any. If
no conversion could be performed, 0 is returned. If the
correct value is out of the range of representable values,
plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is
stored in errno. If the correct value would cause underflow, 0
is returned and <<ERANGE>> is stored in errno.
 
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
 
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by AT&T.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
 
/* Please send bug reports to
David M. Gay
AT&T Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-2070
U.S.A.
dmg@research.att.com or research!dmg
*/
 
#include <_ansi.h>
#include <reent.h>
#include <string.h>
#include "mprec.h"
 
double
_DEFUN (_strtod_r, (ptr, s00, se),
struct _reent *ptr _AND
_CONST char *s00 _AND
char **se)
{
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e1, esign, i, j,
k, nd, nd0, nf, nz, nz0, sign;
long e;
_CONST char *s, *s0, *s1;
double aadj, aadj1, adj;
long L;
unsigned long z;
__ULong y;
union double_union rv, rv0;
 
_Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
sign = nz0 = nz = 0;
rv.d = 0.;
for (s = s00;; s++)
switch (*s)
{
case '-':
sign = 1;
/* no break */
case '+':
if (*++s)
goto break2;
/* no break */
case 0:
s = s00;
goto ret;
case '\t':
case '\n':
case '\v':
case '\f':
case '\r':
case ' ':
continue;
default:
goto break2;
}
break2:
if (*s == '0')
{
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;
if (c == '.')
{
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)
{
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')
{
e = c - '0';
s1 = s;
while ((c = *++s) >= '0' && c <= '9')
e = 10 * e + c - '0';
if (s - s1 > 8)
/* Avoid confusion from exponents
* so large that e might overflow.
*/
e = 9999999L;
if (esign)
e = -e;
}
else
e = 0;
}
else
s = s00;
}
if (!nd)
{
if (!nz && !nz0)
s = s00;
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;
rv.d = y;
if (k > 9)
rv.d = tens[k - 9] * rv.d + z;
bd0 = 0;
if (nd <= DBL_DIG
#ifndef RND_PRODQUOT
&& FLT_ROUNDS == 1
#endif
)
{
if (!e)
goto ret;
if (e > 0)
{
if (e <= Ten_pmax)
{
#ifdef VAX
goto vax_ovfl_check;
#else
/* rv.d = */ rounded_product (rv.d, 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.
*/
e -= i;
rv.d *= 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.d = */ rounded_product (rv.d, tens[e]);
if ((word0 (rv) & Exp_mask)
> Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P))
goto ovfl;
word0 (rv) += P * Exp_msk1;
#else
/* rv.d = */ rounded_product (rv.d, tens[e]);
#endif
goto ret;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax)
{
/* rv.d = */ rounded_quotient (rv.d, tens[-e]);
goto ret;
}
#endif
}
e1 += nd - k;
 
/* Get starting approximation = rv.d * 10**e1 */
 
if (e1 > 0)
{
if ((i = e1 & 15) != 0)
rv.d *= tens[i];
if (e1 &= ~15)
{
if (e1 > DBL_MAX_10_EXP)
{
ovfl:
ptr->_errno = ERANGE;
#ifdef _HAVE_STDC
rv.d = HUGE_VAL;
#else
/* Can't trust HUGE_VAL */
#ifdef IEEE_Arith
word0 (rv) = Exp_mask;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = 0;
#endif
#else
word0 (rv) = Big0;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = Big1;
#endif
#endif
#endif
if (bd0)
goto retfree;
goto ret;
}
if (e1 >>= 4)
{
for (j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
rv.d *= bigtens[j];
/* The last multiplication could overflow. */
word0 (rv) -= P * Exp_msk1;
rv.d *= 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;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = Big1;
#endif
}
else
word0 (rv) += P * Exp_msk1;
}
 
}
}
else if (e1 < 0)
{
e1 = -e1;
if ((i = e1 & 15) != 0)
rv.d /= tens[i];
if (e1 &= ~15)
{
e1 >>= 4;
if (e1 >= 1 << n_bigtens)
goto undfl;
for (j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
rv.d *= tinytens[j];
/* The last multiplication could underflow. */
rv0.d = rv.d;
rv.d *= tinytens[j];
if (!rv.d)
{
rv.d = 2. * rv0.d;
rv.d *= tinytens[j];
if (!rv.d)
{
undfl:
rv.d = 0.;
ptr->_errno = ERANGE;
if (bd0)
goto retfree;
goto ret;
}
#ifndef _DOUBLE_IS_32BITS
word0 (rv) = Tiny0;
word1 (rv) = Tiny1;
#else
word0 (rv) = Tiny1;
#endif
/* The refinement below will clean
* this approximation up.
*/
}
}
}
 
/* Now the hard part -- adjusting rv to the correct value.*/
 
/* Put digits into bd: true value = bd * 10^e */
 
bd0 = s2b (ptr, s0, nd0, nd, y);
 
for (;;)
{
bd = Balloc (ptr, bd0->_k);
Bcopy (bd, bd0);
bb = d2b (ptr, rv.d, &bbe, &bbbits); /* rv.d = bb * 2^bbe */
bs = i2b (ptr, 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 Sudden_Underflow
#ifdef IBM
j = 1 + 4 * P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
#else
j = P + 1 - bbbits;
#endif
#else
i = bbe + bbbits - 1; /* logb(rv.d) */
if (i < Emin) /* denormal */
j = bbe + (P - Emin);
else
j = P + 1 - bbbits;
#endif
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 (ptr, bs, bb5);
bb1 = mult (ptr, bs, bb);
Bfree (ptr, bb);
bb = bb1;
}
if (bb2 > 0)
bb = lshift (ptr, bb, bb2);
if (bd5 > 0)
bd = pow5mult (ptr, bd, bd5);
if (bd2 > 0)
bd = lshift (ptr, bd, bd2);
if (bs2 > 0)
bs = lshift (ptr, bs, bs2);
delta = diff (ptr, bb, bd);
dsign = delta->_sign;
delta->_sign = 0;
i = cmp (delta, bs);
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)
break;
delta = lshift (ptr, 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) == 0xffffffff)
{
/*boundary case -- increment exponent*/
word0 (rv) = (word0 (rv) & Exp_mask)
+ Exp_msk1
#ifdef IBM
| Exp_msk1 >> 4
#endif
;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = 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
if (L <= Exp_msk1)
#endif
goto undfl;
L -= Exp_msk1;
#else
L = (word0 (rv) & Exp_mask) - Exp_msk1;
#endif
word0 (rv) = L | Bndry_mask1;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = 0xffffffff;
#endif
#ifdef IBM
goto cont;
#else
break;
#endif
}
#ifndef ROUND_BIASED
if (!(word1 (rv) & LSB))
break;
#endif
if (dsign)
rv.d += ulp (rv.d);
#ifndef ROUND_BIASED
else
{
rv.d -= ulp (rv.d);
#ifndef Sudden_Underflow
if (!rv.d)
goto undfl;
#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 (FLT_ROUNDS)
{
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
}
y = word0 (rv) & Exp_mask;
 
/* Check for overflow */
 
if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
{
rv0.d = rv.d;
word0 (rv) -= P * Exp_msk1;
adj = aadj1 * ulp (rv.d);
rv.d += adj;
if ((word0 (rv) & Exp_mask) >=
Exp_msk1 * (DBL_MAX_EXP + Bias - P))
{
if (word0 (rv0) == Big0 && word1 (rv0) == Big1)
goto ovfl;
#ifdef _DOUBLE_IS_32BITS
word0 (rv) = Big1;
#else
word0 (rv) = Big0;
word1 (rv) = Big1;
#endif
goto cont;
}
else
word0 (rv) += P * Exp_msk1;
}
else
{
#ifdef Sudden_Underflow
if ((word0 (rv) & Exp_mask) <= P * Exp_msk1)
{
rv0.d = rv.d;
word0 (rv) += P * Exp_msk1;
adj = aadj1 * ulp (rv.d);
rv.d += 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 (rv.d);
rv.d += adj;
}
#else
/* Compute adj so that the IEEE rounding rules will
* correctly round rv.d + adj in some half-way cases.
* If rv.d * ulp(rv.d) 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 (rv.d);
rv.d += adj;
#endif
}
z = word0 (rv) & Exp_mask;
if (y == z)
{
/* Can we stop now? */
L = 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;
}
cont:
Bfree (ptr, bb);
Bfree (ptr, bd);
Bfree (ptr, bs);
Bfree (ptr, delta);
}
retfree:
Bfree (ptr, bb);
Bfree (ptr, bd);
Bfree (ptr, bs);
Bfree (ptr, bd0);
Bfree (ptr, delta);
ret:
if (se)
*se = (char *) s;
return sign ? -rv.d : rv.d;
}
 
#ifndef NO_REENT
 
double
_DEFUN (strtod, (s00, se),
_CONST char *s00 _AND char **se)
{
return _strtod_r (_REENT, s00, se);
}
 
float
_DEFUN (strtodf, (s00, se),
_CONST char *s00 _AND
char **se)
{
return _strtod_r (_REENT, s00, se);
}
 
#endif
/putenv.c
0,0 → 1,32
/*-
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
#include <string.h>
 
int
_DEFUN (putenv, (str),
_CONST char *str)
{
return _putenv_r (_REENT, str);
}
 
#endif /* !_REENT_ONLY */
/labs.c
0,0 → 1,49
/*
FUNCTION
<<labs>>---long integer absolute value
 
INDEX
labs
 
ANSI_SYNOPSIS
#include <stdlib.h>
long labs(long <[i]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
long labs(<[i]>)
long <[i]>;
 
DESCRIPTION
<<labs>> returns
@tex
$|x|$,
@end tex
the absolute value of <[i]> (also called the magnitude
of <[i]>). That is, if <[i]> is negative, the result is the opposite
of <[i]>, but if <[i]> is nonnegative the result is <[i]>.
 
The similar function <<abs>> uses and returns <<int>> rather than
<<long>> values.
 
RETURNS
The result is a nonnegative long integer.
 
PORTABILITY
<<labs>> is ANSI.
 
No supporting OS subroutine calls are required.
*/
 
#include <stdlib.h>
 
long
_DEFUN (labs, (x),
long x)
{
if (x < 0)
{
x = -x;
}
return x;
}
/div.c
0,0 → 1,132
/*
FUNCTION
<<div>>---divide two integers
 
INDEX
div
 
ANSI_SYNOPSIS
#include <stdlib.h>
div_t div(int <[n]>, int <[d]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
div_t div(<[n]>, <[d]>)
int <[n]>, <[d]>;
 
DESCRIPTION
Divide
@tex
$n/d$,
@end tex
@ifinfo
<[n]>/<[d]>,
@end ifinfo
returning quotient and remainder as two integers in a structure <<div_t>>.
 
RETURNS
The result is represented with the structure
 
. typedef struct
. {
. int quot;
. int rem;
. } div_t;
 
where the <<quot>> field represents the quotient, and <<rem>> the
remainder. For nonzero <[d]>, if `<<<[r]> = div(<[n]>,<[d]>);>>' then
<[n]> equals `<<<[r]>.rem + <[d]>*<[r]>.quot>>'.
 
To divide <<long>> rather than <<int>> values, use the similar
function <<ldiv>>.
 
PORTABILITY
<<div>> is ANSI.
 
No supporting OS subroutines are required.
*/
 
/*
* Copyright (c) 1990 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 <_ansi.h>
#include <stdlib.h> /* div_t */
 
div_t
_DEFUN (div, (num, denom),
int num _AND
int denom)
{
div_t r;
 
r.quot = num / denom;
r.rem = num % denom;
/*
* The ANSI standard says that |r.quot| <= |n/d|, where
* n/d is to be computed in infinite precision. In other
* words, we should always truncate the quotient towards
* 0, never -infinity or +infinity.
*
* Machine division and remainer may work either way when
* one or both of n or d is negative. If only one is
* negative and r.quot has been truncated towards -inf,
* r.rem will have the same sign as denom and the opposite
* sign of num; if both are negative and r.quot has been
* truncated towards -inf, r.rem will be positive (will
* have the opposite sign of num). These are considered
* `wrong'.
*
* If both are num and denom are positive, r will always
* be positive.
*
* This all boils down to:
* if num >= 0, but r.rem < 0, we got the wrong answer.
* In that case, to get the right answer, add 1 to r.quot and
* subtract denom from r.rem.
* if num < 0, but r.rem > 0, we also have the wrong answer.
* In this case, to get the right answer, subtract 1 from r.quot and
* add denom to r.rem.
*/
if (num >= 0 && r.rem < 0) {
++r.quot;
r.rem -= denom;
}
else if (num < 0 && r.rem > 0) {
--r.quot;
r.rem += denom;
}
return (r);
}
/rand.c
0,0 → 1,89
/*
FUNCTION
<<rand>>, <<srand>>---pseudo-random numbers
 
INDEX
rand
INDEX
srand
INDEX
rand_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
int rand(void);
void srand(unsigned int <[seed]>);
int rand_r(unsigned int *<[seed]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int rand();
 
void srand(<[seed]>)
unsigned int <[seed]>;
 
void rand_r(<[seed]>)
unsigned int *<[seed]>;
 
 
DESCRIPTION
<<rand>> returns a different integer each time it is called; each
integer is chosen by an algorithm designed to be unpredictable, so
that you can use <<rand>> when you require a random number.
The algorithm depends on a static variable called the ``random seed'';
starting with a given value of the random seed always produces the
same sequence of numbers in successive calls to <<rand>>.
 
You can set the random seed using <<srand>>; it does nothing beyond
storing its argument in the static variable used by <<rand>>. You can
exploit this to make the pseudo-random sequence less predictable, if
you wish, by using some other unpredictable value (often the least
significant parts of a time-varying value) as the random seed before
beginning a sequence of calls to <<rand>>; or, if you wish to ensure
(for example, while debugging) that successive runs of your program
use the same ``random'' numbers, you can use <<srand>> to set the same
random seed at the outset.
 
RETURNS
<<rand>> returns the next pseudo-random integer in sequence; it is a
number between <<0>> and <<RAND_MAX>> (inclusive).
 
<<srand>> does not return a result.
 
NOTES
<<rand>> and <<srand>> are unsafe for multi-thread applications.
<<rand_r>> is MT-Safe and should be used instead.
 
 
PORTABILITY
<<rand>> is required by ANSI, but the algorithm for pseudo-random
number generation is not specified; therefore, even if you use
the same random seed, you cannot expect the same sequence of results
on two different systems.
 
<<rand>> requires no supporting OS subroutines.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
#include <reent.h>
 
void
_DEFUN (srand, (seed), unsigned int seed)
{
_REENT->_new._reent._rand_next = seed;
}
 
int
_DEFUN_VOID (rand)
{
/* This multiplier was obtained from Knuth, D.E., "The Art of
Computer Programming," Vol 2, Seminumerical Algorithms, Third
Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 */
_REENT->_new._reent._rand_next =
_REENT->_new._reent._rand_next * __extension__ 6364136223846793005LL + 1;
return (int)((_REENT->_new._reent._rand_next >> 32) & RAND_MAX);
}
 
#endif /* _REENT_ONLY */
/strtol.c
0,0 → 1,226
/*
FUNCTION
<<strtol>>---string to long
 
INDEX
strtol
INDEX
_strtol_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
long strtol(const char *<[s]>, char **<[ptr]>,int <[base]>);
 
long _strtol_r(void *<[reent]>,
const char *<[s]>, char **<[ptr]>,int <[base]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
long strtol (<[s]>, <[ptr]>, <[base]>)
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
long _strtol_r (<[reent]>, <[s]>, <[ptr]>, <[base]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
DESCRIPTION
The function <<strtol>> converts the string <<*<[s]>>> to
a <<long>>. First, it breaks down the string into three parts:
leading whitespace, which is ignored; a subject string consisting
of characters resembling an integer in the radix specified by <[base]>;
and a trailing portion consisting of zero or more unparseable characters,
and always including the terminating null character. Then, it attempts
to convert the subject string into a <<long>> and returns the
result.
 
If the value of <[base]> is 0, the subject string is expected to look
like a normal C integer constant: an optional sign, a possible `<<0x>>'
indicating a hexadecimal base, and a number. If <[base]> is between
2 and 36, the expected form of the subject is a sequence of letters
and digits representing an integer in the radix specified by <[base]>,
with an optional plus or minus sign. The letters <<a>>--<<z>> (or,
equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35;
only letters whose ascribed values are less than <[base]> are
permitted. If <[base]> is 16, a leading <<0x>> is permitted.
 
The subject sequence is the longest initial sequence of the input
string that has the expected form, starting with the first
non-whitespace character. If the string is empty or consists entirely
of whitespace, or if the first non-whitespace character is not a
permissible letter or digit, the subject string is empty.
 
If the subject string is acceptable, and the value of <[base]> is zero,
<<strtol>> attempts to determine the radix from the input string. A
string with a leading <<0x>> is treated as a hexadecimal value; a string with
a leading 0 and no <<x>> is treated as octal; all other strings are
treated as decimal. If <[base]> is between 2 and 36, it is used as the
conversion radix, as described above. If the subject string begins with
a minus sign, the value is negated. Finally, a pointer to the first
character past the converted subject string is stored in <[ptr]>, if
<[ptr]> is not <<NULL>>.
 
If the subject string is empty (or not in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
 
The alternate function <<_strtol_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
 
RETURNS
<<strtol>> returns the converted value, if any. If no conversion was
made, 0 is returned.
 
<<strtol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of
the converted value is too large, and sets <<errno>> to <<ERANGE>>.
 
PORTABILITY
<<strtol>> is ANSI.
 
No supporting OS subroutines are required.
*/
 
/*-
* Copyright (c) 1990 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 <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
 
/*
* Convert a string to a long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long
_DEFUN (_strtol_r, (rptr, nptr, endptr, base),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr _AND
int base)
{
register const char *s = nptr;
register unsigned long acc;
register int c;
register unsigned long cutoff;
register int neg = 0, 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.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else 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;
 
/*
* 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 longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, 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 ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : '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;
rptr->_errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
 
#ifndef _REENT_ONLY
 
long
_DEFUN (strtol, (s, ptr, base),
_CONST char *s _AND
char **ptr _AND
int base)
{
return _strtol_r (_REENT, s, ptr, base);
}
 
#endif
/Makefile.am
0,0 → 1,212
## Process this file with automake to generate Makefile.in
 
AUTOMAKE_OPTIONS = cygnus
 
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
 
LIB_SOURCES = \
__adjust.c \
__exp10.c \
__ten_mu.c \
abort.c \
abs.c \
assert.c \
atexit.c \
atof.c \
atoff.c \
atoi.c \
atol.c \
bsearch.c \
calloc.c \
div.c \
drand48.c \
dtoa.c \
dtoastub.c \
ecvtbuf.c \
efgcvt.c \
environ.c \
envlock.c \
eprintf.c \
erand48.c \
exit.c \
getenv.c \
getenv_r.c \
getopt.c \
jrand48.c \
labs.c \
lcong48.c \
ldiv.c \
ldtoa.c \
lrand48.c \
malign.c \
malloc.c \
mblen.c \
mblen_r.c \
mbstowcs.c \
mbstowcs_r.c \
mbtowc.c \
mbtowc_r.c \
mlock.c \
mprec.c \
mrand48.c \
msize.c \
mstats.c \
mtrim.c \
nrand48.c \
putenv.c \
putenv_r.c \
qsort.c \
rand.c \
rand48.c \
rand_r.c \
realloc.c \
seed48.c \
setenv.c \
setenv_r.c \
srand48.c \
strdup.c \
strdup_r.c \
strtod.c \
strtol.c \
strtoll.c \
strtoll_r.c \
strtoul.c \
strtoull.c \
strtoull_r.c \
system.c \
valloc.c \
wcstombs.c \
wcstombs_r.c \
wctomb.c \
wctomb_r.c
 
# Because of how libtool moves objects around, mallocr must be built last.
LIBADD_OBJS = freer.$(oext) reallocr.$(oext) callocr.$(oext) cfreer.$(oext) malignr.$(oext) \
vallocr.$(oext) pvallocr.$(oext) mallinfor.$(oext) mallstatsr.$(oext) msizer.$(oext) malloptr.$(oext) mallocr.$(oext)
 
libstdlib_la_LDFLAGS = -Xcompiler -nostdlib
 
if USE_LIBTOOL
noinst_LTLIBRARIES = libstdlib.la
libstdlib_la_SOURCES = $(LIB_SOURCES)
libstdlib_la_LIBADD = $(LIBADD_OBJS)
LIB_COMPILE = $(LTCOMPILE)
noinst_DATA = objectlist.awk.in
else
noinst_LIBRARIES = lib.a
lib_a_SOURCES = $(LIB_SOURCES)
lib_a_LIBADD = $(LIBADD_OBJS)
LIB_COMPILE = $(COMPILE)
noinst_DATA =
endif # USE_LIBTOOL
 
include $(srcdir)/../../Makefile.shared
 
MALLOC_COMPILE = $(LIB_COMPILE) -DINTERNAL_NEWLIB
 
mallocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/mallocr.c -o $@
 
freer.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/mallocr.c -o $@
 
reallocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/mallocr.c -o $@
 
callocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/mallocr.c -o $@
 
cfreer.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_CFREE -c $(srcdir)/mallocr.c -o $@
 
malignr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/mallocr.c -o $@
 
vallocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_VALLOC -c $(srcdir)/mallocr.c -o $@
 
pvallocr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_PVALLOC -c $(srcdir)/mallocr.c -o $@
 
mallinfor.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLINFO -c $(srcdir)/mallocr.c -o $@
 
mallstatsr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLOC_STATS -c $(srcdir)/mallocr.c -o $@
 
msizer.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLOC_USABLE_SIZE -c $(srcdir)/mallocr.c -o $@
 
malloptr.$(oext): mallocr.c
$(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/mallocr.c -o $@
 
CHEWOUT_FILES= \
abort.def \
abs.def \
assert.def \
atexit.def \
atof.def \
ecvtbuf.def \
atoi.def \
bsearch.def \
calloc.def \
div.def \
efgcvt.def \
envlock.def \
exit.def \
getenv.def \
labs.def \
ldiv.def \
malloc.def \
mallocr.def \
mblen.def \
mbstowcs.def \
mbtowc.def \
mlock.def \
mstats.def \
qsort.def \
rand.def \
rand48.def \
strtod.def \
strtol.def \
strtoll.def \
strtoul.def \
strtoull.def \
system.def \
wcstombs.def \
wctomb.def
 
SUFFIXES = .def
 
CHEW = ../../doc/makedoc -f $(srcdir)/../../doc/doc.str
 
.c.def:
$(CHEW) < $< > $*.def 2> $*.ref
touch stmp-def
 
TARGETDOC = ../tmp.texi
 
doc: $(CHEWOUT_FILES)
cat $(srcdir)/stdlib.tex >> $(TARGETDOC)
 
CLEANFILES = $(CHEWOUT_FILES) *.ref
 
dtoa.$(oext): dtoa.c mprec.h
ldtoa.$(oext): ldtoa.c mprec.h
ecvtbuf.$(oext): ecvtbuf.c mprec.h
mbtowc_r.$(oext): mbtowc_r.c mbctype.h
$(LIB_COMPILE) -c -fshort-enums $(srcdir)/mbtowc_r.c -o $@
 
mprec.$(oext): mprec.c mprec.h
strtod.$(oext): strtod.c mprec.h
wctomb_r.$(oext): wctomb_r.c mbctype.h
drand48.$(oext): drand48.c rand48.h
erand48.$(oext): erand48.c rand48.h
jrand48.$(oext): jrand48.c rand48.h
lcong48.$(oext): lcong48.c rand48.h
lrand48.$(oext): lrand48.c rand48.h
mrand48.$(oext): mrand48.c rand48.h
nrand48.$(oext): nrand48.c rand48.h
rand48.$(oext): rand48.c rand48.h
seed48.$(oext): seed48.c rand48.h
srand48.$(oext): srand48.c rand48.h
/getenv.c
0,0 → 1,94
/*
FUNCTION
<<getenv>>---look up environment variable
 
INDEX
getenv
INDEX
environ
 
ANSI_SYNOPSIS
#include <stdlib.h>
char *getenv(const char *<[name]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
char *getenv(<[name]>)
char *<[name]>;
 
DESCRIPTION
<<getenv>> searches the list of environment variable names and values
(using the global pointer ``<<char **environ>>'') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<getenv>> returns a pointer to the associated value.
 
RETURNS
A pointer to the (string) value of the environment variable, or
<<NULL>> if there is no such environment variable.
 
PORTABILITY
<<getenv>> is ANSI, but the rules for properly forming names of environment
variables vary from one system to another.
 
<<getenv>> requires a global pointer <<environ>>.
*/
 
/*
* Copyright (c) 1987, 2000 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
 
/*
* _findenv --
* Returns pointer to value associated with name, if any, else NULL.
* Sets offset to be the offset of the name/value combination in the
* environmental array, for use by setenv(3) and unsetenv(3).
* Explicitly removes '=' in argument name.
*
* This routine *should* be a static; don't use it.
*/
 
char *
_DEFUN (_findenv, (name, offset),
register _CONST char *name _AND
int *offset)
{
return _findenv_r (_REENT, name, offset);
}
 
/*
* getenv --
* Returns ptr to value associated with name, if any, else NULL.
*/
 
char *
_DEFUN (getenv, (name),
_CONST char *name)
{
int offset;
char *_findenv_r ();
 
return _findenv_r (_REENT, name, &offset);
}
 
#endif /* !_REENT_ONLY */
/__exp10.c
0,0 → 1,29
/*
* compute 10**x by successive squaring.
*/
 
#include <_ansi.h>
 
double
_DEFUN (__exp10, (x),
unsigned x)
{
static _CONST double powtab[] =
{1.0,
10.0,
100.0,
1000.0,
10000.0};
 
if (x < (sizeof (powtab) / sizeof (double)))
return powtab[x];
else if (x & 1)
{
return 10.0 * __exp10 (x - 1);
}
else
{
double n = __exp10 (x / 2);
return n * n;
}
}
/atoi.c
0,0 → 1,54
/*
FUNCTION
<<atoi>>, <<atol>>---string to integer
 
INDEX
atoi
INDEX
atol
 
ANSI_SYNOPSIS
#include <stdlib.h>
int atoi(const char *<[s]>);
long atol(const char *<[s]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int atoi(<[s]>)
char *<[s]>;
 
long atol(<[s]>)
char *<[s]>;
 
 
DESCRIPTION
<<atoi>> converts the initial portion of a string to an <<int>>.
<<atol>> converts the initial portion of a string to a <<long>>.
 
<<atoi(s)>> is implemented as <<(int)strtol(s, NULL, 10).>>
<<atol(s)>> is implemented as <<strtol(s, NULL, 10).>>
 
RETURNS
The functions return the converted value, if any. If no conversion was
made, <<0>> is returned.
 
PORTABILITY
<<atoi>> is ANSI.
 
No supporting OS subroutines are required.
*/
 
/*
* Andy Wilson, 2-Oct-89.
*/
 
#include <stdlib.h>
#include <_ansi.h>
 
int
_DEFUN (atoi, (s),
_CONST char *s)
{
return (int) strtol (s, NULL, 10);
}
 
/calloc.c
0,0 → 1,69
#ifdef MALLOC_PROVIDED
int _dummy_calloc = 1;
#else
/*
FUNCTION
<<calloc>>---allocate space for arrays
 
INDEX
calloc
 
INDEX
_calloc_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
void *calloc(size_t <[n]>, size_t <[s]>);
void *calloc_r(void *<[reent]>, size_t <n>, <size_t> <[s]>);
TRAD_SYNOPSIS
#include <stdlib.h>
char *calloc(<[n]>, <[s]>)
size_t <[n]>, <[s]>;
 
char *_calloc_r(<[reent]>, <[n]>, <[s]>)
char *<[reent]>;
size_t <[n]>;
size_t <[s]>;
 
 
 
DESCRIPTION
Use <<calloc>> to request a block of memory sufficient to hold an
array of <[n]> elements, each of which has size <[s]>.
 
The memory allocated by <<calloc>> comes out of the same memory pool
used by <<malloc>>, but the memory block is initialized to all zero
bytes. (To avoid the overhead of initializing the space, use
<<malloc>> instead.)
 
The alternate function <<_calloc_r>> is reentrant.
The extra argument <[reent]> is a pointer to a reentrancy structure.
 
RETURNS
If successful, a pointer to the newly allocated space.
 
If unsuccessful, <<NULL>>.
 
PORTABILITY
<<calloc>> is ANSI.
 
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
 
#include <string.h>
#include <stdlib.h>
 
#ifndef _REENT_ONLY
 
_PTR
_DEFUN (calloc, (n, size),
size_t n _AND
size_t size)
{
return _calloc_r (_REENT, n, size);
}
 
#endif
#endif /* MALLOC_PROVIDED */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.