From d210a76d458b799e300d55b6799f0d64c8449129 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Wed, 19 Oct 2016 01:34:56 +0000 Subject: [PATCH] newlib: wide char support git-svn-id: svn://kolibrios.org@6607 a494cfbc-eb01-0410-851d-a64ba20cac60 --- contrib/sdk/sources/newlib/libc/Makefile | 100 +- .../sdk/sources/newlib/libc/include/newlib.h | 2 +- .../sources/newlib/libc/include/sys/unistd.h | 6 +- .../sdk/sources/newlib/libc/stdio/fgetwc.c | 243 ++ .../sdk/sources/newlib/libc/stdio/fgetwc_u.c | 49 + .../sdk/sources/newlib/libc/stdio/fgetws.c | 212 + .../sdk/sources/newlib/libc/stdio/fgetws_u.c | 28 + .../sdk/sources/newlib/libc/stdio/fputwc_u.c | 51 + .../sdk/sources/newlib/libc/stdio/fputws.c | 193 + .../sdk/sources/newlib/libc/stdio/fputws_u.c | 28 + .../sdk/sources/newlib/libc/stdio/fwprintf.c | 56 + .../sdk/sources/newlib/libc/stdio/fwscanf.c | 53 + contrib/sdk/sources/newlib/libc/stdio/getw.c | 69 + contrib/sdk/sources/newlib/libc/stdio/getwc.c | 52 + .../sdk/sources/newlib/libc/stdio/getwc_u.c | 53 + .../sdk/sources/newlib/libc/stdio/getwchar.c | 126 + .../sources/newlib/libc/stdio/getwchar_u.c | 51 + contrib/sdk/sources/newlib/libc/stdio/putw.c | 65 + contrib/sdk/sources/newlib/libc/stdio/putwc.c | 53 + .../sdk/sources/newlib/libc/stdio/putwc_u.c | 54 + .../sdk/sources/newlib/libc/stdio/putwchar.c | 125 + .../sources/newlib/libc/stdio/putwchar_u.c | 53 + .../sdk/sources/newlib/libc/stdio/swprintf.c | 635 +++ .../sdk/sources/newlib/libc/stdio/swscanf.c | 487 +++ .../sdk/sources/newlib/libc/stdio/ungetwc.c | 117 + .../sdk/sources/newlib/libc/stdio/vfwprintf.c | 2019 +++++++++ .../sdk/sources/newlib/libc/stdio/vfwscanf.c | 1499 +++++++ .../sdk/sources/newlib/libc/stdio/vswprintf.c | 82 + .../sdk/sources/newlib/libc/stdio/vswscanf.c | 62 + .../sdk/sources/newlib/libc/stdio/vwprintf.c | 49 + .../sdk/sources/newlib/libc/stdio/vwscanf.c | 51 + .../sdk/sources/newlib/libc/stdio/wprintf.c | 58 + .../sdk/sources/newlib/libc/stdio/wscanf.c | 56 + .../sdk/sources/newlib/libc/stdlib/btowc.c | 33 + .../sdk/sources/newlib/libc/stdlib/ldtoa.c | 3868 +++++++++++++++++ .../sdk/sources/newlib/libc/stdlib/mblen.c | 81 + .../sdk/sources/newlib/libc/stdlib/mblen_r.c | 77 + .../sdk/sources/newlib/libc/stdlib/mbrlen.c | 22 + .../sdk/sources/newlib/libc/stdlib/mbsinit.c | 14 + .../sources/newlib/libc/stdlib/mbsnrtowcs.c | 182 + .../sources/newlib/libc/stdlib/mbsrtowcs.c | 31 + .../sdk/sources/newlib/libc/stdlib/mbstowcs.c | 83 + .../sources/newlib/libc/stdlib/mbstowcs_r.c | 38 + .../sdk/sources/newlib/libc/stdlib/mbtowc.c | 192 +- .../sdk/sources/newlib/libc/stdlib/mbtowc_r.c | 1296 +++--- .../sdk/sources/newlib/libc/stdlib/mlock.c | 128 +- .../sdk/sources/newlib/libc/stdlib/random.c | 82 + .../sources/newlib/libc/stdlib/wcsnrtombs.c | 188 + .../sources/newlib/libc/stdlib/wcsrtombs.c | 28 + .../sdk/sources/newlib/libc/stdlib/wcstod.c | 232 + .../sdk/sources/newlib/libc/stdlib/wcstol.c | 227 + .../sdk/sources/newlib/libc/stdlib/wcstold.c | 108 + .../sdk/sources/newlib/libc/stdlib/wcstoll.c | 139 + .../sources/newlib/libc/stdlib/wcstoll_r.c | 140 + .../sdk/sources/newlib/libc/stdlib/wcstombs.c | 83 + .../sources/newlib/libc/stdlib/wcstombs_r.c | 48 + .../sdk/sources/newlib/libc/stdlib/wcstoul.c | 207 + .../sdk/sources/newlib/libc/stdlib/wcstoull.c | 140 + .../sources/newlib/libc/stdlib/wcstoull_r.c | 130 + .../sdk/sources/newlib/libc/stdlib/wctob.c | 26 + .../sdk/sources/newlib/libc/stdlib/wctomb.c | 81 + 61 files changed, 13918 insertions(+), 823 deletions(-) create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fgetwc.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fgetwc_u.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fgetws.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fgetws_u.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fputwc_u.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fputws.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fputws_u.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fwprintf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/fwscanf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/getw.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/getwc.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/getwc_u.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/getwchar.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/getwchar_u.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/putw.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/putwc.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/putwc_u.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/putwchar.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/putwchar_u.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/swprintf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/swscanf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/ungetwc.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/vfwprintf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/vfwscanf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/vswprintf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/vswscanf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/vwprintf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/vwscanf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/wprintf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdio/wscanf.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/btowc.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/ldtoa.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/mblen.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/mblen_r.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/mbrlen.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/mbsinit.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/mbsnrtowcs.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/mbsrtowcs.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/mbstowcs.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/mbstowcs_r.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/random.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcsnrtombs.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcsrtombs.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstod.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstol.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstold.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstoll.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstoll_r.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstombs.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstombs_r.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstoul.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstoull.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wcstoull_r.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wctob.c create mode 100644 contrib/sdk/sources/newlib/libc/stdlib/wctomb.c diff --git a/contrib/sdk/sources/newlib/libc/Makefile b/contrib/sdk/sources/newlib/libc/Makefile index 52328de7d4..783d7a598b 100644 --- a/contrib/sdk/sources/newlib/libc/Makefile +++ b/contrib/sdk/sources/newlib/libc/Makefile @@ -165,6 +165,8 @@ STDLIB_SRCS= \ atof.c \ atoi.c \ atol.c \ + btowc.c \ + calloc.c \ cxa_atexit.c \ cxa_finalize.c \ div.c \ @@ -180,18 +182,28 @@ STDLIB_SRCS= \ getenv.c \ getenv_r.c \ itoa.c \ + ldiv.c \ labs.c \ - mprec.c \ - mbtowc.c \ - mbtowc_r.c \ - mbrtowc.c \ - mlock.c \ - calloc.c \ + ldtoa.c \ malloc.c \ mallocr.c \ + mblen.c \ + mblen_r.c \ + mbrlen.c \ + mbrtowc.c \ + mbsinit.c \ + mbsnrtowcs.c \ + mbsrtowcs.c \ + mbstowcs.c \ + mbstowcs_r.c \ + mbtowc.c \ + mbtowc_r.c \ + mlock.c \ + mprec.c \ rand.c \ rand_r.c \ rand48.c \ + random.c \ realloc.c \ seed48.c \ srand48.c \ @@ -208,6 +220,20 @@ STDLIB_SRCS= \ system.c \ utoa.c \ wcrtomb.c \ + wcsnrtombs.c \ + wcsrtombs.c \ + wcstod.c \ + wcstol.c \ + wcstold.c \ + wcstoll.c \ + wcstoll_r.c \ + wcstombs.c \ + wcstombs_r.c \ + wcstoul.c \ + wcstoull.c \ + wcstoull_r.c \ + wctob.c \ + wctomb.c \ wctomb_r.c @@ -322,6 +348,10 @@ STDIO_SRCS= \ fgetpos.c \ fgets.c \ fgets_u.c \ + fgetwc.c \ + fgetwc_u.c \ + fgetws.c \ + fgetws_u.c \ fileno.c \ fileno_u.c \ findfp.c \ @@ -338,6 +368,9 @@ STDIO_SRCS= \ fputs.c \ fputs_u.c \ fputwc.c \ + fputwc_u.c \ + fputws.c \ + fputws_u.c \ fsetpos.c \ funopen.c \ fread.c \ @@ -352,8 +385,10 @@ STDIO_SRCS= \ fvwrite.c \ fwalk.c \ fwide.c \ + fwprintf.c \ fwrite.c \ fwrite_u.c \ + fwscanf.c \ getc.c \ getc_u.c \ getchar.c \ @@ -361,10 +396,14 @@ STDIO_SRCS= \ getdelim.c \ getline.c \ gets.c \ + getw.c \ + getwc.c \ + getwc_u.c \ + getwchar.c \ + getwchar_u.c \ iprintf.c \ iscanf.c \ makebuf.c \ - mbstowcs.c \ mktemp.c \ open_memstream.c \ perror.c \ @@ -374,6 +413,11 @@ STDIO_SRCS= \ putchar.c \ putchar_u.c \ puts.c \ + putw.c \ + putwc.c \ + putwc_u.c \ + putwchar.c \ + putwchar_u.c \ refill.c \ remove.c \ rename.c \ @@ -393,15 +437,19 @@ STDIO_SRCS= \ sscanf.c \ stdio.c \ stdio_ext.c \ + swprintf.c \ + swscanf.c \ tmpfile.c \ tmpnam.c \ ungetc.c \ + ungetwc.c \ vasiprintf.c \ vasniprintf.c \ vasnprintf.c \ vasprintf.c \ vdiprintf.c \ vdprintf.c \ + vfwscanf.c \ viprintf.c \ viscanf.c \ vprintf.c \ @@ -412,8 +460,14 @@ STDIO_SRCS= \ vsniprintf.c \ vsnprintf.c \ vsscanf.c \ - wsetup.c \ - wbuf.c + vswprintf.c \ + vswscanf.c \ + vwprintf.c \ + vwscanf.c \ + wbuf.c \ + wprintf.c \ + wscanf.c \ + wsetup.c MATH_SRCS = e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c e_exp.c e_fmod.c \ @@ -481,10 +535,16 @@ PRINTF_OBJS= stdio/vfprintf.o \ stdio/vfiprintf.o \ stdio/svfprintf.o \ stdio/svfiprintf.o \ + stdio/svfiwprintf.o \ + stdio/svfwprintf.o \ + stdio/vfiwprintf.o \ + stdio/vfwprintf.o \ stdio/vfscanf.o \ stdio/vfiscanf.o \ stdio/svscanf.o \ - stdio/svfiscanf.o + stdio/svfiscanf.o \ + stdio/svfiwscanf.o \ + stdio/svfwscanf.o ifeq ($(findstring static,$(MAKECMDGOALS)),static) @@ -561,7 +621,18 @@ stdio/vfiprintf.o: stdio/vfprintf.c stdio/vfprintf.o: stdio/vfprintf.c $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums stdio/vfprintf.c -o $@ +stdio/svfiwprintf.o: stdio/vfwprintf.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DINTEGER_ONLY -DSTRING_ONLY stdio/vfwprintf.c -o $@ +stdio/svfwprintf.o: stdio/vfwprintf.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DSTRING_ONLY stdio/vfwprintf.c -o $@ + +stdio/vfiwprintf.o: stdio/vfwprintf.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DINTEGER_ONLY stdio/vfwprintf.c -o $@ + +stdio/vfwprintf.o: stdio/vfwprintf.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums stdio/vfwprintf.c -o $@ + stdio/svfiscanf.o: stdio/vfscanf.c $(CC) $(CFLAGS) $(DEFINES) -DINTEGER_ONLY -DSTRING_ONLY $(INCLUDES) stdio/vfscanf.c -o $@ @@ -574,7 +645,14 @@ stdio/vfscanf.o: stdio/vfscanf.c stdio/vfiscanf.o: stdio/vfscanf.c $(CC) $(CFLAGS) $(DEFINES) -DINTEGER_ONLY $(INCLUDES) stdio/vfscanf.c -o $@ - +stdio/svfiwscanf.o: stdio/vfwscanf.c + $(CC) $(CFLAGS) $(DEFINES) -DINTEGER_ONLY -DSTRING_ONLY $(INCLUDES) stdio/vfwscanf.c -o $@ + +stdio/svfwscanf.o: stdio/vfwscanf.c + $(CC) $(CFLAGS) $(DEFINES) -DSTRING_ONLY $(INCLUDES) stdio/vfwscanf.c -o $@ + +stdio/vfiwscanf.o: stdio/vfwscanf.c + $(CC) $(CFLAGS) $(DEFINES) -DINTEGER_ONLY $(INCLUDES) stdio/vfwscanf.c -o $@ diff --git a/contrib/sdk/sources/newlib/libc/include/newlib.h b/contrib/sdk/sources/newlib/libc/include/newlib.h index 873431933e..7585a3a0b4 100644 --- a/contrib/sdk/sources/newlib/libc/include/newlib.h +++ b/contrib/sdk/sources/newlib/libc/include/newlib.h @@ -56,7 +56,7 @@ #define _ATEXIT_DYNAMIC_ALLOC 1 /* True if long double supported. */ -//#define _HAVE_LONG_DOUBLE 1 +#define _HAVE_LONG_DOUBLE 1 /* Define if compiler supports -fno-tree-loop-distribute-patterns. */ #define _HAVE_CC_INHIBIT_LOOP_TO_LIBCALL 1 diff --git a/contrib/sdk/sources/newlib/libc/include/sys/unistd.h b/contrib/sdk/sources/newlib/libc/include/sys/unistd.h index 1ee065378c..e4cda592be 100644 --- a/contrib/sdk/sources/newlib/libc/include/sys/unistd.h +++ b/contrib/sdk/sources/newlib/libc/include/sys/unistd.h @@ -20,7 +20,7 @@ void _EXFUN(_exit, (int __status ) _ATTRIBUTE ((__noreturn__))); int _EXFUN(access,(const char *__path, int __amode )); unsigned _EXFUN(alarm, (unsigned __secs )); int _EXFUN(chdir, (const char *__path )); -int _EXFUN(chmod, (const char *__path, mode_t __mode )); +//int _EXFUN(chmod, (const char *__path, mode_t __mode )); #if !defined(__INSIDE_CYGWIN__) int _EXFUN(chown, (const char *__path, uid_t __owner, gid_t __group )); #endif @@ -66,7 +66,7 @@ int _EXFUN(faccessat, (int __dirfd, const char *__path, int __mode, int __flags) #if __BSD_VISIBLE || __XSI_VISIBLE >= 4 int _EXFUN(fchdir, (int __fildes)); #endif -int _EXFUN(fchmod, (int __fildes, mode_t __mode )); +//int _EXFUN(fchmod, (int __fildes, mode_t __mode )); #if !defined(__INSIDE_CYGWIN__) int _EXFUN(fchown, (int __fildes, uid_t __owner, gid_t __group )); #endif @@ -202,7 +202,7 @@ long _EXFUN(sysconf, (int __name )); pid_t _EXFUN(tcgetpgrp, (int __fildes )); int _EXFUN(tcsetpgrp, (int __fildes, pid_t __pgrp_id )); char * _EXFUN(ttyname, (int __fildes )); -int _EXFUN(ttyname_r, (int, char *, size_t)); +int _EXFUN(ttyname_r, (int, char *, size_t)); int _EXFUN(unlink, (const char *__path )); int _EXFUN(usleep, (useconds_t __useconds)); int _EXFUN(vhangup, (void )); diff --git a/contrib/sdk/sources/newlib/libc/stdio/fgetwc.c b/contrib/sdk/sources/newlib/libc/stdio/fgetwc.c new file mode 100644 index 0000000000..d6de4b6cbd --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fgetwc.c @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +FUNCTION +<>, <>, <>, <>---get a wide character from a file or stream + +INDEX + fgetwc +INDEX + fgetwc_unlocked +INDEX + _fgetwc_r +INDEX + _fgetwc_unlocked_r +INDEX + getwc +INDEX + getwc_unlocked +INDEX + _getwc_r +INDEX + _getwc_unlocked_r + +ANSI_SYNOPSIS + #include + #include + wint_t fgetwc(FILE *<[fp]>); + + #define _GNU_SOURCE + #include + #include + wint_t fgetwc_unlocked(FILE *<[fp]>); + + #include + #include + wint_t _fgetwc_r(struct _reent *<[ptr]>, FILE *<[fp]>); + + #include + #include + wint_t _fgetwc_unlocked_r(struct _reent *<[ptr]>, FILE *<[fp]>); + + #include + #include + wint_t getwc(FILE *<[fp]>); + + #define _GNU_SOURCE + #include + #include + wint_t getwc_unlocked(FILE *<[fp]>); + + #include + #include + wint_t _getwc_r(struct _reent *<[ptr]>, FILE *<[fp]>); + + #include + #include + wint_t _getwc_unlocked_r(struct _reent *<[ptr]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include + #include + wint_t fgetwc(<[fp]>) + FILE *<[fp]>; + + #define _GNU_SOURCE + #include + #include + wint_t fgetwc_unlocked(<[fp]>) + FILE *<[fp]>; + + #include + #include + wint_t _fgetwc_r(<[ptr]>, <[fp]>) + struct _reent *<[ptr]>; + FILE *<[fp]>; + + #include + #include + wint_t _fgetwc_unlocked_r(<[ptr]>, <[fp]>) + struct _reent *<[ptr]>; + FILE *<[fp]>; + + #include + #include + wint_t getwc(<[fp]>) + FILE *<[fp]>; + + #define _GNU_SOURCE + #include + #include + wint_t getwc_unlocked(<[fp]>) + FILE *<[fp]>; + + #include + #include + wint_t _getwc_r(<[ptr]>, <[fp]>) + struct _reent *<[ptr]>; + FILE *<[fp]>; + + #include + #include + wint_t _getwc_unlocked_r(<[ptr]>, <[fp]>) + struct _reent *<[ptr]>; + FILE *<[fp]>; + +DESCRIPTION +Use <> to get the next wide character from the file or stream +identified by <[fp]>. As a side effect, <> advances the file's +current position indicator. + +<> is a non-thread-safe version of <>. +<> may only safely be used within a scope +protected by flockfile() (or ftrylockfile()) and funlockfile(). This +function may safely be used in a multi-threaded program if and only +if they are called while the invoking thread owns the (FILE *) +object, as is the case after a successful call to the flockfile() or +ftrylockfile() functions. If threads are disabled, then +<> is equivalent to <>. + +The <> and <> functions or macros functions identically +to <> and <>. It may be implemented as a macro, and +may evaluate its argument more than once. There is no reason ever to use it. + +<<_fgetwc_r>>, <<_getwc_r>>, <<_fgetwc_unlocked_r>>, and <<_getwc_unlocked_r>> +are simply reentrant versions of the above functions that are passed the +additional reentrant structure pointer argument: <[ptr]>. + +RETURNS +The next wide character cast to <>, unless there is no more data, +or the host system reports a read error; in either of these situations, +<> and <> return <>. + +You can distinguish the two situations that cause an <> result by +using the <> and <> functions. + +PORTABILITY +<> and <> are required by C99 and POSIX.1-2001. + +<> and <> are GNU extensions. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include "local.h" + +wint_t +_DEFUN(__fgetwc, (ptr, fp), + struct _reent *ptr _AND + register FILE *fp) +{ + wchar_t wc; + size_t nconv; + + if (fp->_r <= 0 && __srefill_r (ptr, fp)) + return (WEOF); + if (MB_CUR_MAX == 1) + { + /* Fast path for single-byte encodings. */ + wc = *fp->_p++; + fp->_r--; + return (wc); + } + do + { + nconv = _mbrtowc_r (ptr, &wc, (char *) fp->_p, fp->_r, &fp->_mbstate); + if (nconv == (size_t)-1) + break; + else if (nconv == (size_t)-2) + continue; + else if (nconv == 0) + { + /* + * Assume that the only valid representation of + * the null wide character is a single null byte. + */ + fp->_p++; + fp->_r--; + return (L'\0'); + } + else + { + fp->_p += nconv; + fp->_r -= nconv; + return (wc); + } + } + while (__srefill_r(ptr, fp) == 0); + fp->_flags |= __SERR; + errno = EILSEQ; + return (WEOF); +} + +wint_t +_DEFUN(_fgetwc_r, (ptr, fp), + struct _reent *ptr _AND + register FILE *fp) +{ + wint_t r; + + _newlib_flockfile_start (fp); + ORIENT(fp, 1); + r = __fgetwc (ptr, fp); + _newlib_flockfile_end (fp); + return r; +} + +wint_t +_DEFUN(fgetwc, (fp), + FILE *fp) +{ + struct _reent *reent = _REENT; + + CHECK_INIT(reent, fp); + return _fgetwc_r (reent, fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/fgetwc_u.c b/contrib/sdk/sources/newlib/libc/stdio/fgetwc_u.c new file mode 100644 index 0000000000..4ccd5765c0 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fgetwc_u.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <_ansi.h> +#include +#include +#include "local.h" + +wint_t +_DEFUN(_fgetwc_unlocked_r, (ptr, fp), + struct _reent *ptr _AND + register FILE *fp) +{ + ORIENT(fp, 1); + return __fgetwc (ptr, fp); +} + +wint_t +_DEFUN(fgetwc_unlocked, (fp), + FILE *fp) +{ + struct _reent *reent = _REENT; + + CHECK_INIT(reent, fp); + return _fgetwc_unlocked_r (reent, fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/fgetws.c b/contrib/sdk/sources/newlib/libc/stdio/fgetws.c new file mode 100644 index 0000000000..ae1f48e661 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fgetws.c @@ -0,0 +1,212 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +FUNCTION +<>, <>---get wide character string from a file or stream + +INDEX + fgetws +INDEX + fgetws_unlocked +INDEX + _fgetws_r +INDEX + _fgetws_unlocked_r + +ANSI_SYNOPSIS + #include + wchar_t *fgetws(wchar_t *__restrict <[ws]>, int <[n]>, + FILE *__restrict <[fp]>); + + #define _GNU_SOURCE + #include + wchar_t *fgetws_unlocked(wchar_t *__restrict <[ws]>, int <[n]>, + FILE *__restrict <[fp]>); + + #include + wchar_t *_fgetws_r(struct _reent *<[ptr]>, wchar_t *<[ws]>, + int <[n]>, FILE *<[fp]>); + + #include + wchar_t *_fgetws_unlocked_r(struct _reent *<[ptr]>, wchar_t *<[ws]>, + int <[n]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include + wchar_t *fgetws(<[ws]>,<[n]>,<[fp]>) + wchar_t *__restrict <[ws]>; + int <[n]>; + FILE *__restrict <[fp]>; + + #define _GNU_SOURCE + #include + wchar_t *fgetws_unlocked(<[ws]>,<[n]>,<[fp]>) + wchar_t *__restrict <[ws]>; + int <[n]>; + FILE *__restrict <[fp]>; + + #include + wchar_t *_fgetws_r(<[ptr]>, <[ws]>,<[n]>,<[fp]>) + struct _reent *<[ptr]>; + wchar_t *<[ws]>; + int <[n]>; + FILE *<[fp]>; + + #include + wchar_t *_fgetws_unlocked_r(<[ptr]>, <[ws]>,<[n]>,<[fp]>) + struct _reent *<[ptr]>; + wchar_t *<[ws]>; + int <[n]>; + FILE *<[fp]>; + +DESCRIPTION +Reads at most <[n-1]> wide characters from <[fp]> until a newline +is found. The wide characters including to the newline are stored +in <[ws]>. The buffer is terminated with a 0. + +<> is a non-thread-safe version of <>. +<> may only safely be used within a scope +protected by flockfile() (or ftrylockfile()) and funlockfile(). This +function may safely be used in a multi-threaded program if and only +if they are called while the invoking thread owns the (FILE *) +object, as is the case after a successful call to the flockfile() or +ftrylockfile() functions. If threads are disabled, then +<> is equivalent to <>. + +The <<_fgetws_r>> and <<_fgetws_unlocked_r>> functions are simply reentrant +version of the above and are passed an additional reentrancy structure +pointer: <[ptr]>. + +RETURNS +<> returns the buffer passed to it, with the data +filled in. If end of file occurs with some data already +accumulated, the data is returned with no other indication. If +no data are read, NULL is returned instead. + +PORTABILITY +<> is required by C99 and POSIX.1-2001. + +<> is a GNU extension. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include "local.h" + +#ifdef __IMPL_UNLOCKED__ +#define _fgetws_r _fgetws_unlocked_r +#define fgetws fgetws_unlocked +#endif + +wchar_t * +_DEFUN(_fgetws_r, (ptr, ws, n, fp), + struct _reent *ptr _AND + wchar_t * ws _AND + int n _AND + FILE * fp) +{ + wchar_t *wsp; + size_t nconv; + const char *src; + unsigned char *nl; + + _newlib_flockfile_start (fp); + ORIENT (fp, 1); + + if (n <= 0) + { + errno = EINVAL; + goto error; + } + + if (fp->_r <= 0 && __srefill_r (ptr, fp)) + /* EOF */ + goto error; + wsp = ws; + do + { + src = (char *) fp->_p; + nl = memchr (fp->_p, '\n', fp->_r); + nconv = _mbsnrtowcs_r (ptr, wsp, &src, + /* Read all bytes up to the next NL, or up to the + end of the buffer if there is no NL. */ + nl != NULL ? (nl - fp->_p + 1) : fp->_r, + /* But never more than n - 1 wide chars. */ + n - 1, + &fp->_mbstate); + if (nconv == (size_t) -1) + /* Conversion error */ + goto error; + if (src == NULL) + { + /* + * We hit a null byte. Increment the character count, + * since mbsnrtowcs()'s return value doesn't include + * the terminating null, then resume conversion + * after the null. + */ + nconv++; + src = memchr (fp->_p, '\0', fp->_r); + src++; + } + fp->_r -= (unsigned char *) src - fp->_p; + fp->_p = (unsigned char *) src; + n -= nconv; + wsp += nconv; + } + while (wsp[-1] != L'\n' && n > 1 && (fp->_r > 0 + || __srefill_r (ptr, fp) == 0)); + if (wsp == ws) + /* EOF */ + goto error; + if (!mbsinit (&fp->_mbstate)) + /* Incomplete character */ + goto error; + *wsp++ = L'\0'; + _newlib_flockfile_exit (fp); + return ws; + +error: + _newlib_flockfile_end (fp); + return NULL; +} + +wchar_t * +_DEFUN(fgetws, (ws, n, fp), + wchar_t *__restrict ws _AND + int n _AND + FILE *__restrict fp) +{ + struct _reent *reent = _REENT; + + CHECK_INIT (reent, fp); + return _fgetws_r (reent, ws, n, fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/fgetws_u.c b/contrib/sdk/sources/newlib/libc/stdio/fgetws_u.c new file mode 100644 index 0000000000..ae4d7d9c25 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fgetws_u.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __IMPL_UNLOCKED__ +#include "fgetws.c" diff --git a/contrib/sdk/sources/newlib/libc/stdio/fputwc_u.c b/contrib/sdk/sources/newlib/libc/stdio/fputwc_u.c new file mode 100644 index 0000000000..43be648f75 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fputwc_u.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <_ansi.h> +#include +#include +#include "local.h" + +wint_t +_DEFUN(_fputwc_unlocked_r, (ptr, wc, fp), + struct _reent *ptr _AND + wchar_t wc _AND + FILE *fp) +{ + ORIENT(fp, 1); + return __fputwc(ptr, wc, fp); +} + +wint_t +_DEFUN(fputwc_unlocked, (wc, fp), + wchar_t wc _AND + FILE *fp) +{ + struct _reent *reent = _REENT; + + CHECK_INIT(reent, fp); + return _fputwc_unlocked_r (reent, wc, fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/fputws.c b/contrib/sdk/sources/newlib/libc/stdio/fputws.c new file mode 100644 index 0000000000..bb2fa6dbeb --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fputws.c @@ -0,0 +1,193 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +FUNCTION +<>, <>---write a wide character string in a file or stream + +INDEX + fputws +INDEX + fputws_unlocked +INDEX + _fputws_r +INDEX + _fputws_unlocked_r + +ANSI_SYNOPSIS + #include + int fputws(const wchar_t *__restrict <[ws]>, FILE *__restrict <[fp]>); + + #define _GNU_SOURCE + #include + int fputws_unlocked(const wchar_t *__restrict <[ws]>, FILE *__restrict <[fp]>); + + #include + int _fputws_r(struct _reent *<[ptr]>, const wchar_t *<[ws]>, + FILE *<[fp]>); + + #include + int _fputws_unlocked_r(struct _reent *<[ptr]>, const wchar_t *<[ws]>, + FILE *<[fp]>); + +TRAD_SYNOPSIS + #include + int fputws(<[ws]>, <[fp]>) + wchar_t *__restrict <[ws]>; + FILE *__restrict <[fp]>; + + #define _GNU_SOURCE + #include + int fputws_unlocked(<[ws]>, <[fp]>) + wchar_t *__restrict <[ws]>; + FILE *__restrict <[fp]>; + + #include + int _fputws_r(<[ptr]>, <[ws]>, <[fp]>) + struct _reent *<[ptr]>; + wchar_t *<[ws]>; + FILE *<[fp]>; + + #include + int _fputws_unlocked_r(<[ptr]>, <[ws]>, <[fp]>) + struct _reent *<[ptr]>; + wchar_t *<[ws]>; + FILE *<[fp]>; + +DESCRIPTION +<> writes the wide character string at <[ws]> (but without the +trailing null) to the file or stream identified by <[fp]>. + +<> is a non-thread-safe version of <>. +<> may only safely be used within a scope +protected by flockfile() (or ftrylockfile()) and funlockfile(). This +function may safely be used in a multi-threaded program if and only +if they are called while the invoking thread owns the (FILE *) +object, as is the case after a successful call to the flockfile() or +ftrylockfile() functions. If threads are disabled, then +<> is equivalent to <>. + +<<_fputws_r>> and <<_fputws_unlocked_r>> are simply reentrant versions of the +above that take an additional reentrant struct pointer argument: <[ptr]>. + +RETURNS +If successful, the result is a non-negative integer; otherwise, the result +is <<-1>> to indicate an error. + +PORTABILITY +<> is required by C99 and POSIX.1-2001. + +<> is a GNU extension. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include "fvwrite.h" +#include "local.h" + +#ifdef __IMPL_UNLOCKED__ +#define _fputws_r _fputws_unlocked_r +#define fputws fputws_unlocked +#endif + +int +_DEFUN(_fputws_r, (ptr, ws, fp), + struct _reent *ptr _AND + const wchar_t *ws _AND + FILE *fp) +{ + size_t nbytes; + char buf[BUFSIZ]; +#ifdef _FVWRITE_IN_STREAMIO + struct __suio uio; + struct __siov iov; + + _newlib_flockfile_start (fp); + ORIENT (fp, 1); + if (cantwrite (ptr, fp) != 0) + goto error; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + iov.iov_base = buf; + do + { + nbytes = _wcsrtombs_r(ptr, buf, &ws, sizeof (buf), &fp->_mbstate); + if (nbytes == (size_t) -1) + goto error; + iov.iov_len = uio.uio_resid = nbytes; + if (__sfvwrite_r(ptr, fp, &uio) != 0) + goto error; + } + while (ws != NULL); + _newlib_flockfile_exit (fp); + return (0); + +error: + _newlib_flockfile_end (fp); + return (-1); +#else + _newlib_flockfile_start (fp); + ORIENT (fp, 1); + if (cantwrite (ptr, fp) != 0) + goto error; + + do + { + size_t i = 0; + nbytes = _wcsrtombs_r (ptr, buf, &ws, sizeof (buf), &fp->_mbstate); + if (nbytes == (size_t) -1) + goto error; + while (i < nbytes) + { + if (__sputc_r (ptr, buf[i], fp) == EOF) + goto error; + i++; + } + } + while (ws != NULL); + _newlib_flockfile_exit (fp); + return (0); + +error: + _newlib_flockfile_end (fp); + return (-1); +#endif +} + +int +_DEFUN(fputws, (ws, fp), + const wchar_t *__restrict ws _AND + FILE *__restrict fp) +{ + struct _reent *reent = _REENT; + + CHECK_INIT (reent, fp); + return _fputws_r (reent, ws, fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/fputws_u.c b/contrib/sdk/sources/newlib/libc/stdio/fputws_u.c new file mode 100644 index 0000000000..0583e79fa6 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fputws_u.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __IMPL_UNLOCKED__ +#include "fputws.c" diff --git a/contrib/sdk/sources/newlib/libc/stdio/fwprintf.c b/contrib/sdk/sources/newlib/libc/stdio/fwprintf.c new file mode 100644 index 0000000000..4b05824c45 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fwprintf.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ +/* doc in swprintf.c */ + +#include <_ansi.h> +#include +#include +#include +#include + +int +_DEFUN(_fwprintf_r, (ptr, fp, fmt), + struct _reent *ptr _AND + FILE *fp _AND + const wchar_t *fmt _DOTS) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = _vfwprintf_r (ptr, fp, fmt, ap); + va_end (ap); + return ret; +} + +#ifndef _REENT_ONLY + +int +_DEFUN(fwprintf, (fp, fmt), + FILE *__restrict fp _AND + const wchar_t *__restrict fmt _DOTS) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = _vfwprintf_r (_REENT, fp, fmt, ap); + va_end (ap); + return ret; +} + +#endif /* ! _REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdio/fwscanf.c b/contrib/sdk/sources/newlib/libc/stdio/fwscanf.c new file mode 100644 index 0000000000..8572f4185f --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/fwscanf.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ +/* Doc in swscanf.c */ + +#include <_ansi.h> +#include +#include +#include +#include +#include "local.h" + +#ifndef _REENT_ONLY + +int +fwscanf (FILE *__restrict fp, _CONST wchar_t *__restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = _vfwscanf_r (_REENT, fp, fmt, ap); + va_end (ap); + return ret; +} + +#endif /* !_REENT_ONLY */ + +int +_fwscanf_r (struct _reent *ptr, FILE *fp, _CONST wchar_t *fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = _vfwscanf_r (ptr, fp, fmt, ap); + va_end (ap); + return (ret); +} + diff --git a/contrib/sdk/sources/newlib/libc/stdio/getw.c b/contrib/sdk/sources/newlib/libc/stdio/getw.c new file mode 100644 index 0000000000..210c5939a1 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/getw.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ + +/* +FUNCTION +<>---read a word (int) + +INDEX + getw + +ANSI_SYNOPSIS + #include + int getw(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include + int getw(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +<> is a function, defined in <>. You can use <> +to get the next word from the file or stream identified by <[fp]>. As +a side effect, <> advances the file's current position +indicator. + +RETURNS +The next word (read as an <>), unless there is no more +data or the host system reports a read error; in either of these +situations, <> returns <>. Since <> is a valid +<>, you must use <> or <> to distinguish these +situations. + +PORTABILITY +<> is a remnant of K&R C; it is not part of any ISO C Standard. +<> should be used instead. In fact, this implementation of +<> is based upon <>. + +Supporting OS subroutines required: <>. */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <_ansi.h> +#include + +int +_DEFUN(getw, (fp), + register FILE *fp) +{ + int result; + if (fread ((char*)&result, sizeof (result), 1, fp) != 1) + return EOF; + return result; +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/getwc.c b/contrib/sdk/sources/newlib/libc/stdio/getwc.c new file mode 100644 index 0000000000..6d88fa8698 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/getwc.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <_ansi.h> +#include +#include +#include +#include "local.h" + +#undef getwc + +wint_t +_DEFUN(_getwc_r, (ptr, fp), + struct _reent *ptr _AND + FILE *fp) +{ + return _fgetwc_r (ptr, fp); +} + +/* + * Synonym for fgetwc(). The only difference is that getwc(), if it is a + * macro, may evaluate `fp' more than once. + */ +wint_t +_DEFUN(getwc, (fp), + FILE *fp) +{ + return fgetwc(fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/getwc_u.c b/contrib/sdk/sources/newlib/libc/stdio/getwc_u.c new file mode 100644 index 0000000000..613b69ecaf --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/getwc_u.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define _GNU_SOURCE +#include <_ansi.h> +#include +#include +#include +#include "local.h" + +#undef getwc_unlocked + +wint_t +_DEFUN(_getwc_unlocked_r, (ptr, fp), + struct _reent *ptr _AND + FILE *fp) +{ + return _fgetwc_unlocked_r (ptr, fp); +} + +/* + * Synonym for fgetwc_unlocked(). The only difference is that getwc(), if it is + * a macro, may evaluate `fp' more than once. + */ +wint_t +_DEFUN(getwc_unlocked, (fp), + FILE *fp) +{ + return fgetwc_unlocked(fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/getwchar.c b/contrib/sdk/sources/newlib/libc/stdio/getwchar.c new file mode 100644 index 0000000000..7ab230a4cc --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/getwchar.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +FUNCTION +<>, <>---read a wide character from standard input + +INDEX + getwchar +INDEX + getwchar_unlocked +INDEX + _getwchar_r +INDEX + _getwchar_unlocked_r + +ANSI_SYNOPSIS + #include + wint_t getwchar(void); + + #define _GNU_SOURCE + #include + wint_t getwchar_unlocked(void); + + #include + wint_t _getwchar_r(struct _reent *<[reent]>); + + #include + wint_t _getwchar_unlocked_r(struct _reent *<[reent]>); + +TRAD_SYNOPSIS + #include + wint_t getwchar(); + + #define _GNU_SOURCE + #include + wint_t getwchar_unlocked(); + + #include + wint_t _getwchar_r(<[reent]>) + char * <[reent]>; + + #include + wint_t _getwchar_unlocked_r(<[reent]>) + char * <[reent]>; + +DESCRIPTION +<> function or macro is the wide character equivalent of +the <> function. You can use <> to get the next +wide character from the standard input stream. As a side effect, +<> advances the standard input's current position indicator. + +<> is a non-thread-safe version of <>. +<> may only safely be used within a scope +protected by flockfile() (or ftrylockfile()) and funlockfile(). This +function may safely be used in a multi-threaded program if and only +if they are called while the invoking thread owns the (FILE *) +object, as is the case after a successful call to the flockfile() or +ftrylockfile() functions. If threads are disabled, then +<> is equivalent to <>. + +The alternate functions <<_getwchar_r>> and <<_getwchar_unlocked_r>> are +reentrant versions of the above. The extra argument <[reent]> is a pointer to +a reentrancy structure. + +RETURNS +The next wide character cast to <>, unless there is no more +data, or the host system reports a read error; in either of these +situations, <> returns <>. + +You can distinguish the two situations that cause an <> result by +using `<>' and `<>'. + +PORTABILITY +<> is required by C99. + +<> is a GNU extension. +*/ + +#include <_ansi.h> +#include +#include +#include +#include "local.h" + +#undef getwchar + +wint_t +_DEFUN (_getwchar_r, (ptr), + struct _reent *ptr) +{ + return _fgetwc_r (ptr, stdin); +} + +/* + * Synonym for fgetwc(stdin). + */ +wint_t +_DEFUN_VOID (getwchar) +{ + _REENT_SMALL_CHECK_INIT (_REENT); + return fgetwc (stdin); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/getwchar_u.c b/contrib/sdk/sources/newlib/libc/stdio/getwchar_u.c new file mode 100644 index 0000000000..f5c50ccedf --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/getwchar_u.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define _GNU_SOURCE +#include <_ansi.h> +#include +#include +#include +#include "local.h" + +#undef getwchar_unlocked + +wint_t +_DEFUN (_getwchar_unlocked_r, (ptr), + struct _reent *ptr) +{ + return _fgetwc_unlocked_r (ptr, stdin); +} + +/* + * Synonym for fgetwc_unlocked(stdin). + */ +wint_t +_DEFUN_VOID (getwchar_unlocked) +{ + _REENT_SMALL_CHECK_INIT (_REENT); + return fgetwc_unlocked (stdin); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/putw.c b/contrib/sdk/sources/newlib/libc/stdio/putw.c new file mode 100644 index 0000000000..682015c0a7 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/putw.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ + +/* +FUNCTION +<>---write a word (int) + +INDEX + putw + +ANSI_SYNOPSIS + #include + int putw(int <[w]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include + int putw(, <[fp]>) + int ; + FILE *<[fp]>; + +DESCRIPTION +<> is a function, defined in <>. You can use <> +to write a word to the file or stream identified by <[fp]>. As a side +effect, <> advances the file's current position indicator. + +RETURNS +Zero on success, <> on failure. + +PORTABILITY +<> is a remnant of K&R C; it is not part of any ISO C Standard. +<> should be used instead. In fact, this implementation of +<> is based upon <>. + +Supporting OS subroutines required: <>. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include + +int +_DEFUN(putw, (w, fp), + int w _AND + register FILE *fp) +{ + if (fwrite ((_CONST char*)&w, sizeof (w), 1, fp) != 1) + return EOF; + return 0; +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/putwc.c b/contrib/sdk/sources/newlib/libc/stdio/putwc.c new file mode 100644 index 0000000000..9a84f35fb8 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/putwc.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <_ansi.h> +#include +#include +#include +#include "local.h" + +#undef putwc + +wint_t +_DEFUN(_putwc_r, (ptr, wc, fp), + struct _reent *ptr _AND + wchar_t wc _AND + FILE *fp) +{ + return _fputwc_r (ptr, wc, fp); +} +/* + * Synonym for fputwc(). The only difference is that putwc(), if it is a + * macro, may evaluate `fp' more than once. + */ +wint_t +_DEFUN(putwc, (wc, fp), + wchar_t wc _AND + FILE *fp) +{ + return fputwc (wc, fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/putwc_u.c b/contrib/sdk/sources/newlib/libc/stdio/putwc_u.c new file mode 100644 index 0000000000..bb71acc2a7 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/putwc_u.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2014 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define _GNU_SOURCE +#include <_ansi.h> +#include +#include +#include +#include "local.h" + +#undef putwc_unlocked + +wint_t +_DEFUN(_putwc_unlocked_r, (ptr, wc, fp), + struct _reent *ptr _AND + wchar_t wc _AND + FILE *fp) +{ + return _fputwc_unlocked_r (ptr, wc, fp); +} +/* + * Synonym for fputwc_unlocked(). The only difference is that putwc_unlocked(), + * if it is a macro, may evaluate `fp' more than once. + */ +wint_t +_DEFUN(putwc_unlocked, (wc, fp), + wchar_t wc _AND + FILE *fp) +{ + return fputwc_unlocked (wc, fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/putwchar.c b/contrib/sdk/sources/newlib/libc/stdio/putwchar.c new file mode 100644 index 0000000000..cdd2542172 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/putwchar.c @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +FUNCTION +<>, <>---write a wide character to standard output + +INDEX + putwchar +INDEX + putwchar_unlocked +INDEX + _putwchar_r +INDEX + _putwchar_unlocked_r + +ANSI_SYNOPSIS + #include + wint_t putwchar(wchar_t <[wc]>); + + #include + wint_t putwchar_unlocked(wchar_t <[wc]>); + + #include + wint_t _putwchar_r(struct _reent *<[reent]>, wchar_t <[wc]>); + + #include + wint_t _putwchar_unlocked_r(struct _reent *<[reent]>, wchar_t <[wc]>); + +TRAD_SYNOPSIS + #include + wint_t putwchar(<[wc]>) + wchar_t <[wc]>; + + #include + wint_t putwchar_unlocked(<[wc]>) + wchar_t <[wc]>; + + #include + wint_t _putwchar_r(<[reent]>, <[wc]>) + struct _reent *<[reent]>; + wchar_t <[wc]>; + + #include + wint_t _putwchar_unlocked_r(<[reent]>, <[wc]>) + struct _reent *<[reent]>; + wchar_t <[wc]>; + +DESCRIPTION +The <> function or macro is the wide-character equivalent of +the <> function. It writes the wide character wc to stdout. + +<> is a non-thread-safe version of <>. +<> may only safely be used within a scope +protected by flockfile() (or ftrylockfile()) and funlockfile(). This +function may safely be used in a multi-threaded program if and only +if they are called while the invoking thread owns the (FILE *) +object, as is the case after a successful call to the flockfile() or +ftrylockfile() functions. If threads are disabled, then +<> is equivalent to <>. + +The alternate functions <<_putwchar_r>> and <<_putwchar_unlocked_r>> are +reentrant versions of the above. The extra argument <[reent]> is a pointer +to a reentrancy structure. + +RETURNS +If successful, <> returns its argument <[wc]>. If an error +intervenes, the result is <>. You can use `<>' to +query for errors. + +PORTABILITY +<> is required by C99. + +<> is a GNU extension. +*/ + +#include <_ansi.h> +#include +#include +#include +#include "local.h" + +#undef putwchar + +wint_t +_DEFUN(_putwchar_r, (ptr, wc), + struct _reent *ptr _AND + wchar_t wc) +{ + return _fputwc_r (ptr, wc, stdout); +} + +/* + * Synonym for fputwc(wc, stdout). + */ +wint_t +_DEFUN(putwchar, (wc), + wchar_t wc) +{ + _REENT_SMALL_CHECK_INIT (_REENT); + return fputwc (wc, stdout); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/putwchar_u.c b/contrib/sdk/sources/newlib/libc/stdio/putwchar_u.c new file mode 100644 index 0000000000..3235472a28 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/putwchar_u.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define _GNU_SOURCE +#include <_ansi.h> +#include +#include +#include +#include "local.h" + +#undef putwchar_unlocked + +wint_t +_DEFUN(_putwchar_unlocked_r, (ptr, wc), + struct _reent *ptr _AND + wchar_t wc) +{ + return _fputwc_unlocked_r (ptr, wc, stdout); +} + +/* + * Synonym for fputwc_unlocked(wc, stdout). + */ +wint_t +_DEFUN(putwchar_unlocked, (wc), + wchar_t wc) +{ + _REENT_SMALL_CHECK_INIT (_REENT); + return fputwc_unlocked (wc, stdout); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/swprintf.c b/contrib/sdk/sources/newlib/libc/stdio/swprintf.c new file mode 100644 index 0000000000..2233b3ba7e --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/swprintf.c @@ -0,0 +1,635 @@ +/* + * Copyright (c) 1990, 2007 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ + +/* +FUNCTION +<>, <>, <>---wide character format output + +INDEX + fwprintf +INDEX + _fwprintf_r +INDEX + wprintf +INDEX + _wprintf_r +INDEX + swprintf +INDEX + _swprintf_r + +ANSI_SYNOPSIS + #include + + int wprintf(const wchar_t *<[format]>, ...); + int fwprintf(FILE *__restrict <[fd]>, + const wchar_t *__restrict <[format]>, ...); + int swprintf(wchar_t *__restrict <[str]>, size_t <[size]>, + const wchar_t *__restrict <[format]>, ...); + + int _wprintf_r(struct _reent *<[ptr]>, const wchar_t *<[format]>, ...); + int _fwprintf_r(struct _reent *<[ptr]>, FILE *<[fd]>, + const wchar_t *<[format]>, ...); + int _swprintf_r(struct _reent *<[ptr]>, wchar_t *<[str]>, + size_t <[size]>, const wchar_t *<[format]>, ...); + +DESCRIPTION + <> accepts a series of arguments, applies to each a + format specifier from <<*<[format]>>>, and writes the + formatted data to <>, without a terminating NUL + wide character. The behavior of <> is undefined if there + are not enough arguments for the format or if any argument is not the + right type for the corresponding conversion specifier. <> + returns when it reaches the end of the format string. If there are + more arguments than the format requires, excess arguments are + ignored. + + <> is like <>, except that output is directed + to the stream <[fd]> rather than <>. + + <> is like <>, except that output is directed + to the buffer <[str]> with a terminating wide <>, and the + resulting string length is limited to at most <[size]> wide characters, + including the terminating <>. It is considered an error if the + output (including the terminating wide-<>) does not fit into + <[size]> wide characters. (This error behavior is not the same as for + <>, which <> is otherwise completely analogous to. + While <> allows the needed size to be known simply by giving + <[size]>=0, <> does not, giving an error instead.) + + For <> the behavior is undefined if the output + <<*<[str]>>> overlaps with one of the arguments. Behavior is also + undefined if the argument for <<%n>> within <<*<[format]>>> + overlaps another argument. + + <[format]> is a pointer to a wide character string containing two + types of objects: ordinary characters (other than <<%>>), + which are copied unchanged to the output, and conversion + specifications, each of which is introduced by <<%>>. (To + include <<%>> in the output, use <<%%>> in the format string.) + A conversion specification has the following form: + +. %[<[pos]>][<[flags]>][<[width]>][.<[prec]>][<[size]>]<[type]> + + The fields of the conversion specification have the following + meanings: + + O+ + o <[pos]> + + Conversions normally consume arguments in the order that they + are presented. However, it is possible to consume arguments + out of order, and reuse an argument for more than one + conversion specification (although the behavior is undefined + if the same argument is requested with different types), by + specifying <[pos]>, which is a decimal integer followed by + '$'. The integer must be between 1 and from + limits.h, and if argument <<%n$>> is requested, all earlier + arguments must be requested somewhere within <[format]>. If + positional parameters are used, then all conversion + specifications except for <<%%>> must specify a position. + This positional parameters method is a POSIX extension to the C + standard definition for the functions. + + o <[flags]> + + <[flags]> is an optional sequence of characters which control + output justification, numeric signs, decimal points, trailing + zeros, and octal and hex prefixes. The flag characters are + minus (<<->>), plus (<<+>>), space ( ), zero (<<0>>), sharp + (<<#>>), and quote (<<'>>). They can appear in any + combination, although not all flags can be used for all + conversion specification types. + + o+ + o ' + A POSIX extension to the C standard. However, this + implementation presently treats it as a no-op, which + is the default behavior for the C locale, anyway. (If + it did what it is supposed to, when <[type]> were <>, + <>, <>, <>, <>, <>, or <>, the + integer portion of the conversion would be formatted + with thousands' grouping wide characters.) + + o - + The result of the conversion is left + justified, and the right is padded with + blanks. If you do not use this flag, the + result is right justified, and padded on the + left. + + o + + The result of a signed conversion (as + determined by <[type]> of <>, <>, <>, + <>, <>, <>, <>, <>, <>, or + <>) will always begin with a plus or minus + sign. (If you do not use this flag, positive + values do not begin with a plus sign.) + + o " " (space) + If the first character of a signed conversion + specification is not a sign, or if a signed + conversion results in no characters, the + result will begin with a space. If the space + ( ) flag and the plus (<<+>>) flag both + appear, the space flag is ignored. + + o 0 + If the <[type]> character is <>, <>, + <>, <>, <>, <>, <>, <>, + <>, <>, <>, <>, <>, or <>: leading + zeros are used to pad the field width + (following any indication of sign or base); no + spaces are used for padding. If the zero + (<<0>>) and minus (<<->>) flags both appear, + the zero (<<0>>) flag will be ignored. For + <>, <>, <>, <>, <>, and <> + conversions, if a precision <[prec]> is + specified, the zero (<<0>>) flag is ignored. + + Note that <<0>> is interpreted as a flag, not + as the beginning of a field width. + + o # + The result is to be converted to an + alternative form, according to the <[type]> + character. + o- + + The alternative form output with the # flag depends on the <[type]> + character: + + o+ + o o + Increases precision to force the first + digit of the result to be a zero. + + o x + A non-zero result will have a <<0x>> + prefix. + + o X + A non-zero result will have a <<0X>> + prefix. + + o a, A, e, E, f, or F + The result will always contain a + decimal point even if no digits follow + the point. (Normally, a decimal point + appears only if a digit follows it.) + Trailing zeros are removed. + + o g or G + The result will always contain a + decimal point even if no digits follow + the point. Trailing zeros are not + removed. + + o all others + Undefined. + + o- + + + o <[width]> + + <[width]> is an optional minimum field width. You can + either specify it directly as a decimal integer, or + indirectly by using instead an asterisk (<<*>>), in + which case an <> argument is used as the field + width. If positional arguments are used, then the + width must also be specified positionally as <<*m$>>, + with m as a decimal integer. Negative field widths + are treated as specifying the minus (<<->>) flag for + left justfication, along with a positive field width. + The resulting format may be wider than the specified + width. + + o <[prec]> + + <[prec]> is an optional field; if present, it is + introduced with `<<.>>' (a period). You can specify + the precision either directly as a decimal integer or + indirectly by using an asterisk (<<*>>), in which case + an <> argument is used as the precision. If + positional arguments are used, then the precision must + also be specified positionally as <<*m$>>, with m as a + decimal integer. Supplying a negative precision is + equivalent to omitting the precision. If only a + period is specified the precision is zero. The effect + depends on the conversion <[type]>. + + o+ + o d, i, o, u, x, or X + Minimum number of digits to appear. If no + precision is given, defaults to 1. + + o a or A + Number of digits to appear after the decimal + point. If no precision is given, the + precision defaults to the minimum needed for + an exact representation. + + o e, E, f or F + Number of digits to appear after the decimal + point. If no precision is given, the + precision defaults to 6. + + o g or G + Maximum number of significant digits. A + precision of 0 is treated the same as a + precision of 1. If no precision is given, the + precision defaults to 6. + + o s or S + Maximum number of characters to print from the + string. If no precision is given, the entire + string is printed. + + o all others + undefined. + + o- + + o <[size]> + + <[size]> is an optional modifier that changes the data + type that the corresponding argument has. Behavior is + unspecified if a size is given that does not match the + <[type]>. + + o+ + o hh + With <>, <>, <>, <>, <>, or + <>, specifies that the argument should be + converted to a <> or <> before printing. + + With <>, specifies that the argument is a + pointer to a <>. + + o h + With <>, <>, <>, <>, <>, or + <>, specifies that the argument should be + converted to a <> or <> + before printing. + + With <>, specifies that the argument is a + pointer to a <>. + + o l + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is a + <> or <>. + + With <>, specifies that the argument has + type <>. + + With <>, specifies that the argument is a + pointer to <>. + + With <>, specifies that the argument is a + pointer to a <>. + + With <>, <>, <>, <>, <>, <>, + <>, or <>, has no effect (because of + vararg promotion rules, there is no need to + distinguish between <> and <>). + + o ll + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is a + <> or <>. + + With <>, specifies that the argument is a + pointer to a <>. + + o j + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is an + <> or <>. + + With <>, specifies that the argument is a + pointer to an <>. + + o z + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is a <>. + + With <>, specifies that the argument is a + pointer to a <>. + + o t + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is a + <>. + + With <>, specifies that the argument is a + pointer to a <>. + + o L + With <>, <>, <>, <>, <>, <>, + <>, or <>, specifies that the argument + is a <>. + + o- + + o <[type]> + + <[type]> specifies what kind of conversion <> + performs. Here is a table of these: + + o+ + o % + Prints the percent character (<<%>>). + + o c + If no <> qualifier is present, the int argument shall + be converted to a wide character as if by calling + the btowc() function and the resulting wide character + shall be written. Otherwise, the wint_t argument + shall be converted to wchar_t, and written. + + o C + Short for <<%lc>>. A POSIX extension to the C standard. + + o s + If no <> qualifier is present, the application + shall ensure that the argument is a pointer to a + character array containing a character sequence + beginning in the initial shift state. Characters + from the array shall be converted as if by repeated + calls to the mbrtowc() function, with the conversion + state described by an mbstate_t object initialized to + zero before the first character is converted, and + written up to (but not including) the terminating + null wide character. If the precision is specified, + no more than that many wide characters shall be + written. If the precision is not specified, or is + greater than the size of the array, the application + shall ensure that the array contains a null wide + character. + + If an <> qualifier is present, the application + shall ensure that the argument is a pointer to an + array of type wchar_t. Wide characters from the array + shall be written up to (but not including) a + terminating null wide character. If no precision is + specified, or is greater than the size of the array, + the application shall ensure that the array contains + a null wide character. If a precision is specified, + no more than that many wide characters shall be + written. + + o S + Short for <<%ls>>. A POSIX extension to the C standard. + + o d or i + Prints a signed decimal integer; takes an + <>. Leading zeros are inserted as + necessary to reach the precision. A value of 0 with + a precision of 0 produces an empty string. + + o o + Prints an unsigned octal integer; takes an + <>. Leading zeros are inserted as + necessary to reach the precision. A value of 0 with + a precision of 0 produces an empty string. + + o u + Prints an unsigned decimal integer; takes an + <>. Leading zeros are inserted as + necessary to reach the precision. A value of 0 with + a precision of 0 produces an empty string. + + o x + Prints an unsigned hexadecimal integer (using + <> as digits beyond <<9>>); takes an + <>. Leading zeros are inserted as + necessary to reach the precision. A value of 0 with + a precision of 0 produces an empty string. + + o X + Like <>, but uses <> as digits + beyond <<9>>. + + o f + Prints a signed value of the form + <<[-]9999.9999>>, with the precision + determining how many digits follow the decimal + point; takes a <> (remember that + <> promotes to <> as a vararg). + The low order digit is rounded to even. If + the precision results in at most DECIMAL_DIG + digits, the result is rounded correctly; if + more than DECIMAL_DIG digits are printed, the + result is only guaranteed to round back to the + original value. + + If the value is infinite, the result is + <>, and no zero padding is performed. If + the value is not a number, the result is + <>, and no zero padding is performed. + + o F + Like <>, but uses <> and <> for + non-finite numbers. + + o e + Prints a signed value of the form + <<[-]9.9999e[+|-]999>>; takes a <>. + The digit before the decimal point is non-zero + if the value is non-zero. The precision + determines how many digits appear between + <<.>> and <>, and the exponent always + contains at least two digits. The value zero + has an exponent of zero. If the value is not + finite, it is printed like <>. + + o E + Like <>, but using <> to introduce the + exponent, and like <> for non-finite + values. + + o g + Prints a signed value in either <> or <> + form, based on the given value and + precision---an exponent less than -4 or + greater than the precision selects the <> + form. Trailing zeros and the decimal point + are printed only if necessary; takes a + <>. + + o G + Like <>, except use <> or <> form. + + o a + Prints a signed value of the form + <<[-]0x1.ffffp[+|-]9>>; takes a <>. + The letters <> are used for digits + beyond <<9>>. The precision determines how + many digits appear after the decimal point. + The exponent contains at least one digit, and + is a decimal value representing the power of + 2; a value of 0 has an exponent of 0. + Non-finite values are printed like <>. + + o A + Like <>, except uses <>, <

>, and + <> instead of lower case. + + o n + Takes a pointer to <>, and stores a count + of the number of bytes written so far. No + output is created. + + o p + Takes a pointer to <>, and prints it in + an implementation-defined format. This + implementation is similar to <<%#tx>>), except + that <<0x>> appears even for the NULL pointer. + + o m + Prints the output of <>; no + argument is required. A GNU extension. + + o- + O- + + <<_wprintf_r>>, <<_fwprintf_r>>, <<_swprintf_r>>, are simply + reentrant versions of the functions above. + +RETURNS +On success, <> return the number of wide characters in +the output string, except the concluding <> is not counted. +<> and <> return the number of characters transmitted. + +If an error occurs, the result of <>, <>, and +<> is a negative value. For <> and <>, +<> may be set according to <>. For <>, <> +may be set to EOVERFLOW if <[size]> is greater than INT_MAX / sizeof (wchar_t), +or when the output does not fit into <[size]> wide characters (including the +terminating wide <>). + +BUGS +The ``''' (quote) flag does not work when locale's thousands_sep is not empty. + +PORTABILITY +POSIX-1.2008 with extensions; C99 (compliant except for POSIX extensions). + +Depending on how newlib was configured, not all format specifiers are +supported. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. +*/ + + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#include "local.h" + +/* NOTE: _swprintf_r() should be identical to swprintf() except for the + * former having ptr as a parameter and the latter needing to declare it as + * a variable set to _REENT. */ + +int +_DEFUN(_swprintf_r, (ptr, str, size, fmt), + struct _reent *ptr _AND + wchar_t *str _AND + size_t size _AND + _CONST wchar_t *fmt _DOTS) +{ + int ret; + va_list ap; + FILE f; + + if (size > INT_MAX / sizeof (wchar_t)) + { + ptr->_errno = EOVERFLOW; /* POSIX extension */ + return EOF; + } + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = (size > 0 ? (size - 1) * sizeof (wchar_t) : 0); + f._file = -1; /* No file. */ + va_start (ap, fmt); + ret = _svfwprintf_r (ptr, &f, fmt, ap); + va_end (ap); + /* _svfwprintf_r() does not put in a terminating NUL, so add one if + * appropriate, which is whenever size is > 0. _svfwprintf_r() stops + * after n-1, so always just put at the end. */ + if (size > 0) { + *(wchar_t *)f._p = L'\0'; /* terminate the string */ + } + if(ret >= size) { + /* _svfwprintf_r() returns how many wide characters it would have printed + * if there were enough space. Return an error if too big to fit in str, + * unlike snprintf, which returns the size needed. */ + ptr->_errno = EOVERFLOW; /* POSIX extension */ + ret = -1; + } + return (ret); +} + +#ifndef _REENT_ONLY + +int +_DEFUN(swprintf, (str, size, fmt), + wchar_t *__restrict str _AND + size_t size _AND + _CONST wchar_t *__restrict fmt _DOTS) +{ + int ret; + va_list ap; + FILE f; + struct _reent *ptr = _REENT; + + if (size > INT_MAX / sizeof (wchar_t)) + { + ptr->_errno = EOVERFLOW; /* POSIX extension */ + return EOF; + } + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = (size > 0 ? (size - 1) * sizeof (wchar_t) : 0); + f._file = -1; /* No file. */ + va_start (ap, fmt); + ret = _svfwprintf_r (ptr, &f, fmt, ap); + va_end (ap); + /* _svfwprintf_r() does not put in a terminating NUL, so add one if + * appropriate, which is whenever size is > 0. _svfwprintf_r() stops + * after n-1, so always just put at the end. */ + if (size > 0) { + *(wchar_t *)f._p = L'\0'; /* terminate the string */ + } + if(ret >= size) { + /* _svfwprintf_r() returns how many wide characters it would have printed + * if there were enough space. Return an error if too big to fit in str, + * unlike snprintf, which returns the size needed. */ + ptr->_errno = EOVERFLOW; /* POSIX extension */ + ret = -1; + } + return (ret); +} + +#endif diff --git a/contrib/sdk/sources/newlib/libc/stdio/swscanf.c b/contrib/sdk/sources/newlib/libc/stdio/swscanf.c new file mode 100644 index 0000000000..6a469ac313 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/swscanf.c @@ -0,0 +1,487 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ + +/* +FUNCTION +<>, <>, <>---scan and format wide character input + +INDEX + wscanf +INDEX + _wscanf_r +INDEX + fwscanf +INDEX + _fwscanf_r +INDEX + swscanf +INDEX + _swscanf_r + +ANSI_SYNOPSIS + #include + + int wscanf(const wchar_t *__restrict <[format]>, ...); + int fwscanf(FILE *__restrict <[fd]>, + const wchar_t *__restrict <[format]>, ...); + int swscanf(const wchar_t *__restrict <[str]>, + const wchar_t *__restrict <[format]>, ...); + + int _wscanf_r(struct _reent *<[ptr]>, const wchar_t *<[format]>, ...); + int _fwscanf_r(struct _reent *<[ptr]>, FILE *<[fd]>, + const wchar_t *<[format]>, ...); + int _swscanf_r(struct _reent *<[ptr]>, const wchar_t *<[str]>, + const wchar_t *<[format]>, ...); + + +TRAD_SYNOPSIS + #include + + int wscanf(<[format]> [, <[arg]>, ...]) + wchar_t *__restrict <[format]>; + + int fwscanf(<[fd]>, <[format]> [, <[arg]>, ...]); + FILE *<[fd]>; + wchar_t *<[format]>; + + int swscanf(<[str]>, <[format]> [, <[arg]>, ...]); + wchar_t *__restrict <[str]>; + wchar_t *__restrict <[format]>; + + int _wscanf_r(<[ptr]>, <[format]> [, <[arg]>, ...]) + struct _reent *<[ptr]>; + wchar_t *<[format]>; + + int _fwscanf_r(<[ptr]>, <[fd]>, <[format]> [, <[arg]>, ...]); + struct _reent *<[ptr]>; + FILE *<[fd]>; + wchar_t *<[format]>; + + int _swscanf_r(<[ptr]>, <[str]>, <[format]> [, <[arg]>, ...]); + struct _reent *<[ptr]>; + wchar_t *<[str]>; + wchar_t *<[format]>; + + +DESCRIPTION + <> scans a series of input fields from standard input, + one wide character at a time. Each field is interpreted according to + a format specifier passed to <> in the format string at + <<*<[format]>>>. <> stores the interpreted input from + each field at the address passed to it as the corresponding argument + following <[format]>. You must supply the same number of + format specifiers and address arguments as there are input fields. + + There must be sufficient address arguments for the given format + specifiers; if not the results are unpredictable and likely + disasterous. Excess address arguments are merely ignored. + + <> often produces unexpected results if the input diverges from + an expected pattern. Since the combination of <> or <> + followed by <> is safe and easy, that is the preferred way + to be certain that a program is synchronized with input at the end + of a line. + + <> and <> are identical to <>, other than the + source of input: <> reads from a file, and <> + from a string. + + The routines <<_wscanf_r>>, <<_fwscanf_r>>, and <<_swscanf_r>> are reentrant + versions of <>, <>, and <> that take an additional + first argument pointing to a reentrancy structure. + + The string at <<*<[format]>>> is a wide character sequence composed + of zero or more directives. Directives are composed of + one or more whitespace characters, non-whitespace characters, + and format specifications. + + Whitespace characters are blank (<< >>), tab (<<\t>>), or + newline (<<\n>>). + When <> encounters a whitespace character in the format string + it will read (but not store) all consecutive whitespace characters + up to the next non-whitespace character in the input. + + Non-whitespace characters are all other ASCII characters except the + percent sign (<<%>>). When <> encounters a non-whitespace + character in the format string it will read, but not store + a matching non-whitespace character. + + Format specifications tell <> to read and convert characters + from the input field into specific types of values, and store then + in the locations specified by the address arguments. + + Trailing whitespace is left unread unless explicitly + matched in the format string. + + The format specifiers must begin with a percent sign (<<%>>) + and have the following form: + +. %[*][<[width]>][<[size]>]<[type]> + + Each format specification begins with the percent character (<<%>>). + The other fields are: + O+ + o * + + an optional marker; if present, it suppresses interpretation and + assignment of this input field. + + o <[width]> + + an optional maximum field width: a decimal integer, + which controls the maximum number of characters that + will be read before converting the current input field. If the + input field has fewer than <[width]> characters, <> + reads all the characters in the field, and then + proceeds with the next field and its format specification. + + If a whitespace or a non-convertable wide character occurs + before <[width]> character are read, the characters up + to that character are read, converted, and stored. + Then <> proceeds to the next format specification. + + o <[size]> + + <>, <>, <>, <>, <>, and <> are optional size + characters which override the default way that <> + interprets the data type of the corresponding argument. + + @multitable @columnfractions 0.18 0.30 0.52 + @headitem + Modifier + @tab + Type(s) + @tab + @item + hh + @tab + d, i, o, u, x, n + @tab + convert input to char, store in char object + @item + h + @tab + d, i, o, u, x, n + @tab + convert input to short, store in short object + @item + h + @tab + e, f, c, s, p + @tab + no effect + @item + j + @tab + d, i, o, u, x, n + @tab + convert input to intmax_t, store in intmax_t object + @item + j + @tab + all others + @tab + no effect + @item + l + @tab + d, i, o, u, x, n + @tab + convert input to long, store in long object + @item + l + @tab + e, f, g + @tab + convert input to double, store in a double object + @item + l + @tab + c, s, [ + @tab + the input is stored in a wchar_t object + @item + l + @tab + p + @tab + no effect + @item + ll + @tab + d, i, o, u, x, n + @tab + convert to long long, store in long long object + @item + L + @tab + d, i, o, u, x, n + @tab + convert to long long, store in long long object + @item + L + @tab + e, f, g, E, G + @tab + convert to long double, store in long double object + @item + L + @tab + all others + @tab + no effect + @item + t + @tab + d, i, o, u, x, n + @tab + convert input to ptrdiff_t, store in ptrdiff_t object + @item + t + @tab + all others + @tab + no effect + @item + z + @tab + d, i, o, u, x, n + @tab + convert input to size_t, store in size_t object + @item + z + @tab + all others + @tab + no effect + @end multitable + + o <[type]> + + A character to specify what kind of conversion + <> performs. Here is a table of the conversion + characters: + + o+ + o % + No conversion is done; the percent character (<<%>>) is stored. + + o c + Scans one wide character. Corresponding <[arg]>: <<(char *arg)>>. + Otherwise, if an <> specifier is present, the corresponding + <[arg]> is a <<(wchar_t *arg)>>. + + o s + Reads a character string into the array supplied. + Corresponding <[arg]>: <<(char arg[])>>. + If an <> specifier is present, the corresponding <[arg]> is a <<(wchar_t *arg)>>. + + o [<[pattern]>] + Reads a non-empty character string into memory + starting at <[arg]>. This area must be large + enough to accept the sequence and a + terminating null character which will be added + automatically. (<[pattern]> is discussed in the paragraph following + this table). Corresponding <[arg]>: <<(char *arg)>>. + If an <> specifier is present, the corresponding <[arg]> is + a <<(wchar_t *arg)>>. + + o d + Reads a decimal integer into the corresponding <[arg]>: <<(int *arg)>>. + + o o + Reads an octal integer into the corresponding <[arg]>: <<(int *arg)>>. + + o u + Reads an unsigned decimal integer into the corresponding + <[arg]>: <<(unsigned int *arg)>>. + + o x,X + Read a hexadecimal integer into the corresponding <[arg]>: + <<(int *arg)>>. + + o e, f, g + Read a floating-point number into the corresponding <[arg]>: + <<(float *arg)>>. + + o E, F, G + Read a floating-point number into the corresponding <[arg]>: + <<(double *arg)>>. + + o i + Reads a decimal, octal or hexadecimal integer into the + corresponding <[arg]>: <<(int *arg)>>. + + o n + Stores the number of characters read in the corresponding + <[arg]>: <<(int *arg)>>. + + o p + Stores a scanned pointer. ANSI C leaves the details + to each implementation; this implementation treats + <<%p>> exactly the same as <<%U>>. Corresponding + <[arg]>: <<(void **arg)>>. + o- + + A <[pattern]> of characters surrounded by square brackets can be used + instead of the <> type character. <[pattern]> is a set of + characters which define a search set of possible characters making up + the <> input field. If the first character in the brackets is a + caret (<<^>>), the search set is inverted to include all ASCII characters + except those between the brackets. There is no range facility as is + defined in the corresponding non-wide character scanf functions. + Ranges are not part of the POSIX standard. + + Here are some <[pattern]> examples: + o+ + o %[abcd] + matches wide character strings containing only + <>, <>, <>, and <>. + + o %[^abcd] + matches wide character strings containing any characters except + <>, <>, <>, or <>. + + o %[A-DW-Z] + Note: No wide character ranges, so this expression matches wide + character strings containing <>, <<->>, <>, <>, <>. + o- + + Floating point numbers (for field types <>, <>, <>, <>, + <>, <>) must correspond to the following general form: + +. [+/-] ddddd[.]ddd [E|e[+|-]ddd] + + where objects inclosed in square brackets are optional, and <> + represents decimal, octal, or hexadecimal digits. + O- + +RETURNS + <> returns the number of input fields successfully + scanned, converted and stored; the return value does + not include scanned fields which were not stored. + + If <> attempts to read at end-of-file, the return + value is <>. + + If no fields were stored, the return value is <<0>>. + + <> might stop scanning a particular field before + reaching the normal field end character, or may + terminate entirely. + + <> stops scanning and storing the current field + and moves to the next input field (if any) + in any of the following situations: + + O+ + o The assignment suppressing character (<<*>>) appears + after the <<%>> in the format specification; the current + input field is scanned but not stored. + + o <[width]> characters have been read (<[width]> is a + width specification, a positive decimal integer). + + o The next wide character read cannot be converted + under the the current format (for example, + if a <> is read when the format is decimal). + + o The next wide character in the input field does not appear + in the search set (or does appear in the inverted search set). + O- + + When <> stops scanning the current input field for one of + these reasons, the next character is considered unread and + used as the first character of the following input field, or the + first character in a subsequent read operation on the input. + + <> will terminate under the following circumstances: + + O+ + o The next wide character in the input field conflicts + with a corresponding non-whitespace character in the + format string. + + o The next wide character in the input field is <>. + + o The format string has been exhausted. + O- + + When the format string contains a wide character sequence that is + not part of a format specification, the same wide character + sequence must appear in the input; <> will + scan but not store the matched characters. If a + conflict occurs, the first conflicting wide character remains in the + input as if it had never been read. + +PORTABILITY +<> is C99, POSIX-1.2008. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include "local.h" + +#ifndef _REENT_ONLY + +int +swscanf (_CONST wchar_t *__restrict str, _CONST wchar_t *__restrict fmt, ...) +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SRD | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._r = wcslen (str) * sizeof (wchar_t); + f._read = __seofread; + f._ub._base = NULL; + f._lb._base = NULL; + f._file = -1; /* No file. */ + va_start (ap, fmt); + ret = __ssvfwscanf_r (_REENT, &f, fmt, ap); + va_end (ap); + return ret; +} + +#endif /* !_REENT_ONLY */ + +int +_swscanf_r (struct _reent *ptr, _CONST wchar_t *str, _CONST wchar_t *fmt, ...) +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SRD | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._r = wcslen (str) * sizeof (wchar_t); + f._read = __seofread; + f._ub._base = NULL; + f._lb._base = NULL; + f._file = -1; /* No file. */ + va_start (ap, fmt); + ret = __ssvfwscanf_r (ptr, &f, fmt, ap); + va_end (ap); + return ret; +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/ungetwc.c b/contrib/sdk/sources/newlib/libc/stdio/ungetwc.c new file mode 100644 index 0000000000..a69449eb22 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/ungetwc.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +FUNCTION +<>---push wide character data back into a stream + +INDEX + ungetwc +INDEX + _ungetwc_r + +ANSI_SYNOPSIS + #include + #include + wint_t ungetwc(wint_t <[wc]>, FILE *<[stream]>); + + wint_t _ungetwc_r(struct _reent *<[reent]>, wint_t <[wc]>, FILE *<[stream]>); + +DESCRIPTION +<> is used to return wide characters back to <[stream]> to be +read again. If <[wc]> is WEOF, the stream is unchanged. Otherwise, the +wide character <[wc]> is put back on the stream, and subsequent reads will see +the wide chars pushed back in reverse order. Pushed wide chars are lost if the +stream is repositioned, such as by <>, <>, or +<>. + +The underlying file is not changed, but it is possible to push back +something different than what was originally read. Ungetting a +character will clear the end-of-stream marker, and decrement the file +position indicator. Pushing back beyond the beginning of a file gives +unspecified behavior. + +The alternate function <<_ungetwc_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +The wide character pushed back, or <> on error. + +PORTABILITY +C99 +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#include "local.h" + +wint_t +_DEFUN(_ungetwc_r, (ptr, wc, fp), + struct _reent *ptr _AND + wint_t wc _AND + register FILE *fp) +{ + char buf[MB_LEN_MAX]; + size_t len; + + _newlib_flockfile_start (fp); + ORIENT (fp, 1); + if (wc == WEOF) + wc = WEOF; + else if ((len = _wcrtomb_r(ptr, buf, wc, &fp->_mbstate)) == (size_t)-1) + { + fp->_flags |= __SERR; + wc = WEOF; + } + else + while (len-- != 0) + if (_ungetc_r(ptr, (unsigned char)buf[len], fp) == EOF) + { + wc = WEOF; + break; + } + _newlib_flockfile_end (fp); + return wc; +} + +/* + * MT-safe version. + */ +wint_t +_DEFUN(ungetwc, (wint_t wc, FILE *fp), + wint_t wc _AND + FILE *fp) +{ + struct _reent *reent = _REENT; + + CHECK_INIT (reent, fp); + return _ungetwc_r (reent, wc, fp); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/vfwprintf.c b/contrib/sdk/sources/newlib/libc/stdio/vfwprintf.c new file mode 100644 index 0000000000..c3b8b27bbd --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/vfwprintf.c @@ -0,0 +1,2019 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + */ + +/* +FUNCTION +<>, <>, <>---wide character format argument list + +INDEX + vfwprintf +INDEX + _vfwprintf_r +INDEX + vwprintf +INDEX + _vwprintf_r +INDEX + vswprintf +INDEX + _vswprintf_r + +ANSI_SYNOPSIS + #include + #include + #include + int vwprintf(const wchar_t *__restrict <[fmt]>, va_list <[list]>); + int vfwprintf(FILE *__restrict <[fp]>, + const wchar_t *__restrict <[fmt]>, va_list <[list]>); + int vswprintf(wchar_t * __restrict <[str]>, size_t <[size]>, + const wchar_t *__ restrict <[fmt]>, va_list <[list]>); + + int _vwprintf_r(struct _reent *<[reent]>, const wchar_t *<[fmt]>, + va_list <[list]>); + int _vfwprintf_r(struct _reent *<[reent]>, FILE *<[fp]>, + const wchar_t *<[fmt]>, va_list <[list]>); + int _vswprintf_r(struct _reent *<[reent]>, wchar_t *<[str]>, + size_t <[size]>, const wchar_t *<[fmt]>, va_list <[list]>); + +DESCRIPTION +<>, <> and <> are (respectively) variants +of <>, <> and <>. They differ only in allowing +their caller to pass the variable argument list as a <> object +(initialized by <>) rather than directly accepting a variable +number of arguments. The caller is responsible for calling <>. + +<<_vwprintf_r>>, <<_vfwprintf_r>> and <<_vswprintf_r>> are reentrant +versions of the above. + +RETURNS +The return values are consistent with the corresponding functions. + +PORTABILITY +POSIX-1.2008 with extensions; C99 (compliant except for POSIX extensions). + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. + +SEEALSO +<>, <> and <>. +*/ + +/* + * Actual wprintf innards. + * + * This code is large and complicated... + */ +#include + +#ifdef INTEGER_ONLY +# define VFWPRINTF vfiwprintf +# ifdef STRING_ONLY +# define _VFWPRINTF_R _svfiwprintf_r +# else +# define _VFWPRINTF_R _vfiwprintf_r +# endif +#else +# define VFWPRINTF vfwprintf +# ifdef STRING_ONLY +# define _VFWPRINTF_R _svfwprintf_r +# else +# define _VFWPRINTF_R _vfwprintf_r +# endif +# ifndef NO_FLOATING_POINT +# define FLOATING_POINT +# endif +#endif + +#define _NO_POS_ARGS +#ifdef _WANT_IO_POS_ARGS +# undef _NO_POS_ARGS +#endif + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" +#include "fvwrite.h" +#include "vfieeefp.h" +#ifdef __HAVE_LOCALE_INFO_EXTENDED__ +#include "../locale/lnumeric.h" +#endif + +/* Currently a test is made to see if long double processing is warranted. + This could be changed in the future should the _ldtoa_r code be + preferred over _dtoa_r. */ +#define _NO_LONGDBL +#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG) +#undef _NO_LONGDBL +#endif + +#define _NO_LONGLONG +#if defined _WANT_IO_LONG_LONG \ + && (defined __GNUC__ || __STDC_VERSION__ >= 199901L) +# undef _NO_LONGLONG +#endif + +int _EXFUN(_VFWPRINTF_R, (struct _reent *, FILE *, _CONST wchar_t *, va_list)); +/* Defined in vfprintf.c. */ +#ifdef _FVWRITE_IN_STREAMIO +# ifdef STRING_ONLY +# define __SPRINT __ssprint_r +# else +# define __SPRINT __sprint_r +# endif +int _EXFUN(__SPRINT, (struct _reent *, FILE *, register struct __suio *)); +#else +# ifdef STRING_ONLY +# define __SPRINT __ssputs_r +# else +# define __SPRINT __sfputs_r +# endif +int _EXFUN(__SPRINT, (struct _reent *, FILE *, _CONST char *, size_t)); +#endif +#ifndef STRING_ONLY +#ifdef _UNBUF_STREAM_OPT +/* + * Helper function for `fprintf to unbuffered unix file': creates a + * temporary buffer. We only work on write-only files; this avoids + * worries about ungetc buffers and so forth. + */ +static int +_DEFUN(__sbwprintf, (rptr, fp, fmt, ap), + struct _reent *rptr _AND + register FILE *fp _AND + _CONST wchar_t *fmt _AND + va_list ap) +{ + int ret; + FILE fake; + unsigned char buf[BUFSIZ]; + + /* copy the important variables */ + fake._flags = fp->_flags & ~__SNBF; + fake._flags2 = fp->_flags2; + fake._file = fp->_file; + fake._cookie = fp->_cookie; + fake._write = fp->_write; + + /* set up the buffer */ + fake._bf._base = fake._p = buf; + fake._bf._size = fake._w = sizeof (buf); + fake._lbfsize = 0; /* not actually used, but Just In Case */ +#ifndef __SINGLE_THREAD__ + __lock_init_recursive (fake._lock); +#endif + + /* do the work, then copy any error status */ + ret = _VFWPRINTF_R (rptr, &fake, fmt, ap); + if (ret >= 0 && _fflush_r (rptr, &fake)) + ret = EOF; + if (fake._flags & __SERR) + fp->_flags |= __SERR; + +#ifndef __SINGLE_THREAD__ + __lock_close_recursive (fake._lock); +#endif + return (ret); +} +#endif /* _UNBUF_STREAM_OPT */ +#endif /* !STRING_ONLY */ + + +#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS) +# include +#endif +#ifdef FLOATING_POINT +# include + +/* For %La, an exponent of 15 bits occupies the exponent character, a + sign, and up to 5 digits. */ +# define MAXEXPLEN 7 +# define DEFPREC 6 + +# ifdef _NO_LONGDBL + +extern char *_dtoa_r _PARAMS((struct _reent *, double, int, + int, int *, int *, char **)); + +# define _PRINTF_FLOAT_TYPE double +# define _DTOA_R _dtoa_r +# define FREXP frexp + +# else /* !_NO_LONGDBL */ + +extern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int, + int, int *, int *, char **)); + +extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *)); + +# define _PRINTF_FLOAT_TYPE _LONG_DOUBLE +# define _DTOA_R _ldtoa_r +/* FIXME - frexpl is not yet supported; and cvt infloops if (double)f + converts a finite value into infinity. */ +/* # define FREXP frexpl */ +# define FREXP(f,e) ((_LONG_DOUBLE) frexp ((double)f, e)) +# endif /* !_NO_LONGDBL */ + +static wchar_t *wcvt(struct _reent *, _PRINTF_FLOAT_TYPE, int, int, wchar_t *, + int *, int, int *, wchar_t *, int); + +static int wexponent(wchar_t *, int, int); + +#endif /* FLOATING_POINT */ + +/* BUF must be big enough for the maximum %#llo (assuming long long is + at most 64 bits, this would be 23 characters), the maximum + multibyte character %C, and the maximum default precision of %La + (assuming long double is at most 128 bits with 113 bits of + mantissa, this would be 29 characters). %e, %f, and %g use + reentrant storage shared with mprec. All other formats that use + buf get by with fewer characters. Making BUF slightly bigger + reduces the need for malloc in %.*a and %ls/%S, when large precision or + long strings are processed. + The bigger size of 100 bytes is used on systems which allow number + strings using the locale's grouping character. Since that's a multibyte + value, we should use a conservative value. + */ +#ifdef _WANT_IO_C99_FORMATS +#define BUF 100 +#else +#define BUF 40 +#endif +#if defined _MB_CAPABLE && MB_LEN_MAX > BUF +# undef BUF +# define BUF MB_LEN_MAX +#endif + +#ifndef _NO_LONGLONG +# define quad_t long long +# define u_quad_t unsigned long long +#else +# define quad_t long +# define u_quad_t unsigned long +#endif + +typedef quad_t * quad_ptr_t; +typedef _PTR void_ptr_t; +typedef char * char_ptr_t; +typedef wchar_t* wchar_ptr_t; +typedef long * long_ptr_t; +typedef int * int_ptr_t; +typedef short * short_ptr_t; + +#ifndef _NO_POS_ARGS +# ifdef NL_ARGMAX +# define MAX_POS_ARGS NL_ARGMAX +# else +# define MAX_POS_ARGS 32 +# endif + +union arg_val +{ + int val_int; + u_int val_u_int; + long val_long; + u_long val_u_long; + float val_float; + double val_double; + _LONG_DOUBLE val__LONG_DOUBLE; + int_ptr_t val_int_ptr_t; + short_ptr_t val_short_ptr_t; + long_ptr_t val_long_ptr_t; + char_ptr_t val_char_ptr_t; + wchar_ptr_t val_wchar_ptr_t; + quad_ptr_t val_quad_ptr_t; + void_ptr_t val_void_ptr_t; + quad_t val_quad_t; + u_quad_t val_u_quad_t; + wint_t val_wint_t; +}; + +static union arg_val * +_EXFUN(get_arg, (struct _reent *data, int n, wchar_t *fmt, + va_list *ap, int *numargs, union arg_val *args, + int *arg_type, wchar_t **last_fmt)); +#endif /* !_NO_POS_ARGS */ + +/* + * Macros for converting digits to letters and vice versa + */ +#define to_digit(c) ((c) - L'0') +#define is_digit(c) ((unsigned)to_digit (c) <= 9) +#define to_char(n) ((n) + L'0') + +/* + * Flags used during conversion. + */ +#define ALT 0x001 /* alternate form */ +#define HEXPREFIX 0x002 /* add 0x or 0X prefix */ +#define LADJUST 0x004 /* left adjustment */ +#define LONGDBL 0x008 /* long double */ +#define LONGINT 0x010 /* long integer */ +#ifndef _NO_LONGLONG +# define QUADINT 0x020 /* quad integer */ +#else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so + that %lld behaves the same as %ld, not as %d, as expected if: + sizeof (long long) = sizeof long > sizeof int */ +# define QUADINT LONGINT +#endif +#define SHORTINT 0x040 /* short integer */ +#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ +#define FPT 0x100 /* Floating point number */ +#ifdef _WANT_IO_C99_FORMATS +# define CHARINT 0x200 /* char as integer */ +#else /* define as 0, to make SARG and UARG occupy fewer instructions */ +# define CHARINT 0 +#endif +#ifdef _WANT_IO_C99_FORMATS +# define GROUPING 0x400 /* use grouping ("'" flag) */ +#endif + +#ifndef STRING_ONLY +int +_DEFUN(VFWPRINTF, (fp, fmt0, ap), + FILE *__restrict fp _AND + _CONST wchar_t *__restrict fmt0 _AND + va_list ap) +{ + int result; + result = _VFWPRINTF_R (_REENT, fp, fmt0, ap); + return result; +} +#endif /* STRING_ONLY */ + +int +_DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap), + struct _reent *data _AND + FILE * fp _AND + _CONST wchar_t *fmt0 _AND + va_list ap) +{ + register wchar_t *fmt; /* format string */ + register wint_t ch; /* character from fmt */ + register int n, m; /* handy integers (short term usage) */ + register wchar_t *cp; /* handy char pointer (short term usage) */ + register int flags; /* flags as above */ + wchar_t *fmt_anchor; /* current format spec being processed */ +#ifndef _NO_POS_ARGS + int N; /* arg number */ + int arg_index; /* index into args processed directly */ + int numargs; /* number of varargs read */ + wchar_t *saved_fmt; /* saved fmt pointer */ + union arg_val args[MAX_POS_ARGS]; + int arg_type[MAX_POS_ARGS]; + int is_pos_arg; /* is current format positional? */ + int old_is_pos_arg; /* is current format positional? */ +#endif + int ret; /* return value accumulator */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */ +#ifdef _WANT_IO_C99_FORMATS + /* locale specific numeric grouping */ + wchar_t thousands_sep = L'\0'; + const char *grouping = NULL; +#endif +#if defined (_MB_CAPABLE) && !defined (__HAVE_LOCALE_INFO_EXTENDED__) \ + && (defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)) + mbstate_t state; /* mbtowc calls from library must not change state */ +#endif +#ifdef FLOATING_POINT + wchar_t decimal_point; + wchar_t softsign; /* temporary negative sign for floats */ + union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0}; +# define _fpvalue (_double_.fp) + int expt; /* integer value of exponent */ + int expsize = 0; /* character count for expstr */ + wchar_t expstr[MAXEXPLEN]; /* buffer for exponent string */ + int lead; /* sig figs before decimal or group sep */ +#endif /* FLOATING_POINT */ +#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS) + int ndig = 0; /* actual number of digits returned by cvt */ +#endif +#if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS) + int nseps; /* number of group separators with ' */ + int nrepeats; /* number of repeats of the last group */ +#endif + u_quad_t _uquad; /* integer arguments %[diouxX] */ + enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int realsz; /* field size expanded by dprec */ + int size = 0; /* size of converted field or string */ + wchar_t *xdigs = NULL; /* digits for [xX] conversion */ +#ifdef _FVWRITE_IN_STREAMIO +#define NIOV 8 + struct __suio uio; /* output information: summary */ + struct __siov iov[NIOV];/* ... and individual io vectors */ + register struct __siov *iovp;/* for PRINT macro */ +#endif + wchar_t buf[BUF]; /* space for %c, %ls/%S, %[diouxX], %[aA] */ + wchar_t ox[2]; /* space for 0x hex-prefix */ + wchar_t *malloc_buf = NULL;/* handy pointer for malloced buffers */ + + /* + * Choose PADSIZE to trade efficiency vs. size. If larger printf + * fields occur frequently, increase PADSIZE and make the initialisers + * below longer. + */ +#define PADSIZE 16 /* pad chunk size */ + static _CONST wchar_t blanks[PADSIZE] = + {L' ',L' ',L' ',L' ',L' ',L' ',L' ',L' ', + L' ',L' ',L' ',L' ',L' ',L' ',L' ',L' '}; + static _CONST wchar_t zeroes[PADSIZE] = + {L'0',L'0',L'0',L'0',L'0',L'0',L'0',L'0', + L'0',L'0',L'0',L'0',L'0',L'0',L'0',L'0'}; + +#ifdef FLOATING_POINT +#ifdef _MB_CAPABLE +#ifdef __HAVE_LOCALE_INFO_EXTENDED__ + decimal_point = *__get_current_numeric_locale ()->wdecimal_point; +#else + { + size_t nconv; + + memset (&state, '\0', sizeof (state)); + nconv = _mbrtowc_r (data, &decimal_point, + _localeconv_r (data)->decimal_point, + MB_CUR_MAX, &state); + if (nconv == (size_t) -1 || nconv == (size_t) -2) + decimal_point = L'.'; + } +#endif +#else + decimal_point = (wchar_t) *_localeconv_r (data)->decimal_point; +#endif +#endif + /* + * BEWARE, these `goto error' on error, and PAD uses `n'. + */ +#ifdef _FVWRITE_IN_STREAMIO +#define PRINT(ptr, len) { \ + iovp->iov_base = (char *) (ptr); \ + iovp->iov_len = (len) * sizeof (wchar_t); \ + uio.uio_resid += (len) * sizeof (wchar_t); \ + iovp++; \ + if (++uio.uio_iovcnt >= NIOV) { \ + if (__SPRINT(data, fp, &uio)) \ + goto error; \ + iovp = iov; \ + } \ +} +#define PAD(howmany, with) { \ + if ((n = (howmany)) > 0) { \ + while (n > PADSIZE) { \ + PRINT (with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT (with, n); \ + } \ +} +#define PRINTANDPAD(p, ep, len, with) { \ + int n = (ep) - (p); \ + if (n > (len)) \ + n = (len); \ + if (n > 0) \ + PRINT((p), n); \ + PAD((len) - (n > 0 ? n : 0), (with)); \ +} +#define FLUSH() { \ + if (uio.uio_resid && __SPRINT(data, fp, &uio)) \ + goto error; \ + uio.uio_iovcnt = 0; \ + iovp = iov; \ +} +#else +#define PRINT(ptr, len) { \ + if (__SPRINT (data, fp, (_CONST char *)(ptr), (len) * sizeof (wchar_t)) == EOF) \ + goto error; \ +} +#define PAD(howmany, with) { \ + if ((n = (howmany)) > 0) { \ + while (n > PADSIZE) { \ + PRINT (with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT (with, n); \ + } \ +} +#define PRINTANDPAD(p, ep, len, with) { \ + int n = (ep) - (p); \ + if (n > (len)) \ + n = (len); \ + if (n > 0) \ + PRINT((p), n); \ + PAD((len) - (n > 0 ? n : 0), (with)); \ +} +#define FLUSH() +#endif + + /* Macros to support positional arguments */ +#ifndef _NO_POS_ARGS +# define GET_ARG(n, ap, type) \ + (is_pos_arg \ + ? (n < numargs \ + ? args[n].val_##type \ + : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \ + arg_type, &saved_fmt)->val_##type) \ + : (arg_index++ < numargs \ + ? args[n].val_##type \ + : (numargs < MAX_POS_ARGS \ + ? args[numargs++].val_##type = va_arg (ap, type) \ + : va_arg (ap, type)))) +#else +# define GET_ARG(n, ap, type) (va_arg (ap, type)) +#endif + + /* + * To extend shorts properly, we need both signed and unsigned + * argument extraction methods. + */ +#ifndef _NO_LONGLONG +#define SARG() \ + (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \ + flags&LONGINT ? GET_ARG (N, ap, long) : \ + flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \ + flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \ + (long)GET_ARG (N, ap, int)) +#define UARG() \ + (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \ + flags&LONGINT ? GET_ARG (N, ap, u_long) : \ + flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \ + flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \ + (u_long)GET_ARG (N, ap, u_int)) +#else +#define SARG() \ + (flags&LONGINT ? GET_ARG (N, ap, long) : \ + flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \ + flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \ + (long)GET_ARG (N, ap, int)) +#define UARG() \ + (flags&LONGINT ? GET_ARG (N, ap, u_long) : \ + flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \ + flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \ + (u_long)GET_ARG (N, ap, u_int)) +#endif + +#ifndef STRING_ONLY + /* Initialize std streams if not dealing with sprintf family. */ + CHECK_INIT (data, fp); + _newlib_flockfile_start (fp); + + ORIENT(fp, 1); + + /* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */ + if (cantwrite (data, fp)) { + _newlib_flockfile_exit (fp); + return (EOF); + } + +#ifdef _UNBUF_STREAM_OPT + /* optimise fwprintf(stderr) (and other unbuffered Unix files) */ + if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && + fp->_file >= 0) { + _newlib_flockfile_exit (fp); + return (__sbwprintf (data, fp, fmt0, ap)); + } +#endif +#else /* STRING_ONLY */ + /* Create initial buffer if we are called by asprintf family. */ + if (fp->_flags & __SMBF && !fp->_bf._base) + { + fp->_bf._base = fp->_p = _malloc_r (data, 64); + if (!fp->_p) + { + data->_errno = ENOMEM; + return EOF; + } + fp->_bf._size = 64; + } +#endif /* STRING_ONLY */ + + fmt = (wchar_t *)fmt0; +#ifdef _FVWRITE_IN_STREAMIO + uio.uio_iov = iovp = iov; + uio.uio_resid = 0; + uio.uio_iovcnt = 0; +#endif + ret = 0; +#ifndef _NO_POS_ARGS + arg_index = 0; + saved_fmt = NULL; + arg_type[0] = -1; + numargs = 0; + is_pos_arg = 0; +#endif + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + cp = fmt; + while (*fmt != L'\0' && *fmt != L'%') + ++fmt; + if ((m = fmt - cp) != 0) { + PRINT (cp, m); + ret += m; + } + if (*fmt == L'\0') + goto done; + fmt_anchor = fmt; + fmt++; /* skip over '%' */ + + flags = 0; + dprec = 0; + width = 0; + prec = -1; + sign = L'\0'; +#ifdef FLOATING_POINT + lead = 0; +#ifdef _WANT_IO_C99_FORMATS + nseps = nrepeats = 0; +#endif +#endif +#ifndef _NO_POS_ARGS + N = arg_index; + is_pos_arg = 0; +#endif + +rflag: ch = *fmt++; +reswitch: switch (ch) { +#ifdef _WANT_IO_C99_FORMATS + case L'\'': +#ifdef _MB_CAPABLE +#ifdef __HAVE_LOCALE_INFO_EXTENDED__ + thousands_sep = *__get_current_numeric_locale ()->wthousands_sep; +#else + { + size_t nconv; + + memset (&state, '\0', sizeof (state)); + nconv = _mbrtowc_r (data, &thousands_sep, + _localeconv_r (data)->thousands_sep, + MB_CUR_MAX, &state); + if (nconv == (size_t) -1 || nconv == (size_t) -2) + thousands_sep = L'\0'; + } +#endif +#else + thousands_sep = (wchar_t) *_localeconv_r(data)->thousands_sep; +#endif + grouping = _localeconv_r (data)->grouping; + if (thousands_sep && grouping && *grouping) + flags |= GROUPING; + goto rflag; +#endif + case L' ': + /* + * ``If the space and + flags both appear, the space + * flag will be ignored.'' + * -- ANSI X3J11 + */ + if (!sign) + sign = L' '; + goto rflag; + case L'#': + flags |= ALT; + goto rflag; + case L'*': +#ifndef _NO_POS_ARGS + /* we must check for positional arg used for dynamic width */ + n = N; + old_is_pos_arg = is_pos_arg; + is_pos_arg = 0; + if (is_digit (*fmt)) { + wchar_t *old_fmt = fmt; + + n = 0; + ch = *fmt++; + do { + n = 10 * n + to_digit (ch); + ch = *fmt++; + } while (is_digit (ch)); + + if (ch == L'$') { + if (n <= MAX_POS_ARGS) { + n -= 1; + is_pos_arg = 1; + } + else + goto error; + } + else { + fmt = old_fmt; + goto rflag; + } + } +#endif /* !_NO_POS_ARGS */ + + /* + * ``A negative field width argument is taken as a + * - flag followed by a positive field width.'' + * -- ANSI X3J11 + * They don't exclude field widths read from args. + */ + width = GET_ARG (n, ap, int); +#ifndef _NO_POS_ARGS + is_pos_arg = old_is_pos_arg; +#endif + if (width >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case L'-': + flags |= LADJUST; + goto rflag; + case L'+': + sign = L'+'; + goto rflag; + case L'.': + if ((ch = *fmt++) == L'*') { +#ifndef _NO_POS_ARGS + /* we must check for positional arg used for dynamic width */ + n = N; + old_is_pos_arg = is_pos_arg; + is_pos_arg = 0; + if (is_digit (*fmt)) { + wchar_t *old_fmt = fmt; + + n = 0; + ch = *fmt++; + do { + n = 10 * n + to_digit (ch); + ch = *fmt++; + } while (is_digit (ch)); + + if (ch == L'$') { + if (n <= MAX_POS_ARGS) { + n -= 1; + is_pos_arg = 1; + } + else + goto error; + } + else { + fmt = old_fmt; + goto rflag; + } + } +#endif /* !_NO_POS_ARGS */ + prec = GET_ARG (n, ap, int); +#ifndef _NO_POS_ARGS + is_pos_arg = old_is_pos_arg; +#endif + if (prec < 0) + prec = -1; + goto rflag; + } + n = 0; + while (is_digit (ch)) { + n = 10 * n + to_digit (ch); + ch = *fmt++; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case L'0': + /* + * ``Note that 0 is taken as a flag, not as the + * beginning of a field width.'' + * -- ANSI X3J11 + */ + flags |= ZEROPAD; + goto rflag; + case L'1': case L'2': case L'3': case L'4': + case L'5': case L'6': case L'7': case L'8': case L'9': + n = 0; + do { + n = 10 * n + to_digit (ch); + ch = *fmt++; + } while (is_digit (ch)); +#ifndef _NO_POS_ARGS + if (ch == L'$') { + if (n <= MAX_POS_ARGS) { + N = n - 1; + is_pos_arg = 1; + goto rflag; + } + else + goto error; + } +#endif /* !_NO_POS_ARGS */ + width = n; + goto reswitch; +#ifdef FLOATING_POINT + case L'L': + flags |= LONGDBL; + goto rflag; +#endif + case L'h': +#ifdef _WANT_IO_C99_FORMATS + if (*fmt == L'h') { + fmt++; + flags |= CHARINT; + } else +#endif + flags |= SHORTINT; + goto rflag; + case L'l': +#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG + if (*fmt == L'l') { + fmt++; + flags |= QUADINT; + } else +#endif + flags |= LONGINT; + goto rflag; + case L'q': /* GNU extension */ + flags |= QUADINT; + goto rflag; +#ifdef _WANT_IO_C99_FORMATS + case L'j': + if (sizeof (intmax_t) == sizeof (long)) + flags |= LONGINT; + else + flags |= QUADINT; + goto rflag; + case L'z': + if (sizeof (size_t) < sizeof (int)) + /* POSIX states size_t is 16 or more bits, as is short. */ + flags |= SHORTINT; + else if (sizeof (size_t) == sizeof (int)) + /* no flag needed */; + else if (sizeof (size_t) <= sizeof (long)) + flags |= LONGINT; + else + /* POSIX states that at least one programming + environment must support size_t no wider than + long, but that means other environments can + have size_t as wide as long long. */ + flags |= QUADINT; + goto rflag; + case L't': + if (sizeof (ptrdiff_t) < sizeof (int)) + /* POSIX states ptrdiff_t is 16 or more bits, as + is short. */ + flags |= SHORTINT; + else if (sizeof (ptrdiff_t) == sizeof (int)) + /* no flag needed */; + else if (sizeof (ptrdiff_t) <= sizeof (long)) + flags |= LONGINT; + else + /* POSIX states that at least one programming + environment must support ptrdiff_t no wider than + long, but that means other environments can + have ptrdiff_t as wide as long long. */ + flags |= QUADINT; + goto rflag; + case L'C': /* POSIX extension */ +#endif /* _WANT_IO_C99_FORMATS */ + case L'c': + cp = buf; + if (ch == L'c' && !(flags & LONGINT)) { + wint_t wc = btowc ((int) GET_ARG (N, ap, int)); + if (wc == WEOF) { + fp->_flags |= __SERR; + goto error; + } + cp[0] = (wchar_t) wc; + } + else + { + cp[0] = GET_ARG (N, ap, int); + } + cp[1] = L'\0'; + size = 1; + sign = L'\0'; + break; + case L'd': + case L'i': + _uquad = SARG (); +#ifndef _NO_LONGLONG + if ((quad_t)_uquad < 0) +#else + if ((long) _uquad < 0) +#endif + { + + _uquad = -_uquad; + sign = L'-'; + } + base = DEC; + goto number; +#ifdef FLOATING_POINT +# ifdef _WANT_IO_C99_FORMATS + case L'a': + case L'A': + case L'F': +# endif + case L'e': + case L'E': + case L'f': + case L'g': + case L'G': +# ifdef _NO_LONGDBL + if (flags & LONGDBL) { + _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE); + } else { + _fpvalue = GET_ARG (N, ap, double); + } + + /* do this before tricky precision changes + + If the output is infinite or NaN, leading + zeros are not permitted. Otherwise, scanf + could not read what printf wrote. + */ + if (isinf (_fpvalue)) { + if (_fpvalue < 0) + sign = '-'; + if (ch <= L'G') /* 'A', 'E', 'F', or 'G' */ + cp = L"INF"; + else + cp = L"inf"; + size = 3; + flags &= ~ZEROPAD; + break; + } + if (isnan (_fpvalue)) { + if (ch <= L'G') /* 'A', 'E', 'F', or 'G' */ + cp = L"NAN"; + else + cp = L"nan"; + size = 3; + flags &= ~ZEROPAD; + break; + } + +# else /* !_NO_LONGDBL */ + + if (flags & LONGDBL) { + _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE); + } else { + _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double); + } + + /* do this before tricky precision changes */ + expt = _ldcheck (&_fpvalue); + if (expt == 2) { + if (_fpvalue < 0) + sign = L'-'; + if (ch <= L'G') /* 'A', 'E', 'F', or 'G' */ + cp = L"INF"; + else + cp = L"inf"; + size = 3; + flags &= ~ZEROPAD; + break; + } + if (expt == 1) { + if (ch <= L'G') /* 'A', 'E', 'F', or 'G' */ + cp = L"NAN"; + else + cp = L"nan"; + size = 3; + flags &= ~ZEROPAD; + break; + } +# endif /* !_NO_LONGDBL */ + + cp = buf; +# ifdef _WANT_IO_C99_FORMATS + if (ch == L'a' || ch == L'A') { + ox[0] = L'0'; + ox[1] = ch == L'a' ? L'x' : L'X'; + flags |= HEXPREFIX; + if (prec >= BUF) + { + if ((malloc_buf = + (wchar_t *)_malloc_r (data, (prec + 1) * sizeof (wchar_t))) + == NULL) + { + fp->_flags |= __SERR; + goto error; + } + cp = malloc_buf; + } + } else +# endif /* _WANT_IO_C99_FORMATS */ + if (prec == -1) { + prec = DEFPREC; + } else if ((ch == L'g' || ch == L'G') && prec == 0) { + prec = 1; + } + + flags |= FPT; + + cp = wcvt (data, _fpvalue, prec, flags, &softsign, + &expt, ch, &ndig, cp, BUF); + + /* If buf is not large enough for the converted wchar_t + sequence, call wcvt again with a malloced new buffer. + This should happen fairly rarely. + */ + if (cp == buf && ndig > BUF && malloc_buf == NULL) { + if ((malloc_buf = + (wchar_t *)_malloc_r (data, ndig * sizeof (wchar_t))) + == NULL) + { + fp->_flags |= __SERR; + goto error; + } + cp = wcvt (data, _fpvalue, prec, flags, &softsign, + &expt, ch, &ndig, malloc_buf, ndig); + } + + if (ch == L'g' || ch == L'G') { + if (expt <= -4 || expt > prec) + ch -= 2; /* 'e' or 'E' */ + else + ch = L'g'; + } +# ifdef _WANT_IO_C99_FORMATS + else if (ch == L'F') + ch = L'f'; +# endif + if (ch <= L'e') { /* 'a', 'A', 'e', or 'E' fmt */ + --expt; + expsize = wexponent (expstr, expt, ch); + size = expsize + ndig; + if (ndig > 1 || flags & ALT) + ++size; +# ifdef _WANT_IO_C99_FORMATS + flags &= ~GROUPING; +# endif + } else { + if (ch == L'f') { /* f fmt */ + if (expt > 0) { + size = expt; + if (prec || flags & ALT) + size += prec + 1; + } else /* "0.X" */ + size = (prec || flags & ALT) + ? prec + 2 + : 1; + } else if (expt >= ndig) { /* fixed g fmt */ + size = expt; + if (flags & ALT) + ++size; + } else + size = ndig + (expt > 0 ? + 1 : 2 - expt); +# ifdef _WANT_IO_C99_FORMATS + if ((flags & GROUPING) && expt > 0) { + /* space for thousands' grouping */ + nseps = nrepeats = 0; + lead = expt; + while (*grouping != CHAR_MAX) { + if (lead <= *grouping) + break; + lead -= *grouping; + if (grouping[1]) { + nseps++; + grouping++; + } else + nrepeats++; + } + size += nseps + nrepeats; + } else +# endif + lead = expt; + } + if (softsign) + sign = L'-'; + break; +#endif /* FLOATING_POINT */ +#ifdef _GLIBC_EXTENSION + case L'm': /* GNU extension */ + { + int dummy; + cp = (wchar_t *) _strerror_r (data, data->_errno, 1, &dummy); + } + flags &= ~LONGINT; + goto string; +#endif + case L'n': +#ifndef _NO_LONGLONG + if (flags & QUADINT) + *GET_ARG (N, ap, quad_ptr_t) = ret; + else +#endif + if (flags & LONGINT) + *GET_ARG (N, ap, long_ptr_t) = ret; + else if (flags & SHORTINT) + *GET_ARG (N, ap, short_ptr_t) = ret; +#ifdef _WANT_IO_C99_FORMATS + else if (flags & CHARINT) + *GET_ARG (N, ap, char_ptr_t) = ret; +#endif + else + *GET_ARG (N, ap, int_ptr_t) = ret; + continue; /* no output */ + case L'o': + _uquad = UARG (); + base = OCT; +#ifdef _WANT_IO_C99_FORMATS + flags &= ~GROUPING; +#endif + goto nosign; + case L'p': + /* + * ``The argument shall be a pointer to void. The + * value of the pointer is converted to a sequence + * of printable characters, in an implementation- + * defined manner.'' + * -- ANSI X3J11 + */ + /* NOSTRICT */ + _uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t); + base = HEX; + xdigs = L"0123456789abcdef"; + flags |= HEXPREFIX; + ox[0] = L'0'; + ox[1] = ch = L'x'; + goto nosign; + case L's': +#ifdef _WANT_IO_C99_FORMATS + case L'S': /* POSIX extension */ +#endif + cp = GET_ARG (N, ap, wchar_ptr_t); +#ifdef _GLIBC_EXTENSION +string: +#endif + sign = '\0'; +#ifndef __OPTIMIZE_SIZE__ + /* Behavior is undefined if the user passed a + NULL string when precision is not 0. + However, if we are not optimizing for size, + we might as well mirror glibc behavior. */ + if (cp == NULL) { + cp = L"(null)"; + size = ((unsigned) prec > 6U) ? 6 : prec; + } + else +#endif /* __OPTIMIZE_SIZE__ */ +#ifdef _MB_CAPABLE + if (ch != L'S' && !(flags & LONGINT)) { + char *arg = (char *) cp; + size_t insize = 0, nchars = 0, nconv = 0; + mbstate_t ps; + wchar_t *p; + + if (prec >= 0) { + char *p = arg; + memset ((_PTR)&ps, '\0', sizeof (mbstate_t)); + while (nchars < (size_t)prec) { + nconv = mbrlen (p, MB_CUR_MAX, &ps); + if (nconv == 0 || nconv == (size_t)-1 || + nconv == (size_t)-2) + break; + p += nconv; + ++nchars; + insize += nconv; + } + if (nconv == (size_t) -1 || nconv == (size_t) -2) { + fp->_flags |= __SERR; + goto error; + } + } else + insize = strlen(arg); + if (insize >= BUF) { + if ((malloc_buf = (wchar_t *) _malloc_r (data, (insize + 1) * sizeof (wchar_t))) + == NULL) { + fp->_flags |= __SERR; + goto error; + } + cp = malloc_buf; + } else + cp = buf; + memset ((_PTR)&ps, '\0', sizeof (mbstate_t)); + p = cp; + while (insize != 0) { + nconv = _mbrtowc_r (data, p, arg, insize, &ps); + if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2) + break; + ++p; + arg += nconv; + insize -= nconv; + } + if (nconv == (size_t) -1 || nconv == (size_t) -2) { + fp->_flags |= __SERR; + goto error; + } + *p = L'\0'; + size = p - cp; + } +#else + if (ch != L'S' && !(flags & LONGINT)) { + char *arg = (char *) cp; + size_t insize = 0; + + if (prec >= 0) { + char *p = memchr (arg, '\0', prec); + insize = p ? p - arg : prec; + } else + insize = strlen (arg); + if (insize >= BUF) { + if ((malloc_buf = (wchar_t *) _malloc_r (data, (insize + 1) * sizeof (wchar_t))) + == NULL) { + fp->_flags |= __SERR; + goto error; + } + cp = malloc_buf; + } else + cp = buf; + for (size = 0; size < insize; ++size) + cp[size] = arg[size]; + cp[size] = L'\0'; + } +#endif /* _MB_CAPABLE */ + else if (prec >= 0) { + /* + * can't use wcslen; can only look for the + * NUL in the first `prec' characters, and + * strlen () will go further. + */ + wchar_t *p = wmemchr (cp, L'\0', prec); + + if (p != NULL) { + size = p - cp; + if (size > prec) + size = prec; + } else + size = prec; + } else + size = wcslen (cp); + + break; + case L'u': + _uquad = UARG (); + base = DEC; + goto nosign; + case L'X': + xdigs = L"0123456789ABCDEF"; + goto hex; + case L'x': + xdigs = L"0123456789abcdef"; +hex: _uquad = UARG (); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _uquad != 0) { + ox[0] = L'0'; + ox[1] = ch; + flags |= HEXPREFIX; + } + +#ifdef _WANT_IO_C99_FORMATS + flags &= ~GROUPING; +#endif + /* unsigned conversions */ +nosign: sign = L'\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ +number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + * ``The result of converting a zero value with an + * explicit precision of zero is no characters.'' + * -- ANSI X3J11 + */ + cp = buf + BUF; + if (_uquad != 0 || prec != 0) { + /* + * Unsigned mod is hard, and unsigned mod + * by a constant is easier than that by + * a variable; hence this switch. + */ + switch (base) { + case OCT: + do { + *--cp = to_char (_uquad & 7); + _uquad >>= 3; + } while (_uquad); + /* handle octal leading 0 */ + if (flags & ALT && *cp != L'0') + *--cp = L'0'; + break; + + case DEC: + /* many numbers are 1 digit */ + if (_uquad < 10) { + *--cp = to_char(_uquad); + break; + } +#ifdef _WANT_IO_C99_FORMATS + ndig = 0; +#endif + do { + *--cp = to_char (_uquad % 10); +#ifdef _WANT_IO_C99_FORMATS + ndig++; + /* If (*grouping == CHAR_MAX) then no + more grouping */ + if ((flags & GROUPING) + && ndig == *grouping + && *grouping != CHAR_MAX + && _uquad > 9) { + *--cp = thousands_sep; + ndig = 0; + /* If (grouping[1] == '\0') then we + have to use *grouping character + (last grouping rule) for all + next cases. */ + if (grouping[1] != '\0') + grouping++; + } +#endif + _uquad /= 10; + } while (_uquad != 0); + break; + + case HEX: + do { + *--cp = xdigs[_uquad & 15]; + _uquad >>= 4; + } while (_uquad); + break; + + default: + cp = L"bug in vfprintf: bad base"; + size = wcslen (cp); + goto skipsize; + } + } + /* + * ...result is to be converted to an 'alternate form'. + * For o conversion, it increases the precision to force + * the first digit of the result to be a zero." + * -- ANSI X3J11 + * + * To demonstrate this case, compile and run: + * printf ("%#.0o",0); + */ + else if (base == OCT && (flags & ALT)) + *--cp = L'0'; + + size = buf + BUF - cp; + skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == L'\0') + goto done; + /* pretend it was %c with argument ch */ + cp = buf; + *cp = ch; + size = 1; + sign = L'\0'; + break; + } + + /* + * All reasonable formats wind up here. At this point, `cp' + * points to a string which (if not flags&LADJUST) should be + * padded out to `width' places. If flags&ZEROPAD, it should + * first be prefixed by any sign or other prefix; otherwise, + * it should be blank padded before the prefix is emitted. + * After any left-hand padding and prefixing, emit zeroes + * required by a decimal [diouxX] precision, then print the + * string proper, then emit zeroes required by any leftover + * floating precision; finally, if LADJUST, pad with blanks. + * If flags&FPT, ch must be in [aAeEfg]. + * + * Compute actual size, so we know how much to pad. + * size excludes decimal prec; realsz includes it. + */ + realsz = dprec > size ? dprec : size; + if (sign) + realsz++; + if (flags & HEXPREFIX) + realsz+= 2; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST|ZEROPAD)) == 0) + PAD (width - realsz, blanks); + + /* prefix */ + if (sign) + PRINT (&sign, 1); + if (flags & HEXPREFIX) + PRINT (ox, 2); + + /* right-adjusting zero padding */ + if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) + PAD (width - realsz, zeroes); + + /* leading zeroes from decimal precision */ + PAD (dprec - size, zeroes); + + /* the string or number proper */ +#ifdef FLOATING_POINT + if ((flags & FPT) == 0) { + PRINT (cp, size); + } else { /* glue together f_p fragments */ + if (ch >= L'f') { /* 'f' or 'g' */ + if (_fpvalue == 0) { + /* kludge for __dtoa irregularity */ + PRINT (L"0", 1); + if (expt < ndig || flags & ALT) { + PRINT (&decimal_point, 1); + PAD (ndig - 1, zeroes); + } + } else if (expt <= 0) { + PRINT (L"0", 1); + if (expt || ndig || flags & ALT) { + PRINT (&decimal_point, 1); + PAD (-expt, zeroes); + PRINT (cp, ndig); + } + } else { + wchar_t *convbuf = cp; + PRINTANDPAD(cp, convbuf + ndig, + lead, zeroes); + cp += lead; +#ifdef _WANT_IO_C99_FORMATS + if (flags & GROUPING) { + while (nseps > 0 || nrepeats > 0) { + if (nrepeats > 0) + nrepeats--; + else { + grouping--; + nseps--; + } + PRINT (&thousands_sep, 1); + PRINTANDPAD (cp, convbuf + ndig, + *grouping, zeroes); + cp += *grouping; + } + if (cp > convbuf + ndig) + cp = convbuf + ndig; + } +#endif + if (expt < ndig || flags & ALT) + PRINT (&decimal_point, 1); + PRINTANDPAD (cp, convbuf + ndig, + ndig - expt, zeroes); + } + + } else { /* 'a', 'A', 'e', or 'E' */ + if (ndig > 1 || flags & ALT) { + PRINT (cp, 1); + cp++; + PRINT (&decimal_point, 1); + if (_fpvalue) { + PRINT (cp, ndig - 1); + } else /* 0.[0..] */ + /* __dtoa irregularity */ + PAD (ndig - 1, zeroes); + } else /* XeYYY */ + PRINT (cp, 1); + PRINT (expstr, expsize); + } + } +#else /* !FLOATING_POINT */ + PRINT (cp, size); +#endif + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) + PAD (width - realsz, blanks); + + /* finally, adjust ret */ + ret += width > realsz ? width : realsz; + + FLUSH (); /* copy out the I/O vectors */ + + if (malloc_buf != NULL) { + _free_r (data, malloc_buf); + malloc_buf = NULL; + } + } +done: + FLUSH (); +error: + if (malloc_buf != NULL) + _free_r (data, malloc_buf); +#ifndef STRING_ONLY + _newlib_flockfile_end (fp); +#endif + return (__sferror (fp) ? EOF : ret); + /* NOTREACHED */ +} + +#ifdef FLOATING_POINT + +/* Using reentrant DATA, convert finite VALUE into a string of digits + with no decimal point, using NDIGITS precision and FLAGS as guides + to whether trailing zeros must be included. Set *SIGN to nonzero + if VALUE was negative. Set *DECPT to the exponent plus one. Set + *LENGTH to the length of the returned string. CH must be one of + [aAeEfFgG]; different from vfprintf.c:cvt(), the return string + lives in BUF regardless of CH. LEN is the length of BUF, except + when CH is [aA], in which case LEN is not in use. If BUF is not + large enough for the converted string, only the first LEN number + of characters will be returned in BUF, but *LENGTH will be set to + the full length of the string before the truncation. */ +static wchar_t * +wcvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags, + wchar_t *sign, int *decpt, int ch, int *length, wchar_t *buf, int len) +{ + int mode, dsgn; +# ifdef _NO_LONGDBL + union double_union tmp; + + tmp.d = value; + if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */ + value = -value; + *sign = L'-'; + } else + *sign = L'\0'; +# else /* !_NO_LONGDBL */ + union + { + struct ldieee ieee; + _LONG_DOUBLE val; + } ld; + + ld.val = value; + if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */ + value = -value; + *sign = L'-'; + } else + *sign = L'\0'; +# endif /* !_NO_LONGDBL */ + +# ifdef _WANT_IO_C99_FORMATS + if (ch == L'a' || ch == L'A') { + wchar_t *digits, *bp, *rve; + /* This code assumes FLT_RADIX is a power of 2. The initial + division ensures the digit before the decimal will be less + than FLT_RADIX (unless it is rounded later). There is no + loss of precision in these calculations. */ + value = FREXP (value, decpt) / 8; + if (!value) + *decpt = 1; + digits = ch == L'a' ? L"0123456789abcdef" : L"0123456789ABCDEF"; + bp = buf; + do { + value *= 16; + mode = (int) value; + value -= mode; + *bp++ = digits[mode]; + } while (ndigits-- && value); + if (value > 0.5 || (value == 0.5 && mode & 1)) { + /* round to even */ + rve = bp; + while (*--rve == digits[0xf]) { + *rve = L'0'; + } + *rve = *rve == L'9' ? digits[0xa] : *rve + 1; + } else { + while (ndigits-- >= 0) { + *bp++ = L'0'; + } + } + *length = bp - buf; + return buf; + } +# endif /* _WANT_IO_C99_FORMATS */ + if (ch == L'f' || ch == L'F') { + mode = 3; /* ndigits after the decimal point */ + } else { + /* To obtain ndigits after the decimal point for the 'e' + * and 'E' formats, round to ndigits + 1 significant + * figures. + */ + if (ch == L'e' || ch == L'E') { + ndigits++; + } + mode = 2; /* ndigits significant digits */ + } + + { + char *digits, *bp, *rve; +#ifndef _MB_CAPABLE + int i; +#endif + + digits = _DTOA_R (data, value, mode, ndigits, decpt, &dsgn, &rve); + + if ((ch != L'g' && ch != L'G') || flags & ALT) { /* Print trailing zeros */ + bp = digits + ndigits; + if (ch == L'f' || ch == L'F') { + if (*digits == L'0' && value) + *decpt = -ndigits + 1; + bp += *decpt; + } + if (value == 0) /* kludge for __dtoa irregularity */ + rve = bp; + while (rve < bp) + *rve++ = '0'; + } + + *length = rve - digits; /* full length of the string */ +#ifdef _MB_CAPABLE + _mbsnrtowcs_r (data, buf, (const char **) &digits, *length, + len, NULL); +#else + for (i = 0; i < *length && i < len; ++i) + buf[i] = (wchar_t) digits[i]; +#endif + return buf; + } +} + +static int +wexponent(wchar_t *p0, int exp, int fmtch) +{ + register wchar_t *p, *t; + wchar_t expbuf[MAXEXPLEN]; +# ifdef _WANT_IO_C99_FORMATS + int isa = fmtch == L'a' || fmtch == L'A'; +# else +# define isa 0 +# endif + + p = p0; + *p++ = isa ? L'p' - L'a' + fmtch : fmtch; + if (exp < 0) { + exp = -exp; + *p++ = L'-'; + } + else + *p++ = L'+'; + t = expbuf + MAXEXPLEN; + if (exp > 9) { + do { + *--t = to_char (exp % 10); + } while ((exp /= 10) > 9); + *--t = to_char (exp); + for (; t < expbuf + MAXEXPLEN; *p++ = *t++); + } + else { + if (!isa) + *p++ = L'0'; + *p++ = to_char (exp); + } + return (p - p0); +} +#endif /* FLOATING_POINT */ + + +#ifndef _NO_POS_ARGS + +/* Positional argument support. + Written by Jeff Johnston + + Copyright (c) 2002 Red Hat Incorporated. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 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. + + The name of Red Hat Incorporated may not be used to endorse + or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 RED HAT INCORPORATED BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* function to get positional parameter N where n = N - 1 */ +static union arg_val * +_DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), + struct _reent *data _AND + int n _AND + wchar_t *fmt _AND + va_list *ap _AND + int *numargs_p _AND + union arg_val *args _AND + int *arg_type _AND + wchar_t **last_fmt) +{ + wchar_t ch; + int number, flags; + int spec_type; + int numargs = *numargs_p; + __CH_CLASS chtype; + __STATE state, next_state; + __ACTION action; + int pos, last_arg; + int max_pos_arg = n; + /* Only need types that can be reached via vararg promotions. */ + enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR }; + + /* if this isn't the first call, pick up where we left off last time */ + if (*last_fmt != NULL) + fmt = *last_fmt; + + /* we need to process either to end of fmt string or until we have actually + read the desired parameter from the vararg list. */ + while (*fmt && n >= numargs) + { + while (*fmt != L'\0' && *fmt != L'%') + fmt += 1; + + if (*fmt == L'\0') + break; + state = START; + flags = 0; + pos = -1; + number = 0; + spec_type = INT; + + /* Use state/action table to process format specifiers. We ignore invalid + formats and we are only interested in information that tells us how to + read the vararg list. */ + while (state != DONE) + { + ch = *fmt++; + chtype = ch < (wchar_t) 256 ? __chclass[ch] : OTHER; + next_state = __state_table[state][chtype]; + action = __action_table[state][chtype]; + state = next_state; + + switch (action) + { + case GETMOD: /* we have format modifier */ + switch (ch) + { + case L'h': + /* No flag needed, since short and char promote to int. */ + break; + case L'L': + flags |= LONGDBL; + break; + case L'q': + flags |= QUADINT; + break; +# ifdef _WANT_IO_C99_FORMATS + case L'j': + if (sizeof (intmax_t) == sizeof (long)) + flags |= LONGINT; + else + flags |= QUADINT; + break; + case L'z': + if (sizeof (size_t) <= sizeof (int)) + /* no flag needed */; + else if (sizeof (size_t) <= sizeof (long)) + flags |= LONGINT; + else + /* POSIX states that at least one programming + environment must support size_t no wider than + long, but that means other environments can + have size_t as wide as long long. */ + flags |= QUADINT; + break; + case L't': + if (sizeof (ptrdiff_t) <= sizeof (int)) + /* no flag needed */; + else if (sizeof (ptrdiff_t) <= sizeof (long)) + flags |= LONGINT; + else + /* POSIX states that at least one programming + environment must support ptrdiff_t no wider than + long, but that means other environments can + have ptrdiff_t as wide as long long. */ + flags |= QUADINT; + break; +# endif /* _WANT_IO_C99_FORMATS */ + case L'l': + default: +# if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG + if (*fmt == L'l') + { + flags |= QUADINT; + ++fmt; + } + else +# endif + flags |= LONGINT; + break; + } + break; + case GETARG: /* we have format specifier */ + { + numargs &= (MAX_POS_ARGS - 1); + /* process the specifier and translate it to a type to fetch from varargs */ + switch (ch) + { + case L'd': + case L'i': + case L'o': + case L'x': + case L'X': + case L'u': + if (flags & LONGINT) + spec_type = LONG_INT; +# ifndef _NO_LONGLONG + else if (flags & QUADINT) + spec_type = QUAD_INT; +# endif + else + spec_type = INT; + break; +# ifdef _WANT_IO_C99_FORMATS + case L'a': + case L'A': + case L'F': +# endif + case L'f': + case L'g': + case L'G': + case L'E': + case L'e': +# ifndef _NO_LONGDBL + if (flags & LONGDBL) + spec_type = LONG_DOUBLE; + else +# endif + spec_type = DOUBLE; + break; + case L's': +# ifdef _WANT_IO_C99_FORMATS + case L'S': /* POSIX extension */ +# endif + case L'p': + case L'n': + spec_type = CHAR_PTR; + break; + case L'c': +# ifdef _WANT_IO_C99_FORMATS + if (flags & LONGINT) + spec_type = WIDE_CHAR; + else +# endif + spec_type = INT; + break; +# ifdef _WANT_IO_C99_FORMATS + case L'C': /* POSIX extension */ + spec_type = WIDE_CHAR; + break; +# endif + } + + /* if we have a positional parameter, just store the type, otherwise + fetch the parameter from the vararg list */ + if (pos != -1) + arg_type[pos] = spec_type; + else + { + switch (spec_type) + { + case LONG_INT: + args[numargs++].val_long = va_arg (*ap, long); + break; + case QUAD_INT: + args[numargs++].val_quad_t = va_arg (*ap, quad_t); + break; + case WIDE_CHAR: + args[numargs++].val_wint_t = va_arg (*ap, wint_t); + break; + case INT: + args[numargs++].val_int = va_arg (*ap, int); + break; + case CHAR_PTR: + args[numargs++].val_wchar_ptr_t = va_arg (*ap, wchar_t *); + break; + case DOUBLE: + args[numargs++].val_double = va_arg (*ap, double); + break; + case LONG_DOUBLE: + args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE); + break; + } + } + } + break; + case GETPOS: /* we have positional specifier */ + if (arg_type[0] == -1) + memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS); + pos = number - 1; + max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos); + break; + case PWPOS: /* we have positional specifier for width or precision */ + if (arg_type[0] == -1) + memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS); + number -= 1; + arg_type[number] = INT; + max_pos_arg = (max_pos_arg > number ? max_pos_arg : number); + break; + case GETPWB: /* we require format pushback */ + --fmt; + /* fallthrough */ + case GETPW: /* we have a variable precision or width to acquire */ + args[numargs++].val_int = va_arg (*ap, int); + break; + case NUMBER: /* we have a number to process */ + number = (ch - '0'); + while ((ch = *fmt) != '\0' && is_digit (ch)) + { + number = number * 10 + (ch - '0'); + ++fmt; + } + break; + case SKIPNUM: /* we have a number to skip */ + while ((ch = *fmt) != '\0' && is_digit (ch)) + ++fmt; + break; + case NOOP: + default: + break; /* do nothing */ + } + } + } + + /* process all arguments up to at least the one we are looking for and if we + have seen the end of the string, then process up to the max argument needed */ + if (*fmt == '\0') + last_arg = max_pos_arg; + else + last_arg = n; + + while (numargs <= last_arg) + { + switch (arg_type[numargs]) + { + case LONG_INT: + args[numargs++].val_long = va_arg (*ap, long); + break; + case QUAD_INT: + args[numargs++].val_quad_t = va_arg (*ap, quad_t); + break; + case CHAR_PTR: + args[numargs++].val_wchar_ptr_t = va_arg (*ap, wchar_t *); + break; + case DOUBLE: + args[numargs++].val_double = va_arg (*ap, double); + break; + case LONG_DOUBLE: + args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE); + break; + case WIDE_CHAR: + args[numargs++].val_wint_t = va_arg (*ap, wint_t); + break; + case INT: + default: + args[numargs++].val_int = va_arg (*ap, int); + break; + } + } + + /* alter the global numargs value and keep a reference to the last bit of the fmt + string we processed here because the caller will continue processing where we started */ + *numargs_p = numargs; + *last_fmt = fmt; + return &args[n]; +} +#endif /* !_NO_POS_ARGS */ diff --git a/contrib/sdk/sources/newlib/libc/stdio/vfwscanf.c b/contrib/sdk/sources/newlib/libc/stdio/vfwscanf.c new file mode 100644 index 0000000000..38a060d28d --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/vfwscanf.c @@ -0,0 +1,1499 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ + +/* +FUNCTION +<>, <>, <>---scan and format argument list from wide character input + +INDEX + vfwscanf +INDEX + _vfwscanf +INDEX + vwscanf +INDEX + _vwscanf +INDEX + vswscanf +INDEX + _vswscanf + +ANSI_SYNOPSIS + #include + #include + int vwscanf(const wchar_t *__restrict <[fmt]>, va_list <[list]>); + int vfwscanf(FILE *__restrict <[fp]>, + const wchar_t *__restrict <[fmt]>, va_list <[list]>); + int vswscanf(const wchar_t *__restrict <[str]>, + const wchar_t *__restrict <[fmt]>, va_list <[list]>); + + int _vwscanf(struct _reent *<[reent]>, const wchar_t *<[fmt]>, + va_list <[list]>); + int _vfwscanf(struct _reent *<[reent]>, FILE *<[fp]>, + const wchar_t *<[fmt]>, va_list <[list]>); + int _vswscanf(struct _reent *<[reent]>, const wchar_t *<[str]>, + const wchar_t *<[fmt]>, va_list <[list]>); + +TRAD_SYNOPSIS + #include + #include + int vwscanf( <[fmt]>, <[ist]>) + wchar_t *__restrict <[fmt]>; + va_list <[list]>; + + int vfwscanf( <[fp]>, <[fmt]>, <[list]>) + FILE *__restrict <[fp]>; + wchar_t *__restrict <[fmt]>; + va_list <[list]>; + + int vswscanf( <[str]>, <[fmt]>, <[list]>) + wchar_t *__restrict <[str]>; + wchar_t *__restrict <[fmt]>; + va_list <[list]>; + + int _vwscanf( <[reent]>, <[fmt]>, <[ist]>) + struct _reent *<[reent]>; + wchar_t *<[fmt]>; + va_list <[list]>; + + int _vfwscanf( <[reent]>, <[fp]>, <[fmt]>, <[list]>) + struct _reent *<[reent]>; + FILE *<[fp]>; + wchar_t *<[fmt]>; + va_list <[list]>; + + int _vswscanf( <[reent]>, <[str]>, <[fmt]>, <[list]>) + struct _reent *<[reent]>; + wchar_t *<[str]>; + wchar_t *<[fmt]>; + va_list <[list]>; + +DESCRIPTION +<>, <>, and <> are (respectively) variants +of <>, <>, and <>. They differ only in +allowing their caller to pass the variable argument list as a +<> object (initialized by <>) rather than +directly accepting a variable number of arguments. + +RETURNS +The return values are consistent with the corresponding functions: +<> returns the number of input fields successfully scanned, +converted, and stored; the return value does not include scanned +fields which were not stored. + +If <> attempts to read at end-of-file, the return value +is <>. + +If no fields were stored, the return value is <<0>>. + +The routines <<_vwscanf>>, <<_vfwscanf>>, and <<_vswscanf>> are +reentrant versions which take an additional first parameter which points +to the reentrancy structure. + +PORTABILITY +C99, POSIX-1.2008 +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +#ifdef INTEGER_ONLY +#define VFWSCANF vfiwscanf +#define _VFWSCANF_R _vfiwscanf_r +#define __SVFWSCANF __svfiwscanf +#ifdef STRING_ONLY +# define __SVFWSCANF_R __ssvfiwscanf_r +#else +# define __SVFWSCANF_R __svfiwscanf_r +#endif +#else +#define VFWSCANF vfwscanf +#define _VFWSCANF_R _vfwscanf_r +#define __SVFWSCANF __svfwscanf +#ifdef STRING_ONLY +# define __SVFWSCANF_R __ssvfwscanf_r +#else +# define __SVFWSCANF_R __svfwscanf_r +#endif +#ifndef NO_FLOATING_POINT +#define FLOATING_POINT +#endif +#endif + +#ifdef STRING_ONLY +#undef _newlib_flockfile_start +#undef _newlib_flockfile_exit +#undef _newlib_flockfile_end +#define _newlib_flockfile_start(x) {} +#define _newlib_flockfile_exit(x) {} +#define _newlib_flockfile_end(x) {} +#define _ungetwc_r _sungetwc_r +#define __srefill_r __ssrefill_r +#define _fgetwc_r _sfgetwc_r +#endif + +#ifdef FLOATING_POINT +#include +#include +#include +#ifdef __HAVE_LOCALE_INFO_EXTENDED__ +#include "../locale/lnumeric.h" +#endif + +/* Currently a test is made to see if long double processing is warranted. + This could be changed in the future should the _ldtoa_r code be + preferred over _dtoa_r. */ +#define _NO_LONGDBL +#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG) +#undef _NO_LONGDBL +extern _LONG_DOUBLE _wcstold_r _PARAMS((wchar_t *s, wchar_t **sptr)); +#endif + +#include "floatio.h" + +#if ((MAXEXP+MAXFRACT+3) > MB_LEN_MAX) +# define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */ +#else +# define BUF MB_LEN_MAX +#endif + +/* An upper bound for how long a long prints in decimal. 4 / 13 approximates + log (2). Add one char for roundoff compensation and one for the sign. */ +#define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2) +#else +#define BUF 40 +#endif + +#define _NO_LONGLONG +#if defined _WANT_IO_LONG_LONG \ + && (defined __GNUC__ || __STDC_VERSION__ >= 199901L) +# undef _NO_LONGLONG +#endif + +#define _NO_POS_ARGS +#ifdef _WANT_IO_POS_ARGS +# undef _NO_POS_ARGS +# ifdef NL_ARGMAX +# define MAX_POS_ARGS NL_ARGMAX +# else +# define MAX_POS_ARGS 32 +# endif + +static void * get_arg (int, va_list *, int *, void **); +#endif /* _WANT_IO_POS_ARGS */ + +/* + * Flags used during conversion. + */ + +#define LONG 0x01 /* l: long or double */ +#define LONGDBL 0x02 /* L/ll: long double or long long */ +#define SHORT 0x04 /* h: short */ +#define CHAR 0x08 /* hh: 8 bit integer */ +#define SUPPRESS 0x10 /* suppress assignment */ +#define POINTER 0x20 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x40 /* do not skip blanks */ + +/* + * The following are used in numeric conversions only: + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. + */ + +#define SIGNOK 0x80 /* +/- is (still) legal */ +#define NDIGITS 0x100 /* no digits detected */ + +#define DPTOK 0x200 /* (float) decimal point is still legal */ +#define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */ + +#define PFXOK 0x200 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x400 /* no zero digits detected */ +#define HAVESIGN 0x10000 /* sign detected */ + +/* + * Conversion types. + */ + +#define CT_CHAR 0 /* %c conversion */ +#define CT_CCL 1 /* %[...] conversion */ +#define CT_STRING 2 /* %s conversion */ +#define CT_INT 3 /* integer, i.e., wcstol or wcstoul */ +#define CT_FLOAT 4 /* floating, i.e., wcstod */ + +#define INCCL(_c) \ + (cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \ + (wmemchr(ccls, (_c), ccle - ccls) != NULL)) + +/* + * vfwscanf + */ + +#ifndef STRING_ONLY + +#ifndef _REENT_ONLY + +int +_DEFUN(VFWSCANF, (fp, fmt, ap), + register FILE *__restrict fp _AND + _CONST wchar_t *__restrict fmt _AND + va_list ap) +{ + struct _reent *reent = _REENT; + + CHECK_INIT(reent, fp); + return __SVFWSCANF_R (reent, fp, fmt, ap); +} + +int +_DEFUN(__SVFWSCANF, (fp, fmt0, ap), + register FILE *fp _AND + wchar_t _CONST *fmt0 _AND + va_list ap) +{ + return __SVFWSCANF_R (_REENT, fp, fmt0, ap); +} + +#endif /* !_REENT_ONLY */ + +int +_DEFUN(_VFWSCANF_R, (data, fp, fmt, ap), + struct _reent *data _AND + register FILE *fp _AND + _CONST wchar_t *fmt _AND + va_list ap) +{ + CHECK_INIT(data, fp); + return __SVFWSCANF_R (data, fp, fmt, ap); +} +#endif /* !STRING_ONLY */ + +#ifdef STRING_ONLY +/* When dealing with the swscanf family, we don't want to use the + * regular ungetwc which will drag in file I/O items we don't need. + * So, we create our own trimmed-down version. */ +static wint_t +_DEFUN(_sungetwc_r, (data, fp, ch), + struct _reent *data _AND + wint_t wc _AND + register FILE *fp) +{ + if (wc == WEOF) + return (WEOF); + + /* After ungetc, we won't be at eof anymore */ + fp->_flags &= ~__SEOF; + + /* + * If we are in the middle of ungetwc'ing, just continue. + * This may require expanding the current ungetc buffer. + */ + + if (HASUB (fp)) + { + if (fp->_r >= fp->_ub._size && __submore (data, fp)) + { + return EOF; + } + fp->_p -= sizeof (wchar_t); + *fp->_p = (wchar_t) wc; + fp->_r += sizeof (wchar_t); + return wc; + } + + /* + * If we can handle this by simply backing up, do so, + * but never replace the original character. + * (This makes swscanf() work when scanning `const' data.) + */ + + if (fp->_bf._base != NULL && fp->_p > fp->_bf._base + && ((wchar_t *)fp->_p)[-1] == wc) + { + fp->_p -= sizeof (wchar_t); + fp->_r += sizeof (wchar_t); + return wc; + } + + /* + * Create an ungetc buffer. + * Initially, we will use the `reserve' buffer. + */ + + fp->_ur = fp->_r; + fp->_up = fp->_p; + fp->_ub._base = fp->_ubuf; + fp->_ub._size = sizeof (fp->_ubuf); + fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - sizeof (wchar_t)]; + *(wchar_t *) fp->_p = wc; + fp->_r = 2; + return wc; +} + +extern int __ssrefill_r _PARAMS ((struct _reent *ptr, register FILE * fp)); + +static size_t +_DEFUN(_sfgetwc_r, (ptr, fp), + struct _reent * ptr _AND + FILE * fp) +{ + wchar_t wc; + + if (fp->_r <= 0 && __ssrefill_r (ptr, fp)) + return (WEOF); + wc = *(wchar_t *) fp->_p; + fp->_p += sizeof (wchar_t); + fp->_r -= sizeof (wchar_t); + return (wc); +} +#endif /* STRING_ONLY */ + +int +_DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap), + struct _reent *rptr _AND + register FILE *fp _AND + wchar_t _CONST *fmt0 _AND + va_list ap) +{ + register wchar_t *fmt = (wchar_t *) fmt0; + register wint_t c; /* character from format, or conversion */ + register size_t width; /* field width, or 0 */ + register wchar_t *p = NULL; /* points into all kinds of strings */ + register int n; /* handy integer */ + register int flags; /* flags as defined above */ + register wchar_t *p0; /* saves original value of p when necessary */ + int nassigned; /* number of fields assigned */ + int nread; /* number of characters consumed from fp */ +#ifndef _NO_POS_ARGS + int N; /* arg number */ + int arg_index = 0; /* index into args processed directly */ + int numargs = 0; /* number of varargs read */ + void *args[MAX_POS_ARGS]; /* positional args read */ + int is_pos_arg; /* is current format positional? */ +#endif + int base = 0; /* base argument to wcstol/wcstoul */ + + mbstate_t mbs; /* value to keep track of multibyte state */ + + #define CCFN_PARAMS _PARAMS((struct _reent *, const wchar_t *, wchar_t **, int)) + unsigned long (*ccfn)CCFN_PARAMS=0; /* conversion function (wcstol/wcstoul) */ + wchar_t buf[BUF]; /* buffer for numeric conversions */ + const wchar_t *ccls; /* character class start */ + const wchar_t *ccle; /* character class end */ + int cclcompl = 0; /* ccl is complemented? */ + wint_t wi; /* handy wint_t */ + char *mbp = NULL; /* multibyte string pointer for %c %s %[ */ + size_t nconv; /* number of bytes in mb. conversion */ + char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */ + + char *cp; + short *sp; + int *ip; +#ifdef FLOATING_POINT + float *flp; + _LONG_DOUBLE *ldp; + double *dp; + wchar_t decpt; +#endif + long *lp; +#ifndef _NO_LONGLONG + long long *llp; +#endif + + /* `basefix' is used to avoid `if' tests in the integer scanner */ + static _CONST short basefix[17] = + {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + + /* Macro to support positional arguments */ +#ifndef _NO_POS_ARGS +# define GET_ARG(n, ap, type) \ + ((type) (is_pos_arg \ + ? (n < numargs \ + ? args[n] \ + : get_arg (n, &ap, &numargs, args)) \ + : (arg_index++ < numargs \ + ? args[n] \ + : (numargs < MAX_POS_ARGS \ + ? args[numargs++] = va_arg (ap, void *) \ + : va_arg (ap, void *))))) +#else +# define GET_ARG(n, ap, type) (va_arg (ap, type)) +#endif + +#ifdef FLOATING_POINT +#ifdef _MB_CAPABLE +#ifdef __HAVE_LOCALE_INFO_EXTENDED__ + decpt = *__get_current_numeric_locale ()->wdecimal_point; +#else + { + size_t nconv; + + memset (&mbs, '\0', sizeof (mbs)); + nconv = _mbrtowc_r (rptr, &decpt, + _localeconv_r (rptr)->decimal_point, + MB_CUR_MAX, &mbs); + if (nconv == (size_t) -1 || nconv == (size_t) -2) + decpt = L'.'; + } +#endif /* !__HAVE_LOCALE_INFO_EXTENDED__ */ +#else + decpt = (wchar_t) *_localeconv_r (rptr)->decimal_point; +#endif /* !_MB_CAPABLE */ +#endif /* FLOATING_POINT */ + + _newlib_flockfile_start (fp); + + ORIENT (fp, 1); + + nassigned = 0; + nread = 0; + ccls = ccle = NULL; + for (;;) + { + c = *fmt++; + if (c == L'\0') + goto all_done; + if (iswspace (c)) + { + while ((c = _fgetwc_r (rptr, fp)) != WEOF && iswspace(c)) + ; + if (c != WEOF) + _ungetwc_r (rptr, c, fp); + continue; + } + if (c != L'%') + goto literal; + width = 0; + flags = 0; +#ifndef _NO_POS_ARGS + N = arg_index; + is_pos_arg = 0; +#endif + + /* + * switch on the format. continue if done; break once format + * type is derived. + */ + + again: + c = *fmt++; + + switch (c) + { + case L'%': + literal: + if ((wi = _fgetwc_r (rptr, fp)) == WEOF) + goto input_failure; + if (wi != c) + { + _ungetwc_r (rptr, wi, fp); + goto input_failure; + } + nread++; + continue; + + case L'*': + flags |= SUPPRESS; + goto again; + case L'l': +#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG + if (*fmt == L'l') /* Check for 'll' = long long (SUSv3) */ + { + ++fmt; + flags |= LONGDBL; + } + else +#endif + flags |= LONG; + goto again; + case L'L': + flags |= LONGDBL; + goto again; + case L'h': +#ifdef _WANT_IO_C99_FORMATS + if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */ + { + ++fmt; + flags |= CHAR; + } + else +#endif + flags |= SHORT; + goto again; +#ifdef _WANT_IO_C99_FORMATS + case L'j': /* intmax_t */ + if (sizeof (intmax_t) == sizeof (long)) + flags |= LONG; + else + flags |= LONGDBL; + goto again; + case L't': /* ptrdiff_t */ + if (sizeof (ptrdiff_t) < sizeof (int)) + /* POSIX states ptrdiff_t is 16 or more bits, as + is short. */ + flags |= SHORT; + else if (sizeof (ptrdiff_t) == sizeof (int)) + /* no flag needed */; + else if (sizeof (ptrdiff_t) <= sizeof (long)) + flags |= LONG; + else + /* POSIX states that at least one programming + environment must support ptrdiff_t no wider than + long, but that means other environments can + have ptrdiff_t as wide as long long. */ + flags |= LONGDBL; + goto again; + case L'z': /* size_t */ + if (sizeof (size_t) < sizeof (int)) + /* POSIX states size_t is 16 or more bits, as is short. */ + flags |= SHORT; + else if (sizeof (size_t) == sizeof (int)) + /* no flag needed */; + else if (sizeof (size_t) <= sizeof (long)) + flags |= LONG; + else + /* POSIX states that at least one programming + environment must support size_t no wider than + long, but that means other environments can + have size_t as wide as long long. */ + flags |= LONGDBL; + goto again; +#endif /* _WANT_IO_C99_FORMATS */ + + case L'0': + case L'1': + case L'2': + case L'3': + case L'4': + case L'5': + case L'6': + case L'7': + case L'8': + case L'9': + width = width * 10 + c - L'0'; + goto again; + +#ifndef _NO_POS_ARGS + case L'$': + if (width <= MAX_POS_ARGS) + { + N = width - 1; + is_pos_arg = 1; + width = 0; + goto again; + } + rptr->_errno = EINVAL; + goto input_failure; +#endif /* !_NO_POS_ARGS */ + + case L'd': + c = CT_INT; + ccfn = (unsigned long (*)CCFN_PARAMS)_wcstol_r; + base = 10; + break; + + case L'i': + c = CT_INT; + ccfn = (unsigned long (*)CCFN_PARAMS)_wcstol_r; + base = 0; + break; + + case L'o': + c = CT_INT; + ccfn = _wcstoul_r; + base = 8; + break; + + case L'u': + c = CT_INT; + ccfn = _wcstoul_r; + base = 10; + break; + + case L'X': + case L'x': + flags |= PFXOK; /* enable 0x prefixing */ + c = CT_INT; + ccfn = _wcstoul_r; + base = 16; + break; + +#ifdef FLOATING_POINT +# ifdef _WANT_IO_C99_FORMATS + case L'A': + case L'a': + case L'F': +# endif + case L'E': + case L'G': + case L'e': + case L'f': + case L'g': + c = CT_FLOAT; + break; +#endif + +#ifdef _WANT_IO_C99_FORMATS + case L'S': + flags |= LONG; + /* FALLTHROUGH */ +#endif + + case L's': + c = CT_STRING; + break; + + case L'[': + ccls = fmt; + if (*fmt == '^') + { + cclcompl = 1; + ++fmt; + } + else + cclcompl = 0; + if (*fmt == ']') + fmt++; + while (*fmt != '\0' && *fmt != ']') + fmt++; + ccle = fmt; + fmt++; + flags |= NOSKIP; + c = CT_CCL; + break; + +#ifdef _WANT_IO_C99_FORMATS + case 'C': + flags |= LONG; + /* FALLTHROUGH */ +#endif + + case 'c': + flags |= NOSKIP; + c = CT_CHAR; + break; + + case 'p': /* pointer format is like hex */ + flags |= POINTER | PFXOK; + c = CT_INT; + ccfn = _wcstoul_r; + base = 16; + break; + + case 'n': + if (flags & SUPPRESS) /* ??? */ + continue; +#ifdef _WANT_IO_C99_FORMATS + if (flags & CHAR) + { + cp = GET_ARG (N, ap, char *); + *cp = nread; + } + else +#endif + if (flags & SHORT) + { + sp = GET_ARG (N, ap, short *); + *sp = nread; + } + else if (flags & LONG) + { + lp = GET_ARG (N, ap, long *); + *lp = nread; + } +#ifndef _NO_LONGLONG + else if (flags & LONGDBL) + { + llp = GET_ARG (N, ap, long long*); + *llp = nread; + } +#endif + else + { + ip = GET_ARG (N, ap, int *); + *ip = nread; + } + continue; + + /* + * Disgusting backwards compatibility hacks. XXX + */ + case L'\0': /* compat */ + _newlib_flockfile_exit (fp); + return EOF; + + default: /* compat */ + goto match_failure; + } + + /* + * Consume leading white space, except for formats that + * suppress this. + */ + if ((flags & NOSKIP) == 0) + { + while ((wi = _fgetwc_r (rptr, fp)) != WEOF && iswspace (wi)) + nread++; + if (wi == WEOF) + goto input_failure; + _ungetwc_r (rptr, wi, fp); + } + + /* + * Do the conversion. + */ + switch (c) + { + + case CT_CHAR: + /* scan arbitrary characters (sets NOSKIP) */ + if (width == 0) + width = 1; + if (flags & LONG) + { + if (!(flags & SUPPRESS)) + p = GET_ARG(N, ap, wchar_t *); + n = 0; + while (width-- != 0 && (wi = _fgetwc_r (rptr, fp)) != WEOF) + { + if (!(flags & SUPPRESS)) + *p++ = (wchar_t) wi; + n++; + } + if (n == 0) + goto input_failure; + nread += n; + if (!(flags & SUPPRESS)) + nassigned++; + } + else + { + if (!(flags & SUPPRESS)) + mbp = GET_ARG(N, ap, char *); + n = 0; + memset ((_PTR)&mbs, '\0', sizeof (mbstate_t)); + while (width != 0 && (wi = _fgetwc_r (rptr, fp)) != WEOF) + { + if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) + { + nconv = _wcrtomb_r (rptr, mbp, wi, &mbs); + if (nconv == (size_t) -1) + goto input_failure; + } + else + { + nconv = _wcrtomb_r (rptr, mbbuf, wi, &mbs); + if (nconv == (size_t) -1) + goto input_failure; + if (nconv > width) + { + _ungetwc_r (rptr, wi, fp); + break; + } + if (!(flags & SUPPRESS)) + memcpy(mbp, mbbuf, nconv); + } + if (!(flags & SUPPRESS)) + mbp += nconv; + width -= nconv; + n++; + } + if (n == 0) + goto input_failure; + nread += n; + if (!(flags & SUPPRESS)) + nassigned++; + } + break; + + case CT_CCL: + /* scan a (nonempty) character class (sets NOSKIP) */ + if (width == 0) + width = (size_t) ~0; /* `infinity' */ + /* take only those things in the class */ + if ((flags & SUPPRESS) && (flags & LONG)) + { + n = 0; + while ((wi = _fgetwc_r (rptr, fp)) != WEOF + && width-- != 0 && INCCL (wi)) + n++; + if (wi != WEOF) + _ungetwc_r (rptr, wi, fp); + if (n == 0) + goto match_failure; + } + else if (flags & LONG) + { + p0 = p = GET_ARG(N, ap, wchar_t *); + while ((wi = _fgetwc_r (rptr, fp)) != WEOF + && width-- != 0 && INCCL (wi)) + *p++ = (wchar_t) wi; + if (wi != WEOF) + _ungetwc_r (rptr, wi, fp); + n = p - p0; + if (n == 0) + goto match_failure; + *p = L'\0'; + nassigned++; + } + else + { + if (!(flags & SUPPRESS)) + mbp = GET_ARG(N, ap, char *); + n = 0; + memset ((_PTR) &mbs, '\0', sizeof (mbstate_t)); + while ((wi = _fgetwc_r (rptr, fp)) != WEOF + && width-- != 0 && INCCL (wi)) + { + if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) + { + nconv = _wcrtomb_r (rptr, mbp, wi, &mbs); + if (nconv == (size_t) -1) + goto input_failure; + } + else + { + nconv = wcrtomb(mbbuf, wi, &mbs); + if (nconv == (size_t) -1) + goto input_failure; + if (nconv > width) + break; + if (!(flags & SUPPRESS)) + memcpy(mbp, mbbuf, nconv); + } + if (!(flags & SUPPRESS)) + mbp += nconv; + width -= nconv; + n++; + } + if (wi != WEOF) + _ungetwc_r (rptr, wi, fp); + if (!(flags & SUPPRESS)) + { + *mbp = 0; + nassigned++; + } + } + nread += n; + break; + + case CT_STRING: + /* like CCL, but zero-length string OK, & no NOSKIP */ + if (width == 0) + width = (size_t)~0; + if ((flags & SUPPRESS) && (flags & LONG)) + { + while ((wi = _fgetwc_r (rptr, fp)) != WEOF + && width-- != 0 && !iswspace (wi)) + nread++; + if (wi != WEOF) + _ungetwc_r (rptr, wi, fp); + } + else if (flags & LONG) + { + p0 = p = GET_ARG(N, ap, wchar_t *); + while ((wi = _fgetwc_r (rptr, fp)) != WEOF + && width-- != 0 && !iswspace (wi)) + { + *p++ = (wchar_t) wi; + nread++; + } + if (wi != WEOF) + _ungetwc_r (rptr, wi, fp); + *p = L'\0'; + nassigned++; + } + else + { + if (!(flags & SUPPRESS)) + mbp = GET_ARG(N, ap, char *); + memset ((_PTR) &mbs, '\0', sizeof (mbstate_t)); + while ((wi = _fgetwc_r (rptr, fp)) != WEOF + && width != 0 && !iswspace (wi)) + { + if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) + { + nconv = wcrtomb(mbp, wi, &mbs); + if (nconv == (size_t)-1) + goto input_failure; + } + else + { + nconv = wcrtomb(mbbuf, wi, &mbs); + if (nconv == (size_t)-1) + goto input_failure; + if (nconv > width) + break; + if (!(flags & SUPPRESS)) + memcpy(mbp, mbbuf, nconv); + } + if (!(flags & SUPPRESS)) + mbp += nconv; + width -= nconv; + nread++; + } + if (wi != WEOF) + _ungetwc_r (rptr, wi, fp); + if (!(flags & SUPPRESS)) + { + *mbp = 0; + nassigned++; + } + } + continue; + + case CT_INT: + { + /* scan an integer as if by wcstol/wcstoul */ + if (width == 0 || width > sizeof (buf) / sizeof (*buf) - 1) + width = sizeof(buf) / sizeof (*buf) - 1; + flags |= SIGNOK | NDIGITS | NZDIGITS; + for (p = buf; width; width--) + { + c = _fgetwc_r (rptr, fp); + /* + * Switch on the character; `goto ok' if we + * accept it as a part of number. + */ + switch (c) + { + /* + * The digit 0 is always legal, but is special. + * For %i conversions, if no digits (zero or nonzero) + * have been scanned (only signs), we will have base==0. + * In that case, we should set it to 8 and enable 0x + * prefixing. Also, if we have not scanned zero digits + * before this, do not turn off prefixing (someone else + * will turn it off if we have scanned any nonzero digits). + */ + case L'0': + if (base == 0) + { + base = 8; + flags |= PFXOK; + } + if (flags & NZDIGITS) + flags &= ~(SIGNOK | NZDIGITS | NDIGITS); + else + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* 1 through 7 always legal */ + case L'1': + case L'2': + case L'3': + case L'4': + case L'5': + case L'6': + case L'7': + base = basefix[base]; + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* digits 8 and 9 ok iff decimal or hex */ + case L'8': + case L'9': + base = basefix[base]; + if (base <= 8) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* letters ok iff hex */ + case L'A': + case L'B': + case L'C': + case L'D': + case L'E': + case L'F': + case L'a': + case L'b': + case L'c': + case L'd': + case L'e': + case L'f': + /* no need to fix base here */ + if (base <= 10) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* sign ok only as first character */ + case L'+': + case L'-': + if (flags & SIGNOK) + { + flags &= ~SIGNOK; + flags |= HAVESIGN; + goto ok; + } + break; + + /* x ok iff flag still set & single 0 seen */ + case L'x': + case L'X': + if ((flags & PFXOK) && p == buf + 1 + !!(flags & HAVESIGN)) + { + base = 16;/* if %i */ + flags &= ~PFXOK; + goto ok; + } + break; + } + + /* + * If we got here, c is not a legal character + * for a number. Stop accumulating digits. + */ + if (c != WEOF) + _ungetwc_r (rptr, c, fp); + break; + ok: + /* + * c is legal: store it and look at the next. + */ + *p++ = (wchar_t) c; + } + /* + * If we had only a sign, it is no good; push back the sign. + * If the number ends in `x', it was [sign] '0' 'x', so push back + * the x and treat it as [sign] '0'. + * Use of ungetc here and below assumes ASCII encoding; we are only + * pushing back 7-bit characters, so casting to unsigned char is + * not necessary. + */ + if (flags & NDIGITS) + { + if (p > buf) + _ungetwc_r (rptr, *--p, fp); /* [-+xX] */ + goto match_failure; + } + c = p[-1]; + if (c == L'x' || c == L'X') + { + --p; + _ungetwc_r (rptr, c, fp); + } + if ((flags & SUPPRESS) == 0) + { + unsigned long res; + + *p = 0; + res = (*ccfn) (rptr, buf, (wchar_t **) NULL, base); + if (flags & POINTER) + { + void **vp = GET_ARG (N, ap, void **); +#ifndef _NO_LONGLONG + if (sizeof (uintptr_t) > sizeof (unsigned long)) + { + unsigned long long resll; + resll = _wcstoull_r (rptr, buf, (wchar_t **) NULL, base); + *vp = (void *) (uintptr_t) resll; + } + else +#endif /* !_NO_LONGLONG */ + *vp = (void *) (uintptr_t) res; + } +#ifdef _WANT_IO_C99_FORMATS + else if (flags & CHAR) + { + cp = GET_ARG (N, ap, char *); + *cp = res; + } +#endif + else if (flags & SHORT) + { + sp = GET_ARG (N, ap, short *); + *sp = res; + } + else if (flags & LONG) + { + lp = GET_ARG (N, ap, long *); + *lp = res; + } +#ifndef _NO_LONGLONG + else if (flags & LONGDBL) + { + unsigned long long resll; + if (ccfn == _wcstoul_r) + resll = _wcstoull_r (rptr, buf, (wchar_t **) NULL, base); + else + resll = _wcstoll_r (rptr, buf, (wchar_t **) NULL, base); + llp = GET_ARG (N, ap, long long*); + *llp = resll; + } +#endif + else + { + ip = GET_ARG (N, ap, int *); + *ip = res; + } + nassigned++; + } + nread += p - buf; + break; + } +#ifdef FLOATING_POINT + case CT_FLOAT: + { + /* scan a floating point number as if by wcstod */ + /* This code used to assume that the number of digits is reasonable. + However, ANSI / ISO C makes no such stipulation; we have to get + exact results even when there is an unreasonable amount of + leading zeroes. */ + long leading_zeroes = 0; + long zeroes, exp_adjust; + wchar_t *exp_start = NULL; + unsigned width_left = 0; + char nancount = 0; + char infcount = 0; +#ifdef hardway + if (width == 0 || width > sizeof (buf) - 1) +#else + /* size_t is unsigned, hence this optimisation */ + if (width - 1 > sizeof (buf) - 2) +#endif + { + width_left = width - (sizeof (buf) - 1); + width = sizeof (buf) - 1; + } + flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; + zeroes = 0; + exp_adjust = 0; + for (p = buf; width; ) + { + c = _fgetwc_r (rptr, fp); + /* + * This code mimicks the integer conversion + * code, but is much simpler. + */ + switch (c) + { + case L'0': + if (flags & NDIGITS) + { + flags &= ~SIGNOK; + zeroes++; + if (width_left) + { + width_left--; + width++; + } + goto fskip; + } + /* Fall through. */ + case L'1': + case L'2': + case L'3': + case L'4': + case L'5': + case L'6': + case L'7': + case L'8': + case L'9': + if (nancount + infcount == 0) + { + flags &= ~(SIGNOK | NDIGITS); + goto fok; + } + break; + + case L'+': + case L'-': + if (flags & SIGNOK) + { + flags &= ~SIGNOK; + goto fok; + } + break; + case L'n': + case L'N': + if (nancount == 0 && zeroes == 0 + && (flags & (NDIGITS | DPTOK | EXPOK)) == + (NDIGITS | DPTOK | EXPOK)) + { + flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS); + nancount = 1; + goto fok; + } + if (nancount == 2) + { + nancount = 3; + goto fok; + } + if (infcount == 1 || infcount == 4) + { + infcount++; + goto fok; + } + break; + case L'a': + case L'A': + if (nancount == 1) + { + nancount = 2; + goto fok; + } + break; + case L'i': + if (infcount == 0 && zeroes == 0 + && (flags & (NDIGITS | DPTOK | EXPOK)) == + (NDIGITS | DPTOK | EXPOK)) + { + flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS); + infcount = 1; + goto fok; + } + if (infcount == 3 || infcount == 5) + { + infcount++; + goto fok; + } + break; + case L'f': + case L'F': + if (infcount == 2) + { + infcount = 3; + goto fok; + } + break; + case L't': + case L'T': + if (infcount == 6) + { + infcount = 7; + goto fok; + } + break; + case L'y': + case L'Y': + if (infcount == 7) + { + infcount = 8; + goto fok; + } + break; + case L'e': + case L'E': + /* no exponent without some digits */ + if ((flags & (NDIGITS | EXPOK)) == EXPOK + || ((flags & EXPOK) && zeroes)) + { + if (! (flags & DPTOK)) + { + exp_adjust = zeroes - leading_zeroes; + exp_start = p; + } + flags = + (flags & ~(EXPOK | DPTOK)) | + SIGNOK | NDIGITS; + zeroes = 0; + goto fok; + } + break; + default: + if ((wchar_t) c == decpt && (flags & DPTOK)) + { + flags &= ~(SIGNOK | DPTOK); + leading_zeroes = zeroes; + goto fok; + } + break; + } + if (c != WEOF) + _ungetwc_r (rptr, c, fp); + break; + fok: + *p++ = c; + fskip: + width--; + ++nread; + } + if (zeroes) + flags &= ~NDIGITS; + /* We may have a 'N' or possibly even [sign] 'N' 'a' as the + start of 'NaN', only to run out of chars before it was + complete (or having encountered a non-matching char). So + check here if we have an outstanding nancount, and if so + put back the chars we did swallow and treat as a failed + match. + + FIXME - we still don't handle NAN([0xdigits]). */ + if (nancount - 1U < 2U) /* nancount && nancount < 3 */ + { + /* Newlib's ungetc works even if we called __srefill in + the middle of a partial parse, but POSIX does not + guarantee that in all implementations of ungetc. */ + while (p > buf) + { + _ungetwc_r (rptr, *--p, fp); /* [-+nNaA] */ + --nread; + } + goto match_failure; + } + /* Likewise for 'inf' and 'infinity'. But be careful that + 'infinite' consumes only 3 characters, leaving the stream + at the second 'i'. */ + if (infcount - 1U < 7U) /* infcount && infcount < 8 */ + { + if (infcount >= 3) /* valid 'inf', but short of 'infinity' */ + while (infcount-- > 3) + { + _ungetwc_r (rptr, *--p, fp); /* [iInNtT] */ + --nread; + } + else + { + while (p > buf) + { + _ungetwc_r (rptr, *--p, fp); /* [-+iInN] */ + --nread; + } + goto match_failure; + } + } + /* + * If no digits, might be missing exponent digits + * (just give back the exponent) or might be missing + * regular digits, but had sign and/or decimal point. + */ + if (flags & NDIGITS) + { + if (flags & EXPOK) + { + /* no digits at all */ + while (p > buf) + { + _ungetwc_r (rptr, *--p, fp); /* [-+.] */ + --nread; + } + goto match_failure; + } + /* just a bad exponent (e and maybe sign) */ + c = *--p; + --nread; + if (c != L'e' && c != L'E') + { + _ungetwc_r (rptr, c, fp); /* [-+] */ + c = *--p; + --nread; + } + _ungetwc_r (rptr, c, fp); /* [eE] */ + } + if ((flags & SUPPRESS) == 0) + { + double res = 0; +#ifdef _NO_LONGDBL +#define QUAD_RES res; +#else /* !_NO_LONG_DBL */ + long double qres = 0; +#define QUAD_RES qres; +#endif /* !_NO_LONG_DBL */ + long new_exp = 0; + + *p = 0; + if ((flags & (DPTOK | EXPOK)) == EXPOK) + { + exp_adjust = zeroes - leading_zeroes; + new_exp = -exp_adjust; + exp_start = p; + } + else if (exp_adjust) + new_exp = _wcstol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust; + if (exp_adjust) + { + + /* If there might not be enough space for the new exponent, + truncate some trailing digits to make room. */ + if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN) + exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1; + swprintf (exp_start, MAX_LONG_LEN, L"e%ld", new_exp); + } + + /* FIXME: We don't have wcstold yet. */ +#if 0//ndef _NO_LONGDBL /* !_NO_LONGDBL */ + if (flags & LONGDBL) + qres = _wcstold_r (rptr, buf, NULL); + else +#endif + res = _wcstod_r (rptr, buf, NULL); + + if (flags & LONG) + { + dp = GET_ARG (N, ap, double *); + *dp = res; + } + else if (flags & LONGDBL) + { + ldp = GET_ARG (N, ap, _LONG_DOUBLE *); + *ldp = QUAD_RES; + } + else + { + flp = GET_ARG (N, ap, float *); + if (isnan (res)) + *flp = nanf (NULL); + else + *flp = res; + } + nassigned++; + } + break; + } +#endif /* FLOATING_POINT */ + } + } +input_failure: + /* On read failure, return EOF failure regardless of matches; errno + should have been set prior to here. On EOF failure (including + invalid format string), return EOF if no matches yet, else number + of matches made prior to failure. */ + _newlib_flockfile_exit (fp); + return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF; +match_failure: +all_done: + /* Return number of matches, which can be 0 on match failure. */ + _newlib_flockfile_end (fp); + return nassigned; +} + +#ifndef _NO_POS_ARGS +/* Process all intermediate arguments. Fortunately, with wscanf, all + intermediate arguments are sizeof(void*), so we don't need to scan + ahead in the format string. */ +static void * +get_arg (int n, va_list *ap, int *numargs_p, void **args) +{ + int numargs = *numargs_p; + while (n >= numargs) + args[numargs++] = va_arg (*ap, void *); + *numargs_p = numargs; + return args[n]; +} +#endif /* !_NO_POS_ARGS */ diff --git a/contrib/sdk/sources/newlib/libc/stdio/vswprintf.c b/contrib/sdk/sources/newlib/libc/stdio/vswprintf.c new file mode 100644 index 0000000000..ac321b662c --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/vswprintf.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ +/* doc in vfwprintf.c */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include + +#include "local.h" + +int +_DEFUN(_vswprintf_r, (ptr, str, size, fmt, ap), + struct _reent *ptr _AND + wchar_t *str _AND + size_t size _AND + const wchar_t *fmt _AND + va_list ap) +{ + int ret; + FILE f; + + if (size > INT_MAX / sizeof (wchar_t)) + { + ptr->_errno = EOVERFLOW; /* POSIX extension */ + return EOF; + } + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = (size > 0 ? (size - 1) * sizeof (wchar_t) : 0); + f._file = -1; /* No file. */ + ret = _svfwprintf_r (ptr, &f, fmt, ap); + /* _svfwprintf_r() does not put in a terminating NUL, so add one if + * appropriate, which is whenever size is > 0. _svfwprintf_r() stops + * after n-1, so always just put at the end. */ + if (size > 0) { + *(wchar_t *)f._p = L'\0'; /* terminate the string */ + } + if(ret >= size) { + /* _svfwprintf_r() returns how many wide characters it would have printed + * if there were enough space. Return an error if too big to fit in str, + * unlike snprintf, which returns the size needed. */ + ptr->_errno = EOVERFLOW; /* POSIX extension */ + ret = -1; + } + return ret; +} + +#ifndef _REENT_ONLY + +int +_DEFUN(vswprintf, (str, size, fmt, ap), + wchar_t *__restrict str _AND + size_t size _AND + const wchar_t *__restrict fmt _AND + va_list ap) +{ + return _vswprintf_r (_REENT, str, size, fmt, ap); +} + +#endif /* !_REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdio/vswscanf.c b/contrib/sdk/sources/newlib/libc/stdio/vswscanf.c new file mode 100644 index 0000000000..0d090f0219 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/vswscanf.c @@ -0,0 +1,62 @@ +/* + * Code created by modifying scanf.c which has following copyright. + * + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ +/* Doc in vfwscanf.c */ + +#include <_ansi.h> +#include +#include +#include +#include +#ifdef _HAVE_STDC +#include +#else +#include +#endif +#include "local.h" + +/* + * vsscanf + */ + +#ifndef _REENT_ONLY + +int +vswscanf (_CONST wchar_t *__restrict str, _CONST wchar_t * __restrict fmt, + va_list ap) +{ + return _vswscanf_r (_REENT, str, fmt, ap); +} + +#endif /* !_REENT_ONLY */ + +int +_vswscanf_r (struct _reent *ptr, _CONST wchar_t *str, _CONST wchar_t *fmt, + va_list ap) +{ + FILE f; + + f._flags = __SRD | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._r = wcslen (str) * sizeof (wchar_t); + f._read = __seofread; + f._ub._base = NULL; + f._lb._base = NULL; + f._file = -1; /* No file. */ + return __ssvfwscanf_r (ptr, &f, fmt, ap); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/vwprintf.c b/contrib/sdk/sources/newlib/libc/stdio/vwprintf.c new file mode 100644 index 0000000000..51d1df3a9a --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/vwprintf.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ +/* doc in vfwprintf.c */ + +#include <_ansi.h> +#include +#include +#include +#include +#include "local.h" + +#ifndef _REENT_ONLY + +int +_DEFUN(vwprintf, (fmt, ap), + _CONST wchar_t *__restrict fmt _AND + va_list ap) +{ + struct _reent *reent = _REENT; + + _REENT_SMALL_CHECK_INIT (reent); + return _vfwprintf_r (reent, _stdout_r (reent), fmt, ap); +} + +#endif /* !_REENT_ONLY */ + +int +_DEFUN(_vwprintf_r, (ptr, fmt, ap), + struct _reent *ptr _AND + _CONST wchar_t *fmt _AND + va_list ap) +{ + _REENT_SMALL_CHECK_INIT (ptr); + return _vfwprintf_r (ptr, _stdout_r (ptr), fmt, ap); +} diff --git a/contrib/sdk/sources/newlib/libc/stdio/vwscanf.c b/contrib/sdk/sources/newlib/libc/stdio/vwscanf.c new file mode 100644 index 0000000000..e40bdede58 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/vwscanf.c @@ -0,0 +1,51 @@ +/*- + * Code created by modifying scanf.c which has following copyright. + * + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ +/* Doc in vfwscanf.c */ + +#include <_ansi.h> +#include +#include +#include +#ifdef _HAVE_STDC +#include +#else +#include +#endif +#include "local.h" + +#ifndef _REENT_ONLY + +int +vwscanf (_CONST wchar_t *__restrict fmt, va_list ap) +{ + struct _reent *reent = _REENT; + + _REENT_SMALL_CHECK_INIT (reent); + return __svfwscanf_r (reent, _stdin_r (reent), fmt, ap); +} + +#endif /* !_REENT_ONLY */ + +int +_vwscanf_r (struct _reent *ptr, _CONST wchar_t *fmt, va_list ap) +{ + _REENT_SMALL_CHECK_INIT (ptr); + return __svfwscanf_r (ptr, _stdin_r (ptr), fmt, ap); +} + diff --git a/contrib/sdk/sources/newlib/libc/stdio/wprintf.c b/contrib/sdk/sources/newlib/libc/stdio/wprintf.c new file mode 100644 index 0000000000..e05ba10135 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/wprintf.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ +/* doc in swprintf.c */ + +#include <_ansi.h> +#include +#include +#include +#include +#include "local.h" + +int +_DEFUN(_wprintf_r, (ptr, fmt), + struct _reent *ptr _AND + const wchar_t *fmt _DOTS) +{ + int ret; + va_list ap; + + _REENT_SMALL_CHECK_INIT (ptr); + va_start (ap, fmt); + ret = _vfwprintf_r (ptr, _stdout_r (ptr), fmt, ap); + va_end (ap); + return ret; +} + +#ifndef _REENT_ONLY + +int +_DEFUN(wprintf, (fmt), + const wchar_t *__restrict fmt _DOTS) +{ + int ret; + va_list ap; + struct _reent *ptr = _REENT; + + _REENT_SMALL_CHECK_INIT (ptr); + va_start (ap, fmt); + ret = _vfwprintf_r (ptr, _stdout_r (ptr), fmt, ap); + va_end (ap); + return ret; +} + +#endif /* ! _REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdio/wscanf.c b/contrib/sdk/sources/newlib/libc/stdio/wscanf.c new file mode 100644 index 0000000000..f953d9f81e --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdio/wscanf.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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 + * by the University of California, Berkeley. The name of the + * University 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. + */ + /* Doc in swscanf.c */ + +#include <_ansi.h> +#include +#include +#include +#include +#include "local.h" + +#ifndef _REENT_ONLY + +int +wscanf(_CONST wchar_t *__restrict fmt, ...) +{ + int ret; + va_list ap; + struct _reent *reent = _REENT; + + _REENT_SMALL_CHECK_INIT (reent); + va_start (ap, fmt); + ret = _vfwscanf_r (reent, _stdin_r (reent), fmt, ap); + va_end (ap); + return ret; +} + +#endif /* !_REENT_ONLY */ + +int +_wscanf_r(struct _reent *ptr, _CONST wchar_t *fmt, ...) +{ + int ret; + va_list ap; + + _REENT_SMALL_CHECK_INIT (ptr); + va_start (ap, fmt); + ret = _vfwscanf_r (ptr, _stdin_r (ptr), fmt, ap); + va_end (ap); + return (ret); +} + diff --git a/contrib/sdk/sources/newlib/libc/stdlib/btowc.c b/contrib/sdk/sources/newlib/libc/stdlib/btowc.c new file mode 100644 index 0000000000..354a1d6e12 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/btowc.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include "local.h" + +wint_t +btowc (int c) +{ + mbstate_t mbs; + int retval = 0; + wchar_t pwc; + unsigned char b; + + if (c == EOF) + return WEOF; + + b = (unsigned char)c; + + /* Put mbs in initial state. */ + memset (&mbs, '\0', sizeof (mbs)); + + _REENT_CHECK_MISC(_REENT); + + retval = __mbtowc (_REENT, &pwc, (const char *) &b, 1, + __locale_charset (), &mbs); + + if (retval != 0 && retval != 1) + return WEOF; + + return (wint_t)pwc; +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/ldtoa.c b/contrib/sdk/sources/newlib/libc/stdlib/ldtoa.c new file mode 100644 index 0000000000..a44413cd67 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/ldtoa.c @@ -0,0 +1,3868 @@ + /* Extended precision arithmetic functions for long double I/O. + * This program has been placed in the public domain. + */ + +#include <_ansi.h> +#include +#include +#include +#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) + + /* Maximum exponent digits - base 10 */ +#define MAX_EXP_DIGITS 5 + +/* Control structure for long double 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 (_CONST short unsigned int *a, _CONST short unsigned int *b, + short unsigned int *c, LDPARMS * ldp); +static void emul (_CONST short unsigned int *a, _CONST short unsigned int *b, + short unsigned int *c, LDPARMS * ldp); +static void ediv (_CONST short unsigned int *a, _CONST short unsigned int *b, + short unsigned int *c, LDPARMS * ldp); +static int ecmp (_CONST short unsigned int *a, _CONST 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 _CONST 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); + +union uconv +{ + unsigned short pe; + long double d; +}; + +#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 _CONST unsigned short ezero[NE] = { 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +/* 1.0E0 */ +static _CONST unsigned short eone[NE] = { 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff, +}; + +#else + +/* 0.0 */ +static _CONST unsigned short ezero[NE] = { + 0, 0000000, 0000000, 0000000, 0000000, 0000000, +}; + +/* 1.0E0 */ +static _CONST 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 _CONST char *_CONST 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 USE_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 + * + * 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 +/* #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 USE_INFINITY + +/* NaN's require infinity support. */ +#ifdef NANS +#ifndef INFINITY +#define USE_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 (_CONST short unsigned int *x); +static int eisinf (_CONST short unsigned int *x); +static void emovi (_CONST 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 (_CONST short unsigned int *a, _CONST short unsigned int *b, + short unsigned int *c, int subflg, LDPARMS * ldp); +static int eisnan (_CONST 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 _CONST 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 (_CONST 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 (_CONST 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 (_CONST 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 USE_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 (_CONST short unsigned int *a, short unsigned int *b) +{ + register _CONST unsigned short *p; + register unsigned short *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 USE_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 USE_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 (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 NBITS) + { + ecleazs (s); + return; + } +#endif + exp -= j; +#ifndef USE_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 USE_INFINITY + overf: +#endif +#ifdef USE_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 (_CONST short unsigned int *a, _CONST 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 (_CONST short unsigned int *a, _CONST 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 USE_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 (_CONST short unsigned int *a, _CONST 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 USE_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 (_CONST short unsigned int *a, _CONST 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 USE_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 USE_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 USE_INFINITY +/* Point to the exponent field. */ + p = &yy[NE - 1]; + if ((*p & 0x7fff) == 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 /* USE_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 USE_INFINITY +#ifdef IBMPC + if (eiisinf (a)) + { + /* Intel long double infinity. */ + *q-- = 0x8000; + *q-- = 0; + *q-- = 0; + *q = 0; + return; + } +#endif /* IBMPC */ +#endif /* USE_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 USE_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 USE_INFINITY + *y |= 0x7ff0; +#ifdef IBMPC + *(--y) = 0; + *(--y) = 0; + *(--y) = 0; +#else /* !IBMPC */ + ++y; + *y++ = 0; + *y++ = 0; + *y++ = 0; +#endif /* IBMPC */ +#else /* !USE_INFINITY */ + *y |= (unsigned short) 0x7fef; +#ifdef IBMPC + *(--y) = 0xffff; + *(--y) = 0xffff; + *(--y) = 0xffff; +#else /* !IBMPC */ + ++y; + *y++ = 0xffff; + *y++ = 0xffff; + *y++ = 0xffff; +#endif +#endif /* !USE_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 USE_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 USE_INFINITY + *y |= (unsigned short) 0x7f80; +#ifdef IBMPC + *(--y) = 0; +#endif +#ifdef DEC + *(--y) = 0; +#endif +#ifdef MIEEE + ++y; + *y = 0; +#endif +#else /* !USE_INFINITY */ + *y |= (unsigned short) 0x7f7f; +#ifdef IBMPC + *(--y) = 0xffff; +#endif +#ifdef DEC + *(--y) = 0xffff; +#endif +#ifdef MIEEE + ++y; + *y = 0xffff; +#endif +#endif /* !USE_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 (_CONST short unsigned int *a, _CONST 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 _CONST 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 _CONST 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 _CONST 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 _CONST 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 i, j, k; + int orig_ndigits; + LDPARMS rnd; + LDPARMS *ldp = &rnd; + char *outstr; + char outbuf[NDEC + MAX_EXP_DIGITS + 10]; + union uconv du; + du.d = d; + + orig_ndigits = ndigits; + rnd.rlast = -1; + rnd.rndprc = NBITS; + + _REENT_CHECK_MP (ptr); + +/* reentrancy addition to use mprec storage pool */ + if (_REENT_MP_RESULT (ptr)) + { + _REENT_MP_RESULT (ptr)->_k = _REENT_MP_RESULT_K (ptr); + _REENT_MP_RESULT (ptr)->_maxwds = 1 << _REENT_MP_RESULT_K (ptr); + Bfree (ptr, _REENT_MP_RESULT (ptr)); + _REENT_MP_RESULT (ptr) = 0; + } + +#if LDBL_MANT_DIG == 24 + e24toe (&du.pe, e, ldp); +#elif LDBL_MANT_DIG == 53 + e53toe (&du.pe, e, ldp); +#elif LDBL_MANT_DIG == 64 + e64toe (&du.pe, e, ldp); +#else + e113toe (&du.pe, 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; + + etoasc (e, outbuf, ndigits, mode, ldp); + s = outbuf; + 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 = outbuf; + 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 > outbuf) + --s; + *s = '\0'; + +stripspaces: + +/* Strip leading spaces and sign. */ + p = outbuf; + while (*p == ' ' || *p == '-') + ++p; + +/* Find new end of string. */ + s = outbuf; + 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 - outbuf) > 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 = outbuf; + *s = '\0'; + *decpt = 0; + } + +/* reentrancy addition to use mprec storage pool */ +/* we want to have enough space to hold the formatted result */ + + if (mode == 3) /* f format, account for sign + dec digits + decpt + frac */ + i = *decpt + orig_ndigits + 3; + else /* account for sign + max precision digs + E + exp sign + exponent */ + i = orig_ndigits + MAX_EXP_DIGITS + 4; + + j = sizeof (__ULong); + for (_REENT_MP_RESULT_K (ptr) = 0; + sizeof (_Bigint) - sizeof (__ULong) + j <= i; j <<= 1) + _REENT_MP_RESULT_K (ptr)++; + _REENT_MP_RESULT (ptr) = Balloc (ptr, _REENT_MP_RESULT_K (ptr)); + +/* Copy from internal temporary buffer to permanent buffer. */ + outstr = (char *) _REENT_MP_RESULT (ptr); + strcpy (outstr, outbuf); + + if (rve) + *rve = outstr + (s - outbuf); + + 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]; + LDPARMS rnd; + LDPARMS *ldp = &rnd; + + union uconv du; + + rnd.rlast = -1; + rnd.rndprc = NBITS; + du.d = *d; +#if LDBL_MANT_DIG == 24 + e24toe (&du.pe, e, ldp); +#elif LDBL_MANT_DIG == 53 + e53toe (&du.pe, e, ldp); +#elif LDBL_MANT_DIG == 64 + e64toe (&du.pe, e, ldp); +#else + e113toe (&du.pe, 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]; + _CONST 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 (ndigs < 0 || (*(s - 1 - (*(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; +} + + +#if 0 /* Broken, unusable implementation of strtold */ + +/* +; 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) +{ + union uconv x; + LDPARMS rnd; + LDPARMS *ldp = &rnd; + int lenldstr; + + rnd.rlast = -1; + rnd.rndprc = NBITS; + + lenldstr = asctoeg (s, &x.pe, LDBL_MANT_DIG, ldp); + if (se) + *se = s + lenldstr; + return x.d; +} + +#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; + _CONST unsigned short *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; +} + +#endif + +/* y = largest integer not greater than x + * (truncated toward minus infinity) + * + * unsigned short x[NE], y[NE] + * LDPARMS *ldp + * + * efloor( x, y, ldp ); + */ +static _CONST 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 +#if !defined(__mips) +static _CONST unsigned short nan113[8] = { + 0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; + +static _CONST unsigned short nan64[6] = { + 0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; +static _CONST unsigned short nan53[4] = { 0x7fff, 0xffff, 0xffff, 0xffff }; +static _CONST unsigned short nan24[2] = { 0x7fff, 0xffff }; +#elif defined(__mips_nan2008) /* __mips */ +static _CONST unsigned short nan113[8] = { 0x7fff, 0x8000, 0, 0, 0, 0, 0, 0 }; +static _CONST unsigned short nan64[6] = { 0x7fff, 0xc000, 0, 0, 0, 0 }; +static _CONST unsigned short nan53[4] = { 0x7ff8, 0, 0, 0 }; +static _CONST unsigned short nan24[2] = { 0x7fc0, 0 }; +#else /* __mips && !__mips_nan2008 */ +static _CONST unsigned short nan113[8] = { + 0x7fff, 0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; + +static _CONST unsigned short nan64[6] = { + 0x7fff, 0xbfff, 0xffff, 0xffff, 0xffff, 0xffff +}; +static _CONST unsigned short nan53[4] = { 0x7ff7, 0xffff, 0xffff, 0xffff }; +static _CONST unsigned short nan24[2] = { 0x7fbf, 0xffff }; +#endif /* __mips && !__mips_nan2008 */ +#else /* !MIEEE */ +#if !defined(__mips) || defined(__mips_nan2008) +static _CONST unsigned short nan113[8] = { 0, 0, 0, 0, 0, 0, 0x8000, 0x7fff }; +static _CONST unsigned short nan64[6] = { 0, 0, 0, 0, 0xc000, 0x7fff }; +static _CONST unsigned short nan53[4] = { 0, 0, 0, 0x7ff8 }; +static _CONST unsigned short nan24[2] = { 0, 0x7fc0 }; +#else /* __mips && !__mips_nan2008 */ +static _CONST unsigned short nan113[8] = { + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff, 0x7fff +}; + +static _CONST unsigned short nan64[6] = { + 0xffff, 0xffff, 0xffff, 0xffff, 0xbfff, 0x7fff +}; +static _CONST unsigned short nan53[4] = { 0xffff, 0xffff, 0xffff, 0x7ff7 }; +static _CONST unsigned short nan24[2] = { 0xffff, 0x7fbf }; +#endif /* __mips && !__mips_nan2008 */ +#endif /* !MIEEE */ + + +static void +enan (short unsigned int *nan, int size) +{ + int i, n; + _CONST 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: +#if !defined(__mips) || defined(__mips_nan2008) + for (i = 0; i < NE - 2; i++) + *nan++ = 0; + *nan++ = 0xc000; +#else /* __mips && !__mips_nan2008 */ + for (i = 0; i < NE - 2; i++) + *nan++ = 0xffff; + *nan++ = 0xbfff; +#endif /* __mips && !__mips_nan2008 */ + *nan++ = 0x7fff; + return; + + case NI * 16: + *nan++ = 0; + *nan++ = 0x7fff; + *nan++ = 0; +#if !defined(__mips) || defined(__mips_nan2008) + *nan++ = 0xc000; + for (i = 4; i < NI - 1; i++) + *nan++ = 0; +#else /* __mips && !__mips_nan2008 */ + *nan++ = 0xbfff; + for (i = 4; i < NI - 1; i++) + *nan++ = 0xffff; +#endif /* __mips && !__mips_nan2008 */ + *nan++ = 0; + return; +#endif + default: + mtherr ("enan", DOMAIN); + return; + } + for (i = 0; i < n; i++) + *nan++ = *p++; +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mblen.c b/contrib/sdk/sources/newlib/libc/stdlib/mblen.c new file mode 100644 index 0000000000..4d9ac38bdc --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/mblen.c @@ -0,0 +1,81 @@ +/* +FUNCTION +<>---minimal multibyte length function + +INDEX + mblen + +ANSI_SYNOPSIS + #include + int mblen(const char *<[s]>, size_t <[n]>); + +TRAD_SYNOPSIS + #include + 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 <>. 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 <> returns <<0>> if +<[s]> is <> 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 +<> is required in the ANSI C standard. However, the precise +effects vary with the locale. + +<> requires no supporting OS subroutines. +*/ + +#ifndef _REENT_ONLY + +#include +#include +#include +#include "local.h" + +int +_DEFUN (mblen, (s, n), + const char *s _AND + size_t n) +{ +#ifdef _MB_CAPABLE + int retval = 0; + struct _reent *reent = _REENT; + mbstate_t *state; + + _REENT_CHECK_MISC(reent); + state = &(_REENT_MBLEN_STATE(reent)); + retval = __mbtowc (reent, NULL, s, n, __locale_charset (), state); + if (retval < 0) + { + state->__count = 0; + return -1; + } + else + return retval; + +#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 */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mblen_r.c b/contrib/sdk/sources/newlib/libc/stdlib/mblen_r.c new file mode 100644 index 0000000000..c3b5964438 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/mblen_r.c @@ -0,0 +1,77 @@ +/* +FUNCTION +<<_mblen_r>>---reentrant minimal multibyte length function + +INDEX + _mblen_r + +ANSI_SYNOPSIS + #include + int _mblen_r(struct _reent *<[r]>, const char *<[s]>, size_t <[n]>, int *<[state]>); + +TRAD_SYNOPSIS + #include + 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 <> 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 +#include +#include +#include "local.h" + +int +_DEFUN (_mblen_r, (r, s, n, state), + struct _reent *r _AND + const char *s _AND + size_t n _AND + mbstate_t *state) +{ +#ifdef _MB_CAPABLE + int retval; + retval = __mbtowc (r, NULL, s, n, __locale_charset (), state); + + if (retval < 0) + { + state->__count = 0; + return -1; + } + + return retval; +#else /* not _MB_CAPABLE */ + if (s == NULL || *s == '\0') + return 0; + if (n == 0) + return -1; + return 1; +#endif /* not _MB_CAPABLE */ +} + diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mbrlen.c b/contrib/sdk/sources/newlib/libc/stdlib/mbrlen.c new file mode 100644 index 0000000000..57a733fed8 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/mbrlen.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include +#include + +size_t +mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps) +{ +#ifdef _MB_CAPABLE + if (ps == NULL) + { + struct _reent *reent = _REENT; + + _REENT_CHECK_MISC(reent); + ps = &(_REENT_MBRLEN_STATE(reent)); + } +#endif + + return mbrtowc(NULL, s, n, ps); +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mbsinit.c b/contrib/sdk/sources/newlib/libc/stdlib/mbsinit.c new file mode 100644 index 0000000000..e32369ae1e --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/mbsinit.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include +#include + +int +mbsinit(const mbstate_t *ps) +{ + if (ps == NULL || ps->__count == 0) + return 1; + else + return 0; +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mbsnrtowcs.c b/contrib/sdk/sources/newlib/libc/stdlib/mbsnrtowcs.c new file mode 100644 index 0000000000..7ab384721c --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/mbsnrtowcs.c @@ -0,0 +1,182 @@ +/* +FUNCTION +<>, <>---convert a character string to a wide-character string + +INDEX + mbsrtowcs +INDEX + _mbsrtowcs_r +INDEX + mbsnrtowcs +INDEX + _mbsnrtowcs_r + +ANSI_SYNOPSIS + #include + size_t mbsrtowcs(wchar_t *__restrict <[dst]>, + const char **__restrict <[src]>, + size_t <[len]>, + mbstate_t *__restrict <[ps]>); + + #include + size_t _mbsrtowcs_r(struct _reent *<[ptr]>, wchar_t *<[dst]>, + const char **<[src]>, size_t <[len]>, + mbstate_t *<[ps]>); + + #include + size_t mbsnrtowcs(wchar_t *__ restrict <[dst]>, + const char **__restrict <[src]>, size_t <[nms]>, + size_t <[len]>, mbstate_t *__restrict <[ps]>); + + #include + size_t _mbsnrtowcs_r(struct _reent *<[ptr]>, wchar_t *<[dst]>, + const char **<[src]>, size_t <[nms]>, + size_t <[len]>, mbstate_t *<[ps]>); + +TRAD_SYNOPSIS + #include + size_t mbsrtowcs(<[dst]>, <[src]>, <[len]>, <[ps]>) + wchar_t *__restrict <[dst]>; + const char **__restrict <[src]>; + size_t <[len]>; + mbstate_t *__restrict <[ps]>; + + #include + size_t _mbsrtowcs_r(<[ptr]>, <[dst]>, <[src]>, <[len]>, <[ps]>) + struct _reent *<[ptr]>; + wchar_t *<[dst]>; + const char **<[src]>; + size_t <[len]>; + mbstate_t *<[ps]>; + + #include + size_t mbsnrtowcs(<[dst]>, <[src]>, <[nms]>, <[len]>, <[ps]>) + wchar_t *__restrict <[dst]>; + const char **__restrict <[src]>; + size_t <[nms]>; + size_t <[len]>; + mbstate_t *__restrict <[ps]>; + + #include + size_t _mbsnrtowcs_r(<[ptr]>, <[dst]>, <[src]>, <[nms]>, <[len]>, <[ps]>) + struct _reent *<[ptr]>; + wchar_t *<[dst]>; + const char **<[src]>; + size_t <[nms]>; + size_t <[len]>; + mbstate_t *<[ps]>; + +DESCRIPTION +The <> function converts a sequence of multibyte characters +pointed to indirectly by <[src]> into a sequence of corresponding wide +characters and stores at most <[len]> of them in the wchar_t array pointed +to by <[dst]>, until it encounters a terminating null character ('\0'). + +If <[dst]> is NULL, no characters are stored. + +If <[dst]> is not NULL, the pointer pointed to by <[src]> is updated to point +to the character after the one that conversion stopped at. If conversion +stops because a null character is encountered, *<[src]> is set to NULL. + +The mbstate_t argument, <[ps]>, is used to keep track of the shift state. If +it is NULL, <> uses an internal, static mbstate_t object, which +is initialized to the initial conversion state at program startup. + +The <> function behaves identically to <>, except that +conversion stops after reading at most <[nms]> bytes from the buffer pointed +to by <[src]>. + +RETURNS +The <> and <> functions return the number of wide +characters stored in the array pointed to by <[dst]> if successful, otherwise +it returns (size_t)-1. + +PORTABILITY +<> is defined by the C99 standard. +<> is defined by the POSIX.1-2008 standard. +*/ + +#include +#include +#include +#include +#include +#include + +size_t +_DEFUN (_mbsnrtowcs_r, (r, dst, src, nms, len, ps), + struct _reent *r _AND + wchar_t *dst _AND + const char **src _AND + size_t nms _AND + size_t len _AND + mbstate_t *ps) +{ + wchar_t *ptr = dst; + const char *tmp_src; + size_t max; + size_t count = 0; + int bytes; + +#ifdef _MB_CAPABLE + if (ps == NULL) + { + _REENT_CHECK_MISC(r); + ps = &(_REENT_MBSRTOWCS_STATE(r)); + } +#endif + + if (dst == NULL) + { + /* Ignore original len value and do not alter src pointer if the + dst pointer is NULL. */ + len = (size_t)-1; + tmp_src = *src; + src = &tmp_src; + } + + max = len; + while (len > 0) + { + bytes = _mbrtowc_r (r, ptr, *src, nms, ps); + if (bytes > 0) + { + *src += bytes; + nms -= bytes; + ++count; + ptr = (dst == NULL) ? NULL : ptr + 1; + --len; + } + else if (bytes == -2) + { + *src += nms; + return count; + } + else if (bytes == 0) + { + *src = NULL; + return count; + } + else + { + ps->__count = 0; + r->_errno = EILSEQ; + return (size_t)-1; + } + } + + return (size_t)max; +} + +#ifndef _REENT_ONLY +size_t +_DEFUN (mbsnrtowcs, (dst, src, nms, len, ps), + wchar_t *__restrict dst _AND + const char **__restrict src _AND + size_t nms _AND + size_t len _AND + mbstate_t *__restrict ps) +{ + return _mbsnrtowcs_r (_REENT, dst, src, nms, len, ps); +} +#endif /* !_REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mbsrtowcs.c b/contrib/sdk/sources/newlib/libc/stdlib/mbsrtowcs.c new file mode 100644 index 0000000000..65e46d32e9 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/mbsrtowcs.c @@ -0,0 +1,31 @@ +/* doc in mbsnrtowcs.c */ + +#include +#include +#include +#include +#include +#include + +size_t +_DEFUN (_mbsrtowcs_r, (r, dst, src, len, ps), + struct _reent *r _AND + wchar_t *dst _AND + const char **src _AND + size_t len _AND + mbstate_t *ps) +{ + return _mbsnrtowcs_r (r, dst, src, (size_t) -1, len, ps); +} + +#ifndef _REENT_ONLY +size_t +_DEFUN (mbsrtowcs, (dst, src, len, ps), + wchar_t *__restrict dst _AND + const char **__restrict src _AND + size_t len _AND + mbstate_t *__restrict ps) +{ + return _mbsnrtowcs_r (_REENT, dst, src, (size_t) -1, len, ps); +} +#endif /* !_REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mbstowcs.c b/contrib/sdk/sources/newlib/libc/stdlib/mbstowcs.c new file mode 100644 index 0000000000..09543451cf --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/mbstowcs.c @@ -0,0 +1,83 @@ +/* +FUNCTION +<>---minimal multibyte string to wide char converter + +INDEX + mbstowcs + +ANSI_SYNOPSIS + #include + int mbstowcs(wchar_t *restrict <[pwc]>, const char *restrict <[s]>, size_t <[n]>); + +TRAD_SYNOPSIS + #include + 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 <>. 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 <> returns <<0>> if +<[s]> is <> 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: <> or the +number of multi-byte characters in <> plus 1 (to +compensate for the nul character). +If the return value is -1, the state of the <> 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 +<> is required in the ANSI C standard. However, the precise +effects vary with the locale. + +<> requires no supporting OS subroutines. +*/ + +#ifndef _REENT_ONLY + +#include +#include +#include + +size_t +_DEFUN (mbstowcs, (pwcs, s, n), + wchar_t *__restrict pwcs _AND + const char *__restrict s _AND + size_t n) +{ +#ifdef _MB_CAPABLE + mbstate_t state; + state.__count = 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 */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mbstowcs_r.c b/contrib/sdk/sources/newlib/libc/stdlib/mbstowcs_r.c new file mode 100644 index 0000000000..cae1f06935 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/mbstowcs_r.c @@ -0,0 +1,38 @@ +#include +#include +#include "local.h" + +size_t +_DEFUN (_mbstowcs_r, (reent, pwcs, s, n, state), + struct _reent *r _AND + wchar_t *__restrict pwcs _AND + const char *__restrict s _AND + size_t n _AND + mbstate_t *state) +{ + size_t ret = 0; + char *t = (char *)s; + int bytes; + + if (!pwcs) + n = (size_t) 1; /* Value doesn't matter as long as it's not 0. */ + while (n > 0) + { + bytes = __mbtowc (r, pwcs, t, MB_CUR_MAX, __locale_charset (), state); + if (bytes < 0) + { + state->__count = 0; + return -1; + } + else if (bytes == 0) + break; + t += bytes; + ++ret; + if (pwcs) + { + ++pwcs; + --n; + } + } + return ret; +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mbtowc.c b/contrib/sdk/sources/newlib/libc/stdlib/mbtowc.c index a5a7c7420d..3c7f84b9e4 100644 --- a/contrib/sdk/sources/newlib/libc/stdlib/mbtowc.c +++ b/contrib/sdk/sources/newlib/libc/stdlib/mbtowc.c @@ -1,96 +1,96 @@ -/* -FUNCTION -<>---minimal multibyte to wide char converter - -INDEX - mbtowc - -ANSI_SYNOPSIS - #include - int mbtowc(wchar_t *restrict <[pwc]>, const char *restrict <[s]>, size_t <[n]>); - -TRAD_SYNOPSIS - #include - 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 <>. In this case, -only ``multi-byte character sequences'' recognized are single bytes, -and they are ``converted'' to themselves. -Each call to <> 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 <> returns <<0>> if -<[s]> is <> 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 <> -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 <> output string. - -PORTABILITY -<> is required in the ANSI C standard. However, the precise -effects vary with the locale. - -<> requires no supporting OS subroutines. -*/ - -#ifndef _REENT_ONLY - -#include -#include -#include -#include "local.h" - -int -_DEFUN (mbtowc, (pwc, s, n), - wchar_t *__restrict pwc _AND - const char *__restrict s _AND - size_t n) -{ -#ifdef _MB_CAPABLE - int retval = 0; - struct _reent *reent = _REENT; - mbstate_t *ps; - - _REENT_CHECK_MISC(reent); - ps = &(_REENT_MBTOWC_STATE(reent)); - - retval = __mbtowc (reent, pwc, s, n, __locale_charset (), ps); - - if (retval < 0) - { - ps->__count = 0; - return -1; - } - return retval; -#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 */ - - - - +/* +FUNCTION +<>---minimal multibyte to wide char converter + +INDEX + mbtowc + +ANSI_SYNOPSIS + #include + int mbtowc(wchar_t *restrict <[pwc]>, const char *restrict <[s]>, size_t <[n]>); + +TRAD_SYNOPSIS + #include + 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 <>. In this case, +only ``multi-byte character sequences'' recognized are single bytes, +and they are ``converted'' to themselves. +Each call to <> 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 <> returns <<0>> if +<[s]> is <> 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 <> +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 <> output string. + +PORTABILITY +<> is required in the ANSI C standard. However, the precise +effects vary with the locale. + +<> requires no supporting OS subroutines. +*/ + +#ifndef _REENT_ONLY + +#include +#include +#include +#include "local.h" + +int +_DEFUN (mbtowc, (pwc, s, n), + wchar_t *__restrict pwc _AND + const char *__restrict s _AND + size_t n) +{ +#ifdef _MB_CAPABLE + int retval = 0; + struct _reent *reent = _REENT; + mbstate_t *ps; + + _REENT_CHECK_MISC(reent); + ps = &(_REENT_MBTOWC_STATE(reent)); + + retval = __mbtowc (reent, pwc, s, n, __locale_charset (), ps); + + if (retval < 0) + { + ps->__count = 0; + return -1; + } + return retval; +#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 */ + + + + diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mbtowc_r.c b/contrib/sdk/sources/newlib/libc/stdlib/mbtowc_r.c index c36b49ddc0..986595cfdc 100644 --- a/contrib/sdk/sources/newlib/libc/stdlib/mbtowc_r.c +++ b/contrib/sdk/sources/newlib/libc/stdlib/mbtowc_r.c @@ -1,648 +1,648 @@ -#include -#include -#include -#include "mbctype.h" -#include -#include -#include -#include "local.h" - -int (*__mbtowc) (struct _reent *, wchar_t *, const char *, size_t, - const char *, mbstate_t *) -#ifdef __CYGWIN__ - /* Cygwin starts up in UTF-8 mode. */ - = __utf8_mbtowc; -#else - = __ascii_mbtowc; -#endif - -int -_DEFUN (_mbtowc_r, (r, pwc, s, n, state), - struct _reent *r _AND - wchar_t *__restrict pwc _AND - const char *__restrict s _AND - size_t n _AND - mbstate_t *state) -{ - return __mbtowc (r, pwc, s, n, __locale_charset (), state); -} - -int -_DEFUN (__ascii_mbtowc, (r, pwc, s, n, charset, state), - struct _reent *r _AND - wchar_t *pwc _AND - const char *s _AND - size_t n _AND - const char *charset _AND - mbstate_t *state) -{ - wchar_t dummy; - unsigned char *t = (unsigned char *)s; - - if (pwc == NULL) - pwc = &dummy; - - if (s == NULL) - return 0; - - if (n == 0) - return -2; - -#ifdef __CYGWIN__ - if ((wchar_t)*t >= 0x80) - { - r->_errno = EILSEQ; - return -1; - } -#endif - - *pwc = (wchar_t)*t; - - if (*t == '\0') - return 0; - - return 1; -} - -#ifdef _MB_CAPABLE -typedef enum { ESCAPE, DOLLAR, BRACKET, AT, B, J, - NUL, JIS_CHAR, OTHER, JIS_C_NUM } JIS_CHAR_TYPE; -typedef enum { ASCII, JIS, A_ESC, A_ESC_DL, JIS_1, J_ESC, J_ESC_BR, - INV, JIS_S_NUM } JIS_STATE; -typedef enum { COPY_A, COPY_J1, COPY_J2, MAKE_A, 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. - *************************************************************************************/ - -#ifndef __CYGWIN__ -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, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII }, -/* JIS */ { J_ESC, JIS_1, JIS_1, JIS_1, JIS_1, JIS_1, INV, JIS_1, INV }, -/* A_ESC */ { ASCII, A_ESC_DL, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII }, -/* A_ESC_DL */{ ASCII, ASCII, ASCII, JIS, JIS, ASCII, ASCII, ASCII, ASCII }, -/* JIS_1 */ { INV, JIS, JIS, JIS, JIS, JIS, INV, JIS, INV }, -/* 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 }, -}; - -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}, -/* JIS */ { NOOP, COPY_J1, COPY_J1, COPY_J1, COPY_J1, COPY_J1, ERROR, COPY_J1, ERROR }, -/* 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, NOOP, NOOP, COPY_A, COPY_A, COPY_A, COPY_A}, -/* JIS_1 */ { ERROR, COPY_J2, COPY_J2, COPY_J2, COPY_J2, COPY_J2, ERROR, COPY_J2, ERROR }, -/* J_ESC */ { ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR }, -/* J_ESC_BR */{ ERROR, ERROR, ERROR, ERROR, MAKE_A, MAKE_A, ERROR, ERROR, ERROR }, -}; -#endif /* !__CYGWIN__ */ - -/* we override the mbstate_t __count field for more complex encodings and use it store a state value */ -#define __state __count - -#ifdef _MB_EXTENDED_CHARSETS_ISO -int -_DEFUN (__iso_mbtowc, (r, pwc, s, n, charset, state), - struct _reent *r _AND - wchar_t *pwc _AND - const char *s _AND - size_t n _AND - const char *charset _AND - mbstate_t *state) -{ - wchar_t dummy; - unsigned char *t = (unsigned char *)s; - - if (pwc == NULL) - pwc = &dummy; - - if (s == NULL) - return 0; - - if (n == 0) - return -2; - - if (*t >= 0xa0) - { - int iso_idx = __iso_8859_index (charset + 9); - if (iso_idx >= 0) - { - *pwc = __iso_8859_conv[iso_idx][*t - 0xa0]; - if (*pwc == 0) /* Invalid character */ - { - r->_errno = EILSEQ; - return -1; - } - return 1; - } - } - - *pwc = (wchar_t) *t; - - if (*t == '\0') - return 0; - - return 1; -} -#endif /* _MB_EXTENDED_CHARSETS_ISO */ - -#ifdef _MB_EXTENDED_CHARSETS_WINDOWS -int -_DEFUN (__cp_mbtowc, (r, pwc, s, n, charset, state), - struct _reent *r _AND - wchar_t *pwc _AND - const char *s _AND - size_t n _AND - const char *charset _AND - mbstate_t *state) -{ - wchar_t dummy; - unsigned char *t = (unsigned char *)s; - - if (pwc == NULL) - pwc = &dummy; - - if (s == NULL) - return 0; - - if (n == 0) - return -2; - - if (*t >= 0x80) - { - int cp_idx = __cp_index (charset + 2); - if (cp_idx >= 0) - { - *pwc = __cp_conv[cp_idx][*t - 0x80]; - if (*pwc == 0) /* Invalid character */ - { - r->_errno = EILSEQ; - return -1; - } - return 1; - } - } - - *pwc = (wchar_t)*t; - - if (*t == '\0') - return 0; - - return 1; -} -#endif /* _MB_EXTENDED_CHARSETS_WINDOWS */ - -int -_DEFUN (__utf8_mbtowc, (r, pwc, s, n, charset, state), - struct _reent *r _AND - wchar_t *pwc _AND - const char *s _AND - size_t n _AND - const char *charset _AND - mbstate_t *state) -{ - wchar_t dummy; - unsigned char *t = (unsigned char *)s; - int ch; - int i = 0; - - if (pwc == NULL) - pwc = &dummy; - - if (s == NULL) - return 0; - - if (n == 0) - return -2; - - if (state->__count == 0) - ch = t[i++]; - else - ch = state->__value.__wchb[0]; - - if (ch == '\0') - { - *pwc = 0; - state->__count = 0; - return 0; /* s points to the null character */ - } - - if (ch <= 0x7f) - { - /* single-byte sequence */ - state->__count = 0; - *pwc = ch; - return 1; - } - if (ch >= 0xc0 && ch <= 0xdf) - { - /* two-byte sequence */ - state->__value.__wchb[0] = ch; - if (state->__count == 0) - state->__count = 1; - else if (n < (size_t)-1) - ++n; - if (n < 2) - return -2; - ch = t[i++]; - if (ch < 0x80 || ch > 0xbf) - { - r->_errno = EILSEQ; - return -1; - } - if (state->__value.__wchb[0] < 0xc2) - { - /* overlong UTF-8 sequence */ - r->_errno = EILSEQ; - return -1; - } - state->__count = 0; - *pwc = (wchar_t)((state->__value.__wchb[0] & 0x1f) << 6) - | (wchar_t)(ch & 0x3f); - return i; - } - if (ch >= 0xe0 && ch <= 0xef) - { - /* three-byte sequence */ - wchar_t tmp; - state->__value.__wchb[0] = ch; - if (state->__count == 0) - state->__count = 1; - else if (n < (size_t)-1) - ++n; - if (n < 2) - return -2; - ch = (state->__count == 1) ? t[i++] : state->__value.__wchb[1]; - if (state->__value.__wchb[0] == 0xe0 && ch < 0xa0) - { - /* overlong UTF-8 sequence */ - r->_errno = EILSEQ; - return -1; - } - if (ch < 0x80 || ch > 0xbf) - { - r->_errno = EILSEQ; - return -1; - } - state->__value.__wchb[1] = ch; - if (state->__count == 1) - state->__count = 2; - else if (n < (size_t)-1) - ++n; - if (n < 3) - return -2; - ch = t[i++]; - if (ch < 0x80 || ch > 0xbf) - { - r->_errno = EILSEQ; - return -1; - } - state->__count = 0; - tmp = (wchar_t)((state->__value.__wchb[0] & 0x0f) << 12) - | (wchar_t)((state->__value.__wchb[1] & 0x3f) << 6) - | (wchar_t)(ch & 0x3f); - *pwc = tmp; - return i; - } - if (ch >= 0xf0 && ch <= 0xf4) - { - /* four-byte sequence */ - wint_t tmp; - state->__value.__wchb[0] = ch; - if (state->__count == 0) - state->__count = 1; - else if (n < (size_t)-1) - ++n; - if (n < 2) - return -2; - ch = (state->__count == 1) ? t[i++] : state->__value.__wchb[1]; - if ((state->__value.__wchb[0] == 0xf0 && ch < 0x90) - || (state->__value.__wchb[0] == 0xf4 && ch >= 0x90)) - { - /* overlong UTF-8 sequence or result is > 0x10ffff */ - r->_errno = EILSEQ; - return -1; - } - if (ch < 0x80 || ch > 0xbf) - { - r->_errno = EILSEQ; - return -1; - } - state->__value.__wchb[1] = ch; - if (state->__count == 1) - state->__count = 2; - else if (n < (size_t)-1) - ++n; - if (n < 3) - return -2; - ch = (state->__count == 2) ? t[i++] : state->__value.__wchb[2]; - if (ch < 0x80 || ch > 0xbf) - { - r->_errno = EILSEQ; - return -1; - } - state->__value.__wchb[2] = ch; - if (state->__count == 2) - state->__count = 3; - else if (n < (size_t)-1) - ++n; - if (state->__count == 3 && sizeof(wchar_t) == 2) - { - /* On systems which have wchar_t being UTF-16 values, the value - doesn't fit into a single wchar_t in this case. So what we - do here is to store the state with a special value of __count - and return the first half of a surrogate pair. The first - three bytes of a UTF-8 sequence are enough to generate the - first half of a UTF-16 surrogate pair. As return value we - choose to return the number of bytes actually read up to - here. - The second half of the surrogate pair is returned in case we - recognize the special __count value of four, and the next - byte is actually a valid value. See below. */ - tmp = (wint_t)((state->__value.__wchb[0] & 0x07) << 18) - | (wint_t)((state->__value.__wchb[1] & 0x3f) << 12) - | (wint_t)((state->__value.__wchb[2] & 0x3f) << 6); - state->__count = 4; - *pwc = 0xd800 | ((tmp - 0x10000) >> 10); - return i; - } - if (n < 4) - return -2; - ch = t[i++]; - if (ch < 0x80 || ch > 0xbf) - { - r->_errno = EILSEQ; - return -1; - } - tmp = (wint_t)((state->__value.__wchb[0] & 0x07) << 18) - | (wint_t)((state->__value.__wchb[1] & 0x3f) << 12) - | (wint_t)((state->__value.__wchb[2] & 0x3f) << 6) - | (wint_t)(ch & 0x3f); - if (state->__count == 4 && sizeof(wchar_t) == 2) - /* Create the second half of the surrogate pair for systems with - wchar_t == UTF-16 . */ - *pwc = 0xdc00 | (tmp & 0x3ff); - else - *pwc = tmp; - state->__count = 0; - return i; - } - - r->_errno = EILSEQ; - return -1; -} - -/* Cygwin defines its own doublebyte charset conversion functions - because the underlying OS requires wchar_t == UTF-16. */ -#ifndef __CYGWIN__ -int -_DEFUN (__sjis_mbtowc, (r, pwc, s, n, charset, state), - struct _reent *r _AND - wchar_t *pwc _AND - const char *s _AND - size_t n _AND - const char *charset _AND - mbstate_t *state) -{ - wchar_t dummy; - unsigned char *t = (unsigned char *)s; - int ch; - int i = 0; - - if (pwc == NULL) - pwc = &dummy; - - if (s == NULL) - return 0; /* not state-dependent */ - - if (n == 0) - return -2; - - ch = t[i++]; - if (state->__count == 0) - { - if (_issjis1 (ch)) - { - state->__value.__wchb[0] = ch; - state->__count = 1; - if (n <= 1) - return -2; - ch = t[i++]; - } - } - if (state->__count == 1) - { - if (_issjis2 (ch)) - { - *pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)ch; - state->__count = 0; - return i; - } - else - { - r->_errno = EILSEQ; - return -1; - } - } - - *pwc = (wchar_t)*t; - - if (*t == '\0') - return 0; - - return 1; -} - -int -_DEFUN (__eucjp_mbtowc, (r, pwc, s, n, charset, state), - struct _reent *r _AND - wchar_t *pwc _AND - const char *s _AND - size_t n _AND - const char *charset _AND - mbstate_t *state) -{ - wchar_t dummy; - unsigned char *t = (unsigned char *)s; - int ch; - int i = 0; - - if (pwc == NULL) - pwc = &dummy; - - if (s == NULL) - return 0; - - if (n == 0) - return -2; - - ch = t[i++]; - if (state->__count == 0) - { - if (_iseucjp1 (ch)) - { - state->__value.__wchb[0] = ch; - state->__count = 1; - if (n <= 1) - return -2; - ch = t[i++]; - } - } - if (state->__count == 1) - { - if (_iseucjp2 (ch)) - { - if (state->__value.__wchb[0] == 0x8f) - { - state->__value.__wchb[1] = ch; - state->__count = 2; - if (n <= i) - return -2; - ch = t[i++]; - } - else - { - *pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)ch; - state->__count = 0; - return i; - } - } - else - { - r->_errno = EILSEQ; - return -1; - } - } - if (state->__count == 2) - { - if (_iseucjp2 (ch)) - { - *pwc = (((wchar_t)state->__value.__wchb[1]) << 8) - + (wchar_t)(ch & 0x7f); - state->__count = 0; - return i; - } - else - { - r->_errno = EILSEQ; - return -1; - } - } - - *pwc = (wchar_t)*t; - - if (*t == '\0') - return 0; - - return 1; -} - -int -_DEFUN (__jis_mbtowc, (r, pwc, s, n, charset, state), - struct _reent *r _AND - wchar_t *pwc _AND - const char *s _AND - size_t n _AND - const char *charset _AND - mbstate_t *state) -{ - wchar_t dummy; - unsigned char *t = (unsigned char *)s; - JIS_STATE curr_state; - JIS_ACTION action; - JIS_CHAR_TYPE ch; - unsigned char *ptr; - unsigned int i; - int curr_ch; - - if (pwc == NULL) - pwc = &dummy; - - if (s == NULL) - { - state->__state = ASCII; - return 1; /* state-dependent */ - } - - if (n == 0) - return -2; - - curr_state = state->__state; - 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->__state = ASCII; - *pwc = (wchar_t)0; - return 0; - case COPY_A: - state->__state = ASCII; - *pwc = (wchar_t)*ptr; - return (i + 1); - case COPY_J1: - state->__value.__wchb[0] = t[i]; - break; - case COPY_J2: - state->__state = JIS; - *pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)(t[i]); - return (i + 1); - case MAKE_A: - ptr = (unsigned char *)(t + i + 1); - break; - case ERROR: - default: - r->_errno = EILSEQ; - return -1; - } - - } - - state->__state = curr_state; - return -2; /* n < bytes needed */ -} -#endif /* !__CYGWIN__*/ -#endif /* _MB_CAPABLE */ +#include +#include +#include +#include "mbctype.h" +#include +#include +#include +#include "local.h" + +int (*__mbtowc) (struct _reent *, wchar_t *, const char *, size_t, + const char *, mbstate_t *) +#ifdef __CYGWIN__ + /* Cygwin starts up in UTF-8 mode. */ + = __utf8_mbtowc; +#else + = __ascii_mbtowc; +#endif + +int +_DEFUN (_mbtowc_r, (r, pwc, s, n, state), + struct _reent *r _AND + wchar_t *__restrict pwc _AND + const char *__restrict s _AND + size_t n _AND + mbstate_t *state) +{ + return __mbtowc (r, pwc, s, n, __locale_charset (), state); +} + +int +_DEFUN (__ascii_mbtowc, (r, pwc, s, n, charset, state), + struct _reent *r _AND + wchar_t *pwc _AND + const char *s _AND + size_t n _AND + const char *charset _AND + mbstate_t *state) +{ + wchar_t dummy; + unsigned char *t = (unsigned char *)s; + + if (pwc == NULL) + pwc = &dummy; + + if (s == NULL) + return 0; + + if (n == 0) + return -2; + +#ifdef __CYGWIN__ + if ((wchar_t)*t >= 0x80) + { + r->_errno = EILSEQ; + return -1; + } +#endif + + *pwc = (wchar_t)*t; + + if (*t == '\0') + return 0; + + return 1; +} + +#ifdef _MB_CAPABLE +typedef enum { ESCAPE, DOLLAR, BRACKET, AT, B, J, + NUL, JIS_CHAR, OTHER, JIS_C_NUM } JIS_CHAR_TYPE; +typedef enum { ASCII, JIS, A_ESC, A_ESC_DL, JIS_1, J_ESC, J_ESC_BR, + INV, JIS_S_NUM } JIS_STATE; +typedef enum { COPY_A, COPY_J1, COPY_J2, MAKE_A, 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. + *************************************************************************************/ + +#ifndef __CYGWIN__ +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, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII }, +/* JIS */ { J_ESC, JIS_1, JIS_1, JIS_1, JIS_1, JIS_1, INV, JIS_1, INV }, +/* A_ESC */ { ASCII, A_ESC_DL, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII }, +/* A_ESC_DL */{ ASCII, ASCII, ASCII, JIS, JIS, ASCII, ASCII, ASCII, ASCII }, +/* JIS_1 */ { INV, JIS, JIS, JIS, JIS, JIS, INV, JIS, INV }, +/* 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 }, +}; + +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}, +/* JIS */ { NOOP, COPY_J1, COPY_J1, COPY_J1, COPY_J1, COPY_J1, ERROR, COPY_J1, ERROR }, +/* 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, NOOP, NOOP, COPY_A, COPY_A, COPY_A, COPY_A}, +/* JIS_1 */ { ERROR, COPY_J2, COPY_J2, COPY_J2, COPY_J2, COPY_J2, ERROR, COPY_J2, ERROR }, +/* J_ESC */ { ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR }, +/* J_ESC_BR */{ ERROR, ERROR, ERROR, ERROR, MAKE_A, MAKE_A, ERROR, ERROR, ERROR }, +}; +#endif /* !__CYGWIN__ */ + +/* we override the mbstate_t __count field for more complex encodings and use it store a state value */ +#define __state __count + +#ifdef _MB_EXTENDED_CHARSETS_ISO +int +_DEFUN (__iso_mbtowc, (r, pwc, s, n, charset, state), + struct _reent *r _AND + wchar_t *pwc _AND + const char *s _AND + size_t n _AND + const char *charset _AND + mbstate_t *state) +{ + wchar_t dummy; + unsigned char *t = (unsigned char *)s; + + if (pwc == NULL) + pwc = &dummy; + + if (s == NULL) + return 0; + + if (n == 0) + return -2; + + if (*t >= 0xa0) + { + int iso_idx = __iso_8859_index (charset + 9); + if (iso_idx >= 0) + { + *pwc = __iso_8859_conv[iso_idx][*t - 0xa0]; + if (*pwc == 0) /* Invalid character */ + { + r->_errno = EILSEQ; + return -1; + } + return 1; + } + } + + *pwc = (wchar_t) *t; + + if (*t == '\0') + return 0; + + return 1; +} +#endif /* _MB_EXTENDED_CHARSETS_ISO */ + +#ifdef _MB_EXTENDED_CHARSETS_WINDOWS +int +_DEFUN (__cp_mbtowc, (r, pwc, s, n, charset, state), + struct _reent *r _AND + wchar_t *pwc _AND + const char *s _AND + size_t n _AND + const char *charset _AND + mbstate_t *state) +{ + wchar_t dummy; + unsigned char *t = (unsigned char *)s; + + if (pwc == NULL) + pwc = &dummy; + + if (s == NULL) + return 0; + + if (n == 0) + return -2; + + if (*t >= 0x80) + { + int cp_idx = __cp_index (charset + 2); + if (cp_idx >= 0) + { + *pwc = __cp_conv[cp_idx][*t - 0x80]; + if (*pwc == 0) /* Invalid character */ + { + r->_errno = EILSEQ; + return -1; + } + return 1; + } + } + + *pwc = (wchar_t)*t; + + if (*t == '\0') + return 0; + + return 1; +} +#endif /* _MB_EXTENDED_CHARSETS_WINDOWS */ + +int +_DEFUN (__utf8_mbtowc, (r, pwc, s, n, charset, state), + struct _reent *r _AND + wchar_t *pwc _AND + const char *s _AND + size_t n _AND + const char *charset _AND + mbstate_t *state) +{ + wchar_t dummy; + unsigned char *t = (unsigned char *)s; + int ch; + int i = 0; + + if (pwc == NULL) + pwc = &dummy; + + if (s == NULL) + return 0; + + if (n == 0) + return -2; + + if (state->__count == 0) + ch = t[i++]; + else + ch = state->__value.__wchb[0]; + + if (ch == '\0') + { + *pwc = 0; + state->__count = 0; + return 0; /* s points to the null character */ + } + + if (ch <= 0x7f) + { + /* single-byte sequence */ + state->__count = 0; + *pwc = ch; + return 1; + } + if (ch >= 0xc0 && ch <= 0xdf) + { + /* two-byte sequence */ + state->__value.__wchb[0] = ch; + if (state->__count == 0) + state->__count = 1; + else if (n < (size_t)-1) + ++n; + if (n < 2) + return -2; + ch = t[i++]; + if (ch < 0x80 || ch > 0xbf) + { + r->_errno = EILSEQ; + return -1; + } + if (state->__value.__wchb[0] < 0xc2) + { + /* overlong UTF-8 sequence */ + r->_errno = EILSEQ; + return -1; + } + state->__count = 0; + *pwc = (wchar_t)((state->__value.__wchb[0] & 0x1f) << 6) + | (wchar_t)(ch & 0x3f); + return i; + } + if (ch >= 0xe0 && ch <= 0xef) + { + /* three-byte sequence */ + wchar_t tmp; + state->__value.__wchb[0] = ch; + if (state->__count == 0) + state->__count = 1; + else if (n < (size_t)-1) + ++n; + if (n < 2) + return -2; + ch = (state->__count == 1) ? t[i++] : state->__value.__wchb[1]; + if (state->__value.__wchb[0] == 0xe0 && ch < 0xa0) + { + /* overlong UTF-8 sequence */ + r->_errno = EILSEQ; + return -1; + } + if (ch < 0x80 || ch > 0xbf) + { + r->_errno = EILSEQ; + return -1; + } + state->__value.__wchb[1] = ch; + if (state->__count == 1) + state->__count = 2; + else if (n < (size_t)-1) + ++n; + if (n < 3) + return -2; + ch = t[i++]; + if (ch < 0x80 || ch > 0xbf) + { + r->_errno = EILSEQ; + return -1; + } + state->__count = 0; + tmp = (wchar_t)((state->__value.__wchb[0] & 0x0f) << 12) + | (wchar_t)((state->__value.__wchb[1] & 0x3f) << 6) + | (wchar_t)(ch & 0x3f); + *pwc = tmp; + return i; + } + if (ch >= 0xf0 && ch <= 0xf4) + { + /* four-byte sequence */ + wint_t tmp; + state->__value.__wchb[0] = ch; + if (state->__count == 0) + state->__count = 1; + else if (n < (size_t)-1) + ++n; + if (n < 2) + return -2; + ch = (state->__count == 1) ? t[i++] : state->__value.__wchb[1]; + if ((state->__value.__wchb[0] == 0xf0 && ch < 0x90) + || (state->__value.__wchb[0] == 0xf4 && ch >= 0x90)) + { + /* overlong UTF-8 sequence or result is > 0x10ffff */ + r->_errno = EILSEQ; + return -1; + } + if (ch < 0x80 || ch > 0xbf) + { + r->_errno = EILSEQ; + return -1; + } + state->__value.__wchb[1] = ch; + if (state->__count == 1) + state->__count = 2; + else if (n < (size_t)-1) + ++n; + if (n < 3) + return -2; + ch = (state->__count == 2) ? t[i++] : state->__value.__wchb[2]; + if (ch < 0x80 || ch > 0xbf) + { + r->_errno = EILSEQ; + return -1; + } + state->__value.__wchb[2] = ch; + if (state->__count == 2) + state->__count = 3; + else if (n < (size_t)-1) + ++n; + if (state->__count == 3 && sizeof(wchar_t) == 2) + { + /* On systems which have wchar_t being UTF-16 values, the value + doesn't fit into a single wchar_t in this case. So what we + do here is to store the state with a special value of __count + and return the first half of a surrogate pair. The first + three bytes of a UTF-8 sequence are enough to generate the + first half of a UTF-16 surrogate pair. As return value we + choose to return the number of bytes actually read up to + here. + The second half of the surrogate pair is returned in case we + recognize the special __count value of four, and the next + byte is actually a valid value. See below. */ + tmp = (wint_t)((state->__value.__wchb[0] & 0x07) << 18) + | (wint_t)((state->__value.__wchb[1] & 0x3f) << 12) + | (wint_t)((state->__value.__wchb[2] & 0x3f) << 6); + state->__count = 4; + *pwc = 0xd800 | ((tmp - 0x10000) >> 10); + return i; + } + if (n < 4) + return -2; + ch = t[i++]; + if (ch < 0x80 || ch > 0xbf) + { + r->_errno = EILSEQ; + return -1; + } + tmp = (wint_t)((state->__value.__wchb[0] & 0x07) << 18) + | (wint_t)((state->__value.__wchb[1] & 0x3f) << 12) + | (wint_t)((state->__value.__wchb[2] & 0x3f) << 6) + | (wint_t)(ch & 0x3f); + if (state->__count == 4 && sizeof(wchar_t) == 2) + /* Create the second half of the surrogate pair for systems with + wchar_t == UTF-16 . */ + *pwc = 0xdc00 | (tmp & 0x3ff); + else + *pwc = tmp; + state->__count = 0; + return i; + } + + r->_errno = EILSEQ; + return -1; +} + +/* Cygwin defines its own doublebyte charset conversion functions + because the underlying OS requires wchar_t == UTF-16. */ +#ifndef __CYGWIN__ +int +_DEFUN (__sjis_mbtowc, (r, pwc, s, n, charset, state), + struct _reent *r _AND + wchar_t *pwc _AND + const char *s _AND + size_t n _AND + const char *charset _AND + mbstate_t *state) +{ + wchar_t dummy; + unsigned char *t = (unsigned char *)s; + int ch; + int i = 0; + + if (pwc == NULL) + pwc = &dummy; + + if (s == NULL) + return 0; /* not state-dependent */ + + if (n == 0) + return -2; + + ch = t[i++]; + if (state->__count == 0) + { + if (_issjis1 (ch)) + { + state->__value.__wchb[0] = ch; + state->__count = 1; + if (n <= 1) + return -2; + ch = t[i++]; + } + } + if (state->__count == 1) + { + if (_issjis2 (ch)) + { + *pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)ch; + state->__count = 0; + return i; + } + else + { + r->_errno = EILSEQ; + return -1; + } + } + + *pwc = (wchar_t)*t; + + if (*t == '\0') + return 0; + + return 1; +} + +int +_DEFUN (__eucjp_mbtowc, (r, pwc, s, n, charset, state), + struct _reent *r _AND + wchar_t *pwc _AND + const char *s _AND + size_t n _AND + const char *charset _AND + mbstate_t *state) +{ + wchar_t dummy; + unsigned char *t = (unsigned char *)s; + int ch; + int i = 0; + + if (pwc == NULL) + pwc = &dummy; + + if (s == NULL) + return 0; + + if (n == 0) + return -2; + + ch = t[i++]; + if (state->__count == 0) + { + if (_iseucjp1 (ch)) + { + state->__value.__wchb[0] = ch; + state->__count = 1; + if (n <= 1) + return -2; + ch = t[i++]; + } + } + if (state->__count == 1) + { + if (_iseucjp2 (ch)) + { + if (state->__value.__wchb[0] == 0x8f) + { + state->__value.__wchb[1] = ch; + state->__count = 2; + if (n <= i) + return -2; + ch = t[i++]; + } + else + { + *pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)ch; + state->__count = 0; + return i; + } + } + else + { + r->_errno = EILSEQ; + return -1; + } + } + if (state->__count == 2) + { + if (_iseucjp2 (ch)) + { + *pwc = (((wchar_t)state->__value.__wchb[1]) << 8) + + (wchar_t)(ch & 0x7f); + state->__count = 0; + return i; + } + else + { + r->_errno = EILSEQ; + return -1; + } + } + + *pwc = (wchar_t)*t; + + if (*t == '\0') + return 0; + + return 1; +} + +int +_DEFUN (__jis_mbtowc, (r, pwc, s, n, charset, state), + struct _reent *r _AND + wchar_t *pwc _AND + const char *s _AND + size_t n _AND + const char *charset _AND + mbstate_t *state) +{ + wchar_t dummy; + unsigned char *t = (unsigned char *)s; + JIS_STATE curr_state; + JIS_ACTION action; + JIS_CHAR_TYPE ch; + unsigned char *ptr; + unsigned int i; + int curr_ch; + + if (pwc == NULL) + pwc = &dummy; + + if (s == NULL) + { + state->__state = ASCII; + return 1; /* state-dependent */ + } + + if (n == 0) + return -2; + + curr_state = state->__state; + 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->__state = ASCII; + *pwc = (wchar_t)0; + return 0; + case COPY_A: + state->__state = ASCII; + *pwc = (wchar_t)*ptr; + return (i + 1); + case COPY_J1: + state->__value.__wchb[0] = t[i]; + break; + case COPY_J2: + state->__state = JIS; + *pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)(t[i]); + return (i + 1); + case MAKE_A: + ptr = (unsigned char *)(t + i + 1); + break; + case ERROR: + default: + r->_errno = EILSEQ; + return -1; + } + + } + + state->__state = curr_state; + return -2; /* n < bytes needed */ +} +#endif /* !__CYGWIN__*/ +#endif /* _MB_CAPABLE */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/mlock.c b/contrib/sdk/sources/newlib/libc/stdlib/mlock.c index 34ca2be331..888c986a9a 100644 --- a/contrib/sdk/sources/newlib/libc/stdlib/mlock.c +++ b/contrib/sdk/sources/newlib/libc/stdlib/mlock.c @@ -1,64 +1,64 @@ -#ifndef MALLOC_PROVIDED -/* -FUNCTION -<<__malloc_lock>>, <<__malloc_unlock>>---lock malloc pool - -INDEX - __malloc_lock -INDEX - __malloc_unlock - -ANSI_SYNOPSIS - #include - 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 <> family of routines call these functions when they need to lock -the memory pool. The version of these routines supplied in the library use -the lock API defined in sys/lock.h. If multiple threads of execution can -call <>, or if <> 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 <> 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 -#include - -#ifndef __SINGLE_THREAD__ -__LOCK_INIT_RECURSIVE(static, __malloc_lock_object); -#endif - -void -__malloc_lock (ptr) - struct _reent *ptr; -{ -#ifndef __SINGLE_THREAD__ - __lock_acquire_recursive (__malloc_lock_object); -#endif -} - -void -__malloc_unlock (ptr) - struct _reent *ptr; -{ -#ifndef __SINGLE_THREAD__ - __lock_release_recursive (__malloc_lock_object); -#endif -} - -#endif +#ifndef MALLOC_PROVIDED +/* +FUNCTION +<<__malloc_lock>>, <<__malloc_unlock>>---lock malloc pool + +INDEX + __malloc_lock +INDEX + __malloc_unlock + +ANSI_SYNOPSIS + #include + 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 <> family of routines call these functions when they need to lock +the memory pool. The version of these routines supplied in the library use +the lock API defined in sys/lock.h. If multiple threads of execution can +call <>, or if <> 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 <> 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 +#include + +#ifndef __SINGLE_THREAD__ +__LOCK_INIT_RECURSIVE(static, __malloc_lock_object); +#endif + +void +__malloc_lock (ptr) + struct _reent *ptr; +{ +#ifndef __SINGLE_THREAD__ + __lock_acquire_recursive (__malloc_lock_object); +#endif +} + +void +__malloc_unlock (ptr) + struct _reent *ptr; +{ +#ifndef __SINGLE_THREAD__ + __lock_release_recursive (__malloc_lock_object); +#endif +} + +#endif diff --git a/contrib/sdk/sources/newlib/libc/stdlib/random.c b/contrib/sdk/sources/newlib/libc/stdlib/random.c new file mode 100644 index 0000000000..de132f3634 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/random.c @@ -0,0 +1,82 @@ +/* +FUNCTION +<>, <>---pseudo-random numbers + +INDEX + random +INDEX + srandom + +ANSI_SYNOPSIS + #define _XOPEN_SOURCE 500 + #include + long int random(void); + void srandom(unsigned int <[seed]>); + + + +DESCRIPTION +<> 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 <> 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 <>. + +You can set the random seed using <>; it does nothing beyond +storing its argument in the static variable used by <>. 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 <>; or, if you wish to ensure +(for example, while debugging) that successive runs of your program +use the same ``random'' numbers, you can use <> to set the same +random seed at the outset. + +RETURNS +<> returns the next pseudo-random integer in sequence; it is a +number between <<0>> and <> (inclusive). + +<> does not return a result. + +NOTES +<> and <> are unsafe for multi-threaded applications. + +_XOPEN_SOURCE may be any value >= 500. + +PORTABILITY +<> is required by XSI. This implementation uses the same +algorithm as <>. + +<> requires no supporting OS subroutines. +*/ + +#ifndef _REENT_ONLY + +#include +#include + +void +_DEFUN (srandom, (seed), unsigned int seed) +{ + struct _reent *reent = _REENT; + + _REENT_CHECK_RAND48(reent); + _REENT_RAND_NEXT(reent) = seed; +} + +long int +_DEFUN_VOID (random) +{ + struct _reent *reent = _REENT; + + /* 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_CHECK_RAND48(reent); + _REENT_RAND_NEXT(reent) = + _REENT_RAND_NEXT(reent) * __extension__ 6364136223846793005LL + 1; + return (long int)((_REENT_RAND_NEXT(reent) >> 32) & RAND_MAX); +} + +#endif /* _REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcsnrtombs.c b/contrib/sdk/sources/newlib/libc/stdlib/wcsnrtombs.c new file mode 100644 index 0000000000..99c8bd1752 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcsnrtombs.c @@ -0,0 +1,188 @@ +/* +FUNCTION +<>, <>---convert a wide-character string to a character string + +INDEX + wcsrtombs +INDEX + _wcsrtombs_r +INDEX + wcsnrtombs +INDEX + _wcsnrtombs_r + +ANSI_SYNOPSIS + #include + size_t wcsrtombs(char *__restrict <[dst]>, + const wchar_t **__restrict <[src]>, size_t <[len]>, + mbstate_t *__restrict <[ps]>); + + #include + size_t _wcsrtombs_r(struct _reent *<[ptr]>, char *<[dst]>, + const wchar_t **<[src]>, size_t <[len]>, + mbstate_t *<[ps]>); + + #include + size_t wcsnrtombs(char *__restrict <[dst]>, + const wchar_t **__restrict <[src]>, + size_t <[nwc]>, size_t <[len]>, + mbstate_t *__restrict <[ps]>); + + #include + size_t _wcsnrtombs_r(struct _reent *<[ptr]>, char *<[dst]>, + const wchar_t **<[src]>, size_t <[nwc]>, + size_t <[len]>, mbstate_t *<[ps]>); + +TRAD_SYNOPSIS + #include + size_t wcsrtombs(<[dst]>, <[src]>, <[len]>, <[ps]>) + char *__restrict <[dst]>; + const wchar_t **__restrict <[src]>; + size_t <[len]>; + mbstate_t *__restrict <[ps]>; + + #include + size_t _wcsrtombs_r(<[ptr]>, <[dst]>, <[src]>, <[len]>, <[ps]>) + struct _rent *<[ptr]>; + char *<[dst]>; + const wchar_t **<[src]>; + size_t <[len]>; + mbstate_t *<[ps]>; + + #include + size_t wcsnrtombs(<[dst]>, <[src]>, <[nwc]>, <[len]>, <[ps]>) + char *__restrict <[dst]>; + const wchar_t **__restrict <[src]>; + size_t <[nwc]>; + size_t <[len]>; + mbstate_t *__restrict <[ps]>; + + #include + size_t _wcsnrtombs_r(<[ptr]>, <[dst]>, <[src]>, <[nwc]>, <[len]>, <[ps]>) + struct _rent *<[ptr]>; + char *<[dst]>; + const wchar_t **<[src]>; + size_t <[nwc]>; + size_t <[len]>; + mbstate_t *<[ps]>; + +DESCRIPTION +The <> function converts a string of wide characters indirectly +pointed to by <[src]> to a corresponding multibyte character string stored in +the array pointed to by <[dst]>. No more than <[len]> bytes are written to +<[dst]>. + +If <[dst]> is NULL, no characters are stored. + +If <[dst]> is not NULL, the pointer pointed to by <[src]> is updated to point +to the character after the one that conversion stopped at. If conversion +stops because a null character is encountered, *<[src]> is set to NULL. + +The mbstate_t argument, <[ps]>, is used to keep track of the shift state. If +it is NULL, <> uses an internal, static mbstate_t object, which +is initialized to the initial conversion state at program startup. + +The <> function behaves identically to <>, except that +conversion stops after reading at most <[nwc]> characters from the buffer +pointed to by <[src]>. + +RETURNS +The <> and <> functions return the number of bytes +stored in the array pointed to by <[dst]> (not including any terminating +null), if successful, otherwise it returns (size_t)-1. + +PORTABILITY +<> is defined by C99 standard. +<> is defined by the POSIX.1-2008 standard. +*/ + +#include +#include +#include +#include +#include +#include +#include "local.h" + +size_t +_DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps), + struct _reent *r _AND + char *dst _AND + const wchar_t **src _AND + size_t nwc _AND + size_t len _AND + mbstate_t *ps) +{ + char *ptr = dst; + char buff[10]; + wchar_t *pwcs; + size_t n; + int i; + +#ifdef _MB_CAPABLE + if (ps == NULL) + { + _REENT_CHECK_MISC(r); + ps = &(_REENT_WCSRTOMBS_STATE(r)); + } +#endif + + /* If no dst pointer, treat len as maximum possible value. */ + if (dst == NULL) + len = (size_t)-1; + + n = 0; + pwcs = (wchar_t *)(*src); + + while (n < len && nwc-- > 0) + { + int count = ps->__count; + wint_t wch = ps->__value.__wch; + int bytes = __wctomb (r, buff, *pwcs, __locale_charset (), ps); + if (bytes == -1) + { + r->_errno = EILSEQ; + ps->__count = 0; + return (size_t)-1; + } + if (n + bytes <= len) + { + n += bytes; + if (dst) + { + for (i = 0; i < bytes; ++i) + *ptr++ = buff[i]; + ++(*src); + } + if (*pwcs++ == 0x00) + { + if (dst) + *src = NULL; + ps->__count = 0; + return n - 1; + } + } + else + { + /* not enough room, we must back up state to before __wctomb call */ + ps->__count = count; + ps->__value.__wch = wch; + len = 0; + } + } + + return n; +} + +#ifndef _REENT_ONLY +size_t +_DEFUN (wcsnrtombs, (dst, src, nwc, len, ps), + char *__restrict dst _AND + const wchar_t **__restrict src _AND + size_t nwc _AND + size_t len _AND + mbstate_t *__restrict ps) +{ + return _wcsnrtombs_r (_REENT, dst, src, nwc, len, ps); +} +#endif /* !_REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcsrtombs.c b/contrib/sdk/sources/newlib/libc/stdlib/wcsrtombs.c new file mode 100644 index 0000000000..2b6777caed --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcsrtombs.c @@ -0,0 +1,28 @@ +/* Doc in wcsnrtombs.c */ + +#include +#include +#include + +size_t +_DEFUN (_wcsrtombs_r, (r, dst, src, len, ps), + struct _reent *r _AND + char *dst _AND + const wchar_t **src _AND + size_t len _AND + mbstate_t *ps) +{ + return _wcsnrtombs_r (r, dst, src, (size_t) -1, len, ps); +} + +#ifndef _REENT_ONLY +size_t +_DEFUN (wcsrtombs, (dst, src, len, ps), + char *__restrict dst _AND + const wchar_t **__restrict src _AND + size_t len _AND + mbstate_t *__restrict ps) +{ + return _wcsnrtombs_r (_REENT, dst, src, (size_t) -1, len, ps); +} +#endif /* !_REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstod.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstod.c new file mode 100644 index 0000000000..c91ecf2fee --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstod.c @@ -0,0 +1,232 @@ +/* +FUNCTION + <>, <>---wide char string to double or float + +INDEX + wcstod +INDEX + _wcstod_r +INDEX + wcstof +INDEX + _wcstof_r + +ANSI_SYNOPSIS + #include + double wcstod(const wchar_t *__restrict <[str]>, + wchar_t **__restrict <[tail]>); + float wcstof(const wchar_t *__restrict <[str]>, + wchar_t **__restrict <[tail]>); + + double _wcstod_r(void *<[reent]>, + const wchar_t *<[str]>, wchar_t **<[tail]>); + float _wcstof_r(void *<[reent]>, + const wchar_t *<[str]>, wchar_t **<[tail]>); + +TRAD_SYNOPSIS + #include + double wcstod(<[str]>,<[tail]>) + wchar_t *__restrict <[str]>; + wchar_t **__restrict <[tail]>; + + float wcstof(<[str]>,<[tail]>) + wchar_t *__restrict <[str]>; + wchar_t **__restrict <[tail]>; + + double _wcstod_r(<[reent]>,<[str]>,<[tail]>) + wchar_t *<[reent]>; + wchar_t *<[str]>; + wchar_t **<[tail]>; + + float _wcstof_r(<[reent]>,<[str]>,<[tail]>) + wchar_t *<[reent]>; + wchar_t *<[str]>; + wchar_t **<[tail]>; + +DESCRIPTION + The function <> parses the wide 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 one of these formats: + .[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>] + .[+|-].<[digits]>[(e|E)[+|-]<[digits]>] + .[+|-](i|I)(n|N)(f|F)[(i|I)(n|N)(i|I)(t|T)(y|Y)] + .[+|-](n|N)(a|A)(n|N)[<(>[<[hexdigits]>]<)>] + .[+|-]0(x|X)<[hexdigits]>[.[<[hexdigits]>]][(p|P)[+|-]<[digits]>] + .[+|-]0(x|X).<[hexdigits]>[(p|P)[+|-]<[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, and cannot be parsed as infinity or NaN. If the platform + does not support NaN, then NaN is treated as an empty substring. + 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]>. + <> is identical to <> 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. However, <> is currently subject to + double rounding errors. + + The alternate functions <<_wcstod_r>> and <<_wcstof_r>> are + reentrant versions of <> and <>, respectively. + The extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS + Return 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 <> is returned, and <> is + stored in errno. If the correct value would cause underflow, 0 + is returned and <> is stored in errno. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. +*/ + +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#include + +double +_DEFUN (_wcstod_r, (ptr, nptr, endptr), + struct _reent *ptr _AND + _CONST wchar_t *nptr _AND + wchar_t **endptr) +{ + static const mbstate_t initial; + mbstate_t mbs; + double val; + char *buf, *end; + const wchar_t *wcp; + size_t len; + + while (iswspace(*nptr)) + nptr++; + + /* + * Convert the supplied numeric wide char. string to multibyte. + * + * We could attempt to find the end of the numeric portion of the + * wide char. string to avoid converting unneeded characters but + * choose not to bother; optimising the uncommon case where + * the input string contains a lot of text after the number + * duplicates a lot of strtod()'s functionality and slows down the + * most common cases. + */ + wcp = nptr; + mbs = initial; + if ((len = _wcsrtombs_r(ptr, NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if (endptr != NULL) + *endptr = (wchar_t *)nptr; + return (0.0); + } + if ((buf = _malloc_r(ptr, len + 1)) == NULL) + return (0.0); + mbs = initial; + _wcsrtombs_r(ptr, buf, &wcp, len + 1, &mbs); + + /* Let strtod() do most of the work for us. */ + val = _strtod_r(ptr, buf, &end); + + /* + * We only know where the number ended in the _multibyte_ + * representation of the string. If the caller wants to know + * where it ended, count multibyte characters to find the + * corresponding position in the wide char string. + */ + if (endptr != NULL) { + /* The only valid multibyte char in a float converted by + strtod/wcstod is the radix char. What we do here is, + figure out if the radix char was in the valid leading + float sequence in the incoming string. If so, the + multibyte float string is strlen(radix char) - 1 bytes + longer than the incoming wide char string has characters. + To fix endptr, reposition end as if the radix char was + just one byte long. The resulting difference (end - buf) + is then equivalent to the number of valid wide characters + in the input string. */ + len = strlen (_localeconv_r (ptr)->decimal_point); + if (len > 1) { + char *d = strstr (buf, + _localeconv_r (ptr)->decimal_point); + if (d && d < end) + end -= len - 1; + } + *endptr = (wchar_t *)nptr + (end - buf); + } + + _free_r(ptr, buf); + + return (val); +} + +float +_DEFUN (_wcstof_r, (ptr, nptr, endptr), + struct _reent *ptr _AND + _CONST wchar_t *nptr _AND + wchar_t **endptr) +{ + double retval = _wcstod_r (ptr, nptr, endptr); + if (isnan (retval)) + return nanf (NULL); + return (float)retval; +} + +#ifndef _REENT_ONLY + +double +_DEFUN (wcstod, (nptr, endptr), + _CONST wchar_t *__restrict nptr _AND wchar_t **__restrict endptr) +{ + return _wcstod_r (_REENT, nptr, endptr); +} + +float +_DEFUN (wcstof, (nptr, endptr), + _CONST wchar_t *__restrict nptr _AND + wchar_t **__restrict endptr) +{ + double retval = _wcstod_r (_REENT, nptr, endptr); + if (isnan (retval)) + return nanf (NULL); + return (float)retval; +} + +#endif diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstol.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstol.c new file mode 100644 index 0000000000..adda9c296d --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstol.c @@ -0,0 +1,227 @@ +/* +FUNCTION + <>---wide string to long + +INDEX + wcstol +INDEX + _wcstol_r + +ANSI_SYNOPSIS + #include + long wcstol(const wchar_t *__restrict <[s]>, + wchar_t **__restrict <[ptr]>,int <[base]>); + + long _wcstol_r(void *<[reent]>, + const wchar_t *<[s]>, wchar_t **<[ptr]>,int <[base]>); + +TRAD_SYNOPSIS + #include + long wcstol (<[s]>, <[ptr]>, <[base]>) + wchar_t *__restrict <[s]>; + wchar_t **__restrict <[ptr]>; + int <[base]>; + + long _wcstol_r (<[reent]>, <[s]>, <[ptr]>, <[base]>) + struct _reent *<[reent]>; + wchar_t *<[s]>; + wchar_t **<[ptr]>; + int <[base]>; + +DESCRIPTION +The function <> converts the wide string <<*<[s]>>> to +a <>. 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 <> 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 <>--<> (or, +equivalently, <>--<>) 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, +<> 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 <> 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 <>. + +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 <>). + +The alternate function <<_wcstol_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +<> returns the converted value, if any. If no conversion was +made, 0 is returned. + +<> returns <> or <> if the magnitude of +the converted value is too large, and sets <> to <>. + +PORTABILITY +<> 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 +#include +#include +#include +#include + +/* + * Convert a wide string to a long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long +_DEFUN (_wcstol_r, (rptr, nptr, endptr, base), + struct _reent *rptr _AND + _CONST wchar_t *nptr _AND + wchar_t **endptr _AND + int base) +{ + register const wchar_t *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 (iswspace(c)); + if (c == L'-') { + neg = 1; + c = *s++; + } else if (c == L'+') + c = *s++; + if ((base == 0 || base == 16) && + c == L'0' && (*s == L'x' || *s == L'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == L'0' ? 8 : 10; + + /* + * 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 (iswdigit(c)) + c -= L'0'; + else if (iswalpha(c)) + c -= iswupper(c) ? L'A' - 10 : L'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; + rptr->_errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (wchar_t *) (any ? s - 1 : nptr); + return (acc); +} + +#ifndef _REENT_ONLY + +long +_DEFUN (wcstol, (s, ptr, base), + _CONST wchar_t *__restrict s _AND + wchar_t **__restrict ptr _AND + int base) +{ + return _wcstol_r (_REENT, s, ptr, base); +} + +#endif diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstold.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstold.c new file mode 100644 index 0000000000..e94aca9198 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstold.c @@ -0,0 +1,108 @@ +/* +(C) Copyright IBM Corp. 2009 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +* 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. +* Neither the name of IBM 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 +#include +#include +#include +#include +#include "local.h" + +long double +wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr) +{ +#ifdef _LDBL_EQ_DBL +/* On platforms where long double is as wide as double. */ + return wcstod(nptr, endptr); + +#else /* This is a duplicate of the code in wcstod.c, but converted to long double. */ + + static const mbstate_t initial; + mbstate_t mbs; + long double val; + char *buf, *end; + const wchar_t *wcp; + size_t len; + + while (iswspace (*nptr)) + nptr++; + + /* Convert the supplied numeric wide char string to multibyte. */ + wcp = nptr; + mbs = initial; + if ((len = wcsrtombs (NULL, &wcp, 0, &mbs)) == (size_t)-1) + { + if (endptr != NULL) + *endptr = (wchar_t *) nptr; + return 0.0L; + } + + if ((buf = malloc (len + 1)) == NULL) + return 0.0L; + + mbs = initial; + wcsrtombs (buf, &wcp, len + 1, &mbs); + + val = strtold (buf, &end); + + /* We only know where the number ended in the _multibyte_ + representation of the string. If the caller wants to know + where it ended, count multibyte characters to find the + corresponding position in the wide char string. */ + + if (endptr != NULL) + { + /* The only valid multibyte char in a float converted by + strtold/wcstold is the radix char. What we do here is, + figure out if the radix char was in the valid leading + float sequence in the incoming string. If so, the + multibyte float string is strlen (radix char) - 1 bytes + longer than the incoming wide char string has characters. + To fix endptr, reposition end as if the radix char was + just one byte long. The resulting difference (end - buf) + is then equivalent to the number of valid wide characters + in the input string. */ + len = strlen (localeconv ()->decimal_point); + if (len > 1) + { + char *d = strstr (buf, localeconv ()->decimal_point); + + if (d && d < end) + end -= len - 1; + } + + *endptr = (wchar_t *) nptr + (end - buf); + } + + free (buf); + + return val; +#endif /* _LDBL_EQ_DBL */ +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstoll.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstoll.c new file mode 100644 index 0000000000..2c36d6d009 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstoll.c @@ -0,0 +1,139 @@ +/* +FUNCTION + <>---wide string to long long + +INDEX + wcstoll +INDEX + _wcstoll_r + +ANSI_SYNOPSIS + #include + long long wcstoll(const wchar_t *__restrict <[s]>, + wchar_t **__restrict <[ptr]>,int <[base]>); + + long long _wcstoll_r(void *<[reent]>, + const wchar_t *<[s]>, wchar_t **<[ptr]>,int <[base]>); + +TRAD_SYNOPSIS + #include + long long wcstoll (<[s]>, <[ptr]>, <[base]>) + const wchar_t *__restrict <[s]>; + wchar_t **__restrict <[ptr]>; + int <[base]>; + + long long _wcstoll_r (<[reent]>, <[s]>, <[ptr]>, <[base]>) + wchar_t *<[reent]>; + const wchar_t *<[s]>; + wchar_t **<[ptr]>; + int <[base]>; + +DESCRIPTION +The function <> converts the wide string <<*<[s]>>> to +a <>. 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 <> 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 <>--<> (or, +equivalently, <>--<>) 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, +<> 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 <> 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 <>. + +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 <>). + +The alternate function <<_wcstoll_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +<> returns the converted value, if any. If no conversion was +made, 0 is returned. + +<> returns <> or <> if the magnitude of +the converted value is too large, and sets <> to <>. + +PORTABILITY +<> 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 +#include +#include +#include +#include + +#ifndef _REENT_ONLY + +long long +_DEFUN (wcstoll, (s, ptr, base), + _CONST wchar_t *__restrict s _AND + wchar_t **__restrict ptr _AND + int base) +{ + return _wcstoll_r (_REENT, s, ptr, base); +} + +#endif diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstoll_r.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstoll_r.c new file mode 100644 index 0000000000..d6baacaf5c --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstoll_r.c @@ -0,0 +1,140 @@ +/* + This code is based on strtoul.c which has the following copyright. + It is used to convert a wide string into a signed long long. + + long long _wcstoll_r (struct _reent *rptr, const wchar_t *s, + wchar_t **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 +#include +#include +#include +#include + +/* + * Convert a wide 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 (_wcstoll_r, (rptr, nptr, endptr, base), + struct _reent *rptr _AND + _CONST wchar_t *nptr _AND + wchar_t **endptr _AND + int base) +{ + register const wchar_t *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 (iswspace(c)); + if (c == L'-') { + neg = 1; + c = *s++; + } else if (c == L'+') + c = *s++; + if ((base == 0 || base == 16) && + c == L'0' && (*s == L'x' || *s == L'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == L'0' ? 8 : 10; + + /* + * 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 (iswdigit(c)) + c -= L'0'; + else if (iswalpha(c)) + c -= iswupper(c) ? L'A' - 10 : L'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX; + rptr->_errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (wchar_t *) (any ? s - 1 : nptr); + return (acc); +} + +#endif /* __GNUC__ */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstombs.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstombs.c new file mode 100644 index 0000000000..b0123a3137 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstombs.c @@ -0,0 +1,83 @@ +/* +FUNCTION +<>---minimal wide char string to multibyte string converter + +INDEX + wcstombs + +ANSI_SYNOPSIS + #include + size_t wcstombs(char *restrict <[s]>, const wchar_t *restrict <[pwc]>, size_t <[n]>); + +TRAD_SYNOPSIS + #include + size_t wcstombs(<[s]>, <[pwc]>, <[n]>) + char *<[s]>; + const wchar_t *<[pwc]>; + size_t <[n]>; + +DESCRIPTION +When _MB_CAPABLE is not defined, this is a minimal ANSI-conforming +implementation of <>. 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 <> returns <<0>> if +<[s]> is <> 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: <> or the +number of bytes that are transferred to <>, not including the +nul terminator. + +If the return value is -1, the state of the <> 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 +<> > 0. + +PORTABILITY +<> is required in the ANSI C standard. However, the precise +effects vary with the locale. + +<> requires no supporting OS subroutines. +*/ + +#ifndef _REENT_ONLY + +#include +#include +#include + +size_t +_DEFUN (wcstombs, (s, pwcs, n), + char *__restrict s _AND + const wchar_t *__restrict pwcs _AND + size_t n) +{ +#ifdef _MB_CAPABLE + mbstate_t state; + state.__count = 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 */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstombs_r.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstombs_r.c new file mode 100644 index 0000000000..3bac8a3374 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstombs_r.c @@ -0,0 +1,48 @@ +#include +#include +#include "local.h" + +size_t +_DEFUN (_wcstombs_r, (reent, s, pwcs, n, state), + struct _reent *r _AND + char *__restrict s _AND + const wchar_t *__restrict pwcs _AND + size_t n _AND + mbstate_t *state) +{ + char *ptr = s; + size_t max = n; + char buff[8]; + int i, bytes, num_to_copy; + + if (s == NULL) + { + size_t num_bytes = 0; + while (*pwcs != 0) + { + bytes = __wctomb (r, buff, *pwcs++, __locale_charset (), state); + if (bytes == -1) + return -1; + num_bytes += bytes; + } + return num_bytes; + } + else + { + while (n > 0) + { + bytes = __wctomb (r, buff, *pwcs, __locale_charset (), 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; + } +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstoul.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstoul.c new file mode 100644 index 0000000000..4b0a95031b --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstoul.c @@ -0,0 +1,207 @@ +/* +FUNCTION + <>---wide string to unsigned long + +INDEX + wcstoul +INDEX + _wcstoul_r + +ANSI_SYNOPSIS + #include + unsigned long wcstoul(const wchar_t *__restrict <[s]>, + wchar_t **__restrict <[ptr]>, int <[base]>); + + unsigned long _wcstoul_r(void *<[reent]>, const wchar_t *<[s]>, + wchar_t **<[ptr]>, int <[base]>); + +TRAD_SYNOPSIS + #include + unsigned long wcstoul(<[s]>, <[ptr]>, <[base]>) + wchar_t *__restrict <[s]>; + wchar_t **__restrict <[ptr]>; + int <[base]>; + + unsigned long _wcstoul_r(<[reent]>, <[s]>, <[ptr]>, <[base]>) + wchar_t *<[reent]>; + wchar_t *<[s]>; + wchar_t **<[ptr]>; + int <[base]>; + +DESCRIPTION +The function <> converts the wide string <<*<[s]>>> to +an <>. 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 <>--<> (or <>--<>) 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, +<> 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 <> 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 <>. + +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 <>). + +The alternate function <<_wcstoul_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + + +RETURNS +<> returns the converted value, if any. If no conversion was +made, <<0>> is returned. + +<> returns <> if the magnitude of the converted +value is too large, and sets <> to <>. + +PORTABILITY +<> is ANSI. + +<> 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 +#include +#include +#include +#include +#include + +/* + * Convert a wide 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 (_wcstoul_r, (rptr, nptr, endptr, base), + struct _reent *rptr _AND + _CONST wchar_t *nptr _AND + wchar_t **endptr _AND + int base) +{ + register const wchar_t *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 (iswspace(c)); + if (c == L'-') { + neg = 1; + c = *s++; + } else if (c == L'+') + c = *s++; + if ((base == 0 || base == 16) && + c == L'0' && (*s == L'x' || *s == L'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == L'0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (iswdigit(c)) + c -= L'0'; + else if (iswalpha(c)) + c -= iswupper(c) ? L'A' - 10 : L'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + rptr->_errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (wchar_t *) (any ? s - 1 : nptr); + return (acc); +} + +#ifndef _REENT_ONLY + +unsigned long +_DEFUN (wcstoul, (s, ptr, base), + _CONST wchar_t *__restrict s _AND + wchar_t **__restrict ptr _AND + int base) +{ + return _wcstoul_r (_REENT, s, ptr, base); +} + +#endif diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstoull.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstoull.c new file mode 100644 index 0000000000..206bb3428b --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstoull.c @@ -0,0 +1,140 @@ +/* +FUNCTION + <>---wide string to unsigned long long + +INDEX + wcstoull +INDEX + _wcstoull_r + +ANSI_SYNOPSIS + #include + unsigned long long wcstoull(const wchar_t *__restrict <[s]>, + wchar_t **__restrict <[ptr]>, int <[base]>); + + unsigned long long _wcstoull_r(void *<[reent]>, const wchar_t *<[s]>, + wchar_t **<[ptr]>, int <[base]>); + +TRAD_SYNOPSIS + #include + unsigned long long wcstoull(<[s]>, <[ptr]>, <[base]>) + wchar_t *__restrict <[s]>; + wchar_t **__restrict <[ptr]>; + int <[base]>; + + unsigned long long _wcstoull_r(<[reent]>, <[s]>, <[ptr]>, <[base]>) + wchar_t *<[reent]>; + wchar_t *<[s]>; + wchar_t **<[ptr]>; + int <[base]>; + +DESCRIPTION +The function <> converts the wide string <<*<[s]>>> to +an <>. 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: an optional sign (<<+>> or <<->>), +a possible <<0x>> indicating hexadecimal radix or a possible <0> indicating +octal 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 <>--<> (or <>--<>) 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, +<> 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 <> 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 <>. + +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 <>). + +The alternate function <<_wcstoull_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + + +RETURNS +<> returns <<0>> and sets <> to <> if the value of +<[base]> is not supported. + +<> returns the converted value, if any. If no conversion was +made, <<0>> is returned. + +<> returns <> if the magnitude of the converted +value is too large, and sets <> to <>. + +PORTABILITY +<> is ANSI. + +<> 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 +#include + +#ifndef _REENT_ONLY + +unsigned long long +_DEFUN (wcstoull, (s, ptr, base), + _CONST wchar_t *__restrict s _AND + wchar_t **__restrict ptr _AND + int base) +{ + return _wcstoull_r (_REENT, s, ptr, base); +} + +#endif diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wcstoull_r.c b/contrib/sdk/sources/newlib/libc/stdlib/wcstoull_r.c new file mode 100644 index 0000000000..abad681a3c --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wcstoull_r.c @@ -0,0 +1,130 @@ +/* + This code is based on wcstoul.c which has the following copyright. + It is used to convert a wide string into an unsigned long long. + + unsigned long long _wcstoull_r (struct _reent *rptr, const wchar_t *s, + wchar_t **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 +#include +#include +#include +#include + +/* Make up for older non-compliant limits.h. (This is a C99/POSIX function, + * and both require ULLONG_MAX in limits.h.) */ +#if !defined(ULLONG_MAX) +# define ULLONG_MAX ULONG_LONG_MAX +#endif + +/* + * Convert a wide 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 (_wcstoull_r, (rptr, nptr, endptr, base), + struct _reent *rptr _AND + _CONST wchar_t *nptr _AND + wchar_t **endptr _AND + int base) +{ + register const wchar_t *s = nptr; + register unsigned long long acc; + register int c; + register unsigned long long cutoff; + register int neg = 0, any, cutlim; + + if(base < 0 || base == 1 || base > 36) { + rptr->_errno = EINVAL; + return(0ULL); + } + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (iswspace(c)); + if (c == L'-') { + neg = 1; + c = *s++; + } else if (c == L'+') + c = *s++; + if ((base == 0 || base == 16) && + c == L'0' && (*s == L'x' || *s == L'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == L'0' ? 8 : 10; + cutoff = (unsigned long long)ULLONG_MAX / (unsigned long long)base; + cutlim = (unsigned long long)ULLONG_MAX % (unsigned long long)base; + for (acc = 0, any = 0;; c = *s++) { + if (iswdigit(c)) + c -= L'0'; + else if (iswalpha(c)) + c -= iswupper(c) ? L'A' - 10 : L'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + rptr->_errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (wchar_t *) (any ? s - 1 : nptr); + return (acc); +} + +#endif /* __GNUC__ */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wctob.c b/contrib/sdk/sources/newlib/libc/stdlib/wctob.c new file mode 100644 index 0000000000..eebaec84f4 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wctob.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include "local.h" + +int +wctob (wint_t wc) +{ + struct _reent *reent; + mbstate_t mbs; + unsigned char pmb[MB_LEN_MAX]; + + if (wc == WEOF) + return EOF; + + /* Put mbs in initial state. */ + memset (&mbs, '\0', sizeof (mbs)); + + reent = _REENT; + _REENT_CHECK_MISC(reent); + + return __wctomb (reent, (char *) pmb, wc, __locale_charset (), &mbs) == 1 + ? (int) pmb[0] : EOF; +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/wctomb.c b/contrib/sdk/sources/newlib/libc/stdlib/wctomb.c new file mode 100644 index 0000000000..8d4ceb8adb --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/wctomb.c @@ -0,0 +1,81 @@ +/* +FUNCTION +<>---minimal wide char to multibyte converter + +INDEX + wctomb + +ANSI_SYNOPSIS + #include + int wctomb(char *<[s]>, wchar_t <[wchar]>); + +TRAD_SYNOPSIS + #include + int wctomb(<[s]>, <[wchar]>) + char *<[s]>; + wchar_t <[wchar]>; + +DESCRIPTION +When _MB_CAPABLE is not defined, this is a minimal ANSI-conforming +implementation of <>. 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 <> modifies <<*<[s]>>> unless <[s]> is a null +pointer or _MB_CAPABLE is defined and <[wchar]> is invalid. + +RETURNS +This implementation of <> returns <<0>> if +<[s]> is <>; 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 +<> is required in the ANSI C standard. However, the precise +effects vary with the locale. + +<> requires no supporting OS subroutines. +*/ + +#ifndef _REENT_ONLY + +#include +#include +#include +#include "local.h" + +int +_DEFUN (wctomb, (s, wchar), + char *s _AND + wchar_t wchar) +{ +#ifdef _MB_CAPABLE + struct _reent *reent = _REENT; + + _REENT_CHECK_MISC(reent); + + return __wctomb (reent, s, wchar, __locale_charset (), + &(_REENT_WCTOMB_STATE(reent))); +#else /* not _MB_CAPABLE */ + if (s == NULL) + return 0; + + /* Verify that wchar is a valid single-byte character. */ + if ((size_t)wchar >= 0x100) { + errno = EILSEQ; + return -1; + } + + *s = (char) wchar; + return 1; +#endif /* not _MB_CAPABLE */ +} + +#endif /* !_REENT_ONLY */