2001-03-27 16:47:33 +04:00
/*************************************************************************
*
* $ Id $
*
* Copyright ( C ) 1998 Bjorn Reese and Daniel Stenberg .
*
* Permission to use , copy , modify , and distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* copyright notice and this permission notice appear in all copies .
*
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES , INCLUDING , WITHOUT LIMITATION , THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE . THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
2001-04-21 20:57:29 +04:00
* A note to trio contributors :
*
2001-03-27 16:47:33 +04:00
* Avoid heap allocation at all costs to ensure that the trio functions
* are async - safe . The exceptions are the printf / fprintf functions , which
* uses fputc , and the asprintf functions and the < alloc > modifier , which
* by design are required to allocate form the heap .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
2001-04-21 20:57:29 +04:00
* TODO :
2001-03-27 16:47:33 +04:00
* - Scan is probably too permissive about its modifiers .
* - C escapes in % # [ ] ?
* - Multibyte characters ( done for format parsing , except scan groups )
* - Complex numbers ? ( C99 _Complex )
* - Boolean values ? ( C99 _Bool )
2003-04-03 19:28:28 +04:00
* - C99 NaN ( n - char - sequence ) missing . The n - char - sequence can be used
* to print the mantissa , e . g . NaN ( 0xc000000000000000 )
2001-03-27 16:47:33 +04:00
* - Should we support the GNU % a alloc modifier ? GNU has an ugly hack
* for % a , because C99 used % a for other purposes . If specified as
* % as or % a [ it is interpreted as the alloc modifier , otherwise as
* the C99 hex - float . This means that you cannot scan % as as a hex - float
* immediately followed by an ' s ' .
2001-06-05 16:46:33 +04:00
* - Scanning of collating symbols .
2001-03-27 16:47:33 +04:00
*/
2001-06-05 16:46:33 +04:00
/*************************************************************************
* Trio include files
*/
2001-08-21 13:23:53 +04:00
# include "triodef.h"
2001-06-05 16:46:33 +04:00
# include "trio.h"
# include "triop.h"
2001-08-21 13:23:53 +04:00
# include "trionan.h"
2002-09-26 02:44:43 +04:00
# if !defined(TRIO_MINIMAL)
# include "triostr.h"
2001-06-05 16:46:33 +04:00
# endif
2002-09-26 02:44:43 +04:00
/**************************************************************************
*
* Definitions
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-04-03 19:28:28 +04:00
# include <math.h>
# include <limits.h>
# include <float.h>
2007-04-17 16:44:58 +04:00
# if (defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) \
| | defined ( USE_MULTIBYTE ) | | TRIO_WIDECHAR ) \
& & ! defined ( _WIN32_WCE )
2001-06-05 16:46:33 +04:00
# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
# if !defined(MB_LEN_MAX)
# define MB_LEN_MAX 6
# endif
# endif
2003-04-03 19:28:28 +04:00
# if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
# define TRIO_COMPILER_SUPPORTS_MSVC_INT
# endif
2007-04-17 16:44:58 +04:00
# if defined(_WIN32_WCE)
# include <wincecompat.h>
# endif
2001-03-27 16:47:33 +04:00
/*************************************************************************
2001-06-05 16:46:33 +04:00
* Generic definitions
2001-03-27 16:47:33 +04:00
*/
2001-06-05 16:46:33 +04:00
# if !(defined(DEBUG) || defined(NDEBUG))
2001-04-21 20:57:29 +04:00
# define NDEBUG
# endif
2003-04-03 19:28:28 +04:00
2001-04-21 20:57:29 +04:00
# include <assert.h>
2001-03-27 16:47:33 +04:00
# include <ctype.h>
2001-06-05 16:46:33 +04:00
# if !defined(TRIO_COMPILER_SUPPORTS_C99)
# define isblank(x) (((x)==32) || ((x)==9))
# endif
2002-09-26 02:44:43 +04:00
# if defined(TRIO_COMPILER_ANCIENT)
# include <varargs.h>
# else
# include <stdarg.h>
# endif
2001-06-05 16:46:33 +04:00
# include <stddef.h>
2007-04-17 16:44:58 +04:00
2013-12-17 11:32:57 +04:00
# if defined( HAVE_ERRNO_H ) || defined( __VMS )
2001-03-27 16:47:33 +04:00
# include <errno.h>
2007-04-17 16:44:58 +04:00
# endif
2001-03-27 16:47:33 +04:00
# ifndef NULL
# define NULL 0
# endif
# define NIL ((char)0)
2001-06-05 16:46:33 +04:00
# ifndef FALSE
# define FALSE (1 == 0)
# define TRUE (! FALSE)
2001-03-27 16:47:33 +04:00
# endif
2001-06-05 16:46:33 +04:00
# define BOOLEAN_T int
2001-03-27 16:47:33 +04:00
/* mincore() can be used for debugging purposes */
# define VALID(x) (NULL != (x))
2002-09-26 02:44:43 +04:00
# if TRIO_ERRORS
/*
* Encode the error code and the position . This is decoded
* with TRIO_ERROR_CODE and TRIO_ERROR_POSITION .
*/
# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
# else
# define TRIO_ERROR_RETURN(x,y) (-1)
# endif
2001-06-05 16:46:33 +04:00
2013-12-12 11:04:43 +04:00
# ifndef VA_LIST_IS_ARRAY
# define TRIO_VA_LIST_PTR va_list *
# define TRIO_VA_LIST_ADDR(l) (&(l))
# define TRIO_VA_LIST_DEREF(l) (*(l))
# else
# define TRIO_VA_LIST_PTR va_list
# define TRIO_VA_LIST_ADDR(l) (l)
# define TRIO_VA_LIST_DEREF(l) (l)
# endif
2003-04-03 19:28:28 +04:00
typedef unsigned long trio_flags_t ;
2001-06-05 16:46:33 +04:00
/*************************************************************************
* Platform specific definitions
2001-03-27 16:47:33 +04:00
*/
2013-12-12 11:04:43 +04:00
# if defined(TRIO_PLATFORM_UNIX) || defined(TRIO_PLATFORM_OS400)
2001-06-05 16:46:33 +04:00
# include <unistd.h>
# include <signal.h>
# include <locale.h>
# define USE_LOCALE
2002-01-19 18:40:18 +03:00
# endif /* TRIO_PLATFORM_UNIX */
# if defined(TRIO_PLATFORM_VMS)
# include <unistd.h>
# endif
# if defined(TRIO_PLATFORM_WIN32)
2007-04-17 16:44:58 +04:00
# if defined(_WIN32_WCE)
# include <wincecompat.h>
# else
# include <io.h>
# define read _read
# define write _write
# endif
2002-01-19 18:40:18 +03:00
# endif /* TRIO_PLATFORM_WIN32 */
2001-06-05 16:46:33 +04:00
# if TRIO_WIDECHAR
# if defined(TRIO_COMPILER_SUPPORTS_ISO94)
# include <wchar.h>
# include <wctype.h>
2002-09-26 02:44:43 +04:00
typedef wchar_t trio_wchar_t ;
typedef wint_t trio_wint_t ;
2001-06-05 16:46:33 +04:00
# else
2002-09-26 02:44:43 +04:00
typedef char trio_wchar_t ;
typedef int trio_wint_t ;
2002-01-19 18:40:18 +03:00
# define WCONST(x) L ## x
2001-06-05 16:46:33 +04:00
# define WEOF EOF
# define iswalnum(x) isalnum(x)
# define iswalpha(x) isalpha(x)
# define iswblank(x) isblank(x)
# define iswcntrl(x) iscntrl(x)
# define iswdigit(x) isdigit(x)
# define iswgraph(x) isgraph(x)
# define iswlower(x) islower(x)
# define iswprint(x) isprint(x)
# define iswpunct(x) ispunct(x)
# define iswspace(x) isspace(x)
# define iswupper(x) isupper(x)
# define iswxdigit(x) isxdigit(x)
# endif
2001-03-27 16:47:33 +04:00
# endif
2001-06-05 16:46:33 +04:00
2001-03-27 16:47:33 +04:00
/*************************************************************************
2001-06-05 16:46:33 +04:00
* Compiler dependent definitions
2001-03-27 16:47:33 +04:00
*/
2001-06-05 16:46:33 +04:00
/* Support for long long */
# ifndef __cplusplus
# if !defined(USE_LONGLONG)
2002-01-19 18:40:18 +03:00
# if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
2001-06-05 16:46:33 +04:00
# define USE_LONGLONG
2002-01-19 18:40:18 +03:00
# elif defined(TRIO_COMPILER_SUNPRO)
2001-06-05 16:46:33 +04:00
# define USE_LONGLONG
# elif defined(_LONG_LONG) || defined(_LONGLONG)
# define USE_LONGLONG
# endif
2001-03-27 16:47:33 +04:00
# endif
# endif
/* The extra long numbers */
# if defined(USE_LONGLONG)
2001-06-05 16:46:33 +04:00
typedef signed long long int trio_longlong_t ;
typedef unsigned long long int trio_ulonglong_t ;
2003-04-03 19:28:28 +04:00
# elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
2001-06-05 16:46:33 +04:00
typedef signed __int64 trio_longlong_t ;
typedef unsigned __int64 trio_ulonglong_t ;
# else
2002-09-26 02:44:43 +04:00
typedef TRIO_SIGNED long int trio_longlong_t ;
2001-06-05 16:46:33 +04:00
typedef unsigned long int trio_ulonglong_t ;
# endif
/* Maximal and fixed integer types */
2013-12-17 11:32:57 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_C99) && !defined( __VMS )
2001-06-05 16:46:33 +04:00
# include <stdint.h>
typedef intmax_t trio_intmax_t ;
typedef uintmax_t trio_uintmax_t ;
typedef int8_t trio_int8_t ;
typedef int16_t trio_int16_t ;
typedef int32_t trio_int32_t ;
typedef int64_t trio_int64_t ;
2013-12-17 11:32:57 +04:00
# elif defined(TRIO_COMPILER_SUPPORTS_UNIX98) || defined( __VMS )
2001-06-05 16:46:33 +04:00
# include <inttypes.h>
2013-12-17 11:32:57 +04:00
# ifdef __VMS
typedef long long int intmax_t ;
typedef unsigned long long int uintmax_t ;
# endif
2001-06-05 16:46:33 +04:00
typedef intmax_t trio_intmax_t ;
typedef uintmax_t trio_uintmax_t ;
typedef int8_t trio_int8_t ;
typedef int16_t trio_int16_t ;
typedef int32_t trio_int32_t ;
typedef int64_t trio_int64_t ;
2003-04-03 19:28:28 +04:00
# elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
2001-06-05 16:46:33 +04:00
typedef trio_longlong_t trio_intmax_t ;
typedef trio_ulonglong_t trio_uintmax_t ;
typedef __int8 trio_int8_t ;
typedef __int16 trio_int16_t ;
typedef __int32 trio_int32_t ;
typedef __int64 trio_int64_t ;
2001-03-27 16:47:33 +04:00
# else
2001-06-05 16:46:33 +04:00
typedef trio_longlong_t trio_intmax_t ;
typedef trio_ulonglong_t trio_uintmax_t ;
# if defined(TRIO_INT8_T)
typedef TRIO_INT8_T trio_int8_t ;
# else
2002-09-26 02:44:43 +04:00
typedef TRIO_SIGNED char trio_int8_t ;
2001-06-05 16:46:33 +04:00
# endif
# if defined(TRIO_INT16_T)
typedef TRIO_INT16_T trio_int16_t ;
# else
2002-09-26 02:44:43 +04:00
typedef TRIO_SIGNED short trio_int16_t ;
2001-06-05 16:46:33 +04:00
# endif
# if defined(TRIO_INT32_T)
typedef TRIO_INT32_T trio_int32_t ;
# else
2002-09-26 02:44:43 +04:00
typedef TRIO_SIGNED int trio_int32_t ;
2001-06-05 16:46:33 +04:00
# endif
# if defined(TRIO_INT64_T)
typedef TRIO_INT64_T trio_int64_t ;
# else
typedef trio_longlong_t trio_int64_t ;
# endif
2001-03-27 16:47:33 +04:00
# endif
2007-04-17 16:44:58 +04:00
# if (!(defined(TRIO_COMPILER_SUPPORTS_C99) \
| | defined ( TRIO_COMPILER_SUPPORTS_UNIX01 ) ) ) \
& & ! defined ( _WIN32_WCE )
2002-09-26 02:44:43 +04:00
# define floorl(x) floor((double)(x))
# define fmodl(x,y) fmod((double)(x),(double)(y))
# define powl(x,y) pow((double)(x),(double)(y))
# endif
# define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
2001-06-05 16:46:33 +04:00
/*************************************************************************
2002-09-26 02:44:43 +04:00
* Internal Definitions
2001-06-05 16:46:33 +04:00
*/
2002-09-26 02:44:43 +04:00
# ifndef DECIMAL_DIG
# define DECIMAL_DIG DBL_DIG
# endif
2001-06-05 16:46:33 +04:00
/* Long double sizes */
# ifdef LDBL_DIG
# define MAX_MANTISSA_DIGITS LDBL_DIG
# define MAX_EXPONENT_DIGITS 4
2002-09-26 02:44:43 +04:00
# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
2001-03-27 16:47:33 +04:00
# else
2002-09-26 02:44:43 +04:00
# define MAX_MANTISSA_DIGITS DECIMAL_DIG
2001-06-05 16:46:33 +04:00
# define MAX_EXPONENT_DIGITS 3
2002-09-26 02:44:43 +04:00
# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
# endif
# if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
# undef LDBL_DIG
# undef LDBL_MANT_DIG
# undef LDBL_EPSILON
# define LDBL_DIG DBL_DIG
# define LDBL_MANT_DIG DBL_MANT_DIG
# define LDBL_EPSILON DBL_EPSILON
2001-03-27 16:47:33 +04:00
# endif
2001-06-05 16:46:33 +04:00
/* The maximal number of digits is for base 2 */
# define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
2001-03-27 16:47:33 +04:00
/* The width of a pointer. The number of bits in a hex digit is 4 */
2002-09-26 02:44:43 +04:00
# define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
2001-03-27 16:47:33 +04:00
/* Infinite and Not-A-Number for floating-point */
2001-04-21 20:57:29 +04:00
# define INFINITE_LOWER "inf"
# define INFINITE_UPPER "INF"
# define LONG_INFINITE_LOWER "infinite"
# define LONG_INFINITE_UPPER "INFINITE"
# define NAN_LOWER "nan"
# define NAN_UPPER "NAN"
2001-03-27 16:47:33 +04:00
Various "make distcheck" and portability fixups
Makefile.am:
* Don't use @VAR@, use $(VAR). Autoconf's AC_SUBST provides us the Make
variable, it allows overriding the value at the command line, and
(notably) it avoids a Make parse error in the libxml2_la_LDFLAGS
assignment when @MODULE_PLATFORM_LIBS@ is empty
* Changed how the THREADS_W32 mechanism switches the build between
testThreads.c and testThreadsWin32.c as appropriate; using AM_CONDITIONAL
allows this to work cleanly and plays well with dependencies
* testapi.c should be specified as BUILT_SOURCES
* Create symlinks to the test/ and result/ subdirs so that the runtests
target is usable in out-of-source-tree builds
* Don't do MAKEFLAGS+=--silent as this is not portable to non-GNU Makes
* Fixed incorrect find(1) syntax in the "cleanup" rule, and doing "rm -f"
instead of just "rm" is good form
* (DIST)CLEANFILES needed a bit more coverage to allow "make distcheck" to
pass
configure.in:
* Need AC_PROG_LN_S to create test/ and result/ symlinks in Makefile.am
* AC_LIBTOOL_WIN32_DLL and AM_PROG_LIBTOOL are obsolete; these have been
superceded by LT_INIT
* Don't rebuild docs by default, as this requires GNU Make (as
implemented)
* Check for uint32_t as some platforms don't provide it
* Check for some more functions, and undefine HAVE_MMAP if we don't also
HAVE_MUNMAP (one system I tested on actually needed this)
* Changed THREADS_W32 from a filename insert into an Automake conditional
* The "Copyright" file will not be in the current directory if builddir !=
srcdir
doc/Makefile.am:
* EXTRA_DIST cannot use wildcards when they refer to generated files; this
breaks dependencies. What I did was define EXTRA_DIST_wc, which uses GNU
Make $(wildcard) directives to build up a list of files, and EXTRA_DIST,
as a literal expansion of EXTRA_DIST_wc. I also added a new rule,
"check-extra-dist", to simplify checking that the two variables are
equivalent. (Note that this works only when builddir == srcdir)
(I can implement this differently if desired; this is just one way of
doing it)
* Don't define an "all" target; this steps on Automake's toes
* Fixed up the "libxml2-api.xml ..." rule by using $(wildcard) for
dependencies (as Make doesn't process the wildcards otherwise) and
qualifying appropriate files with $(srcdir)
(Note that $(srcdir) is not needed in the dependencies, thanks to VPATH,
which we can count on as this is GNU-Make-only code anyway)
doc/devhelp/Makefile.am:
* Qualified appropriate files with $(srcdir)
* Added an "uninstall-local" rule so that "make distcheck" passes
doc/examples/Makefile.am:
* Rather than use a wildcard that doesn't work, use a substitution that
most Make programs can handle
doc/examples/index.py:
* Do the same here
include/libxml/nanoftp.h:
* Some platforms (e.g. MSVC 6) already #define INVALID_SOCKET:
user@host:/cygdrive/c/Program Files/Microsoft Visual Studio/VC98/\
Include$ grep -R INVALID_SOCKET .
./WINSOCK.H:#define INVALID_SOCKET (SOCKET)(~0)
./WINSOCK2.H:#define INVALID_SOCKET (SOCKET)(~0)
include/libxml/xmlversion.h.in:
* Support ancient GCCs (I was actually able to build the library with 2.5
but for this bit)
python/Makefile.am:
* Expanded CLEANFILES to allow "make distcheck" to pass
python/tests/Makefile.am:
* Define CLEANFILES instead of a "clean" rule, and added tmp.xml to allow
"make distcheck" to pass
testRelax.c:
* Use HAVE_MMAP instead of the less explicit HAVE_SYS_MMAN_H (as some
systems have the header but not the function)
testSchemas.c:
* Use HAVE_MMAP instead of the less explicit HAVE_SYS_MMAN_H
testapi.c:
* Don't use putenv() if it's not available
threads.c:
* This fixes the following build error on Solaris 8:
libtool: compile: cc -DHAVE_CONFIG_H -I. -I./include -I./include \
-D_REENTRANT -D__EXTENSIONS__ -D_REENTRANT -Dsparc -Xa -mt -v \
-xarch=v9 -xcrossfile -xO5 -c threads.c -KPIC -DPIC -o threads.o
"threads.c", line 442: controlling expressions must have scalar type
"threads.c", line 512: controlling expressions must have scalar type
cc: acomp failed for threads.c
*** Error code 1
trio.c:
* Define isascii() if the system doesn't provide it
trio.h:
* The trio library's HAVE_CONFIG_H header is not the same as LibXML2's
HAVE_CONFIG_H header; this change is needed to avoid a double-inclusion
win32/configure.js:
* Added support for the LZMA compression option
win32/Makefile.{bcb,mingw,msvc}:
* Added appropriate bits to support WITH_LZMA=1
* Install the header files under $(INCPREFIX)\libxml2\libxml instead of
$(INCPREFIX)\libxml, to mirror the install location on Unix+Autotools
xml2-config.in:
* @MODULE_PLATFORM_LIBS@ (usually "-ldl") needs to be in there in order for
`xml2-config --libs` to provide a complete set of dependencies
xmllint.c:
* Use HAVE_MMAP instead of the less-explicit HAVE_SYS_MMAN_H
2012-08-06 07:32:54 +04:00
# if !defined(HAVE_ISASCII) && !defined(isascii)
2013-12-17 11:32:57 +04:00
# ifndef __VMS
# define isascii(x) ((unsigned int)(x) < 128)
# endif
Various "make distcheck" and portability fixups
Makefile.am:
* Don't use @VAR@, use $(VAR). Autoconf's AC_SUBST provides us the Make
variable, it allows overriding the value at the command line, and
(notably) it avoids a Make parse error in the libxml2_la_LDFLAGS
assignment when @MODULE_PLATFORM_LIBS@ is empty
* Changed how the THREADS_W32 mechanism switches the build between
testThreads.c and testThreadsWin32.c as appropriate; using AM_CONDITIONAL
allows this to work cleanly and plays well with dependencies
* testapi.c should be specified as BUILT_SOURCES
* Create symlinks to the test/ and result/ subdirs so that the runtests
target is usable in out-of-source-tree builds
* Don't do MAKEFLAGS+=--silent as this is not portable to non-GNU Makes
* Fixed incorrect find(1) syntax in the "cleanup" rule, and doing "rm -f"
instead of just "rm" is good form
* (DIST)CLEANFILES needed a bit more coverage to allow "make distcheck" to
pass
configure.in:
* Need AC_PROG_LN_S to create test/ and result/ symlinks in Makefile.am
* AC_LIBTOOL_WIN32_DLL and AM_PROG_LIBTOOL are obsolete; these have been
superceded by LT_INIT
* Don't rebuild docs by default, as this requires GNU Make (as
implemented)
* Check for uint32_t as some platforms don't provide it
* Check for some more functions, and undefine HAVE_MMAP if we don't also
HAVE_MUNMAP (one system I tested on actually needed this)
* Changed THREADS_W32 from a filename insert into an Automake conditional
* The "Copyright" file will not be in the current directory if builddir !=
srcdir
doc/Makefile.am:
* EXTRA_DIST cannot use wildcards when they refer to generated files; this
breaks dependencies. What I did was define EXTRA_DIST_wc, which uses GNU
Make $(wildcard) directives to build up a list of files, and EXTRA_DIST,
as a literal expansion of EXTRA_DIST_wc. I also added a new rule,
"check-extra-dist", to simplify checking that the two variables are
equivalent. (Note that this works only when builddir == srcdir)
(I can implement this differently if desired; this is just one way of
doing it)
* Don't define an "all" target; this steps on Automake's toes
* Fixed up the "libxml2-api.xml ..." rule by using $(wildcard) for
dependencies (as Make doesn't process the wildcards otherwise) and
qualifying appropriate files with $(srcdir)
(Note that $(srcdir) is not needed in the dependencies, thanks to VPATH,
which we can count on as this is GNU-Make-only code anyway)
doc/devhelp/Makefile.am:
* Qualified appropriate files with $(srcdir)
* Added an "uninstall-local" rule so that "make distcheck" passes
doc/examples/Makefile.am:
* Rather than use a wildcard that doesn't work, use a substitution that
most Make programs can handle
doc/examples/index.py:
* Do the same here
include/libxml/nanoftp.h:
* Some platforms (e.g. MSVC 6) already #define INVALID_SOCKET:
user@host:/cygdrive/c/Program Files/Microsoft Visual Studio/VC98/\
Include$ grep -R INVALID_SOCKET .
./WINSOCK.H:#define INVALID_SOCKET (SOCKET)(~0)
./WINSOCK2.H:#define INVALID_SOCKET (SOCKET)(~0)
include/libxml/xmlversion.h.in:
* Support ancient GCCs (I was actually able to build the library with 2.5
but for this bit)
python/Makefile.am:
* Expanded CLEANFILES to allow "make distcheck" to pass
python/tests/Makefile.am:
* Define CLEANFILES instead of a "clean" rule, and added tmp.xml to allow
"make distcheck" to pass
testRelax.c:
* Use HAVE_MMAP instead of the less explicit HAVE_SYS_MMAN_H (as some
systems have the header but not the function)
testSchemas.c:
* Use HAVE_MMAP instead of the less explicit HAVE_SYS_MMAN_H
testapi.c:
* Don't use putenv() if it's not available
threads.c:
* This fixes the following build error on Solaris 8:
libtool: compile: cc -DHAVE_CONFIG_H -I. -I./include -I./include \
-D_REENTRANT -D__EXTENSIONS__ -D_REENTRANT -Dsparc -Xa -mt -v \
-xarch=v9 -xcrossfile -xO5 -c threads.c -KPIC -DPIC -o threads.o
"threads.c", line 442: controlling expressions must have scalar type
"threads.c", line 512: controlling expressions must have scalar type
cc: acomp failed for threads.c
*** Error code 1
trio.c:
* Define isascii() if the system doesn't provide it
trio.h:
* The trio library's HAVE_CONFIG_H header is not the same as LibXML2's
HAVE_CONFIG_H header; this change is needed to avoid a double-inclusion
win32/configure.js:
* Added support for the LZMA compression option
win32/Makefile.{bcb,mingw,msvc}:
* Added appropriate bits to support WITH_LZMA=1
* Install the header files under $(INCPREFIX)\libxml2\libxml instead of
$(INCPREFIX)\libxml, to mirror the install location on Unix+Autotools
xml2-config.in:
* @MODULE_PLATFORM_LIBS@ (usually "-ldl") needs to be in there in order for
`xml2-config --libs` to provide a complete set of dependencies
xmllint.c:
* Use HAVE_MMAP instead of the less-explicit HAVE_SYS_MMAN_H
2012-08-06 07:32:54 +04:00
# endif
2001-03-27 16:47:33 +04:00
/* Various constants */
enum {
TYPE_PRINT = 1 ,
TYPE_SCAN = 2 ,
2003-04-03 19:28:28 +04:00
/* Flags. FLAGS_LAST must be less than ULONG_MAX */
2001-03-27 16:47:33 +04:00
FLAGS_NEW = 0 ,
FLAGS_STICKY = 1 ,
FLAGS_SPACE = 2 * FLAGS_STICKY ,
FLAGS_SHOWSIGN = 2 * FLAGS_SPACE ,
FLAGS_LEFTADJUST = 2 * FLAGS_SHOWSIGN ,
FLAGS_ALTERNATIVE = 2 * FLAGS_LEFTADJUST ,
FLAGS_SHORT = 2 * FLAGS_ALTERNATIVE ,
FLAGS_SHORTSHORT = 2 * FLAGS_SHORT ,
FLAGS_LONG = 2 * FLAGS_SHORTSHORT ,
FLAGS_QUAD = 2 * FLAGS_LONG ,
FLAGS_LONGDOUBLE = 2 * FLAGS_QUAD ,
FLAGS_SIZE_T = 2 * FLAGS_LONGDOUBLE ,
FLAGS_PTRDIFF_T = 2 * FLAGS_SIZE_T ,
FLAGS_INTMAX_T = 2 * FLAGS_PTRDIFF_T ,
FLAGS_NILPADDING = 2 * FLAGS_INTMAX_T ,
FLAGS_UNSIGNED = 2 * FLAGS_NILPADDING ,
FLAGS_UPPER = 2 * FLAGS_UNSIGNED ,
FLAGS_WIDTH = 2 * FLAGS_UPPER ,
FLAGS_WIDTH_PARAMETER = 2 * FLAGS_WIDTH ,
FLAGS_PRECISION = 2 * FLAGS_WIDTH_PARAMETER ,
FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION ,
FLAGS_BASE = 2 * FLAGS_PRECISION_PARAMETER ,
FLAGS_BASE_PARAMETER = 2 * FLAGS_BASE ,
FLAGS_FLOAT_E = 2 * FLAGS_BASE_PARAMETER ,
FLAGS_FLOAT_G = 2 * FLAGS_FLOAT_E ,
FLAGS_QUOTE = 2 * FLAGS_FLOAT_G ,
FLAGS_WIDECHAR = 2 * FLAGS_QUOTE ,
FLAGS_ALLOC = 2 * FLAGS_WIDECHAR ,
FLAGS_IGNORE = 2 * FLAGS_ALLOC ,
FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE ,
2001-06-05 16:46:33 +04:00
FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER ,
FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER ,
2003-04-03 19:28:28 +04:00
FLAGS_LAST = FLAGS_FIXED_SIZE ,
2001-03-27 16:47:33 +04:00
/* Reused flags */
FLAGS_EXCLUDE = FLAGS_SHORT ,
2001-04-21 20:57:29 +04:00
FLAGS_USER_DEFINED = FLAGS_IGNORE ,
2002-09-26 02:44:43 +04:00
FLAGS_ROUNDING = FLAGS_INTMAX_T ,
2001-03-27 16:47:33 +04:00
/* Compounded flags */
2001-04-21 20:57:29 +04:00
FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T ,
2001-06-05 16:46:33 +04:00
FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT ,
2001-03-27 16:47:33 +04:00
NO_POSITION = - 1 ,
NO_WIDTH = 0 ,
NO_PRECISION = - 1 ,
NO_SIZE = - 1 ,
2002-09-26 02:44:43 +04:00
/* Do not change these */
2001-03-27 16:47:33 +04:00
NO_BASE = - 1 ,
MIN_BASE = 2 ,
MAX_BASE = 36 ,
BASE_BINARY = 2 ,
BASE_OCTAL = 8 ,
BASE_DECIMAL = 10 ,
BASE_HEX = 16 ,
/* Maximal number of allowed parameters */
MAX_PARAMETERS = 64 ,
/* Maximal number of characters in class */
2002-01-19 18:40:18 +03:00
MAX_CHARACTER_CLASS = UCHAR_MAX + 1 ,
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
/* Maximal string lengths for user-defined specifiers */
MAX_USER_NAME = 64 ,
MAX_USER_DATA = 256 ,
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* Maximal length of locale separator strings */
2001-06-05 16:46:33 +04:00
MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX ,
2001-03-27 16:47:33 +04:00
/* Maximal number of integers in grouping */
2002-01-19 18:40:18 +03:00
MAX_LOCALE_GROUPS = 64 ,
/* Initial size of asprintf buffer */
DYNAMIC_START_SIZE = 32
2001-03-27 16:47:33 +04:00
} ;
# define NO_GROUPING ((int)CHAR_MAX)
/* Fundamental formatting parameter types */
# define FORMAT_UNKNOWN 0
# define FORMAT_INT 1
# define FORMAT_DOUBLE 2
# define FORMAT_CHAR 3
# define FORMAT_STRING 4
# define FORMAT_POINTER 5
# define FORMAT_COUNT 6
# define FORMAT_PARAMETER 7
# define FORMAT_GROUP 8
2001-06-05 16:46:33 +04:00
# if TRIO_GNU
2001-04-21 20:57:29 +04:00
# define FORMAT_ERRNO 9
# endif
2001-06-05 16:46:33 +04:00
# if TRIO_EXTENSION
2001-04-21 20:57:29 +04:00
# define FORMAT_USER_DEFINED 10
2001-03-27 16:47:33 +04:00
# endif
/* Character constants */
# define CHAR_IDENTIFIER '%'
# define CHAR_BACKSLASH '\\'
# define CHAR_QUOTE '\"'
# define CHAR_ADJUST ' '
/* Character class expressions */
2002-09-26 02:44:43 +04:00
# define CLASS_ALNUM "[:alnum:]"
# define CLASS_ALPHA "[:alpha:]"
# define CLASS_BLANK "[:blank:]"
# define CLASS_CNTRL "[:cntrl:]"
# define CLASS_DIGIT "[:digit:]"
# define CLASS_GRAPH "[:graph:]"
# define CLASS_LOWER "[:lower:]"
# define CLASS_PRINT "[:print:]"
# define CLASS_PUNCT "[:punct:]"
# define CLASS_SPACE "[:space:]"
# define CLASS_UPPER "[:upper:]"
# define CLASS_XDIGIT "[:xdigit:]"
2001-03-27 16:47:33 +04:00
/*
* SPECIFIERS :
*
*
* a Hex - float
* A Hex - float
* c Character
* C Widechar character ( wint_t )
* d Decimal
* e Float
* E Float
* F Float
* F Float
* g Float
* G Float
* i Integer
* m Error message
* n Count
* o Octal
* p Pointer
* s String
2001-06-05 16:46:33 +04:00
* S Widechar string ( wchar_t * )
2001-03-27 16:47:33 +04:00
* u Unsigned
* x Hex
* X Hex
2001-04-21 20:57:29 +04:00
* [ ] Group
* < > User - defined
2001-03-27 16:47:33 +04:00
*
* Reserved :
*
* D Binary Coded Decimal % D ( length , precision ) ( OS / 390 )
*/
# define SPECIFIER_CHAR 'c'
# define SPECIFIER_STRING 's'
# define SPECIFIER_DECIMAL 'd'
# define SPECIFIER_INTEGER 'i'
# define SPECIFIER_UNSIGNED 'u'
# define SPECIFIER_OCTAL 'o'
# define SPECIFIER_HEX 'x'
# define SPECIFIER_HEX_UPPER 'X'
# define SPECIFIER_FLOAT_E 'e'
# define SPECIFIER_FLOAT_E_UPPER 'E'
# define SPECIFIER_FLOAT_F 'f'
# define SPECIFIER_FLOAT_F_UPPER 'F'
# define SPECIFIER_FLOAT_G 'g'
# define SPECIFIER_FLOAT_G_UPPER 'G'
# define SPECIFIER_POINTER 'p'
# define SPECIFIER_GROUP '['
# define SPECIFIER_UNGROUP ']'
# define SPECIFIER_COUNT 'n'
2001-06-05 16:46:33 +04:00
# if TRIO_UNIX98
2001-03-27 16:47:33 +04:00
# define SPECIFIER_CHAR_UPPER 'C'
# define SPECIFIER_STRING_UPPER 'S'
# endif
2001-06-05 16:46:33 +04:00
# if TRIO_C99
2001-03-27 16:47:33 +04:00
# define SPECIFIER_HEXFLOAT 'a'
# define SPECIFIER_HEXFLOAT_UPPER 'A'
# endif
2001-06-05 16:46:33 +04:00
# if TRIO_GNU
2001-03-27 16:47:33 +04:00
# define SPECIFIER_ERRNO 'm'
# endif
2001-06-05 16:46:33 +04:00
# if TRIO_EXTENSION
2001-03-27 16:47:33 +04:00
# define SPECIFIER_BINARY 'b'
# define SPECIFIER_BINARY_UPPER 'B'
2001-04-21 20:57:29 +04:00
# define SPECIFIER_USER_DEFINED_BEGIN '<'
# define SPECIFIER_USER_DEFINED_END '>'
# define SPECIFIER_USER_DEFINED_SEPARATOR ':'
2001-03-27 16:47:33 +04:00
# endif
/*
* QUALIFIERS :
*
*
* Numbers = d , i , o , u , x , X
* Float = a , A , e , E , f , F , g , G
* String = s
* Char = c
*
*
* 9 $ Position
* Use the 9 th parameter . 9 can be any number between 1 and
* the maximal argument
*
* 9 Width
* Set width to 9. 9 can be any number , but must not be postfixed
* by ' $ '
*
* h Short
* Numbers :
* ( unsigned ) short int
*
* hh Short short
* Numbers :
* ( unsigned ) char
*
* l Long
* Numbers :
* ( unsigned ) long int
* String :
* as the S specifier
* Char :
* as the C specifier
*
* ll Long Long
* Numbers :
* ( unsigned ) long long int
*
* L Long Double
* Float
* long double
*
* # Alternative
* Float :
* Decimal - point is always present
* String :
* non - printable characters are handled as \ number
*
* Spacing
*
* + Sign
*
* - Alignment
*
* . Precision
*
* * Parameter
* print : use parameter
* scan : no parameter ( ignore )
*
* q Quad
*
* Z size_t
*
* w Widechar
*
* ' Thousands / quote
* Numbers :
* Integer part grouped in thousands
* Binary numbers :
* Number grouped in nibbles ( 4 bits )
* String :
* Quoted string
*
* j intmax_t
* t prtdiff_t
* z size_t
*
* ! Sticky
* @ Parameter ( for both print and scan )
2001-06-05 16:46:33 +04:00
*
* I n - bit Integer
* Numbers :
* The following options exists
* I8 = 8 - bit integer
* I16 = 16 - bit integer
* I32 = 32 - bit integer
* I64 = 64 - bit integer
2001-03-27 16:47:33 +04:00
*/
# define QUALIFIER_POSITION '$'
# define QUALIFIER_SHORT 'h'
# define QUALIFIER_LONG 'l'
# define QUALIFIER_LONG_UPPER 'L'
# define QUALIFIER_ALTERNATIVE '#'
# define QUALIFIER_SPACE ' '
# define QUALIFIER_PLUS '+'
# define QUALIFIER_MINUS '-'
# define QUALIFIER_DOT '.'
# define QUALIFIER_STAR '*'
2002-09-26 02:44:43 +04:00
# define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
2001-06-05 16:46:33 +04:00
# if TRIO_C99
2001-03-27 16:47:33 +04:00
# define QUALIFIER_SIZE_T 'z'
# define QUALIFIER_PTRDIFF_T 't'
# define QUALIFIER_INTMAX_T 'j'
# endif
2001-06-05 16:46:33 +04:00
# if TRIO_BSD || TRIO_GNU
2001-03-27 16:47:33 +04:00
# define QUALIFIER_QUAD 'q'
# endif
2001-06-05 16:46:33 +04:00
# if TRIO_GNU
2001-03-27 16:47:33 +04:00
# define QUALIFIER_SIZE_T_UPPER 'Z'
# endif
2001-06-05 16:46:33 +04:00
# if TRIO_MISC
2001-03-27 16:47:33 +04:00
# define QUALIFIER_WIDECHAR 'w'
# endif
2001-06-05 16:46:33 +04:00
# if TRIO_MICROSOFT
# define QUALIFIER_FIXED_SIZE 'I'
# endif
# if TRIO_EXTENSION
2001-03-27 16:47:33 +04:00
# define QUALIFIER_QUOTE '\''
# define QUALIFIER_STICKY '!'
# define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
# define QUALIFIER_PARAM '@' /* Experimental */
# define QUALIFIER_COLON ':' /* For scanlists */
2001-06-05 16:46:33 +04:00
# define QUALIFIER_EQUAL '=' /* For scanlists */
2002-09-26 02:44:43 +04:00
# define QUALIFIER_ROUNDING_UPPER 'R'
2001-03-27 16:47:33 +04:00
# endif
2001-04-21 20:57:29 +04:00
/*************************************************************************
2002-09-26 02:44:43 +04:00
*
* Internal Structures
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-04-21 20:57:29 +04:00
/* Parameters */
2001-03-27 16:47:33 +04:00
typedef struct {
2002-01-19 18:40:18 +03:00
/* An indication of which entry in the data union is used */
2001-03-27 16:47:33 +04:00
int type ;
2002-01-19 18:40:18 +03:00
/* The flags */
2003-04-03 19:28:28 +04:00
trio_flags_t flags ;
2002-01-19 18:40:18 +03:00
/* The width qualifier */
2001-03-27 16:47:33 +04:00
int width ;
2002-01-19 18:40:18 +03:00
/* The precision qualifier */
2001-04-21 20:57:29 +04:00
int precision ;
2002-01-19 18:40:18 +03:00
/* The base qualifier */
2001-03-27 16:47:33 +04:00
int base ;
2002-01-19 18:40:18 +03:00
/* The size for the variable size qualifier */
2001-03-27 16:47:33 +04:00
int varsize ;
2002-01-19 18:40:18 +03:00
/* The marker of the end of the specifier */
2001-03-27 16:47:33 +04:00
int indexAfterSpecifier ;
2002-01-19 18:40:18 +03:00
/* The data from the argument list */
2001-03-27 16:47:33 +04:00
union {
char * string ;
2001-06-05 16:46:33 +04:00
# if TRIO_WIDECHAR
2002-09-26 02:44:43 +04:00
trio_wchar_t * wstring ;
2001-06-05 16:46:33 +04:00
# endif
2002-09-26 02:44:43 +04:00
trio_pointer_t pointer ;
2001-03-27 16:47:33 +04:00
union {
2002-09-26 02:44:43 +04:00
trio_intmax_t as_signed ;
trio_uintmax_t as_unsigned ;
2001-03-27 16:47:33 +04:00
} number ;
double doubleNumber ;
double * doublePointer ;
2002-09-26 02:44:43 +04:00
trio_long_double_t longdoubleNumber ;
trio_long_double_t * longdoublePointer ;
2001-03-27 16:47:33 +04:00
int errorNumber ;
} data ;
2001-04-21 20:57:29 +04:00
/* For the user-defined specifier */
char user_name [ MAX_USER_NAME ] ;
char user_data [ MAX_USER_DATA ] ;
2002-01-19 18:40:18 +03:00
} trio_parameter_t ;
2001-03-27 16:47:33 +04:00
2002-09-26 02:44:43 +04:00
/* Container for customized functions */
typedef struct {
union {
trio_outstream_t out ;
trio_instream_t in ;
} stream ;
trio_pointer_t closure ;
} trio_custom_t ;
2001-04-21 20:57:29 +04:00
/* General trio "class" */
2002-01-19 18:40:18 +03:00
typedef struct _trio_class_t {
/*
* The function to write characters to a stream .
*/
2002-09-26 02:44:43 +04:00
void ( * OutStream ) TRIO_PROTO ( ( struct _trio_class_t * , int ) ) ;
2002-01-19 18:40:18 +03:00
/*
* The function to read characters from a stream .
*/
2002-09-26 02:44:43 +04:00
void ( * InStream ) TRIO_PROTO ( ( struct _trio_class_t * , int * ) ) ;
2002-01-19 18:40:18 +03:00
/*
* The current location in the stream .
*/
2002-09-26 02:44:43 +04:00
trio_pointer_t location ;
2001-04-21 20:57:29 +04:00
/*
2002-01-19 18:40:18 +03:00
* The character currently being processed .
*/
int current ;
/*
* The number of characters that would have been written / read
* if there had been sufficient space .
2001-03-27 16:47:33 +04:00
*/
2001-04-21 20:57:29 +04:00
int processed ;
/*
* The number of characters that are actually written / read .
2002-01-19 18:40:18 +03:00
* Processed and committed will only differ for the * nprintf
2001-03-27 16:47:33 +04:00
* and * nscanf functions .
*/
2001-04-21 20:57:29 +04:00
int committed ;
2002-01-19 18:40:18 +03:00
/*
* The upper limit of characters that may be written / read .
*/
2001-04-21 20:57:29 +04:00
int max ;
2002-01-19 18:40:18 +03:00
/*
* The last output error that was detected .
*/
int error ;
} trio_class_t ;
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
/* References (for user-defined callbacks) */
2002-01-19 18:40:18 +03:00
typedef struct _trio_reference_t {
trio_class_t * data ;
trio_parameter_t * parameter ;
} trio_reference_t ;
2001-04-21 20:57:29 +04:00
/* Registered entries (for user-defined callbacks) */
2002-01-19 18:40:18 +03:00
typedef struct _trio_userdef_t {
struct _trio_userdef_t * next ;
2001-04-21 20:57:29 +04:00
trio_callback_t callback ;
char * name ;
2002-01-19 18:40:18 +03:00
} trio_userdef_t ;
2001-04-21 20:57:29 +04:00
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-09-26 02:44:43 +04:00
*
* Internal Variables
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-03-27 16:47:33 +04:00
2002-01-19 18:40:18 +03:00
static TRIO_CONST char rcsid [ ] = " @(#)$Id$ " ;
/*
* Need this to workaround a parser bug in HP C / iX compiler that fails
* to resolves macro definitions that includes type ' long double ' ,
* e . g : va_arg ( arg_ptr , long double )
*/
# if defined(TRIO_PLATFORM_MPEIX)
2002-09-26 02:44:43 +04:00
static TRIO_CONST trio_long_double_t ___dummy_long_double = 0 ;
2001-03-27 16:47:33 +04:00
# endif
2002-01-19 18:40:18 +03:00
static TRIO_CONST char internalNullString [ ] = " (nil) " ;
2001-03-27 16:47:33 +04:00
# if defined(USE_LOCALE)
2001-04-21 20:57:29 +04:00
static struct lconv * internalLocaleValues = NULL ;
2001-03-27 16:47:33 +04:00
# endif
2001-04-21 20:57:29 +04:00
/*
* UNIX98 says " in a locale where the radix character is not defined,
2001-03-27 16:47:33 +04:00
* the radix character defaults to a period ( . ) "
*/
2002-09-26 02:44:43 +04:00
static int internalDecimalPointLength = 1 ;
static int internalThousandSeparatorLength = 1 ;
static char internalDecimalPoint = ' . ' ;
static char internalDecimalPointString [ MAX_LOCALE_SEPARATOR_LENGTH + 1 ] = " . " ;
2001-06-05 16:46:33 +04:00
static char internalThousandSeparator [ MAX_LOCALE_SEPARATOR_LENGTH + 1 ] = " , " ;
2001-04-21 20:57:29 +04:00
static char internalGrouping [ MAX_LOCALE_GROUPS ] = { ( char ) NO_GROUPING } ;
2001-03-27 16:47:33 +04:00
2002-01-19 18:40:18 +03:00
static TRIO_CONST char internalDigitsLower [ ] = " 0123456789abcdefghijklmnopqrstuvwxyz " ;
static TRIO_CONST char internalDigitsUpper [ ] = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " ;
2001-04-21 20:57:29 +04:00
static BOOLEAN_T internalDigitsUnconverted = TRUE ;
static int internalDigitArray [ 128 ] ;
2001-06-05 16:46:33 +04:00
# if TRIO_EXTENSION
static BOOLEAN_T internalCollationUnconverted = TRUE ;
static char internalCollationArray [ MAX_CHARACTER_CLASS ] [ MAX_CHARACTER_CLASS ] ;
# endif
2001-03-27 16:47:33 +04:00
2002-09-26 02:44:43 +04:00
# if TRIO_EXTENSION
2002-01-19 18:40:18 +03:00
static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL ;
static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL ;
static trio_userdef_t * internalUserDef = NULL ;
2002-09-26 02:44:43 +04:00
# endif
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
/*************************************************************************
2002-09-26 02:44:43 +04:00
*
* Internal Functions
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined(TRIO_MINIMAL)
# define TRIO_STRING_PUBLIC static
# include "triostr.c"
# endif /* defined(TRIO_MINIMAL) */
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioIsQualifier
2001-03-27 16:47:33 +04:00
*
* Description :
* Remember to add all new qualifiers to this function .
* QUALIFIER_POSITION must not be added .
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE BOOLEAN_T
2002-09-26 02:44:43 +04:00
TrioIsQualifier
TRIO_ARGS1 ( ( character ) ,
TRIO_CONST char character )
2001-03-27 16:47:33 +04:00
{
/* QUALIFIER_POSITION is not included */
2002-09-26 02:44:43 +04:00
switch ( character )
2001-03-27 16:47:33 +04:00
{
case ' 0 ' : case ' 1 ' : case ' 2 ' : case ' 3 ' : case ' 4 ' :
case ' 5 ' : case ' 6 ' : case ' 7 ' : case ' 8 ' : case ' 9 ' :
case QUALIFIER_PLUS :
case QUALIFIER_MINUS :
case QUALIFIER_SPACE :
case QUALIFIER_DOT :
case QUALIFIER_STAR :
case QUALIFIER_ALTERNATIVE :
case QUALIFIER_SHORT :
case QUALIFIER_LONG :
case QUALIFIER_LONG_UPPER :
case QUALIFIER_CIRCUMFLEX :
# if defined(QUALIFIER_SIZE_T)
case QUALIFIER_SIZE_T :
# endif
# if defined(QUALIFIER_PTRDIFF_T)
case QUALIFIER_PTRDIFF_T :
# endif
# if defined(QUALIFIER_INTMAX_T)
case QUALIFIER_INTMAX_T :
# endif
# if defined(QUALIFIER_QUAD)
case QUALIFIER_QUAD :
# endif
# if defined(QUALIFIER_SIZE_T_UPPER)
case QUALIFIER_SIZE_T_UPPER :
# endif
# if defined(QUALIFIER_WIDECHAR)
case QUALIFIER_WIDECHAR :
# endif
# if defined(QUALIFIER_QUOTE)
case QUALIFIER_QUOTE :
# endif
# if defined(QUALIFIER_STICKY)
case QUALIFIER_STICKY :
# endif
# if defined(QUALIFIER_VARSIZE)
case QUALIFIER_VARSIZE :
# endif
# if defined(QUALIFIER_PARAM)
case QUALIFIER_PARAM :
2001-06-05 16:46:33 +04:00
# endif
# if defined(QUALIFIER_FIXED_SIZE)
case QUALIFIER_FIXED_SIZE :
2002-09-26 02:44:43 +04:00
# endif
# if defined(QUALIFIER_ROUNDING_UPPER)
case QUALIFIER_ROUNDING_UPPER :
2001-03-27 16:47:33 +04:00
# endif
return TRUE ;
default :
return FALSE ;
}
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioSetLocale
2001-03-27 16:47:33 +04:00
*/
2001-04-21 20:57:29 +04:00
# if defined(USE_LOCALE)
2002-09-26 02:44:43 +04:00
TRIO_PRIVATE void
TrioSetLocale ( TRIO_NOARGS )
2001-03-27 16:47:33 +04:00
{
2001-04-21 20:57:29 +04:00
internalLocaleValues = ( struct lconv * ) localeconv ( ) ;
2001-06-05 16:46:33 +04:00
if ( internalLocaleValues )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
if ( ( internalLocaleValues - > decimal_point ) & &
( internalLocaleValues - > decimal_point [ 0 ] ! = NIL ) )
{
2002-09-26 02:44:43 +04:00
internalDecimalPointLength = trio_length ( internalLocaleValues - > decimal_point ) ;
if ( internalDecimalPointLength = = 1 )
{
internalDecimalPoint = internalLocaleValues - > decimal_point [ 0 ] ;
}
else
{
internalDecimalPoint = NIL ;
trio_copy_max ( internalDecimalPointString ,
sizeof ( internalDecimalPointString ) ,
internalLocaleValues - > decimal_point ) ;
}
2001-06-05 16:46:33 +04:00
}
if ( ( internalLocaleValues - > thousands_sep ) & &
( internalLocaleValues - > thousands_sep [ 0 ] ! = NIL ) )
{
2002-01-19 18:40:18 +03:00
trio_copy_max ( internalThousandSeparator ,
sizeof ( internalThousandSeparator ) ,
internalLocaleValues - > thousands_sep ) ;
2002-09-26 02:44:43 +04:00
internalThousandSeparatorLength = trio_length ( internalThousandSeparator ) ;
2001-06-05 16:46:33 +04:00
}
if ( ( internalLocaleValues - > grouping ) & &
( internalLocaleValues - > grouping [ 0 ] ! = NIL ) )
{
2002-01-19 18:40:18 +03:00
trio_copy_max ( internalGrouping ,
sizeof ( internalGrouping ) ,
internalLocaleValues - > grouping ) ;
2001-06-05 16:46:33 +04:00
}
2001-03-27 16:47:33 +04:00
}
}
2001-04-21 20:57:29 +04:00
# endif /* defined(USE_LOCALE) */
2001-03-27 16:47:33 +04:00
2002-09-26 02:44:43 +04:00
TRIO_PRIVATE int
TrioCalcThousandSeparatorLength
TRIO_ARGS1 ( ( digits ) ,
int digits )
{
# if TRIO_EXTENSION
int count = 0 ;
int step = NO_GROUPING ;
char * groupingPointer = internalGrouping ;
while ( digits > 0 )
{
if ( * groupingPointer = = CHAR_MAX )
{
/* Disable grouping */
break ; /* while */
}
else if ( * groupingPointer = = 0 )
{
/* Repeat last group */
if ( step = = NO_GROUPING )
{
/* Error in locale */
break ; /* while */
}
}
else
{
step = * groupingPointer + + ;
}
if ( digits > step )
count + = internalThousandSeparatorLength ;
digits - = step ;
}
return count ;
# else
return 0 ;
# endif
}
TRIO_PRIVATE BOOLEAN_T
TrioFollowedBySeparator
TRIO_ARGS1 ( ( position ) ,
int position )
{
# if TRIO_EXTENSION
int step = 0 ;
char * groupingPointer = internalGrouping ;
position - - ;
if ( position = = 0 )
return FALSE ;
while ( position > 0 )
{
if ( * groupingPointer = = CHAR_MAX )
{
/* Disable grouping */
break ; /* while */
}
else if ( * groupingPointer ! = 0 )
{
step = * groupingPointer + + ;
}
if ( step = = 0 )
break ;
position - = step ;
}
return ( position = = 0 ) ;
# else
return FALSE ;
# endif
}
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioGetPosition
2001-03-27 16:47:33 +04:00
*
* Get the % n $ position .
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioGetPosition
TRIO_ARGS2 ( ( format , indexPointer ) ,
TRIO_CONST char * format ,
int * indexPointer )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
# if TRIO_UNIX98
2001-03-27 16:47:33 +04:00
char * tmpformat ;
int number = 0 ;
int index = * indexPointer ;
2002-01-19 18:40:18 +03:00
number = ( int ) trio_to_long ( & format [ index ] , & tmpformat , BASE_DECIMAL ) ;
2001-03-27 16:47:33 +04:00
index = ( int ) ( tmpformat - format ) ;
if ( ( number ! = 0 ) & & ( QUALIFIER_POSITION = = format [ index + + ] ) )
{
* indexPointer = index ;
2001-04-21 20:57:29 +04:00
/*
* number is decreased by 1 , because n $ starts from 1 , whereas
2001-03-27 16:47:33 +04:00
* the array it is indexing starts from 0.
*/
return number - 1 ;
}
2002-09-26 02:44:43 +04:00
# endif
2001-03-27 16:47:33 +04:00
return NO_POSITION ;
}
2002-09-26 02:44:43 +04:00
# if TRIO_EXTENSION
2001-04-21 20:57:29 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioFindNamespace
2001-04-21 20:57:29 +04:00
*
* Find registered user - defined specifier .
2002-09-26 02:44:43 +04:00
* The prev argument is used for optimization only .
2001-04-21 20:57:29 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE trio_userdef_t *
2002-09-26 02:44:43 +04:00
TrioFindNamespace
TRIO_ARGS2 ( ( name , prev ) ,
TRIO_CONST char * name ,
trio_userdef_t * * prev )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_userdef_t * def ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
if ( internalEnterCriticalRegion )
( void ) internalEnterCriticalRegion ( NULL ) ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
for ( def = internalUserDef ; def ; def = def - > next )
{
/* Case-sensitive string comparison */
2002-01-19 18:40:18 +03:00
if ( trio_equal_case ( def - > name , name ) )
2001-06-05 16:46:33 +04:00
break ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
if ( prev )
* prev = def ;
}
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
if ( internalLeaveCriticalRegion )
( void ) internalLeaveCriticalRegion ( NULL ) ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
return def ;
}
2002-09-26 02:44:43 +04:00
# endif
/*************************************************************************
* TrioPower
*
* Description :
* Calculate pow ( base , exponent ) , where number and exponent are integers .
*/
TRIO_PRIVATE trio_long_double_t
TrioPower
TRIO_ARGS2 ( ( number , exponent ) ,
int number ,
int exponent )
{
trio_long_double_t result ;
if ( number = = 10 )
{
switch ( exponent )
{
/* Speed up calculation of common cases */
case 0 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E-1 ) ;
break ;
case 1 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+0 ) ;
break ;
case 2 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+1 ) ;
break ;
case 3 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+2 ) ;
break ;
case 4 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+3 ) ;
break ;
case 5 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+4 ) ;
break ;
case 6 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+5 ) ;
break ;
case 7 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+6 ) ;
break ;
case 8 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+7 ) ;
break ;
case 9 :
result = ( trio_long_double_t ) number * TRIO_SUFFIX_LONG ( 1E+8 ) ;
break ;
default :
result = powl ( ( trio_long_double_t ) number ,
( trio_long_double_t ) exponent ) ;
break ;
}
}
else
{
return powl ( ( trio_long_double_t ) number , ( trio_long_double_t ) exponent ) ;
}
return result ;
}
/*************************************************************************
* TrioLogarithm
*/
TRIO_PRIVATE double
TrioLogarithm
TRIO_ARGS2 ( ( number , base ) ,
double number ,
int base )
{
double result ;
if ( number < = 0.0 )
{
/* xlC crashes on log(0) */
result = ( number = = 0.0 ) ? trio_ninf ( ) : trio_nan ( ) ;
}
else
{
if ( base = = 10 )
{
result = log10 ( number ) ;
}
else
{
result = log10 ( number ) / log10 ( ( double ) base ) ;
}
}
return result ;
}
/*************************************************************************
* TrioLogarithmBase
*/
TRIO_PRIVATE double
TrioLogarithmBase
TRIO_ARGS1 ( ( base ) ,
int base )
{
switch ( base )
{
case BASE_BINARY : return 1.0 ;
case BASE_OCTAL : return 3.0 ;
case BASE_DECIMAL : return 3.321928094887362345 ;
case BASE_HEX : return 4.0 ;
default : return TrioLogarithm ( ( double ) base , 2 ) ;
}
}
2001-04-21 20:57:29 +04:00
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioParse
2001-03-27 16:47:33 +04:00
*
* Description :
* Parse the format string
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioParse
TRIO_ARGS5 ( ( type , format , parameters , arglist , argarray ) ,
int type ,
TRIO_CONST char * format ,
trio_parameter_t * parameters ,
2013-12-12 11:04:43 +04:00
TRIO_VA_LIST_PTR arglist ,
2002-09-26 02:44:43 +04:00
trio_pointer_t * argarray )
2001-03-27 16:47:33 +04:00
{
/* Count the number of times a parameter is referenced */
unsigned short usedEntries [ MAX_PARAMETERS ] ;
/* Parameter counters */
int parameterPosition ;
int currentParam ;
int maxParam = - 1 ;
/* Utility variables */
2003-04-03 19:28:28 +04:00
trio_flags_t flags ;
2001-03-27 16:47:33 +04:00
int width ;
int precision ;
int varsize ;
int base ;
int index ; /* Index into formatting string */
int dots ; /* Count number of dots in modifier part */
BOOLEAN_T positional ; /* Does the specifier have a positional? */
2002-09-26 02:44:43 +04:00
BOOLEAN_T gotSticky = FALSE ; /* Are there any sticky modifiers at all? */
2001-04-21 20:57:29 +04:00
/*
* indices specifies the order in which the parameters must be
2001-03-27 16:47:33 +04:00
* read from the va_args ( this is necessary to handle positionals )
*/
int indices [ MAX_PARAMETERS ] ;
int pos = 0 ;
/* Various variables */
char ch ;
2002-01-19 18:40:18 +03:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2001-03-27 16:47:33 +04:00
int charlen ;
2002-01-19 18:40:18 +03:00
# endif
2002-09-26 02:44:43 +04:00
int save_errno ;
2001-03-27 16:47:33 +04:00
int i = - 1 ;
int num ;
char * tmpformat ;
2002-09-26 02:44:43 +04:00
/* One and only one of arglist and argarray must be used */
assert ( ( arglist ! = NULL ) ^ ( argarray ! = NULL ) ) ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
/*
* The ' parameters ' array is not initialized , but we need to
2001-03-27 16:47:33 +04:00
* know which entries we have used .
*/
memset ( usedEntries , 0 , sizeof ( usedEntries ) ) ;
2002-09-26 02:44:43 +04:00
save_errno = errno ;
2001-03-27 16:47:33 +04:00
index = 0 ;
parameterPosition = 0 ;
2001-06-05 16:46:33 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2002-09-26 02:44:43 +04:00
( void ) mblen ( NULL , 0 ) ;
2001-03-27 16:47:33 +04:00
# endif
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
while ( format [ index ] )
{
2001-06-05 16:46:33 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2001-03-27 16:47:33 +04:00
if ( ! isascii ( format [ index ] ) )
{
2001-04-21 20:57:29 +04:00
/*
* Multibyte characters cannot be legal specifiers or
2001-03-27 16:47:33 +04:00
* modifiers , so we skip over them .
*/
charlen = mblen ( & format [ index ] , MB_LEN_MAX ) ;
index + = ( charlen > 0 ) ? charlen : 1 ;
continue ; /* while */
}
2001-06-05 16:46:33 +04:00
# endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
2001-03-27 16:47:33 +04:00
if ( CHAR_IDENTIFIER = = format [ index + + ] )
{
if ( CHAR_IDENTIFIER = = format [ index ] )
{
index + + ;
continue ; /* while */
}
flags = FLAGS_NEW ;
dots = 0 ;
currentParam = TrioGetPosition ( format , & index ) ;
positional = ( NO_POSITION ! = currentParam ) ;
if ( ! positional )
{
/* We have no positional, get the next counter */
currentParam = parameterPosition ;
}
if ( currentParam > = MAX_PARAMETERS )
{
/* Bail out completely to make the error more obvious */
return TRIO_ERROR_RETURN ( TRIO_ETOOMANY , index ) ;
}
if ( currentParam > maxParam )
maxParam = currentParam ;
/* Default values */
width = NO_WIDTH ;
precision = NO_PRECISION ;
base = NO_BASE ;
varsize = NO_SIZE ;
2001-04-21 20:57:29 +04:00
while ( TrioIsQualifier ( format [ index ] ) )
2001-03-27 16:47:33 +04:00
{
ch = format [ index + + ] ;
switch ( ch )
{
case QUALIFIER_SPACE :
flags | = FLAGS_SPACE ;
break ;
case QUALIFIER_PLUS :
flags | = FLAGS_SHOWSIGN ;
break ;
case QUALIFIER_MINUS :
flags | = FLAGS_LEFTADJUST ;
flags & = ~ FLAGS_NILPADDING ;
break ;
case QUALIFIER_ALTERNATIVE :
flags | = FLAGS_ALTERNATIVE ;
break ;
case QUALIFIER_DOT :
if ( dots = = 0 ) /* Precision */
{
dots + + ;
/* Skip if no precision */
if ( QUALIFIER_DOT = = format [ index ] )
break ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* After the first dot we have the precision */
flags | = FLAGS_PRECISION ;
2002-09-26 02:44:43 +04:00
if ( ( QUALIFIER_STAR = = format [ index ] )
# if defined(QUALIFIER_PARAM)
| | ( QUALIFIER_PARAM = = format [ index ] )
# endif
)
2001-03-27 16:47:33 +04:00
{
index + + ;
flags | = FLAGS_PRECISION_PARAMETER ;
precision = TrioGetPosition ( format , & index ) ;
if ( precision = = NO_POSITION )
{
parameterPosition + + ;
if ( positional )
precision = parameterPosition ;
else
{
precision = currentParam ;
currentParam = precision + 1 ;
}
}
else
{
if ( ! positional )
currentParam = precision + 1 ;
if ( width > maxParam )
maxParam = precision ;
}
if ( currentParam > maxParam )
maxParam = currentParam ;
}
else
{
2002-01-19 18:40:18 +03:00
precision = trio_to_long ( & format [ index ] ,
& tmpformat ,
BASE_DECIMAL ) ;
2001-03-27 16:47:33 +04:00
index = ( int ) ( tmpformat - format ) ;
}
}
else if ( dots = = 1 ) /* Base */
{
dots + + ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* After the second dot we have the base */
flags | = FLAGS_BASE ;
2002-09-26 02:44:43 +04:00
if ( ( QUALIFIER_STAR = = format [ index ] )
# if defined(QUALIFIER_PARAM)
| | ( QUALIFIER_PARAM = = format [ index ] )
# endif
)
2001-03-27 16:47:33 +04:00
{
index + + ;
flags | = FLAGS_BASE_PARAMETER ;
base = TrioGetPosition ( format , & index ) ;
if ( base = = NO_POSITION )
{
parameterPosition + + ;
if ( positional )
base = parameterPosition ;
else
{
base = currentParam ;
currentParam = base + 1 ;
}
}
else
{
if ( ! positional )
currentParam = base + 1 ;
if ( base > maxParam )
maxParam = base ;
}
if ( currentParam > maxParam )
maxParam = currentParam ;
}
else
{
2002-01-19 18:40:18 +03:00
base = trio_to_long ( & format [ index ] ,
& tmpformat ,
BASE_DECIMAL ) ;
2001-03-27 16:47:33 +04:00
if ( base > MAX_BASE )
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
index = ( int ) ( tmpformat - format ) ;
}
}
else
{
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
}
break ; /* QUALIFIER_DOT */
2002-09-26 02:44:43 +04:00
# if defined(QUALIFIER_PARAM)
2001-03-27 16:47:33 +04:00
case QUALIFIER_PARAM :
type = TYPE_PRINT ;
/* FALLTHROUGH */
2002-09-26 02:44:43 +04:00
# endif
2001-03-27 16:47:33 +04:00
case QUALIFIER_STAR :
/* This has different meanings for print and scan */
if ( TYPE_PRINT = = type )
{
/* Read with from parameter */
flags | = ( FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER ) ;
width = TrioGetPosition ( format , & index ) ;
if ( width = = NO_POSITION )
{
parameterPosition + + ;
if ( positional )
width = parameterPosition ;
else
{
width = currentParam ;
currentParam = width + 1 ;
}
}
else
{
if ( ! positional )
currentParam = width + 1 ;
if ( width > maxParam )
maxParam = width ;
}
if ( currentParam > maxParam )
maxParam = currentParam ;
}
else
{
/* Scan, but do not store result */
flags | = FLAGS_IGNORE ;
}
break ; /* QUALIFIER_STAR */
case ' 0 ' :
if ( ! ( flags & FLAGS_LEFTADJUST ) )
flags | = FLAGS_NILPADDING ;
/* FALLTHROUGH */
case ' 1 ' : case ' 2 ' : case ' 3 ' : case ' 4 ' :
case ' 5 ' : case ' 6 ' : case ' 7 ' : case ' 8 ' : case ' 9 ' :
flags | = FLAGS_WIDTH ;
/* &format[index - 1] is used to "rewind" the read
* character from format
*/
2002-01-19 18:40:18 +03:00
width = trio_to_long ( & format [ index - 1 ] ,
& tmpformat ,
BASE_DECIMAL ) ;
2001-03-27 16:47:33 +04:00
index = ( int ) ( tmpformat - format ) ;
break ;
case QUALIFIER_SHORT :
if ( flags & FLAGS_SHORTSHORT )
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
else if ( flags & FLAGS_SHORT )
flags | = FLAGS_SHORTSHORT ;
else
flags | = FLAGS_SHORT ;
break ;
case QUALIFIER_LONG :
if ( flags & FLAGS_QUAD )
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
else if ( flags & FLAGS_LONG )
flags | = FLAGS_QUAD ;
else
flags | = FLAGS_LONG ;
break ;
case QUALIFIER_LONG_UPPER :
flags | = FLAGS_LONGDOUBLE ;
break ;
# if defined(QUALIFIER_SIZE_T)
case QUALIFIER_SIZE_T :
flags | = FLAGS_SIZE_T ;
/* Modify flags for later truncation of number */
2001-06-05 16:46:33 +04:00
if ( sizeof ( size_t ) = = sizeof ( trio_ulonglong_t ) )
2001-03-27 16:47:33 +04:00
flags | = FLAGS_QUAD ;
else if ( sizeof ( size_t ) = = sizeof ( long ) )
flags | = FLAGS_LONG ;
break ;
# endif
# if defined(QUALIFIER_PTRDIFF_T)
case QUALIFIER_PTRDIFF_T :
flags | = FLAGS_PTRDIFF_T ;
2001-06-05 16:46:33 +04:00
if ( sizeof ( ptrdiff_t ) = = sizeof ( trio_ulonglong_t ) )
2001-03-27 16:47:33 +04:00
flags | = FLAGS_QUAD ;
else if ( sizeof ( ptrdiff_t ) = = sizeof ( long ) )
flags | = FLAGS_LONG ;
break ;
# endif
# if defined(QUALIFIER_INTMAX_T)
case QUALIFIER_INTMAX_T :
flags | = FLAGS_INTMAX_T ;
2001-06-05 16:46:33 +04:00
if ( sizeof ( trio_intmax_t ) = = sizeof ( trio_ulonglong_t ) )
2001-03-27 16:47:33 +04:00
flags | = FLAGS_QUAD ;
2001-06-05 16:46:33 +04:00
else if ( sizeof ( trio_intmax_t ) = = sizeof ( long ) )
2001-03-27 16:47:33 +04:00
flags | = FLAGS_LONG ;
break ;
# endif
# if defined(QUALIFIER_QUAD)
case QUALIFIER_QUAD :
flags | = FLAGS_QUAD ;
break ;
# endif
2001-06-05 16:46:33 +04:00
# if defined(QUALIFIER_FIXED_SIZE)
case QUALIFIER_FIXED_SIZE :
if ( flags & FLAGS_FIXED_SIZE )
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
if ( flags & ( FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE |
FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER ) )
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
if ( ( format [ index ] = = ' 6 ' ) & &
( format [ index + 1 ] = = ' 4 ' ) )
{
varsize = sizeof ( trio_int64_t ) ;
index + = 2 ;
}
else if ( ( format [ index ] = = ' 3 ' ) & &
( format [ index + 1 ] = = ' 2 ' ) )
{
varsize = sizeof ( trio_int32_t ) ;
index + = 2 ;
}
else if ( ( format [ index ] = = ' 1 ' ) & &
( format [ index + 1 ] = = ' 6 ' ) )
{
varsize = sizeof ( trio_int16_t ) ;
index + = 2 ;
}
else if ( format [ index ] = = ' 8 ' )
{
varsize = sizeof ( trio_int8_t ) ;
index + + ;
}
else
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
flags | = FLAGS_FIXED_SIZE ;
break ;
# endif
2001-03-27 16:47:33 +04:00
# if defined(QUALIFIER_WIDECHAR)
case QUALIFIER_WIDECHAR :
flags | = FLAGS_WIDECHAR ;
break ;
# endif
# if defined(QUALIFIER_SIZE_T_UPPER)
case QUALIFIER_SIZE_T_UPPER :
break ;
# endif
# if defined(QUALIFIER_QUOTE)
case QUALIFIER_QUOTE :
flags | = FLAGS_QUOTE ;
break ;
# endif
# if defined(QUALIFIER_STICKY)
case QUALIFIER_STICKY :
flags | = FLAGS_STICKY ;
2002-09-26 02:44:43 +04:00
gotSticky = TRUE ;
2001-03-27 16:47:33 +04:00
break ;
# endif
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
# if defined(QUALIFIER_VARSIZE)
case QUALIFIER_VARSIZE :
2001-06-05 16:46:33 +04:00
flags | = FLAGS_VARSIZE_PARAMETER ;
2001-03-27 16:47:33 +04:00
parameterPosition + + ;
if ( positional )
varsize = parameterPosition ;
else
{
varsize = currentParam ;
currentParam = varsize + 1 ;
}
if ( currentParam > maxParam )
maxParam = currentParam ;
break ;
# endif
2002-09-26 02:44:43 +04:00
# if defined(QUALIFIER_ROUNDING_UPPER)
case QUALIFIER_ROUNDING_UPPER :
flags | = FLAGS_ROUNDING ;
break ;
# endif
2001-03-27 16:47:33 +04:00
default :
/* Bail out completely to make the error more obvious */
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
}
} /* while qualifier */
2001-04-21 20:57:29 +04:00
/*
* Parameters only need the type and value . The value is
2001-03-27 16:47:33 +04:00
* read later .
*/
if ( flags & FLAGS_WIDTH_PARAMETER )
{
usedEntries [ width ] + = 1 ;
parameters [ pos ] . type = FORMAT_PARAMETER ;
2002-01-19 18:40:18 +03:00
parameters [ pos ] . flags = 0 ;
2001-03-27 16:47:33 +04:00
indices [ width ] = pos ;
width = pos + + ;
}
if ( flags & FLAGS_PRECISION_PARAMETER )
{
usedEntries [ precision ] + = 1 ;
parameters [ pos ] . type = FORMAT_PARAMETER ;
2002-01-19 18:40:18 +03:00
parameters [ pos ] . flags = 0 ;
2001-03-27 16:47:33 +04:00
indices [ precision ] = pos ;
precision = pos + + ;
}
if ( flags & FLAGS_BASE_PARAMETER )
{
usedEntries [ base ] + = 1 ;
parameters [ pos ] . type = FORMAT_PARAMETER ;
2002-01-19 18:40:18 +03:00
parameters [ pos ] . flags = 0 ;
2001-03-27 16:47:33 +04:00
indices [ base ] = pos ;
base = pos + + ;
}
2001-06-05 16:46:33 +04:00
if ( flags & FLAGS_VARSIZE_PARAMETER )
2001-03-27 16:47:33 +04:00
{
usedEntries [ varsize ] + = 1 ;
parameters [ pos ] . type = FORMAT_PARAMETER ;
2002-01-19 18:40:18 +03:00
parameters [ pos ] . flags = 0 ;
2001-03-27 16:47:33 +04:00
indices [ varsize ] = pos ;
varsize = pos + + ;
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
indices [ currentParam ] = pos ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
switch ( format [ index + + ] )
{
# if defined(SPECIFIER_CHAR_UPPER)
case SPECIFIER_CHAR_UPPER :
2001-06-05 16:46:33 +04:00
flags | = FLAGS_WIDECHAR ;
2001-03-27 16:47:33 +04:00
/* FALLTHROUGH */
# endif
case SPECIFIER_CHAR :
2001-06-05 16:46:33 +04:00
if ( flags & FLAGS_LONG )
flags | = FLAGS_WIDECHAR ;
else if ( flags & FLAGS_SHORT )
flags & = ~ FLAGS_WIDECHAR ;
2001-03-27 16:47:33 +04:00
parameters [ pos ] . type = FORMAT_CHAR ;
break ;
# if defined(SPECIFIER_STRING_UPPER)
case SPECIFIER_STRING_UPPER :
2001-06-05 16:46:33 +04:00
flags | = FLAGS_WIDECHAR ;
2001-03-27 16:47:33 +04:00
/* FALLTHROUGH */
# endif
case SPECIFIER_STRING :
2001-06-05 16:46:33 +04:00
if ( flags & FLAGS_LONG )
flags | = FLAGS_WIDECHAR ;
else if ( flags & FLAGS_SHORT )
flags & = ~ FLAGS_WIDECHAR ;
2001-03-27 16:47:33 +04:00
parameters [ pos ] . type = FORMAT_STRING ;
break ;
case SPECIFIER_GROUP :
if ( TYPE_SCAN = = type )
{
2001-06-05 16:46:33 +04:00
int depth = 1 ;
2001-03-27 16:47:33 +04:00
parameters [ pos ] . type = FORMAT_GROUP ;
2001-06-05 16:46:33 +04:00
if ( format [ index ] = = QUALIFIER_CIRCUMFLEX )
index + + ;
if ( format [ index ] = = SPECIFIER_UNGROUP )
index + + ;
if ( format [ index ] = = QUALIFIER_MINUS )
index + + ;
/* Skip nested brackets */
while ( format [ index ] ! = NIL )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
if ( format [ index ] = = SPECIFIER_GROUP )
{
depth + + ;
}
else if ( format [ index ] = = SPECIFIER_UNGROUP )
{
if ( - - depth < = 0 )
{
index + + ;
break ;
}
}
index + + ;
2001-03-27 16:47:33 +04:00
}
}
break ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
case SPECIFIER_INTEGER :
parameters [ pos ] . type = FORMAT_INT ;
break ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
case SPECIFIER_UNSIGNED :
flags | = FLAGS_UNSIGNED ;
parameters [ pos ] . type = FORMAT_INT ;
break ;
case SPECIFIER_DECIMAL :
/* Disable base modifier */
flags & = ~ FLAGS_BASE_PARAMETER ;
base = BASE_DECIMAL ;
parameters [ pos ] . type = FORMAT_INT ;
break ;
case SPECIFIER_OCTAL :
2003-04-03 19:28:28 +04:00
flags | = FLAGS_UNSIGNED ;
2001-03-27 16:47:33 +04:00
flags & = ~ FLAGS_BASE_PARAMETER ;
base = BASE_OCTAL ;
parameters [ pos ] . type = FORMAT_INT ;
break ;
# if defined(SPECIFIER_BINARY)
case SPECIFIER_BINARY_UPPER :
flags | = FLAGS_UPPER ;
/* FALLTHROUGH */
case SPECIFIER_BINARY :
flags | = FLAGS_NILPADDING ;
flags & = ~ FLAGS_BASE_PARAMETER ;
base = BASE_BINARY ;
parameters [ pos ] . type = FORMAT_INT ;
break ;
# endif
case SPECIFIER_HEX_UPPER :
flags | = FLAGS_UPPER ;
/* FALLTHROUGH */
case SPECIFIER_HEX :
flags | = FLAGS_UNSIGNED ;
flags & = ~ FLAGS_BASE_PARAMETER ;
base = BASE_HEX ;
parameters [ pos ] . type = FORMAT_INT ;
break ;
case SPECIFIER_FLOAT_E_UPPER :
flags | = FLAGS_UPPER ;
/* FALLTHROUGH */
case SPECIFIER_FLOAT_E :
flags | = FLAGS_FLOAT_E ;
parameters [ pos ] . type = FORMAT_DOUBLE ;
break ;
case SPECIFIER_FLOAT_G_UPPER :
flags | = FLAGS_UPPER ;
/* FALLTHROUGH */
case SPECIFIER_FLOAT_G :
flags | = FLAGS_FLOAT_G ;
parameters [ pos ] . type = FORMAT_DOUBLE ;
break ;
case SPECIFIER_FLOAT_F_UPPER :
flags | = FLAGS_UPPER ;
/* FALLTHROUGH */
case SPECIFIER_FLOAT_F :
parameters [ pos ] . type = FORMAT_DOUBLE ;
break ;
case SPECIFIER_POINTER :
2002-09-26 02:44:43 +04:00
if ( sizeof ( trio_pointer_t ) = = sizeof ( trio_ulonglong_t ) )
flags | = FLAGS_QUAD ;
else if ( sizeof ( trio_pointer_t ) = = sizeof ( long ) )
flags | = FLAGS_LONG ;
2001-03-27 16:47:33 +04:00
parameters [ pos ] . type = FORMAT_POINTER ;
break ;
case SPECIFIER_COUNT :
parameters [ pos ] . type = FORMAT_COUNT ;
break ;
# if defined(SPECIFIER_HEXFLOAT)
# if defined(SPECIFIER_HEXFLOAT_UPPER)
case SPECIFIER_HEXFLOAT_UPPER :
flags | = FLAGS_UPPER ;
/* FALLTHROUGH */
# endif
case SPECIFIER_HEXFLOAT :
base = BASE_HEX ;
parameters [ pos ] . type = FORMAT_DOUBLE ;
break ;
# endif
# if defined(FORMAT_ERRNO)
case SPECIFIER_ERRNO :
parameters [ pos ] . type = FORMAT_ERRNO ;
break ;
# endif
2001-04-21 20:57:29 +04:00
# if defined(SPECIFIER_USER_DEFINED_BEGIN)
case SPECIFIER_USER_DEFINED_BEGIN :
{
unsigned int max ;
int without_namespace = TRUE ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
parameters [ pos ] . type = FORMAT_USER_DEFINED ;
parameters [ pos ] . user_name [ 0 ] = NIL ;
tmpformat = ( char * ) & format [ index ] ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
while ( ( ch = format [ index ] ) )
{
index + + ;
if ( ch = = SPECIFIER_USER_DEFINED_END )
{
if ( without_namespace )
{
/* We must get the handle first */
parameters [ pos ] . type = FORMAT_PARAMETER ;
parameters [ pos ] . indexAfterSpecifier = index ;
parameters [ pos ] . flags = FLAGS_USER_DEFINED ;
/* Adjust parameters for insertion of new one */
pos + + ;
usedEntries [ currentParam ] + = 1 ;
parameters [ pos ] . type = FORMAT_USER_DEFINED ;
currentParam + + ;
indices [ currentParam ] = pos ;
if ( currentParam > maxParam )
maxParam = currentParam ;
}
/* Copy the user data */
max = ( unsigned int ) ( & format [ index ] - tmpformat ) ;
if ( max > MAX_USER_DATA )
max = MAX_USER_DATA ;
2002-01-19 18:40:18 +03:00
trio_copy_max ( parameters [ pos ] . user_data ,
max ,
tmpformat ) ;
2001-04-21 20:57:29 +04:00
break ; /* while */
}
if ( ch = = SPECIFIER_USER_DEFINED_SEPARATOR )
{
without_namespace = FALSE ;
/* Copy the namespace for later looking-up */
max = ( int ) ( & format [ index ] - tmpformat ) ;
if ( max > MAX_USER_NAME )
max = MAX_USER_NAME ;
2002-01-19 18:40:18 +03:00
trio_copy_max ( parameters [ pos ] . user_name ,
max ,
tmpformat ) ;
2001-04-21 20:57:29 +04:00
tmpformat = ( char * ) & format [ index ] ;
}
}
if ( ch ! = SPECIFIER_USER_DEFINED_END )
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
}
break ;
# endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
default :
/* Bail out completely to make the error more obvious */
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
}
/* Count the number of times this entry has been used */
usedEntries [ currentParam ] + = 1 ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* Find last sticky parameters */
2002-09-26 02:44:43 +04:00
if ( gotSticky & & ! ( flags & FLAGS_STICKY ) )
2001-03-27 16:47:33 +04:00
{
for ( i = pos - 1 ; i > = 0 ; i - - )
{
if ( parameters [ i ] . type = = FORMAT_PARAMETER )
continue ;
if ( ( parameters [ i ] . flags & FLAGS_STICKY ) & &
( parameters [ i ] . type = = parameters [ pos ] . type ) )
{
/* Do not overwrite current qualifiers */
2001-04-21 20:57:29 +04:00
flags | = ( parameters [ i ] . flags & ( unsigned long ) ~ FLAGS_STICKY ) ;
2001-03-27 16:47:33 +04:00
if ( width = = NO_WIDTH )
width = parameters [ i ] . width ;
if ( precision = = NO_PRECISION )
precision = parameters [ i ] . precision ;
if ( base = = NO_BASE )
base = parameters [ i ] . base ;
break ;
}
}
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
parameters [ pos ] . indexAfterSpecifier = index ;
parameters [ pos ] . flags = flags ;
parameters [ pos ] . width = width ;
parameters [ pos ] . precision = precision ;
parameters [ pos ] . base = ( base = = NO_BASE ) ? BASE_DECIMAL : base ;
parameters [ pos ] . varsize = varsize ;
pos + + ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
if ( ! positional )
2001-03-27 16:47:33 +04:00
parameterPosition + + ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
} /* if identifier */
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
} /* while format characters left */
for ( num = 0 ; num < = maxParam ; num + + )
{
if ( usedEntries [ num ] ! = 1 )
{
if ( usedEntries [ num ] = = 0 ) /* gap detected */
return TRIO_ERROR_RETURN ( TRIO_EGAP , num ) ;
else /* double references detected */
return TRIO_ERROR_RETURN ( TRIO_EDBLREF , num ) ;
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
i = indices [ num ] ;
2001-04-21 20:57:29 +04:00
/*
* FORMAT_PARAMETERS are only present if they must be read ,
2001-03-27 16:47:33 +04:00
* so it makes no sense to check the ignore flag ( besides ,
* the flags variable is not set for that particular type )
*/
if ( ( parameters [ i ] . type ! = FORMAT_PARAMETER ) & &
( parameters [ i ] . flags & FLAGS_IGNORE ) )
continue ; /* for all arguments */
2001-04-21 20:57:29 +04:00
/*
* The stack arguments are read according to ANSI C89
2001-03-27 16:47:33 +04:00
* default argument promotions :
*
* char = int
* short = int
* unsigned char = unsigned int
* unsigned short = unsigned int
* float = double
*
* In addition to the ANSI C89 these types are read ( the
* default argument promotions of C99 has not been
* considered yet )
*
* long long
* long double
* size_t
* ptrdiff_t
* intmax_t
*/
switch ( parameters [ i ] . type )
{
case FORMAT_GROUP :
case FORMAT_STRING :
2001-06-05 16:46:33 +04:00
# if TRIO_WIDECHAR
if ( flags & FLAGS_WIDECHAR )
{
parameters [ i ] . data . wstring = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , trio_wchar_t * )
2002-09-26 02:44:43 +04:00
: ( trio_wchar_t * ) ( argarray [ num ] ) ;
2001-06-05 16:46:33 +04:00
}
else
# endif
{
parameters [ i ] . data . string = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , char * )
2001-06-05 16:46:33 +04:00
: ( char * ) ( argarray [ num ] ) ;
}
2001-03-27 16:47:33 +04:00
break ;
2002-09-26 02:44:43 +04:00
# if defined(FORMAT_USER_DEFINED)
case FORMAT_USER_DEFINED :
# endif
2001-03-27 16:47:33 +04:00
case FORMAT_POINTER :
case FORMAT_COUNT :
case FORMAT_UNKNOWN :
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . pointer = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , trio_pointer_t )
2001-04-21 20:57:29 +04:00
: argarray [ num ] ;
2001-03-27 16:47:33 +04:00
break ;
case FORMAT_CHAR :
case FORMAT_INT :
if ( TYPE_SCAN = = type )
{
2001-06-05 16:46:33 +04:00
if ( argarray = = NULL )
2012-09-11 09:26:36 +04:00
parameters [ i ] . data . pointer =
2013-12-12 11:04:43 +04:00
( trio_pointer_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , trio_pointer_t ) ;
2001-04-21 20:57:29 +04:00
else
{
if ( parameters [ i ] . type = = FORMAT_CHAR )
parameters [ i ] . data . pointer =
2002-09-26 02:44:43 +04:00
( trio_pointer_t ) ( ( char * ) argarray [ num ] ) ;
2001-04-21 20:57:29 +04:00
else if ( parameters [ i ] . flags & FLAGS_SHORT )
parameters [ i ] . data . pointer =
2002-09-26 02:44:43 +04:00
( trio_pointer_t ) ( ( short * ) argarray [ num ] ) ;
2001-04-21 20:57:29 +04:00
else
parameters [ i ] . data . pointer =
2002-09-26 02:44:43 +04:00
( trio_pointer_t ) ( ( int * ) argarray [ num ] ) ;
2001-04-21 20:57:29 +04:00
}
2001-03-27 16:47:33 +04:00
}
else
{
2001-06-05 16:46:33 +04:00
# if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
2002-01-19 18:40:18 +03:00
if ( parameters [ i ] . flags
& ( FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE ) )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
if ( parameters [ i ] . flags & FLAGS_VARSIZE_PARAMETER )
{
/*
* Variable sizes are mapped onto the fixed sizes , in
* accordance with integer promotion .
*
* Please note that this may not be portable , as we
* only guess the size , not the layout of the numbers .
* For example , if int is little - endian , and long is
* big - endian , then this will fail .
*/
varsize = ( int ) parameters [ parameters [ i ] . varsize ] . data . number . as_unsigned ;
}
else
{
/* Used for the I<bits> modifiers */
varsize = parameters [ i ] . varsize ;
}
2001-04-21 20:57:29 +04:00
parameters [ i ] . flags & = ~ FLAGS_ALL_VARSIZES ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( varsize < = ( int ) sizeof ( int ) )
;
else if ( varsize < = ( int ) sizeof ( long ) )
parameters [ i ] . flags | = FLAGS_LONG ;
# if defined(QUALIFIER_INTMAX_T)
2001-06-05 16:46:33 +04:00
else if ( varsize < = ( int ) sizeof ( trio_longlong_t ) )
2001-03-27 16:47:33 +04:00
parameters [ i ] . flags | = FLAGS_QUAD ;
else
parameters [ i ] . flags | = FLAGS_INTMAX_T ;
# else
else
parameters [ i ] . flags | = FLAGS_QUAD ;
# endif
}
2001-04-21 20:57:29 +04:00
# endif /* defined(QUALIFIER_VARSIZE) */
2001-03-27 16:47:33 +04:00
# if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
if ( parameters [ i ] . flags & FLAGS_SIZE_T )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? ( trio_uintmax_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , size_t )
2001-06-05 16:46:33 +04:00
: ( trio_uintmax_t ) ( * ( ( size_t * ) argarray [ num ] ) ) ;
2001-03-27 16:47:33 +04:00
else
# endif
# if defined(QUALIFIER_PTRDIFF_T)
if ( parameters [ i ] . flags & FLAGS_PTRDIFF_T )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? ( trio_uintmax_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , ptrdiff_t )
2001-06-05 16:46:33 +04:00
: ( trio_uintmax_t ) ( * ( ( ptrdiff_t * ) argarray [ num ] ) ) ;
2001-03-27 16:47:33 +04:00
else
# endif
# if defined(QUALIFIER_INTMAX_T)
if ( parameters [ i ] . flags & FLAGS_INTMAX_T )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? ( trio_uintmax_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , trio_intmax_t )
2001-06-05 16:46:33 +04:00
: ( trio_uintmax_t ) ( * ( ( trio_intmax_t * ) argarray [ num ] ) ) ;
2001-03-27 16:47:33 +04:00
else
# endif
if ( parameters [ i ] . flags & FLAGS_QUAD )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? ( trio_uintmax_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , trio_ulonglong_t )
2001-06-05 16:46:33 +04:00
: ( trio_uintmax_t ) ( * ( ( trio_ulonglong_t * ) argarray [ num ] ) ) ;
2001-03-27 16:47:33 +04:00
else if ( parameters [ i ] . flags & FLAGS_LONG )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? ( trio_uintmax_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , long )
2001-06-05 16:46:33 +04:00
: ( trio_uintmax_t ) ( * ( ( long * ) argarray [ num ] ) ) ;
2001-03-27 16:47:33 +04:00
else
2001-04-21 20:57:29 +04:00
{
2001-06-05 16:46:33 +04:00
if ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
parameters [ i ] . data . number . as_unsigned = ( trio_uintmax_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , int ) ;
2001-04-21 20:57:29 +04:00
else
{
if ( parameters [ i ] . type = = FORMAT_CHAR )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( trio_uintmax_t ) ( * ( ( char * ) argarray [ num ] ) ) ;
2001-04-21 20:57:29 +04:00
else if ( parameters [ i ] . flags & FLAGS_SHORT )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( trio_uintmax_t ) ( * ( ( short * ) argarray [ num ] ) ) ;
2001-04-21 20:57:29 +04:00
else
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( trio_uintmax_t ) ( * ( ( int * ) argarray [ num ] ) ) ;
2001-04-21 20:57:29 +04:00
}
}
2001-03-27 16:47:33 +04:00
}
break ;
case FORMAT_PARAMETER :
2001-04-21 20:57:29 +04:00
/*
* The parameter for the user - defined specifier is a pointer ,
* whereas the rest ( width , precision , base ) uses an integer .
*/
if ( parameters [ i ] . flags & FLAGS_USER_DEFINED )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . pointer = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , trio_pointer_t )
2001-04-21 20:57:29 +04:00
: argarray [ num ] ;
else
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . number . as_unsigned = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? ( trio_uintmax_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , int )
2001-06-05 16:46:33 +04:00
: ( trio_uintmax_t ) ( * ( ( int * ) argarray [ num ] ) ) ;
2001-03-27 16:47:33 +04:00
break ;
case FORMAT_DOUBLE :
if ( TYPE_SCAN = = type )
{
2002-09-26 02:44:43 +04:00
if ( parameters [ i ] . flags & FLAGS_LONGDOUBLE )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . longdoublePointer = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , trio_long_double_t * )
2002-09-26 02:44:43 +04:00
: ( trio_long_double_t * ) argarray [ num ] ;
2001-03-27 16:47:33 +04:00
else
2001-04-21 20:57:29 +04:00
{
2002-09-26 02:44:43 +04:00
if ( parameters [ i ] . flags & FLAGS_LONG )
parameters [ i ] . data . doublePointer = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , double * )
2002-09-26 02:44:43 +04:00
: ( double * ) argarray [ num ] ;
else
parameters [ i ] . data . doublePointer = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? ( double * ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , float * )
2002-09-26 02:44:43 +04:00
: ( double * ) ( ( float * ) argarray [ num ] ) ;
2001-04-21 20:57:29 +04:00
}
2001-03-27 16:47:33 +04:00
}
else
{
2002-09-26 02:44:43 +04:00
if ( parameters [ i ] . flags & FLAGS_LONGDOUBLE )
2001-06-05 16:46:33 +04:00
parameters [ i ] . data . longdoubleNumber = ( argarray = = NULL )
2013-12-12 11:04:43 +04:00
? va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , trio_long_double_t )
2002-09-26 02:44:43 +04:00
: ( trio_long_double_t ) ( * ( ( trio_long_double_t * ) argarray [ num ] ) ) ;
2001-03-27 16:47:33 +04:00
else
2001-04-21 20:57:29 +04:00
{
2001-06-05 16:46:33 +04:00
if ( argarray = = NULL )
2002-01-19 18:40:18 +03:00
parameters [ i ] . data . longdoubleNumber =
2013-12-12 11:04:43 +04:00
( trio_long_double_t ) va_arg ( TRIO_VA_LIST_DEREF ( arglist ) , double ) ;
2001-04-21 20:57:29 +04:00
else
{
if ( parameters [ i ] . flags & FLAGS_SHORT )
2002-01-19 18:40:18 +03:00
parameters [ i ] . data . longdoubleNumber =
2002-09-26 02:44:43 +04:00
( trio_long_double_t ) ( * ( ( float * ) argarray [ num ] ) ) ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
parameters [ i ] . data . longdoubleNumber =
2002-09-26 02:44:43 +04:00
( trio_long_double_t ) ( * ( ( double * ) argarray [ num ] ) ) ;
2001-04-21 20:57:29 +04:00
}
}
2001-03-27 16:47:33 +04:00
}
break ;
# if defined(FORMAT_ERRNO)
case FORMAT_ERRNO :
2002-09-26 02:44:43 +04:00
parameters [ i ] . data . errorNumber = save_errno ;
2001-03-27 16:47:33 +04:00
break ;
# endif
default :
break ;
}
} /* for all specifiers */
return num ;
}
/*************************************************************************
*
2002-01-19 18:40:18 +03:00
* FORMATTING
2001-03-27 16:47:33 +04:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioWriteNumber
2001-03-27 16:47:33 +04:00
*
* Description :
* Output a number .
* The complexity of this function is a result of the complexity
* of the dependencies of the flags .
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioWriteNumber
TRIO_ARGS6 ( ( self , number , flags , width , precision , base ) ,
trio_class_t * self ,
trio_uintmax_t number ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width ,
int precision ,
int base )
2001-03-27 16:47:33 +04:00
{
BOOLEAN_T isNegative ;
2003-04-03 19:28:28 +04:00
BOOLEAN_T isNumberZero ;
BOOLEAN_T isPrecisionZero ;
BOOLEAN_T ignoreNumber ;
2001-06-05 16:46:33 +04:00
char buffer [ MAX_CHARS_IN ( trio_uintmax_t ) * ( 1 + MAX_LOCALE_SEPARATOR_LENGTH ) + 1 ] ;
2001-03-27 16:47:33 +04:00
char * bufferend ;
char * pointer ;
2002-01-19 18:40:18 +03:00
TRIO_CONST char * digits ;
2001-03-27 16:47:33 +04:00
int i ;
int length ;
char * p ;
int count ;
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > OutStream ) ) ;
2002-01-19 18:40:18 +03:00
assert ( ( ( base > = MIN_BASE ) & & ( base < = MAX_BASE ) ) | | ( base = = NO_BASE ) ) ;
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
digits = ( flags & FLAGS_UPPER ) ? internalDigitsUpper : internalDigitsLower ;
2002-09-26 02:44:43 +04:00
if ( base = = NO_BASE )
base = BASE_DECIMAL ;
2001-03-27 16:47:33 +04:00
2003-04-03 19:28:28 +04:00
isNumberZero = ( number = = 0 ) ;
isPrecisionZero = ( precision = = 0 ) ;
ignoreNumber = ( isNumberZero
& & isPrecisionZero
& & ! ( ( flags & FLAGS_ALTERNATIVE ) & & ( base = = BASE_OCTAL ) ) ) ;
if ( flags & FLAGS_UNSIGNED )
{
isNegative = FALSE ;
flags & = ~ FLAGS_SHOWSIGN ;
}
else
{
isNegative = ( ( trio_intmax_t ) number < 0 ) ;
if ( isNegative )
number = - ( ( trio_intmax_t ) number ) ;
}
2001-03-27 16:47:33 +04:00
if ( flags & FLAGS_QUAD )
2001-06-05 16:46:33 +04:00
number & = ( trio_ulonglong_t ) - 1 ;
2001-03-27 16:47:33 +04:00
else if ( flags & FLAGS_LONG )
number & = ( unsigned long ) - 1 ;
else
number & = ( unsigned int ) - 1 ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* Build number */
pointer = bufferend = & buffer [ sizeof ( buffer ) - 1 ] ;
* pointer - - = NIL ;
for ( i = 1 ; i < ( int ) sizeof ( buffer ) ; i + + )
{
* pointer - - = digits [ number % base ] ;
number / = base ;
if ( number = = 0 )
break ;
2002-09-26 02:44:43 +04:00
if ( ( flags & FLAGS_QUOTE ) & & TrioFollowedBySeparator ( i + 1 ) )
2001-03-27 16:47:33 +04:00
{
/*
* We are building the number from the least significant
* to the most significant digit , so we have to copy the
* thousand separator backwards
*/
2002-09-26 02:44:43 +04:00
length = internalThousandSeparatorLength ;
2001-03-27 16:47:33 +04:00
if ( ( ( int ) ( pointer - buffer ) - length ) > 0 )
{
2001-04-21 20:57:29 +04:00
p = & internalThousandSeparator [ length - 1 ] ;
2001-03-27 16:47:33 +04:00
while ( length - - > 0 )
* pointer - - = * p - - ;
}
}
}
2003-04-03 19:28:28 +04:00
if ( ! ignoreNumber )
{
/* Adjust width */
width - = ( bufferend - pointer ) - 1 ;
}
2001-03-27 16:47:33 +04:00
/* Adjust precision */
if ( NO_PRECISION ! = precision )
{
precision - = ( bufferend - pointer ) - 1 ;
if ( precision < 0 )
precision = 0 ;
flags | = FLAGS_NILPADDING ;
}
2003-04-03 19:28:28 +04:00
/* Calculate padding */
count = ( ! ( ( flags & FLAGS_LEFTADJUST ) | | ( precision = = NO_PRECISION ) ) )
? precision
: 0 ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* Adjust width further */
if ( isNegative | | ( flags & FLAGS_SHOWSIGN ) | | ( flags & FLAGS_SPACE ) )
width - - ;
2003-04-03 19:28:28 +04:00
if ( ( flags & FLAGS_ALTERNATIVE ) & & ! isNumberZero )
2001-03-27 16:47:33 +04:00
{
switch ( base )
{
case BASE_BINARY :
case BASE_HEX :
width - = 2 ;
break ;
case BASE_OCTAL :
2003-04-03 19:28:28 +04:00
if ( ! ( flags & FLAGS_NILPADDING ) | | ( count = = 0 ) )
width - - ;
2001-03-27 16:47:33 +04:00
break ;
default :
break ;
}
}
/* Output prefixes spaces if needed */
if ( ! ( ( flags & FLAGS_LEFTADJUST ) | |
( ( flags & FLAGS_NILPADDING ) & & ( precision = = NO_PRECISION ) ) ) )
{
while ( width - - > count )
self - > OutStream ( self , CHAR_ADJUST ) ;
}
/* width has been adjusted for signs and alternatives */
if ( isNegative )
self - > OutStream ( self , ' - ' ) ;
else if ( flags & FLAGS_SHOWSIGN )
self - > OutStream ( self , ' + ' ) ;
else if ( flags & FLAGS_SPACE )
self - > OutStream ( self , ' ' ) ;
2003-04-03 19:28:28 +04:00
/* Prefix is not written when the value is zero */
if ( ( flags & FLAGS_ALTERNATIVE ) & & ! isNumberZero )
2001-03-27 16:47:33 +04:00
{
switch ( base )
{
case BASE_BINARY :
self - > OutStream ( self , ' 0 ' ) ;
self - > OutStream ( self , ( flags & FLAGS_UPPER ) ? ' B ' : ' b ' ) ;
break ;
case BASE_OCTAL :
2003-04-03 19:28:28 +04:00
if ( ! ( flags & FLAGS_NILPADDING ) | | ( count = = 0 ) )
self - > OutStream ( self , ' 0 ' ) ;
2001-03-27 16:47:33 +04:00
break ;
case BASE_HEX :
self - > OutStream ( self , ' 0 ' ) ;
self - > OutStream ( self , ( flags & FLAGS_UPPER ) ? ' X ' : ' x ' ) ;
break ;
default :
break ;
} /* switch base */
}
/* Output prefixed zero padding if needed */
if ( flags & FLAGS_NILPADDING )
{
if ( precision = = NO_PRECISION )
precision = width ;
while ( precision - - > 0 )
{
self - > OutStream ( self , ' 0 ' ) ;
width - - ;
}
}
2003-04-03 19:28:28 +04:00
if ( ! ignoreNumber )
2001-03-27 16:47:33 +04:00
{
2003-04-03 19:28:28 +04:00
/* Output the number itself */
while ( * ( + + pointer ) )
{
self - > OutStream ( self , * pointer ) ;
}
2001-03-27 16:47:33 +04:00
}
/* Output trailing spaces if needed */
if ( flags & FLAGS_LEFTADJUST )
{
while ( width - - > 0 )
self - > OutStream ( self , CHAR_ADJUST ) ;
}
}
2001-06-05 16:46:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioWriteStringCharacter
2001-06-05 16:46:33 +04:00
*
* Description :
* Output a single character of a string
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioWriteStringCharacter
TRIO_ARGS3 ( ( self , ch , flags ) ,
trio_class_t * self ,
int ch ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags )
2001-06-05 16:46:33 +04:00
{
if ( flags & FLAGS_ALTERNATIVE )
{
2002-09-26 02:44:43 +04:00
if ( ! isprint ( ch ) )
2001-06-05 16:46:33 +04:00
{
/*
* Non - printable characters are converted to C escapes or
* \ number , if no C escape exists .
*/
self - > OutStream ( self , CHAR_BACKSLASH ) ;
switch ( ch )
{
case ' \007 ' : self - > OutStream ( self , ' a ' ) ; break ;
case ' \b ' : self - > OutStream ( self , ' b ' ) ; break ;
case ' \f ' : self - > OutStream ( self , ' f ' ) ; break ;
case ' \n ' : self - > OutStream ( self , ' n ' ) ; break ;
case ' \r ' : self - > OutStream ( self , ' r ' ) ; break ;
case ' \t ' : self - > OutStream ( self , ' t ' ) ; break ;
case ' \v ' : self - > OutStream ( self , ' v ' ) ; break ;
case ' \\ ' : self - > OutStream ( self , ' \\ ' ) ; break ;
default :
self - > OutStream ( self , ' x ' ) ;
2002-09-26 02:44:43 +04:00
TrioWriteNumber ( self , ( trio_uintmax_t ) ch ,
2001-06-05 16:46:33 +04:00
FLAGS_UNSIGNED | FLAGS_NILPADDING ,
2 , 2 , BASE_HEX ) ;
break ;
}
}
else if ( ch = = CHAR_BACKSLASH )
{
self - > OutStream ( self , CHAR_BACKSLASH ) ;
self - > OutStream ( self , CHAR_BACKSLASH ) ;
}
else
{
self - > OutStream ( self , ch ) ;
}
}
else
{
self - > OutStream ( self , ch ) ;
}
}
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioWriteString
2001-03-27 16:47:33 +04:00
*
* Description :
* Output a string
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioWriteString
TRIO_ARGS5 ( ( self , string , flags , width , precision ) ,
trio_class_t * self ,
TRIO_CONST char * string ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width ,
int precision )
2001-03-27 16:47:33 +04:00
{
int length ;
int ch ;
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > OutStream ) ) ;
if ( string = = NULL )
{
2002-01-19 18:40:18 +03:00
string = internalNullString ;
length = sizeof ( internalNullString ) - 1 ;
2001-03-27 16:47:33 +04:00
/* Disable quoting for the null pointer */
flags & = ( ~ FLAGS_QUOTE ) ;
width = 0 ;
}
else
{
2002-01-19 18:40:18 +03:00
length = trio_length ( string ) ;
2001-03-27 16:47:33 +04:00
}
if ( ( NO_PRECISION ! = precision ) & &
( precision < length ) )
{
length = precision ;
}
width - = length ;
if ( flags & FLAGS_QUOTE )
self - > OutStream ( self , CHAR_QUOTE ) ;
if ( ! ( flags & FLAGS_LEFTADJUST ) )
{
while ( width - - > 0 )
self - > OutStream ( self , CHAR_ADJUST ) ;
}
while ( length - - > 0 )
{
/* The ctype parameters must be an unsigned char (or EOF) */
2001-06-05 16:46:33 +04:00
ch = ( int ) ( ( unsigned char ) ( * string + + ) ) ;
TrioWriteStringCharacter ( self , ch , flags ) ;
2001-03-27 16:47:33 +04:00
}
if ( flags & FLAGS_LEFTADJUST )
{
while ( width - - > 0 )
self - > OutStream ( self , CHAR_ADJUST ) ;
}
if ( flags & FLAGS_QUOTE )
self - > OutStream ( self , CHAR_QUOTE ) ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioWriteWideStringCharacter
2001-06-05 16:46:33 +04:00
*
* Description :
* Output a wide string as a multi - byte sequence
2001-03-27 16:47:33 +04:00
*/
2001-06-05 16:46:33 +04:00
# if TRIO_WIDECHAR
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioWriteWideStringCharacter
TRIO_ARGS4 ( ( self , wch , flags , width ) ,
trio_class_t * self ,
trio_wchar_t wch ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
int size ;
2001-03-27 16:47:33 +04:00
int i ;
2001-06-05 16:46:33 +04:00
int ch ;
char * string ;
char buffer [ MB_LEN_MAX + 1 ] ;
2001-04-21 20:57:29 +04:00
2001-06-05 16:46:33 +04:00
if ( width = = NO_WIDTH )
width = sizeof ( buffer ) ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
size = wctomb ( buffer , wch ) ;
if ( ( size < = 0 ) | | ( size > width ) | | ( buffer [ 0 ] = = NIL ) )
return 0 ;
2001-03-27 16:47:33 +04:00
2001-06-05 16:46:33 +04:00
string = buffer ;
i = size ;
while ( ( width > = i ) & & ( width - - > 0 ) & & ( i - - > 0 ) )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
/* The ctype parameters must be an unsigned char (or EOF) */
ch = ( int ) ( ( unsigned char ) ( * string + + ) ) ;
TrioWriteStringCharacter ( self , ch , flags ) ;
}
return size ;
}
# endif /* TRIO_WIDECHAR */
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioWriteWideString
2001-06-05 16:46:33 +04:00
*
* Description :
* Output a wide character string as a multi - byte string
*/
# if TRIO_WIDECHAR
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioWriteWideString
TRIO_ARGS5 ( ( self , wstring , flags , width , precision ) ,
trio_class_t * self ,
TRIO_CONST trio_wchar_t * wstring ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width ,
int precision )
2001-06-05 16:46:33 +04:00
{
int length ;
int size ;
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > OutStream ) ) ;
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2002-09-26 02:44:43 +04:00
( void ) mblen ( NULL , 0 ) ;
2001-06-05 16:46:33 +04:00
# endif
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
if ( wstring = = NULL )
{
TrioWriteString ( self , NULL , flags , width , precision ) ;
return ;
}
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
if ( NO_PRECISION = = precision )
{
length = INT_MAX ;
}
else
{
length = precision ;
width - = length ;
}
if ( flags & FLAGS_QUOTE )
self - > OutStream ( self , CHAR_QUOTE ) ;
if ( ! ( flags & FLAGS_LEFTADJUST ) )
{
while ( width - - > 0 )
self - > OutStream ( self , CHAR_ADJUST ) ;
}
while ( length > 0 )
{
size = TrioWriteWideStringCharacter ( self , * wstring + + , flags , length ) ;
if ( size = = 0 )
break ; /* while */
length - = size ;
}
if ( flags & FLAGS_LEFTADJUST )
{
while ( width - - > 0 )
self - > OutStream ( self , CHAR_ADJUST ) ;
}
if ( flags & FLAGS_QUOTE )
self - > OutStream ( self , CHAR_QUOTE ) ;
}
# endif /* TRIO_WIDECHAR */
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioWriteDouble
2002-09-26 02:44:43 +04:00
*
* http : //wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm
*
* " 5.2.4.2.2 paragraph #4
*
* The accuracy [ . . . ] is implementation defined , as is the accuracy
* of the conversion between floating - point internal representations
* and string representations performed by the libray routine in
* < stdio . h > "
*/
/* FIXME: handle all instances of constant long-double number (L)
* and * l ( ) math functions .
2001-06-05 16:46:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioWriteDouble
TRIO_ARGS6 ( ( self , number , flags , width , precision , base ) ,
trio_class_t * self ,
trio_long_double_t number ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width ,
int precision ,
int base )
{
trio_long_double_t integerNumber ;
trio_long_double_t fractionNumber ;
trio_long_double_t workNumber ;
2001-06-05 16:46:33 +04:00
int integerDigits ;
int fractionDigits ;
int exponentDigits ;
2002-09-26 02:44:43 +04:00
int baseDigits ;
int integerThreshold ;
int fractionThreshold ;
2001-06-05 16:46:33 +04:00
int expectedWidth ;
2002-09-26 02:44:43 +04:00
int exponent = 0 ;
2001-06-05 16:46:33 +04:00
unsigned int uExponent = 0 ;
2002-09-26 02:44:43 +04:00
int exponentBase ;
trio_long_double_t dblBase ;
trio_long_double_t dblIntegerBase ;
trio_long_double_t dblFractionBase ;
trio_long_double_t integerAdjust ;
trio_long_double_t fractionAdjust ;
2001-06-05 16:46:33 +04:00
BOOLEAN_T isNegative ;
BOOLEAN_T isExponentNegative = FALSE ;
2002-09-26 02:44:43 +04:00
BOOLEAN_T requireTwoDigitExponent ;
2001-06-05 16:46:33 +04:00
BOOLEAN_T isHex ;
2002-01-19 18:40:18 +03:00
TRIO_CONST char * digits ;
2002-09-26 02:44:43 +04:00
char * groupingPointer ;
2001-06-05 16:46:33 +04:00
int i ;
2002-09-26 02:44:43 +04:00
int index ;
BOOLEAN_T hasOnlyZeroes ;
2001-06-05 16:46:33 +04:00
int zeroes = 0 ;
2002-09-26 02:44:43 +04:00
register int trailingZeroes ;
BOOLEAN_T keepTrailingZeroes ;
BOOLEAN_T keepDecimalPoint ;
trio_long_double_t epsilon ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > OutStream ) ) ;
2002-09-26 02:44:43 +04:00
assert ( ( ( base > = MIN_BASE ) & & ( base < = MAX_BASE ) ) | | ( base = = NO_BASE ) ) ;
2001-06-05 16:46:33 +04:00
2002-09-26 02:44:43 +04:00
/* Determine sign and look for special quantities */
switch ( trio_fpclassify_and_signbit ( number , & isNegative ) )
2001-06-05 16:46:33 +04:00
{
2002-09-26 02:44:43 +04:00
case TRIO_FP_NAN :
2001-03-27 16:47:33 +04:00
TrioWriteString ( self ,
( flags & FLAGS_UPPER )
2002-09-26 02:44:43 +04:00
? NAN_UPPER
: NAN_LOWER ,
2001-03-27 16:47:33 +04:00
flags , width , precision ) ;
return ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
case TRIO_FP_INFINITE :
if ( isNegative )
{
/* Negative infinity */
TrioWriteString ( self ,
( flags & FLAGS_UPPER )
? " - " INFINITE_UPPER
: " - " INFINITE_LOWER ,
flags , width , precision ) ;
return ;
}
else
{
/* Positive infinity */
TrioWriteString ( self ,
( flags & FLAGS_UPPER )
? INFINITE_UPPER
: INFINITE_LOWER ,
flags , width , precision ) ;
return ;
}
2001-03-27 16:47:33 +04:00
default :
2001-04-21 20:57:29 +04:00
/* Finitude */
2001-03-27 16:47:33 +04:00
break ;
}
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
/* Normal numbers */
if ( flags & FLAGS_LONGDOUBLE )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
baseDigits = ( base = = 10 )
? LDBL_DIG
: ( int ) floor ( LDBL_MANT_DIG / TrioLogarithmBase ( base ) ) ;
epsilon = LDBL_EPSILON ;
}
else if ( flags & FLAGS_SHORT )
{
baseDigits = ( base = = BASE_DECIMAL )
? FLT_DIG
: ( int ) floor ( FLT_MANT_DIG / TrioLogarithmBase ( base ) ) ;
epsilon = FLT_EPSILON ;
}
else
{
baseDigits = ( base = = BASE_DECIMAL )
? DBL_DIG
: ( int ) floor ( DBL_MANT_DIG / TrioLogarithmBase ( base ) ) ;
epsilon = DBL_EPSILON ;
2001-03-27 16:47:33 +04:00
}
2001-04-21 20:57:29 +04:00
digits = ( flags & FLAGS_UPPER ) ? internalDigitsUpper : internalDigitsLower ;
2001-03-27 16:47:33 +04:00
isHex = ( base = = BASE_HEX ) ;
2002-09-26 02:44:43 +04:00
if ( base = = NO_BASE )
base = BASE_DECIMAL ;
dblBase = ( trio_long_double_t ) base ;
keepTrailingZeroes = ! ( ( flags & FLAGS_ROUNDING ) | |
( ( flags & FLAGS_FLOAT_G ) & &
! ( flags & FLAGS_ALTERNATIVE ) ) ) ;
if ( flags & FLAGS_ROUNDING )
precision = baseDigits ;
2003-04-03 19:28:28 +04:00
2001-03-27 16:47:33 +04:00
if ( precision = = NO_PRECISION )
2003-04-03 19:28:28 +04:00
{
if ( isHex )
{
keepTrailingZeroes = FALSE ;
precision = FLT_MANT_DIG ;
}
else
{
precision = FLT_DIG ;
}
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( isNegative )
number = - number ;
2001-06-05 16:46:33 +04:00
2002-09-26 02:44:43 +04:00
if ( isHex )
flags | = FLAGS_FLOAT_E ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
if ( flags & FLAGS_FLOAT_G )
2001-03-27 16:47:33 +04:00
{
if ( precision = = 0 )
precision = 1 ;
2001-06-05 16:46:33 +04:00
2002-09-26 02:44:43 +04:00
if ( ( number < 1.0E-4 ) | | ( number > powl ( base ,
( trio_long_double_t ) precision ) ) )
2001-06-05 16:46:33 +04:00
{
/* Use scientific notation */
flags | = FLAGS_FLOAT_E ;
}
else if ( number < 1.0 )
{
/*
* Use normal notation . If the integer part of the number is
* zero , then adjust the precision to include leading fractional
* zeros .
*/
2002-09-26 02:44:43 +04:00
workNumber = TrioLogarithm ( number , base ) ;
workNumber = TRIO_FABS ( workNumber ) ;
if ( workNumber - floorl ( workNumber ) < 0.001 )
2001-06-05 16:46:33 +04:00
workNumber - - ;
2002-09-26 02:44:43 +04:00
zeroes = ( int ) floorl ( workNumber ) ;
2001-06-05 16:46:33 +04:00
}
2001-03-27 16:47:33 +04:00
}
if ( flags & FLAGS_FLOAT_E )
{
/* Scale the number */
2002-09-26 02:44:43 +04:00
workNumber = TrioLogarithm ( number , base ) ;
2001-08-21 13:23:53 +04:00
if ( trio_isinf ( workNumber ) = = - 1 )
2001-03-27 16:47:33 +04:00
{
exponent = 0 ;
/* Undo setting */
if ( flags & FLAGS_FLOAT_G )
flags & = ~ FLAGS_FLOAT_E ;
}
else
{
2002-09-26 02:44:43 +04:00
exponent = ( int ) floorl ( workNumber ) ;
number / = powl ( dblBase , ( trio_long_double_t ) exponent ) ;
2001-03-27 16:47:33 +04:00
isExponentNegative = ( exponent < 0 ) ;
uExponent = ( isExponentNegative ) ? - exponent : exponent ;
2003-04-03 19:28:28 +04:00
if ( isHex )
uExponent * = 4 ; /* log16(2) */
2001-03-27 16:47:33 +04:00
/* No thousand separators */
flags & = ~ FLAGS_QUOTE ;
}
}
2002-09-26 02:44:43 +04:00
integerNumber = floorl ( number ) ;
fractionNumber = number - integerNumber ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/*
* Truncated number .
*
2002-09-26 02:44:43 +04:00
* Precision is number of significant digits for FLOAT_G
* and number of fractional digits for others .
2001-03-27 16:47:33 +04:00
*/
2002-09-26 02:44:43 +04:00
integerDigits = ( integerNumber > epsilon )
? 1 + ( int ) TrioLogarithm ( integerNumber , base )
2001-03-27 16:47:33 +04:00
: 1 ;
2001-06-05 16:46:33 +04:00
fractionDigits = ( ( flags & FLAGS_FLOAT_G ) & & ( zeroes = = 0 ) )
2001-03-27 16:47:33 +04:00
? precision - integerDigits
2001-06-05 16:46:33 +04:00
: zeroes + precision ;
2002-09-26 02:44:43 +04:00
dblFractionBase = TrioPower ( base , fractionDigits ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
workNumber = number + 0.5 / dblFractionBase ;
if ( floorl ( number ) ! = floorl ( workNumber ) )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
if ( flags & FLAGS_FLOAT_E )
{
/* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
2002-09-26 02:44:43 +04:00
exponent + + ;
isExponentNegative = ( exponent < 0 ) ;
uExponent = ( isExponentNegative ) ? - exponent : exponent ;
2003-04-03 19:28:28 +04:00
if ( isHex )
uExponent * = 4 ; /* log16(2) */
2002-09-26 02:44:43 +04:00
workNumber = ( number + 0.5 / dblFractionBase ) / dblBase ;
integerNumber = floorl ( workNumber ) ;
fractionNumber = workNumber - integerNumber ;
2001-06-05 16:46:33 +04:00
}
else
{
/* Adjust if number was rounded up one digit (ie. 99 to 100) */
2002-09-26 02:44:43 +04:00
integerNumber = floorl ( number + 0.5 ) ;
fractionNumber = 0.0 ;
integerDigits = ( integerNumber > epsilon )
? 1 + ( int ) TrioLogarithm ( integerNumber , base )
: 1 ;
2001-06-05 16:46:33 +04:00
}
2001-03-27 16:47:33 +04:00
}
2002-09-26 02:44:43 +04:00
/* Estimate accuracy */
integerAdjust = fractionAdjust = 0.5 ;
if ( flags & FLAGS_ROUNDING )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
if ( integerDigits > baseDigits )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
integerThreshold = baseDigits ;
fractionDigits = 0 ;
dblFractionBase = 1.0 ;
fractionThreshold = 0 ;
precision = 0 ; /* Disable decimal-point */
integerAdjust = TrioPower ( base , integerDigits - integerThreshold - 1 ) ;
fractionAdjust = 0.0 ;
2001-03-27 16:47:33 +04:00
}
2002-09-26 02:44:43 +04:00
else
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
integerThreshold = integerDigits ;
fractionThreshold = fractionDigits - integerThreshold ;
fractionAdjust = 1.0 ;
2001-03-27 16:47:33 +04:00
}
}
2002-09-26 02:44:43 +04:00
else
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
integerThreshold = INT_MAX ;
fractionThreshold = INT_MAX ;
2001-03-27 16:47:33 +04:00
}
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
/*
* Calculate expected width .
2001-03-27 16:47:33 +04:00
* sign + integer part + thousands separators + decimal point
* + fraction + exponent
*/
2002-09-26 02:44:43 +04:00
fractionAdjust / = dblFractionBase ;
hasOnlyZeroes = ( floorl ( ( fractionNumber + fractionAdjust ) * dblFractionBase ) < epsilon ) ;
keepDecimalPoint = ( ( flags & FLAGS_ALTERNATIVE ) | |
! ( ( precision = = 0 ) | |
( ! keepTrailingZeroes & & hasOnlyZeroes ) ) ) ;
if ( flags & FLAGS_FLOAT_E )
{
exponentDigits = ( uExponent = = 0 )
? 1
2003-04-03 19:28:28 +04:00
: ( int ) ceil ( TrioLogarithm ( ( double ) ( uExponent + 1 ) ,
( isHex ) ? 10.0 : base ) ) ;
2002-09-26 02:44:43 +04:00
}
else
exponentDigits = 0 ;
requireTwoDigitExponent = ( ( base = = BASE_DECIMAL ) & & ( exponentDigits = = 1 ) ) ;
expectedWidth = integerDigits + fractionDigits
+ ( keepDecimalPoint
? internalDecimalPointLength
: 0 )
+ ( ( flags & FLAGS_QUOTE )
? TrioCalcThousandSeparatorLength ( integerDigits )
: 0 ) ;
if ( isNegative | | ( flags & FLAGS_SHOWSIGN ) | | ( flags & FLAGS_SPACE ) )
2001-03-27 16:47:33 +04:00
expectedWidth + = sizeof ( " - " ) - 1 ;
if ( exponentDigits > 0 )
2001-06-05 16:46:33 +04:00
expectedWidth + = exponentDigits +
2002-09-26 02:44:43 +04:00
( ( requireTwoDigitExponent ? sizeof ( " E+0 " ) : sizeof ( " E+ " ) ) - 1 ) ;
2001-03-27 16:47:33 +04:00
if ( isHex )
expectedWidth + = sizeof ( " 0X " ) - 1 ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* Output prefixing */
if ( flags & FLAGS_NILPADDING )
{
/* Leading zeros must be after sign */
if ( isNegative )
self - > OutStream ( self , ' - ' ) ;
else if ( flags & FLAGS_SHOWSIGN )
self - > OutStream ( self , ' + ' ) ;
2002-09-26 02:44:43 +04:00
else if ( flags & FLAGS_SPACE )
self - > OutStream ( self , ' ' ) ;
2001-03-27 16:47:33 +04:00
if ( isHex )
{
self - > OutStream ( self , ' 0 ' ) ;
self - > OutStream ( self , ( flags & FLAGS_UPPER ) ? ' X ' : ' x ' ) ;
}
if ( ! ( flags & FLAGS_LEFTADJUST ) )
{
for ( i = expectedWidth ; i < width ; i + + )
{
self - > OutStream ( self , ' 0 ' ) ;
}
}
}
else
{
/* Leading spaces must be before sign */
if ( ! ( flags & FLAGS_LEFTADJUST ) )
{
for ( i = expectedWidth ; i < width ; i + + )
{
self - > OutStream ( self , CHAR_ADJUST ) ;
}
}
if ( isNegative )
self - > OutStream ( self , ' - ' ) ;
else if ( flags & FLAGS_SHOWSIGN )
self - > OutStream ( self , ' + ' ) ;
2002-09-26 02:44:43 +04:00
else if ( flags & FLAGS_SPACE )
self - > OutStream ( self , ' ' ) ;
2001-03-27 16:47:33 +04:00
if ( isHex )
{
self - > OutStream ( self , ' 0 ' ) ;
self - > OutStream ( self , ( flags & FLAGS_UPPER ) ? ' X ' : ' x ' ) ;
}
}
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
/* Output the integer part and thousand separators */
dblIntegerBase = 1.0 / TrioPower ( base , integerDigits - 1 ) ;
for ( i = 0 ; i < integerDigits ; i + + )
{
workNumber = floorl ( ( ( integerNumber + integerAdjust ) * dblIntegerBase ) ) ;
if ( i > integerThreshold )
{
/* Beyond accuracy */
self - > OutStream ( self , digits [ 0 ] ) ;
}
else
{
self - > OutStream ( self , digits [ ( int ) fmodl ( workNumber , dblBase ) ] ) ;
}
dblIntegerBase * = dblBase ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
if ( ( ( flags & ( FLAGS_FLOAT_E | FLAGS_QUOTE ) ) = = FLAGS_QUOTE )
& & TrioFollowedBySeparator ( integerDigits - i ) )
{
for ( groupingPointer = internalThousandSeparator ;
* groupingPointer ! = NIL ;
groupingPointer + + )
{
self - > OutStream ( self , * groupingPointer ) ;
}
}
}
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
/* Insert decimal point and build the fraction part */
trailingZeroes = 0 ;
if ( keepDecimalPoint )
{
if ( internalDecimalPoint )
{
self - > OutStream ( self , internalDecimalPoint ) ;
}
else
{
for ( i = 0 ; i < internalDecimalPointLength ; i + + )
{
self - > OutStream ( self , internalDecimalPointString [ i ] ) ;
}
}
}
for ( i = 0 ; i < fractionDigits ; i + + )
{
if ( ( integerDigits > integerThreshold ) | | ( i > fractionThreshold ) )
{
/* Beyond accuracy */
trailingZeroes + + ;
}
else
{
fractionNumber * = dblBase ;
fractionAdjust * = dblBase ;
workNumber = floorl ( fractionNumber + fractionAdjust ) ;
fractionNumber - = workNumber ;
index = ( int ) fmodl ( workNumber , dblBase ) ;
if ( index = = 0 )
{
trailingZeroes + + ;
}
else
{
while ( trailingZeroes > 0 )
{
/* Not trailing zeroes after all */
self - > OutStream ( self , digits [ 0 ] ) ;
trailingZeroes - - ;
}
self - > OutStream ( self , digits [ index ] ) ;
}
}
}
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
if ( keepTrailingZeroes )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
while ( trailingZeroes > 0 )
{
self - > OutStream ( self , digits [ 0 ] ) ;
trailingZeroes - - ;
}
2001-03-27 16:47:33 +04:00
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* Output exponent */
if ( exponentDigits > 0 )
{
self - > OutStream ( self ,
isHex
? ( ( flags & FLAGS_UPPER ) ? ' P ' : ' p ' )
: ( ( flags & FLAGS_UPPER ) ? ' E ' : ' e ' ) ) ;
self - > OutStream ( self , ( isExponentNegative ) ? ' - ' : ' + ' ) ;
2001-06-05 16:46:33 +04:00
/* The exponent must contain at least two digits */
2002-09-26 02:44:43 +04:00
if ( requireTwoDigitExponent )
2001-06-05 16:46:33 +04:00
self - > OutStream ( self , ' 0 ' ) ;
2003-04-03 19:28:28 +04:00
if ( isHex )
base = 10.0 ;
2002-09-26 02:44:43 +04:00
exponentBase = ( int ) TrioPower ( base , exponentDigits - 1 ) ;
2001-03-27 16:47:33 +04:00
for ( i = 0 ; i < exponentDigits ; i + + )
{
2002-09-26 02:44:43 +04:00
self - > OutStream ( self , digits [ ( uExponent / exponentBase ) % base ] ) ;
exponentBase / = base ;
2001-03-27 16:47:33 +04:00
}
}
/* Output trailing spaces */
if ( flags & FLAGS_LEFTADJUST )
{
for ( i = expectedWidth ; i < width ; i + + )
{
self - > OutStream ( self , CHAR_ADJUST ) ;
}
}
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioFormatProcess
*
* Description :
* This is the main engine for formatting output
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioFormatProcess
TRIO_ARGS3 ( ( data , format , parameters ) ,
trio_class_t * data ,
TRIO_CONST char * format ,
trio_parameter_t * parameters )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2001-03-27 16:47:33 +04:00
int charlen ;
# endif
int i ;
2002-01-19 18:40:18 +03:00
TRIO_CONST char * string ;
2002-09-26 02:44:43 +04:00
trio_pointer_t pointer ;
2003-04-03 19:28:28 +04:00
trio_flags_t flags ;
2001-03-27 16:47:33 +04:00
int width ;
int precision ;
int base ;
int index ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
index = 0 ;
i = 0 ;
2001-06-05 16:46:33 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2002-09-26 02:44:43 +04:00
( void ) mblen ( NULL , 0 ) ;
2001-03-27 16:47:33 +04:00
# endif
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
while ( format [ index ] )
{
2001-06-05 16:46:33 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2001-03-27 16:47:33 +04:00
if ( ! isascii ( format [ index ] ) )
{
charlen = mblen ( & format [ index ] , MB_LEN_MAX ) ;
2002-09-26 02:44:43 +04:00
/*
* Only valid multibyte characters are handled here . Invalid
* multibyte characters ( charlen = = - 1 ) are handled as normal
* characters .
*/
if ( charlen ! = - 1 )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
while ( charlen - - > 0 )
{
data - > OutStream ( data , format [ index + + ] ) ;
}
continue ; /* while characters left in formatting string */
2001-03-27 16:47:33 +04:00
}
}
2001-06-05 16:46:33 +04:00
# endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
2001-03-27 16:47:33 +04:00
if ( CHAR_IDENTIFIER = = format [ index ] )
{
if ( CHAR_IDENTIFIER = = format [ index + 1 ] )
{
2001-04-21 20:57:29 +04:00
data - > OutStream ( data , CHAR_IDENTIFIER ) ;
2001-03-27 16:47:33 +04:00
index + = 2 ;
}
else
{
/* Skip the parameter entries */
while ( parameters [ i ] . type = = FORMAT_PARAMETER )
i + + ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
flags = parameters [ i ] . flags ;
/* Find width */
width = parameters [ i ] . width ;
if ( flags & FLAGS_WIDTH_PARAMETER )
{
/* Get width from parameter list */
2001-04-21 20:57:29 +04:00
width = ( int ) parameters [ width ] . data . number . as_signed ;
2003-04-03 19:28:28 +04:00
if ( width < 0 )
{
/*
* A negative width is the same as the - flag and
* a positive width .
*/
flags | = FLAGS_LEFTADJUST ;
flags & = ~ FLAGS_NILPADDING ;
width = - width ;
}
2001-03-27 16:47:33 +04:00
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
/* Find precision */
if ( flags & FLAGS_PRECISION )
{
precision = parameters [ i ] . precision ;
if ( flags & FLAGS_PRECISION_PARAMETER )
{
/* Get precision from parameter list */
2001-04-21 20:57:29 +04:00
precision = ( int ) parameters [ precision ] . data . number . as_signed ;
2003-04-03 19:28:28 +04:00
if ( precision < 0 )
{
/*
* A negative precision is the same as no
* precision
*/
precision = NO_PRECISION ;
}
2001-03-27 16:47:33 +04:00
}
}
else
{
precision = NO_PRECISION ;
}
/* Find base */
base = parameters [ i ] . base ;
if ( flags & FLAGS_BASE_PARAMETER )
{
/* Get base from parameter list */
2001-04-21 20:57:29 +04:00
base = ( int ) parameters [ base ] . data . number . as_signed ;
2001-03-27 16:47:33 +04:00
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
switch ( parameters [ i ] . type )
{
case FORMAT_CHAR :
if ( flags & FLAGS_QUOTE )
2001-04-21 20:57:29 +04:00
data - > OutStream ( data , CHAR_QUOTE ) ;
2001-03-27 16:47:33 +04:00
if ( ! ( flags & FLAGS_LEFTADJUST ) )
{
while ( - - width > 0 )
2001-04-21 20:57:29 +04:00
data - > OutStream ( data , CHAR_ADJUST ) ;
2001-03-27 16:47:33 +04:00
}
2001-06-05 16:46:33 +04:00
# if TRIO_WIDECHAR
if ( flags & FLAGS_WIDECHAR )
{
TrioWriteWideStringCharacter ( data ,
2002-09-26 02:44:43 +04:00
( trio_wchar_t ) parameters [ i ] . data . number . as_signed ,
2001-06-05 16:46:33 +04:00
flags ,
NO_WIDTH ) ;
}
else
# endif
2002-01-19 18:40:18 +03:00
{
TrioWriteStringCharacter ( data ,
( int ) parameters [ i ] . data . number . as_signed ,
flags ) ;
}
2001-03-27 16:47:33 +04:00
if ( flags & FLAGS_LEFTADJUST )
{
while ( - - width > 0 )
2001-04-21 20:57:29 +04:00
data - > OutStream ( data , CHAR_ADJUST ) ;
2001-03-27 16:47:33 +04:00
}
if ( flags & FLAGS_QUOTE )
2001-04-21 20:57:29 +04:00
data - > OutStream ( data , CHAR_QUOTE ) ;
2001-03-27 16:47:33 +04:00
break ; /* FORMAT_CHAR */
case FORMAT_INT :
TrioWriteNumber ( data ,
2002-09-26 02:44:43 +04:00
parameters [ i ] . data . number . as_unsigned ,
2001-03-27 16:47:33 +04:00
flags ,
width ,
precision ,
base ) ;
break ; /* FORMAT_INT */
case FORMAT_DOUBLE :
TrioWriteDouble ( data ,
parameters [ i ] . data . longdoubleNumber ,
flags ,
width ,
precision ,
base ) ;
break ; /* FORMAT_DOUBLE */
case FORMAT_STRING :
2001-06-05 16:46:33 +04:00
# if TRIO_WIDECHAR
if ( flags & FLAGS_WIDECHAR )
{
TrioWriteWideString ( data ,
parameters [ i ] . data . wstring ,
flags ,
width ,
precision ) ;
}
else
# endif
{
TrioWriteString ( data ,
parameters [ i ] . data . string ,
flags ,
width ,
precision ) ;
}
2001-03-27 16:47:33 +04:00
break ; /* FORMAT_STRING */
case FORMAT_POINTER :
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_reference_t reference ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
reference . data = data ;
reference . parameter = & parameters [ i ] ;
trio_print_pointer ( & reference , parameters [ i ] . data . pointer ) ;
}
2001-03-27 16:47:33 +04:00
break ; /* FORMAT_POINTER */
case FORMAT_COUNT :
pointer = parameters [ i ] . data . pointer ;
if ( NULL ! = pointer )
{
2001-04-21 20:57:29 +04:00
/*
* C99 paragraph 7.19 .6 .1 .8 says " the number of
2001-03-27 16:47:33 +04:00
* characters written to the output stream so far by
* this call " , which is data->committed
*/
# if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
if ( flags & FLAGS_SIZE_T )
* ( size_t * ) pointer = ( size_t ) data - > committed ;
else
# endif
# if defined(QUALIFIER_PTRDIFF_T)
if ( flags & FLAGS_PTRDIFF_T )
* ( ptrdiff_t * ) pointer = ( ptrdiff_t ) data - > committed ;
else
# endif
# if defined(QUALIFIER_INTMAX_T)
if ( flags & FLAGS_INTMAX_T )
2001-06-05 16:46:33 +04:00
* ( trio_intmax_t * ) pointer = ( trio_intmax_t ) data - > committed ;
2001-03-27 16:47:33 +04:00
else
# endif
if ( flags & FLAGS_QUAD )
{
2001-06-05 16:46:33 +04:00
* ( trio_ulonglong_t * ) pointer = ( trio_ulonglong_t ) data - > committed ;
2001-03-27 16:47:33 +04:00
}
else if ( flags & FLAGS_LONG )
{
* ( long int * ) pointer = ( long int ) data - > committed ;
}
else if ( flags & FLAGS_SHORT )
{
* ( short int * ) pointer = ( short int ) data - > committed ;
}
else
{
* ( int * ) pointer = ( int ) data - > committed ;
}
}
break ; /* FORMAT_COUNT */
case FORMAT_PARAMETER :
break ; /* FORMAT_PARAMETER */
# if defined(FORMAT_ERRNO)
case FORMAT_ERRNO :
2002-01-19 18:40:18 +03:00
string = trio_error ( parameters [ i ] . data . errorNumber ) ;
2001-03-27 16:47:33 +04:00
if ( string )
{
TrioWriteString ( data ,
string ,
flags ,
width ,
precision ) ;
}
else
{
2001-04-21 20:57:29 +04:00
data - > OutStream ( data , ' # ' ) ;
2001-03-27 16:47:33 +04:00
TrioWriteNumber ( data ,
2002-09-26 02:44:43 +04:00
( trio_uintmax_t ) parameters [ i ] . data . errorNumber ,
2001-03-27 16:47:33 +04:00
flags ,
width ,
precision ,
BASE_DECIMAL ) ;
}
break ; /* FORMAT_ERRNO */
2001-04-21 20:57:29 +04:00
# endif /* defined(FORMAT_ERRNO) */
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
# if defined(FORMAT_USER_DEFINED)
case FORMAT_USER_DEFINED :
{
2002-01-19 18:40:18 +03:00
trio_reference_t reference ;
trio_userdef_t * def = NULL ;
2001-04-21 20:57:29 +04:00
if ( parameters [ i ] . user_name [ 0 ] = = NIL )
{
/* Use handle */
if ( ( i > 0 ) | |
( parameters [ i - 1 ] . type = = FORMAT_PARAMETER ) )
2002-01-19 18:40:18 +03:00
def = ( trio_userdef_t * ) parameters [ i - 1 ] . data . pointer ;
2001-04-21 20:57:29 +04:00
}
else
{
/* Look up namespace */
def = TrioFindNamespace ( parameters [ i ] . user_name , NULL ) ;
}
if ( def ) {
reference . data = data ;
reference . parameter = & parameters [ i ] ;
def - > callback ( & reference ) ;
}
}
break ;
# endif /* defined(FORMAT_USER_DEFINED) */
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
default :
break ;
} /* switch parameter type */
/* Prepare for next */
index = parameters [ i ] . indexAfterSpecifier ;
i + + ;
}
}
else /* not identifier */
{
2001-04-21 20:57:29 +04:00
data - > OutStream ( data , format [ index + + ] ) ;
2001-03-27 16:47:33 +04:00
}
}
return data - > processed ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioFormatRef
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioFormatRef
TRIO_ARGS4 ( ( reference , format , arglist , argarray ) ,
trio_reference_t * reference ,
TRIO_CONST char * format ,
2013-12-12 11:04:43 +04:00
TRIO_VA_LIST_PTR arglist ,
2002-09-26 02:44:43 +04:00
trio_pointer_t * argarray )
2001-03-27 16:47:33 +04:00
{
2001-04-21 20:57:29 +04:00
int status ;
2002-01-19 18:40:18 +03:00
trio_parameter_t parameters [ MAX_PARAMETERS ] ;
2001-03-27 16:47:33 +04:00
2002-01-19 18:40:18 +03:00
status = TrioParse ( TYPE_PRINT , format , parameters , arglist , argarray ) ;
2001-04-21 20:57:29 +04:00
if ( status < 0 )
return status ;
2001-03-27 16:47:33 +04:00
2002-01-19 18:40:18 +03:00
status = TrioFormatProcess ( reference - > data , format , parameters ) ;
if ( reference - > data - > error ! = 0 )
{
status = reference - > data - > error ;
}
return status ;
2001-03-27 16:47:33 +04:00
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioFormat
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioFormat
TRIO_ARGS6 ( ( destination , destinationSize , OutStream , format , arglist , argarray ) ,
trio_pointer_t destination ,
2001-04-21 20:57:29 +04:00
size_t destinationSize ,
2002-09-26 02:44:43 +04:00
void ( * OutStream ) TRIO_PROTO ( ( trio_class_t * , int ) ) ,
2002-01-19 18:40:18 +03:00
TRIO_CONST char * format ,
2013-12-12 11:04:43 +04:00
TRIO_VA_LIST_PTR arglist ,
2002-09-26 02:44:43 +04:00
trio_pointer_t * argarray )
2001-03-27 16:47:33 +04:00
{
2001-04-21 20:57:29 +04:00
int status ;
2002-01-19 18:40:18 +03:00
trio_class_t data ;
trio_parameter_t parameters [ MAX_PARAMETERS ] ;
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
assert ( VALID ( OutStream ) ) ;
assert ( VALID ( format ) ) ;
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
memset ( & data , 0 , sizeof ( data ) ) ;
data . OutStream = OutStream ;
data . location = destination ;
data . max = destinationSize ;
2002-01-19 18:40:18 +03:00
data . error = 0 ;
2001-04-21 20:57:29 +04:00
# if defined(USE_LOCALE)
if ( NULL = = internalLocaleValues )
{
TrioSetLocale ( ) ;
}
# endif
2002-01-19 18:40:18 +03:00
status = TrioParse ( TYPE_PRINT , format , parameters , arglist , argarray ) ;
2001-04-21 20:57:29 +04:00
if ( status < 0 )
return status ;
2002-01-19 18:40:18 +03:00
status = TrioFormatProcess ( & data , format , parameters ) ;
if ( data . error ! = 0 )
{
status = data . error ;
}
return status ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioOutStreamFile
2001-04-21 20:57:29 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioOutStreamFile
TRIO_ARGS2 ( ( self , output ) ,
trio_class_t * self ,
int output )
2001-04-21 20:57:29 +04:00
{
2002-09-26 02:44:43 +04:00
FILE * file ;
2001-04-21 20:57:29 +04:00
assert ( VALID ( self ) ) ;
2002-09-26 02:44:43 +04:00
assert ( VALID ( self - > location ) ) ;
2001-04-21 20:57:29 +04:00
2002-09-26 02:44:43 +04:00
file = ( FILE * ) self - > location ;
2001-04-21 20:57:29 +04:00
self - > processed + + ;
2002-01-19 18:40:18 +03:00
if ( fputc ( output , file ) = = EOF )
{
self - > error = TRIO_ERROR_RETURN ( TRIO_EOF , 0 ) ;
}
else
{
self - > committed + + ;
}
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioOutStreamFileDescriptor
2001-04-21 20:57:29 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioOutStreamFileDescriptor
TRIO_ARGS2 ( ( self , output ) ,
trio_class_t * self ,
int output )
2001-04-21 20:57:29 +04:00
{
2002-09-26 02:44:43 +04:00
int fd ;
2001-04-21 20:57:29 +04:00
char ch ;
assert ( VALID ( self ) ) ;
2002-09-26 02:44:43 +04:00
fd = * ( ( int * ) self - > location ) ;
2001-04-21 20:57:29 +04:00
ch = ( char ) output ;
2001-03-27 16:47:33 +04:00
self - > processed + + ;
2002-01-19 18:40:18 +03:00
if ( write ( fd , & ch , sizeof ( char ) ) = = - 1 )
{
self - > error = TRIO_ERROR_RETURN ( TRIO_ERRNO , 0 ) ;
}
else
{
self - > committed + + ;
}
2001-03-27 16:47:33 +04:00
}
2002-09-26 02:44:43 +04:00
/*************************************************************************
* TrioOutStreamCustom
*/
TRIO_PRIVATE void
TrioOutStreamCustom
TRIO_ARGS2 ( ( self , output ) ,
trio_class_t * self ,
int output )
{
int status ;
trio_custom_t * data ;
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > location ) ) ;
data = ( trio_custom_t * ) self - > location ;
if ( data - > stream . out )
{
status = ( data - > stream . out ) ( data - > closure , output ) ;
if ( status > = 0 )
{
self - > committed + + ;
}
else
{
if ( self - > error = = 0 )
{
self - > error = TRIO_ERROR_RETURN ( TRIO_ECUSTOM , - status ) ;
}
}
}
self - > processed + + ;
}
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioOutStreamString
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioOutStreamString
TRIO_ARGS2 ( ( self , output ) ,
trio_class_t * self ,
int output )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
char * * buffer ;
2001-03-27 16:47:33 +04:00
assert ( VALID ( self ) ) ;
2002-09-26 02:44:43 +04:00
assert ( VALID ( self - > location ) ) ;
2001-03-27 16:47:33 +04:00
2002-09-26 02:44:43 +04:00
buffer = ( char * * ) self - > location ;
2001-03-27 16:47:33 +04:00
* * buffer = ( char ) output ;
( * buffer ) + + ;
self - > processed + + ;
self - > committed + + ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioOutStreamStringMax
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioOutStreamStringMax
TRIO_ARGS2 ( ( self , output ) ,
trio_class_t * self ,
int output )
2001-03-27 16:47:33 +04:00
{
char * * buffer ;
assert ( VALID ( self ) ) ;
2002-09-26 02:44:43 +04:00
assert ( VALID ( self - > location ) ) ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
buffer = ( char * * ) self - > location ;
if ( self - > processed < self - > max )
{
* * buffer = ( char ) output ;
( * buffer ) + + ;
self - > committed + + ;
}
self - > processed + + ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioOutStreamStringDynamic
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioOutStreamStringDynamic
TRIO_ARGS2 ( ( self , output ) ,
trio_class_t * self ,
int output )
2001-03-27 16:47:33 +04:00
{
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > location ) ) ;
2002-01-19 18:40:18 +03:00
if ( self - > error = = 0 )
2001-03-27 16:47:33 +04:00
{
2002-01-19 18:40:18 +03:00
trio_xstring_append_char ( ( trio_string_t * ) self - > location ,
( char ) output ) ;
self - > committed + + ;
2001-03-27 16:47:33 +04:00
}
2002-01-19 18:40:18 +03:00
/* The processed variable must always be increased */
2001-03-27 16:47:33 +04:00
self - > processed + + ;
}
2002-01-19 18:40:18 +03:00
/*************************************************************************
*
* Formatted printing functions
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined(TRIO_DOCUMENTATION)
# include "doc / doc_printf.h"
# endif
/** @addtogroup Printf
@ {
*/
2001-03-27 16:47:33 +04:00
/*************************************************************************
2001-04-21 20:57:29 +04:00
* printf
*/
2002-01-19 18:40:18 +03:00
/**
Print to standard output stream .
@ param format Formatting string .
@ param . . . Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_printf
TRIO_VARGS2 ( ( format , va_alist ) ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
2013-12-12 11:04:43 +04:00
status = TrioFormat ( stdout , 0 , TrioOutStreamFile , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
/**
Print to standard output stream .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vprintf
TRIO_ARGS2 ( ( format , args ) ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( format ) ) ;
2013-12-12 11:04:43 +04:00
return TrioFormat ( stdout , 0 , TrioOutStreamFile , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
/**
Print to standard output stream .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_printfv
TRIO_ARGS2 ( ( format , args ) ,
TRIO_CONST char * format ,
trio_pointer_t * args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( format ) ) ;
2002-09-26 02:44:43 +04:00
return TrioFormat ( stdout , 0 , TrioOutStreamFile , format , NULL , args ) ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* fprintf
*/
2002-01-19 18:40:18 +03:00
/**
Print to file .
@ param file File pointer .
@ param format Formatting string .
@ param . . . Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_fprintf
TRIO_VARGS3 ( ( file , format , va_alist ) ,
FILE * file ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
assert ( VALID ( file ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
2013-12-12 11:04:43 +04:00
status = TrioFormat ( file , 0 , TrioOutStreamFile , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
/**
Print to file .
@ param file File pointer .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vfprintf
TRIO_ARGS3 ( ( file , format , args ) ,
FILE * file ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( file ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2013-12-12 11:04:43 +04:00
return TrioFormat ( file , 0 , TrioOutStreamFile , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
/**
Print to file .
@ param file File pointer .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_fprintfv
TRIO_ARGS3 ( ( file , format , args ) ,
FILE * file ,
TRIO_CONST char * format ,
trio_pointer_t * args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( file ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioFormat ( file , 0 , TrioOutStreamFile , format , NULL , args ) ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* dprintf
*/
2002-01-19 18:40:18 +03:00
/**
Print to file descriptor .
@ param fd File descriptor .
@ param format Formatting string .
@ param . . . Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_dprintf
TRIO_VARGS3 ( ( fd , format , va_alist ) ,
int fd ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
2013-12-12 11:04:43 +04:00
status = TrioFormat ( & fd , 0 , TrioOutStreamFileDescriptor , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
/**
Print to file descriptor .
@ param fd File descriptor .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vdprintf
TRIO_ARGS3 ( ( fd , format , args ) ,
int fd ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2013-12-12 11:04:43 +04:00
return TrioFormat ( & fd , 0 , TrioOutStreamFileDescriptor , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
/**
Print to file descriptor .
@ param fd File descriptor .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_dprintfv
TRIO_ARGS3 ( ( fd , format , args ) ,
int fd ,
TRIO_CONST char * format ,
trio_pointer_t * args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioFormat ( & fd , 0 , TrioOutStreamFileDescriptor , format , NULL , args ) ;
}
/*************************************************************************
* cprintf
*/
TRIO_PUBLIC int
trio_cprintf
TRIO_VARGS4 ( ( stream , closure , format , va_alist ) ,
trio_outstream_t stream ,
trio_pointer_t closure ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
{
int status ;
va_list args ;
trio_custom_t data ;
assert ( VALID ( stream ) ) ;
assert ( VALID ( format ) ) ;
TRIO_VA_START ( args , format ) ;
data . stream . out = stream ;
data . closure = closure ;
2013-12-12 11:04:43 +04:00
status = TrioFormat ( & data , 0 , TrioOutStreamCustom , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
return status ;
}
TRIO_PUBLIC int
trio_vcprintf
TRIO_ARGS4 ( ( stream , closure , format , args ) ,
trio_outstream_t stream ,
trio_pointer_t closure ,
TRIO_CONST char * format ,
va_list args )
{
trio_custom_t data ;
assert ( VALID ( stream ) ) ;
assert ( VALID ( format ) ) ;
data . stream . out = stream ;
data . closure = closure ;
2013-12-12 11:04:43 +04:00
return TrioFormat ( & data , 0 , TrioOutStreamCustom , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
}
TRIO_PUBLIC int
trio_cprintfv
TRIO_ARGS4 ( ( stream , closure , format , args ) ,
trio_outstream_t stream ,
trio_pointer_t closure ,
TRIO_CONST char * format ,
void * * args )
{
trio_custom_t data ;
assert ( VALID ( stream ) ) ;
assert ( VALID ( format ) ) ;
data . stream . out = stream ;
data . closure = closure ;
return TrioFormat ( & data , 0 , TrioOutStreamCustom , format , NULL , args ) ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* sprintf
*/
2002-01-19 18:40:18 +03:00
/**
Print to string .
@ param buffer Output string .
@ param format Formatting string .
@ param . . . Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_sprintf
TRIO_VARGS3 ( ( buffer , format , va_alist ) ,
char * buffer ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
2013-12-12 11:04:43 +04:00
status = TrioFormat ( & buffer , 0 , TrioOutStreamString , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
* buffer = NIL ; /* Terminate with NIL character */
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
/**
Print to string .
@ param buffer Output string .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vsprintf
TRIO_ARGS3 ( ( buffer , format , args ) ,
char * buffer ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
int status ;
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2013-12-12 11:04:43 +04:00
status = TrioFormat ( & buffer , 0 , TrioOutStreamString , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
* buffer = NIL ;
return status ;
}
2002-01-19 18:40:18 +03:00
/**
Print to string .
@ param buffer Output string .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_sprintfv
TRIO_ARGS3 ( ( buffer , format , args ) ,
char * buffer ,
TRIO_CONST char * format ,
trio_pointer_t * args )
2001-04-21 20:57:29 +04:00
{
int status ;
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2002-09-26 02:44:43 +04:00
status = TrioFormat ( & buffer , 0 , TrioOutStreamString , format , NULL , args ) ;
2001-04-21 20:57:29 +04:00
* buffer = NIL ;
return status ;
}
/*************************************************************************
* snprintf
*/
2002-01-19 18:40:18 +03:00
/**
Print at most @ p max characters to string .
@ param buffer Output string .
@ param max Maximum number of characters to print .
@ param format Formatting string .
@ param . . . Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_snprintf
TRIO_VARGS4 ( ( buffer , max , format , va_alist ) ,
char * buffer ,
size_t max ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
2002-01-19 18:40:18 +03:00
status = TrioFormat ( & buffer , max > 0 ? max - 1 : 0 ,
2013-12-12 11:04:43 +04:00
TrioOutStreamStringMax , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-01-19 18:40:18 +03:00
if ( max > 0 )
2001-04-21 20:57:29 +04:00
* buffer = NIL ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
/**
Print at most @ p max characters to string .
@ param buffer Output string .
@ param max Maximum number of characters to print .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vsnprintf
TRIO_ARGS4 ( ( buffer , max , format , args ) ,
char * buffer ,
size_t max ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
int status ;
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2002-01-19 18:40:18 +03:00
status = TrioFormat ( & buffer , max > 0 ? max - 1 : 0 ,
2013-12-12 11:04:43 +04:00
TrioOutStreamStringMax , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-01-19 18:40:18 +03:00
if ( max > 0 )
2001-04-21 20:57:29 +04:00
* buffer = NIL ;
return status ;
}
2002-01-19 18:40:18 +03:00
/**
Print at most @ p max characters to string .
@ param buffer Output string .
@ param max Maximum number of characters to print .
@ param format Formatting string .
@ param args Arguments .
@ return Number of printed characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_snprintfv
TRIO_ARGS4 ( ( buffer , max , format , args ) ,
char * buffer ,
size_t max ,
TRIO_CONST char * format ,
trio_pointer_t * args )
2001-04-21 20:57:29 +04:00
{
int status ;
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2002-01-19 18:40:18 +03:00
status = TrioFormat ( & buffer , max > 0 ? max - 1 : 0 ,
2002-09-26 02:44:43 +04:00
TrioOutStreamStringMax , format , NULL , args ) ;
2002-01-19 18:40:18 +03:00
if ( max > 0 )
2001-04-21 20:57:29 +04:00
* buffer = NIL ;
return status ;
}
/*************************************************************************
* snprintfcat
* Appends the new string to the buffer string overwriting the ' \0 '
* character at the end of buffer .
*/
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_snprintfcat
TRIO_VARGS4 ( ( buffer , max , format , va_alist ) ,
char * buffer ,
size_t max ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
size_t buf_len ;
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
2001-04-21 20:57:29 +04:00
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2002-01-19 18:40:18 +03:00
buf_len = trio_length ( buffer ) ;
2001-04-21 20:57:29 +04:00
buffer = & buffer [ buf_len ] ;
2002-01-19 18:40:18 +03:00
status = TrioFormat ( & buffer , max - 1 - buf_len ,
2013-12-12 11:04:43 +04:00
TrioOutStreamStringMax , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
* buffer = NIL ;
return status ;
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vsnprintfcat
TRIO_ARGS4 ( ( buffer , max , format , args ) ,
char * buffer ,
size_t max ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
int status ;
size_t buf_len ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2002-01-19 18:40:18 +03:00
buf_len = trio_length ( buffer ) ;
2001-04-21 20:57:29 +04:00
buffer = & buffer [ buf_len ] ;
2002-01-19 18:40:18 +03:00
status = TrioFormat ( & buffer , max - 1 - buf_len ,
2013-12-12 11:04:43 +04:00
TrioOutStreamStringMax , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
* buffer = NIL ;
return status ;
}
/*************************************************************************
* trio_aprintf
*/
/* Deprecated */
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC char *
2002-09-26 02:44:43 +04:00
trio_aprintf
TRIO_VARGS2 ( ( format , va_alist ) ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
va_list args ;
2002-01-19 18:40:18 +03:00
trio_string_t * info ;
char * result = NULL ;
2001-04-21 20:57:29 +04:00
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
info = trio_xstring_duplicate ( " " ) ;
if ( info )
{
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
2002-01-19 18:40:18 +03:00
( void ) TrioFormat ( info , 0 , TrioOutStreamStringDynamic ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2002-01-19 18:40:18 +03:00
trio_string_terminate ( info ) ;
result = trio_string_extract ( info ) ;
trio_string_destroy ( info ) ;
}
return result ;
2001-04-21 20:57:29 +04:00
}
/* Deprecated */
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC char *
2002-09-26 02:44:43 +04:00
trio_vaprintf
TRIO_ARGS2 ( ( format , args ) ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_string_t * info ;
char * result = NULL ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
info = trio_xstring_duplicate ( " " ) ;
if ( info )
{
( void ) TrioFormat ( info , 0 , TrioOutStreamStringDynamic ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-01-19 18:40:18 +03:00
trio_string_terminate ( info ) ;
result = trio_string_extract ( info ) ;
trio_string_destroy ( info ) ;
}
return result ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_asprintf
TRIO_VARGS3 ( ( result , format , va_alist ) ,
char * * result ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
va_list args ;
int status ;
2002-01-19 18:40:18 +03:00
trio_string_t * info ;
2001-04-21 20:57:29 +04:00
assert ( VALID ( format ) ) ;
2002-01-19 18:40:18 +03:00
* result = NULL ;
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
info = trio_xstring_duplicate ( " " ) ;
if ( info = = NULL )
{
status = TRIO_ERROR_RETURN ( TRIO_ENOMEM , 0 ) ;
}
else
{
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
2002-01-19 18:40:18 +03:00
status = TrioFormat ( info , 0 , TrioOutStreamStringDynamic ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2002-01-19 18:40:18 +03:00
if ( status > = 0 )
{
trio_string_terminate ( info ) ;
* result = trio_string_extract ( info ) ;
}
trio_string_destroy ( info ) ;
}
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vasprintf
TRIO_ARGS3 ( ( result , format , args ) ,
char * * result ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
int status ;
2002-01-19 18:40:18 +03:00
trio_string_t * info ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
assert ( VALID ( format ) ) ;
2002-01-19 18:40:18 +03:00
* result = NULL ;
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
info = trio_xstring_duplicate ( " " ) ;
if ( info = = NULL )
{
status = TRIO_ERROR_RETURN ( TRIO_ENOMEM , 0 ) ;
}
else
{
status = TrioFormat ( info , 0 , TrioOutStreamStringDynamic ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-01-19 18:40:18 +03:00
if ( status > = 0 )
{
trio_string_terminate ( info ) ;
* result = trio_string_extract ( info ) ;
}
trio_string_destroy ( info ) ;
}
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
/** @} End of Printf documentation module */
2001-04-21 20:57:29 +04:00
/*************************************************************************
*
2002-01-19 18:40:18 +03:00
* CALLBACK
2001-04-21 20:57:29 +04:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-19 18:40:18 +03:00
# if defined(TRIO_DOCUMENTATION)
# include "doc / doc_register.h"
# endif
/**
@ addtogroup UserDefined
@ {
*/
2002-09-26 02:44:43 +04:00
# if TRIO_EXTENSION
2001-04-21 20:57:29 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* trio_register
2001-04-21 20:57:29 +04:00
*/
2002-01-19 18:40:18 +03:00
/**
Register new user - defined specifier .
@ param callback
@ param name
@ return Handle .
*/
2012-09-11 09:26:36 +04:00
TRIO_PUBLIC trio_pointer_t
2002-09-26 02:44:43 +04:00
trio_register
TRIO_ARGS2 ( ( callback , name ) ,
trio_callback_t callback ,
TRIO_CONST char * name )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_userdef_t * def ;
trio_userdef_t * prev = NULL ;
2001-04-21 20:57:29 +04:00
if ( callback = = NULL )
return NULL ;
if ( name )
{
2001-06-05 16:46:33 +04:00
/* Handle built-in namespaces */
if ( name [ 0 ] = = ' : ' )
{
2002-01-19 18:40:18 +03:00
if ( trio_equal ( name , " :enter " ) )
2001-06-05 16:46:33 +04:00
{
internalEnterCriticalRegion = callback ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal ( name , " :leave " ) )
2001-06-05 16:46:33 +04:00
{
internalLeaveCriticalRegion = callback ;
}
return NULL ;
}
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
/* Bail out if namespace is too long */
2002-01-19 18:40:18 +03:00
if ( trio_length ( name ) > = MAX_USER_NAME )
2001-04-21 20:57:29 +04:00
return NULL ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
/* Bail out if namespace already is registered */
def = TrioFindNamespace ( name , & prev ) ;
if ( def )
return NULL ;
}
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
def = ( trio_userdef_t * ) TRIO_MALLOC ( sizeof ( trio_userdef_t ) ) ;
2001-04-21 20:57:29 +04:00
if ( def )
{
2001-06-05 16:46:33 +04:00
if ( internalEnterCriticalRegion )
( void ) internalEnterCriticalRegion ( NULL ) ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
if ( name )
{
/* Link into internal list */
if ( prev = = NULL )
internalUserDef = def ;
else
prev - > next = def ;
}
/* Initialize */
def - > callback = callback ;
def - > name = ( name = = NULL )
? NULL
2002-01-19 18:40:18 +03:00
: trio_duplicate ( name ) ;
2001-04-21 20:57:29 +04:00
def - > next = NULL ;
2001-06-05 16:46:33 +04:00
if ( internalLeaveCriticalRegion )
( void ) internalLeaveCriticalRegion ( NULL ) ;
2001-04-21 20:57:29 +04:00
}
2002-09-26 02:44:43 +04:00
return ( trio_pointer_t ) def ;
2001-04-21 20:57:29 +04:00
}
2002-09-26 02:44:43 +04:00
/**
Unregister an existing user - defined specifier .
@ param handle
2001-04-21 20:57:29 +04:00
*/
void
2002-09-26 02:44:43 +04:00
trio_unregister
TRIO_ARGS1 ( ( handle ) ,
trio_pointer_t handle )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_userdef_t * self = ( trio_userdef_t * ) handle ;
trio_userdef_t * def ;
trio_userdef_t * prev = NULL ;
2001-04-21 20:57:29 +04:00
assert ( VALID ( self ) ) ;
if ( self - > name )
{
def = TrioFindNamespace ( self - > name , & prev ) ;
if ( def )
{
2001-06-05 16:46:33 +04:00
if ( internalEnterCriticalRegion )
( void ) internalEnterCriticalRegion ( NULL ) ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
if ( prev = = NULL )
internalUserDef = NULL ;
else
prev - > next = def - > next ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
if ( internalLeaveCriticalRegion )
( void ) internalLeaveCriticalRegion ( NULL ) ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
trio_destroy ( self - > name ) ;
2001-04-21 20:57:29 +04:00
}
2001-06-05 16:46:33 +04:00
TRIO_FREE ( self ) ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_format [ public ]
*/
2002-01-19 18:40:18 +03:00
TRIO_CONST char *
2002-09-26 02:44:43 +04:00
trio_get_format
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2002-09-26 02:44:43 +04:00
# if defined(FORMAT_USER_DEFINED)
2002-01-19 18:40:18 +03:00
assert ( ( ( trio_reference_t * ) ref ) - > parameter - > type = = FORMAT_USER_DEFINED ) ;
2002-09-26 02:44:43 +04:00
# endif
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > user_data ) ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_argument [ public ]
*/
2012-09-11 09:26:36 +04:00
trio_pointer_t
2002-09-26 02:44:43 +04:00
trio_get_argument
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2002-09-26 02:44:43 +04:00
# if defined(FORMAT_USER_DEFINED)
2002-01-19 18:40:18 +03:00
assert ( ( ( trio_reference_t * ) ref ) - > parameter - > type = = FORMAT_USER_DEFINED ) ;
2002-09-26 02:44:43 +04:00
# endif
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
return ( ( trio_reference_t * ) ref ) - > parameter - > data . pointer ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_width / trio_set_width [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_width
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
return ( ( trio_reference_t * ) ref ) - > parameter - > width ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_width
TRIO_ARGS2 ( ( ref , width ) ,
trio_pointer_t ref ,
int width )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > width = width ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_precision / trio_set_precision [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_precision
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > precision ) ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_precision
TRIO_ARGS2 ( ( ref , precision ) ,
trio_pointer_t ref ,
int precision )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > precision = precision ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_base / trio_set_base [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_base
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > base ) ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_base
TRIO_ARGS2 ( ( ref , base ) ,
trio_pointer_t ref ,
int base )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > base = base ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_long / trio_set_long [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_long
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_LONG )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_long
TRIO_ARGS2 ( ( ref , is_long ) ,
trio_pointer_t ref ,
int is_long )
2001-04-21 20:57:29 +04:00
{
if ( is_long )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_LONG ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_LONG ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_longlong / trio_set_longlong [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_longlong
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_QUAD )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_longlong
TRIO_ARGS2 ( ( ref , is_longlong ) ,
trio_pointer_t ref ,
int is_longlong )
2001-04-21 20:57:29 +04:00
{
if ( is_longlong )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_QUAD ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_QUAD ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_longdouble / trio_set_longdouble [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_longdouble
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_LONGDOUBLE )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_longdouble
TRIO_ARGS2 ( ( ref , is_longdouble ) ,
trio_pointer_t ref ,
int is_longdouble )
2001-04-21 20:57:29 +04:00
{
if ( is_longdouble )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_LONGDOUBLE ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_LONGDOUBLE ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_short / trio_set_short [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_short
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_SHORT )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_short
TRIO_ARGS2 ( ( ref , is_short ) ,
trio_pointer_t ref ,
int is_short )
2001-04-21 20:57:29 +04:00
{
if ( is_short )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_SHORT ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_SHORT ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_shortshort / trio_set_shortshort [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_shortshort
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_SHORTSHORT )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_shortshort
TRIO_ARGS2 ( ( ref , is_shortshort ) ,
trio_pointer_t ref ,
int is_shortshort )
2001-04-21 20:57:29 +04:00
{
if ( is_shortshort )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_SHORTSHORT ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_SHORTSHORT ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_alternative / trio_set_alternative [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_alternative
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_ALTERNATIVE )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_alternative
TRIO_ARGS2 ( ( ref , is_alternative ) ,
trio_pointer_t ref ,
int is_alternative )
2001-04-21 20:57:29 +04:00
{
if ( is_alternative )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_ALTERNATIVE ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_ALTERNATIVE ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_alignment / trio_set_alignment [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_alignment
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_LEFTADJUST )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_alignment
TRIO_ARGS2 ( ( ref , is_leftaligned ) ,
trio_pointer_t ref ,
int is_leftaligned )
2001-04-21 20:57:29 +04:00
{
if ( is_leftaligned )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_LEFTADJUST ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_LEFTADJUST ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_spacing / trio_set_spacing [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_spacing
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_SPACE )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_spacing
TRIO_ARGS2 ( ( ref , is_space ) ,
trio_pointer_t ref ,
int is_space )
2001-04-21 20:57:29 +04:00
{
if ( is_space )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_SPACE ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_SPACE ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_sign / trio_set_sign [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_sign
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_SHOWSIGN )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_sign
TRIO_ARGS2 ( ( ref , is_sign ) ,
trio_pointer_t ref ,
int is_sign )
2001-04-21 20:57:29 +04:00
{
if ( is_sign )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_SHOWSIGN ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_SHOWSIGN ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_padding / trio_set_padding [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_padding
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_NILPADDING )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_padding
TRIO_ARGS2 ( ( ref , is_padding ) ,
trio_pointer_t ref ,
int is_padding )
2001-04-21 20:57:29 +04:00
{
if ( is_padding )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_NILPADDING ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_NILPADDING ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_quote / trio_set_quote [ public ]
*/
int
2002-09-26 02:44:43 +04:00
trio_get_quote
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-04-21 20:57:29 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_QUOTE )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_quote
TRIO_ARGS2 ( ( ref , is_quote ) ,
trio_pointer_t ref ,
int is_quote )
2001-04-21 20:57:29 +04:00
{
if ( is_quote )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_QUOTE ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_QUOTE ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* trio_get_upper / trio_set_upper [ public ]
2001-03-27 16:47:33 +04:00
*/
int
2002-09-26 02:44:43 +04:00
trio_get_upper
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-03-27 16:47:33 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_UPPER )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
void
2002-09-26 02:44:43 +04:00
trio_set_upper
TRIO_ARGS2 ( ( ref , is_upper ) ,
trio_pointer_t ref ,
int is_upper )
2001-04-21 20:57:29 +04:00
{
if ( is_upper )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_UPPER ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_UPPER ;
2001-03-27 16:47:33 +04:00
}
/*************************************************************************
2001-04-21 20:57:29 +04:00
* trio_get_largest / trio_set_largest [ public ]
2001-03-27 16:47:33 +04:00
*/
2001-06-05 16:46:33 +04:00
# if TRIO_C99
2001-03-27 16:47:33 +04:00
int
2002-09-26 02:44:43 +04:00
trio_get_largest
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-03-27 16:47:33 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_INTMAX_T )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
void
2002-09-26 02:44:43 +04:00
trio_set_largest
TRIO_ARGS2 ( ( ref , is_largest ) ,
trio_pointer_t ref ,
int is_largest )
2001-04-21 20:57:29 +04:00
{
if ( is_largest )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_INTMAX_T ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_INTMAX_T ;
2001-03-27 16:47:33 +04:00
}
# endif
/*************************************************************************
2001-04-21 20:57:29 +04:00
* trio_get_ptrdiff / trio_set_ptrdiff [ public ]
2001-03-27 16:47:33 +04:00
*/
int
2002-09-26 02:44:43 +04:00
trio_get_ptrdiff
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-03-27 16:47:33 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_PTRDIFF_T )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
void
2002-09-26 02:44:43 +04:00
trio_set_ptrdiff
TRIO_ARGS2 ( ( ref , is_ptrdiff ) ,
trio_pointer_t ref ,
int is_ptrdiff )
2001-04-21 20:57:29 +04:00
{
if ( is_ptrdiff )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_PTRDIFF_T ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_PTRDIFF_T ;
2001-03-27 16:47:33 +04:00
}
/*************************************************************************
2001-04-21 20:57:29 +04:00
* trio_get_size / trio_set_size [ public ]
2001-03-27 16:47:33 +04:00
*/
2001-06-05 16:46:33 +04:00
# if TRIO_C99
2001-03-27 16:47:33 +04:00
int
2002-09-26 02:44:43 +04:00
trio_get_size
TRIO_ARGS1 ( ( ref ) ,
trio_pointer_t ref )
2001-03-27 16:47:33 +04:00
{
2003-04-03 19:28:28 +04:00
return ( ( ( trio_reference_t * ) ref ) - > parameter - > flags & FLAGS_SIZE_T )
? TRUE
: FALSE ;
2001-04-21 20:57:29 +04:00
}
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
void
2002-09-26 02:44:43 +04:00
trio_set_size
TRIO_ARGS2 ( ( ref , is_size ) ,
trio_pointer_t ref ,
int is_size )
2001-04-21 20:57:29 +04:00
{
if ( is_size )
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags | = FLAGS_SIZE_T ;
2001-04-21 20:57:29 +04:00
else
2002-01-19 18:40:18 +03:00
( ( trio_reference_t * ) ref ) - > parameter - > flags & = ~ FLAGS_SIZE_T ;
2001-03-27 16:47:33 +04:00
}
# endif
/*************************************************************************
2001-04-21 20:57:29 +04:00
* trio_print_int [ public ]
2001-03-27 16:47:33 +04:00
*/
2001-04-21 20:57:29 +04:00
void
2002-09-26 02:44:43 +04:00
trio_print_int
TRIO_ARGS2 ( ( ref , number ) ,
trio_pointer_t ref ,
int number )
2001-03-27 16:47:33 +04:00
{
2002-01-19 18:40:18 +03:00
trio_reference_t * self = ( trio_reference_t * ) ref ;
2001-04-21 20:57:29 +04:00
TrioWriteNumber ( self - > data ,
2002-09-26 02:44:43 +04:00
( trio_uintmax_t ) number ,
2001-04-21 20:57:29 +04:00
self - > parameter - > flags ,
self - > parameter - > width ,
self - > parameter - > precision ,
self - > parameter - > base ) ;
}
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
/*************************************************************************
* trio_print_uint [ public ]
*/
void
2002-09-26 02:44:43 +04:00
trio_print_uint
TRIO_ARGS2 ( ( ref , number ) ,
trio_pointer_t ref ,
unsigned int number )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_reference_t * self = ( trio_reference_t * ) ref ;
2001-04-21 20:57:29 +04:00
TrioWriteNumber ( self - > data ,
2002-09-26 02:44:43 +04:00
( trio_uintmax_t ) number ,
2001-04-21 20:57:29 +04:00
self - > parameter - > flags | FLAGS_UNSIGNED ,
self - > parameter - > width ,
self - > parameter - > precision ,
self - > parameter - > base ) ;
}
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
/*************************************************************************
* trio_print_double [ public ]
*/
void
2002-09-26 02:44:43 +04:00
trio_print_double
TRIO_ARGS2 ( ( ref , number ) ,
trio_pointer_t ref ,
double number )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_reference_t * self = ( trio_reference_t * ) ref ;
2001-04-21 20:57:29 +04:00
TrioWriteDouble ( self - > data ,
number ,
self - > parameter - > flags ,
self - > parameter - > width ,
self - > parameter - > precision ,
self - > parameter - > base ) ;
}
/*************************************************************************
* trio_print_string [ public ]
*/
void
2002-09-26 02:44:43 +04:00
trio_print_string
TRIO_ARGS2 ( ( ref , string ) ,
trio_pointer_t ref ,
char * string )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_reference_t * self = ( trio_reference_t * ) ref ;
2001-04-21 20:57:29 +04:00
TrioWriteString ( self - > data ,
string ,
self - > parameter - > flags ,
self - > parameter - > width ,
self - > parameter - > precision ) ;
}
2002-09-26 02:44:43 +04:00
/*************************************************************************
* trio_print_ref [ public ]
*/
int
trio_print_ref
TRIO_VARGS3 ( ( ref , format , va_alist ) ,
trio_pointer_t ref ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
{
int status ;
va_list arglist ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( arglist , format ) ;
2013-12-12 11:04:43 +04:00
status = TrioFormatRef ( ( trio_reference_t * ) ref , format , TRIO_VA_LIST_ADDR ( arglist ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( arglist ) ;
return status ;
}
/*************************************************************************
* trio_vprint_ref [ public ]
*/
int
trio_vprint_ref
TRIO_ARGS3 ( ( ref , format , arglist ) ,
trio_pointer_t ref ,
TRIO_CONST char * format ,
va_list arglist )
{
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2013-12-12 11:04:43 +04:00
return TrioFormatRef ( ( trio_reference_t * ) ref , format , TRIO_VA_LIST_ADDR ( arglist ) , NULL ) ;
2002-09-26 02:44:43 +04:00
}
/*************************************************************************
* trio_printv_ref [ public ]
*/
int
trio_printv_ref
TRIO_ARGS3 ( ( ref , format , argarray ) ,
trio_pointer_t ref ,
TRIO_CONST char * format ,
trio_pointer_t * argarray )
{
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioFormatRef ( ( trio_reference_t * ) ref , format , NULL , argarray ) ;
}
# endif /* TRIO_EXTENSION */
2001-04-21 20:57:29 +04:00
/*************************************************************************
* trio_print_pointer [ public ]
*/
void
2002-09-26 02:44:43 +04:00
trio_print_pointer
TRIO_ARGS2 ( ( ref , pointer ) ,
trio_pointer_t ref ,
trio_pointer_t pointer )
2001-04-21 20:57:29 +04:00
{
2002-01-19 18:40:18 +03:00
trio_reference_t * self = ( trio_reference_t * ) ref ;
2003-04-03 19:28:28 +04:00
trio_flags_t flags ;
2001-06-05 16:46:33 +04:00
trio_uintmax_t number ;
2001-04-21 20:57:29 +04:00
if ( NULL = = pointer )
{
2002-01-19 18:40:18 +03:00
TRIO_CONST char * string = internalNullString ;
2001-04-21 20:57:29 +04:00
while ( * string )
self - > data - > OutStream ( self - > data , * string + + ) ;
}
else
{
/*
* The subtraction of the null pointer is a workaround
* to avoid a compiler warning . The performance overhead
* is negligible ( and likely to be removed by an
2002-09-26 02:44:43 +04:00
* optimizing compiler ) . The ( char * ) casting is done
2001-04-21 20:57:29 +04:00
* to please ANSI C + + .
*/
2001-06-05 16:46:33 +04:00
number = ( trio_uintmax_t ) ( ( char * ) pointer - ( char * ) 0 ) ;
2001-04-21 20:57:29 +04:00
/* Shrink to size of pointer */
2001-06-05 16:46:33 +04:00
number & = ( trio_uintmax_t ) - 1 ;
2001-04-21 20:57:29 +04:00
flags = self - > parameter - > flags ;
flags | = ( FLAGS_UNSIGNED | FLAGS_ALTERNATIVE |
FLAGS_NILPADDING ) ;
TrioWriteNumber ( self - > data ,
2002-09-26 02:44:43 +04:00
number ,
2001-04-21 20:57:29 +04:00
flags ,
POINTER_WIDTH ,
NO_PRECISION ,
BASE_HEX ) ;
}
2001-03-27 16:47:33 +04:00
}
2002-09-26 02:44:43 +04:00
/** @} End of UserDefined documentation module */
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-09-26 02:44:43 +04:00
*
* LOCALES
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*************************************************************************
* trio_locale_set_decimal_point
*
* Decimal point can only be one character . The input argument is a
* string to enable multibyte characters . At most MB_LEN_MAX characters
* will be used .
2001-03-27 16:47:33 +04:00
*/
2002-09-26 02:44:43 +04:00
TRIO_PUBLIC void
trio_locale_set_decimal_point
TRIO_ARGS1 ( ( decimalPoint ) ,
char * decimalPoint )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
# if defined(USE_LOCALE)
if ( NULL = = internalLocaleValues )
{
TrioSetLocale ( ) ;
}
# endif
internalDecimalPointLength = trio_length ( decimalPoint ) ;
if ( internalDecimalPointLength = = 1 )
{
internalDecimalPoint = * decimalPoint ;
}
else
{
internalDecimalPoint = NIL ;
trio_copy_max ( internalDecimalPointString ,
sizeof ( internalDecimalPointString ) ,
decimalPoint ) ;
}
2001-03-27 16:47:33 +04:00
}
/*************************************************************************
2002-09-26 02:44:43 +04:00
* trio_locale_set_thousand_separator
*
* See trio_locale_set_decimal_point
2001-03-27 16:47:33 +04:00
*/
2002-09-26 02:44:43 +04:00
TRIO_PUBLIC void
trio_locale_set_thousand_separator
TRIO_ARGS1 ( ( thousandSeparator ) ,
char * thousandSeparator )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
# if defined(USE_LOCALE)
if ( NULL = = internalLocaleValues )
{
TrioSetLocale ( ) ;
}
# endif
trio_copy_max ( internalThousandSeparator ,
sizeof ( internalThousandSeparator ) ,
thousandSeparator ) ;
internalThousandSeparatorLength = trio_length ( internalThousandSeparator ) ;
2001-04-21 20:57:29 +04:00
}
2001-03-27 16:47:33 +04:00
2001-04-21 20:57:29 +04:00
/*************************************************************************
2002-09-26 02:44:43 +04:00
* trio_locale_set_grouping
*
* Array of bytes . Reversed order .
*
* CHAR_MAX : No further grouping
* 0 : Repeat last group for the remaining digits ( not necessary
* as C strings are zero - terminated )
* n : Set current group to n
*
* Same order as the grouping attribute in LC_NUMERIC .
2001-04-21 20:57:29 +04:00
*/
2002-09-26 02:44:43 +04:00
TRIO_PUBLIC void
trio_locale_set_grouping
TRIO_ARGS1 ( ( grouping ) ,
char * grouping )
2001-04-21 20:57:29 +04:00
{
2002-09-26 02:44:43 +04:00
# if defined(USE_LOCALE)
if ( NULL = = internalLocaleValues )
{
TrioSetLocale ( ) ;
}
# endif
trio_copy_max ( internalGrouping ,
sizeof ( internalGrouping ) ,
grouping ) ;
2001-03-27 16:47:33 +04:00
}
2001-04-21 20:57:29 +04:00
2001-03-27 16:47:33 +04:00
/*************************************************************************
*
2002-01-19 18:40:18 +03:00
* SCANNING
2001-03-27 16:47:33 +04:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioSkipWhitespaces
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioSkipWhitespaces
TRIO_ARGS1 ( ( self ) ,
trio_class_t * self )
2001-03-27 16:47:33 +04:00
{
int ch ;
ch = self - > current ;
while ( isspace ( ch ) )
{
self - > InStream ( self , & ch ) ;
}
return ch ;
}
2001-06-05 16:46:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioGetCollation
2001-06-05 16:46:33 +04:00
*/
# if TRIO_EXTENSION
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioGetCollation ( TRIO_NOARGS )
2001-06-05 16:46:33 +04:00
{
int i ;
int j ;
int k ;
char first [ 2 ] ;
char second [ 2 ] ;
2003-04-03 19:28:28 +04:00
/* This is computationally expensive */
2001-06-05 16:46:33 +04:00
first [ 1 ] = NIL ;
second [ 1 ] = NIL ;
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
{
k = 0 ;
first [ 0 ] = ( char ) i ;
for ( j = 0 ; j < MAX_CHARACTER_CLASS ; j + + )
{
second [ 0 ] = ( char ) j ;
2002-01-19 18:40:18 +03:00
if ( trio_equal_locale ( first , second ) )
2001-06-05 16:46:33 +04:00
internalCollationArray [ i ] [ k + + ] = ( char ) j ;
}
internalCollationArray [ i ] [ k ] = NIL ;
}
}
# endif
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioGetCharacterClass
2001-03-27 16:47:33 +04:00
*
* FIXME :
* multibyte
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioGetCharacterClass
TRIO_ARGS4 ( ( format , indexPointer , flagsPointer , characterclass ) ,
TRIO_CONST char * format ,
int * indexPointer ,
2003-04-03 19:28:28 +04:00
trio_flags_t * flagsPointer ,
2002-09-26 02:44:43 +04:00
int * characterclass )
2001-03-27 16:47:33 +04:00
{
int index = * indexPointer ;
int i ;
char ch ;
char range_begin ;
char range_end ;
* flagsPointer & = ~ FLAGS_EXCLUDE ;
if ( format [ index ] = = QUALIFIER_CIRCUMFLEX )
{
* flagsPointer | = FLAGS_EXCLUDE ;
index + + ;
}
2001-04-21 20:57:29 +04:00
/*
* If the ungroup character is at the beginning of the scanlist ,
2001-03-27 16:47:33 +04:00
* it will be part of the class , and a second ungroup character
* must follow to end the group .
*/
if ( format [ index ] = = SPECIFIER_UNGROUP )
{
characterclass [ ( int ) SPECIFIER_UNGROUP ] + + ;
index + + ;
}
2001-04-21 20:57:29 +04:00
/*
* Minus is used to specify ranges . To include minus in the class ,
2001-03-27 16:47:33 +04:00
* it must be at the beginning of the list
*/
if ( format [ index ] = = QUALIFIER_MINUS )
{
characterclass [ ( int ) QUALIFIER_MINUS ] + + ;
index + + ;
}
/* Collect characters */
for ( ch = format [ index ] ;
2001-06-05 16:46:33 +04:00
( ch ! = SPECIFIER_UNGROUP ) & & ( ch ! = NIL ) ;
2001-03-27 16:47:33 +04:00
ch = format [ + + index ] )
{
switch ( ch )
{
case QUALIFIER_MINUS : /* Scanlist ranges */
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
/*
* Both C99 and UNIX98 describes ranges as implementation -
2001-03-27 16:47:33 +04:00
* defined .
*
* We support the following behaviour ( although this may
* change as we become wiser )
* - only increasing ranges , ie . [ a - b ] but not [ b - a ]
* - transitive ranges , ie . [ a - b - c ] = = [ a - c ]
* - trailing minus , ie . [ a - ] is interpreted as an ' a '
* and a ' - '
* - duplicates ( although we can easily convert these
* into errors )
*/
range_begin = format [ index - 1 ] ;
range_end = format [ + + index ] ;
if ( range_end = = SPECIFIER_UNGROUP )
{
/* Trailing minus is included */
characterclass [ ( int ) ch ] + + ;
ch = range_end ;
break ; /* for */
}
if ( range_end = = NIL )
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
if ( range_begin > range_end )
return TRIO_ERROR_RETURN ( TRIO_ERANGE , index ) ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
for ( i = ( int ) range_begin ; i < = ( int ) range_end ; i + + )
characterclass [ i ] + + ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
ch = range_end ;
break ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
# if TRIO_EXTENSION
2001-03-27 16:47:33 +04:00
2001-06-05 16:46:33 +04:00
case SPECIFIER_GROUP :
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
switch ( format [ index + 1 ] )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
case QUALIFIER_DOT : /* Collating symbol */
/*
* FIXME : This will be easier to implement when multibyte
* characters have been implemented . Until now , we ignore
* this feature .
*/
for ( i = index + 2 ; ; i + + )
{
if ( format [ i ] = = NIL )
/* Error in syntax */
return - 1 ;
else if ( format [ i ] = = QUALIFIER_DOT )
break ; /* for */
}
if ( format [ + + i ] ! = SPECIFIER_UNGROUP )
return - 1 ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
index = i ;
break ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
case QUALIFIER_EQUAL : /* Equivalence class expressions */
{
unsigned int j ;
unsigned int k ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
if ( internalCollationUnconverted )
{
2002-09-26 02:44:43 +04:00
/* Lazy evaluation of collation array */
2001-06-05 16:46:33 +04:00
TrioGetCollation ( ) ;
internalCollationUnconverted = FALSE ;
}
for ( i = index + 2 ; ; i + + )
{
if ( format [ i ] = = NIL )
/* Error in syntax */
return - 1 ;
else if ( format [ i ] = = QUALIFIER_EQUAL )
break ; /* for */
else
{
/* Mark any equivalent character */
k = ( unsigned int ) format [ i ] ;
for ( j = 0 ; internalCollationArray [ k ] [ j ] ! = NIL ; j + + )
characterclass [ ( int ) internalCollationArray [ k ] [ j ] ] + + ;
}
}
if ( format [ + + i ] ! = SPECIFIER_UNGROUP )
return - 1 ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
index = i ;
}
break ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
case QUALIFIER_COLON : /* Character class expressions */
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
if ( trio_equal_max ( CLASS_ALNUM , sizeof ( CLASS_ALNUM ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( isalnum ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_ALNUM ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_ALPHA , sizeof ( CLASS_ALPHA ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( isalpha ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_ALPHA ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_CNTRL , sizeof ( CLASS_CNTRL ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( iscntrl ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_CNTRL ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_DIGIT , sizeof ( CLASS_DIGIT ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( isdigit ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_DIGIT ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_GRAPH , sizeof ( CLASS_GRAPH ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( isgraph ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_GRAPH ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_LOWER , sizeof ( CLASS_LOWER ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( islower ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_LOWER ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_PRINT , sizeof ( CLASS_PRINT ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( isprint ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_PRINT ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_PUNCT , sizeof ( CLASS_PUNCT ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( ispunct ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_PUNCT ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_SPACE , sizeof ( CLASS_SPACE ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( isspace ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_SPACE ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_UPPER , sizeof ( CLASS_UPPER ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( isupper ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_UPPER ) - 1 ;
}
2002-01-19 18:40:18 +03:00
else if ( trio_equal_max ( CLASS_XDIGIT , sizeof ( CLASS_XDIGIT ) - 1 ,
& format [ index ] ) )
2001-06-05 16:46:33 +04:00
{
for ( i = 0 ; i < MAX_CHARACTER_CLASS ; i + + )
if ( isxdigit ( i ) )
characterclass [ i ] + + ;
index + = sizeof ( CLASS_XDIGIT ) - 1 ;
}
else
{
characterclass [ ( int ) ch ] + + ;
}
break ;
default :
2001-03-27 16:47:33 +04:00
characterclass [ ( int ) ch ] + + ;
2001-06-05 16:46:33 +04:00
break ;
2001-03-27 16:47:33 +04:00
}
break ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
# endif /* TRIO_EXTENSION */
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
default :
characterclass [ ( int ) ch ] + + ;
break ;
}
}
return 0 ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioReadNumber
2001-03-27 16:47:33 +04:00
*
* We implement our own number conversion in preference of strtol and
* strtoul , because we must handle ' long long ' and thousand separators .
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE BOOLEAN_T
2002-09-26 02:44:43 +04:00
TrioReadNumber
TRIO_ARGS5 ( ( self , target , flags , width , base ) ,
trio_class_t * self ,
trio_uintmax_t * target ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width ,
int base )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
trio_uintmax_t number = 0 ;
2001-03-27 16:47:33 +04:00
int digit ;
int count ;
BOOLEAN_T isNegative = FALSE ;
2002-09-26 02:44:43 +04:00
BOOLEAN_T gotNumber = FALSE ;
2001-03-27 16:47:33 +04:00
int j ;
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > InStream ) ) ;
assert ( ( base > = MIN_BASE & & base < = MAX_BASE ) | | ( base = = NO_BASE ) ) ;
2001-06-05 16:46:33 +04:00
if ( internalDigitsUnconverted )
{
/* Lazy evaluation of digits array */
memset ( internalDigitArray , - 1 , sizeof ( internalDigitArray ) ) ;
for ( j = 0 ; j < ( int ) sizeof ( internalDigitsLower ) - 1 ; j + + )
{
internalDigitArray [ ( int ) internalDigitsLower [ j ] ] = j ;
internalDigitArray [ ( int ) internalDigitsUpper [ j ] ] = j ;
}
internalDigitsUnconverted = FALSE ;
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
TrioSkipWhitespaces ( self ) ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( ! ( flags & FLAGS_UNSIGNED ) )
{
/* Leading sign */
if ( self - > current = = ' + ' )
{
self - > InStream ( self , NULL ) ;
}
else if ( self - > current = = ' - ' )
{
self - > InStream ( self , NULL ) ;
isNegative = TRUE ;
}
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
count = self - > processed ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( flags & FLAGS_ALTERNATIVE )
{
switch ( base )
{
case NO_BASE :
case BASE_OCTAL :
case BASE_HEX :
case BASE_BINARY :
if ( self - > current = = ' 0 ' )
{
self - > InStream ( self , NULL ) ;
if ( self - > current )
{
if ( ( base = = BASE_HEX ) & &
2003-04-03 19:28:28 +04:00
( trio_to_upper ( self - > current ) = = ' X ' ) )
2001-03-27 16:47:33 +04:00
{
self - > InStream ( self , NULL ) ;
}
else if ( ( base = = BASE_BINARY ) & &
2003-04-03 19:28:28 +04:00
( trio_to_upper ( self - > current ) = = ' B ' ) )
2001-03-27 16:47:33 +04:00
{
self - > InStream ( self , NULL ) ;
}
}
}
else
return FALSE ;
break ;
default :
break ;
}
}
while ( ( ( width = = NO_WIDTH ) | | ( self - > processed - count < width ) ) & &
( ! ( ( self - > current = = EOF ) | | isspace ( self - > current ) ) ) )
{
if ( isascii ( self - > current ) )
{
2001-04-21 20:57:29 +04:00
digit = internalDigitArray [ self - > current ] ;
2001-03-27 16:47:33 +04:00
/* Abort if digit is not allowed in the specified base */
if ( ( digit = = - 1 ) | | ( digit > = base ) )
break ;
}
else if ( flags & FLAGS_QUOTE )
{
/* Compare with thousands separator */
2001-04-21 20:57:29 +04:00
for ( j = 0 ; internalThousandSeparator [ j ] & & self - > current ; j + + )
2001-03-27 16:47:33 +04:00
{
2001-04-21 20:57:29 +04:00
if ( internalThousandSeparator [ j ] ! = self - > current )
2001-03-27 16:47:33 +04:00
break ;
self - > InStream ( self , NULL ) ;
}
2001-04-21 20:57:29 +04:00
if ( internalThousandSeparator [ j ] )
2001-03-27 16:47:33 +04:00
break ; /* Mismatch */
else
continue ; /* Match */
}
else
break ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
number * = base ;
number + = digit ;
2002-09-26 02:44:43 +04:00
gotNumber = TRUE ; /* we need at least one digit */
2001-03-27 16:47:33 +04:00
self - > InStream ( self , NULL ) ;
}
/* Was anything read at all? */
2002-09-26 02:44:43 +04:00
if ( ! gotNumber )
2001-03-27 16:47:33 +04:00
return FALSE ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( target )
2002-09-26 02:44:43 +04:00
* target = ( isNegative ) ? - ( ( trio_intmax_t ) number ) : number ;
2001-03-27 16:47:33 +04:00
return TRUE ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioReadChar
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioReadChar
TRIO_ARGS4 ( ( self , target , flags , width ) ,
trio_class_t * self ,
char * target ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width )
2001-03-27 16:47:33 +04:00
{
int i ;
2001-06-05 16:46:33 +04:00
char ch ;
trio_uintmax_t number ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > InStream ) ) ;
for ( i = 0 ;
( self - > current ! = EOF ) & & ( i < width ) ;
i + + )
{
2001-06-05 16:46:33 +04:00
ch = ( char ) self - > current ;
2001-03-27 16:47:33 +04:00
self - > InStream ( self , NULL ) ;
if ( ( flags & FLAGS_ALTERNATIVE ) & & ( ch = = CHAR_BACKSLASH ) )
{
switch ( self - > current )
{
2001-04-21 20:57:29 +04:00
case ' \\ ' : ch = ' \\ ' ; break ;
2001-06-05 16:46:33 +04:00
case ' a ' : ch = ' \007 ' ; break ;
2001-04-21 20:57:29 +04:00
case ' b ' : ch = ' \b ' ; break ;
case ' f ' : ch = ' \f ' ; break ;
case ' n ' : ch = ' \n ' ; break ;
case ' r ' : ch = ' \r ' ; break ;
case ' t ' : ch = ' \t ' ; break ;
case ' v ' : ch = ' \v ' ; break ;
2001-03-27 16:47:33 +04:00
default :
if ( isdigit ( self - > current ) )
{
/* Read octal number */
if ( ! TrioReadNumber ( self , & number , 0 , 3 , BASE_OCTAL ) )
2001-06-05 16:46:33 +04:00
return 0 ;
2001-03-27 16:47:33 +04:00
ch = ( char ) number ;
}
2003-04-03 19:28:28 +04:00
else if ( trio_to_upper ( self - > current ) = = ' X ' )
2001-03-27 16:47:33 +04:00
{
/* Read hexadecimal number */
self - > InStream ( self , NULL ) ;
if ( ! TrioReadNumber ( self , & number , 0 , 2 , BASE_HEX ) )
2001-06-05 16:46:33 +04:00
return 0 ;
2001-03-27 16:47:33 +04:00
ch = ( char ) number ;
}
else
{
2001-06-05 16:46:33 +04:00
ch = ( char ) self - > current ;
2001-03-27 16:47:33 +04:00
}
break ;
}
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( target )
target [ i ] = ch ;
2001-06-05 16:46:33 +04:00
}
return i + 1 ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioReadString
2001-06-05 16:46:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE BOOLEAN_T
2002-09-26 02:44:43 +04:00
TrioReadString
TRIO_ARGS4 ( ( self , target , flags , width ) ,
trio_class_t * self ,
char * target ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width )
2001-06-05 16:46:33 +04:00
{
int i ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > InStream ) ) ;
TrioSkipWhitespaces ( self ) ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
/*
* Continue until end of string is reached , a whitespace is encountered ,
* or width is exceeded
*/
for ( i = 0 ;
( ( width = = NO_WIDTH ) | | ( i < width ) ) & &
( ! ( ( self - > current = = EOF ) | | isspace ( self - > current ) ) ) ;
i + + )
{
2002-09-26 02:44:43 +04:00
if ( TrioReadChar ( self , ( target ? & target [ i ] : 0 ) , flags , 1 ) = = 0 )
2001-06-05 16:46:33 +04:00
break ; /* for */
2001-03-27 16:47:33 +04:00
}
if ( target )
target [ i ] = NIL ;
return TRUE ;
}
2001-06-05 16:46:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioReadWideChar
2001-06-05 16:46:33 +04:00
*/
# if TRIO_WIDECHAR
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioReadWideChar
TRIO_ARGS4 ( ( self , target , flags , width ) ,
trio_class_t * self ,
trio_wchar_t * target ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width )
2001-06-05 16:46:33 +04:00
{
int i ;
int j ;
int size ;
int amount = 0 ;
2002-09-26 02:44:43 +04:00
trio_wchar_t wch ;
2001-06-05 16:46:33 +04:00
char buffer [ MB_LEN_MAX + 1 ] ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > InStream ) ) ;
for ( i = 0 ;
( self - > current ! = EOF ) & & ( i < width ) ;
i + + )
{
if ( isascii ( self - > current ) )
{
if ( TrioReadChar ( self , buffer , flags , 1 ) = = 0 )
return 0 ;
buffer [ 1 ] = NIL ;
}
else
{
/*
* Collect a multibyte character , by enlarging buffer until
* it contains a fully legal multibyte character , or the
* buffer is full .
*/
j = 0 ;
do
{
buffer [ j + + ] = ( char ) self - > current ;
buffer [ j ] = NIL ;
self - > InStream ( self , NULL ) ;
}
while ( ( j < ( int ) sizeof ( buffer ) ) & & ( mblen ( buffer , ( size_t ) j ) ! = j ) ) ;
}
if ( target )
{
size = mbtowc ( & wch , buffer , sizeof ( buffer ) ) ;
if ( size > 0 )
target [ i ] = wch ;
}
amount + = size ;
self - > InStream ( self , NULL ) ;
}
return amount ;
}
# endif /* TRIO_WIDECHAR */
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioReadWideString
2001-06-05 16:46:33 +04:00
*/
# if TRIO_WIDECHAR
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE BOOLEAN_T
2002-09-26 02:44:43 +04:00
TrioReadWideString
TRIO_ARGS4 ( ( self , target , flags , width ) ,
trio_class_t * self ,
trio_wchar_t * target ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width )
2001-06-05 16:46:33 +04:00
{
int i ;
int size ;
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > InStream ) ) ;
TrioSkipWhitespaces ( self ) ;
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2002-09-26 02:44:43 +04:00
( void ) mblen ( NULL , 0 ) ;
2001-06-05 16:46:33 +04:00
# endif
2012-09-11 09:26:36 +04:00
2001-06-05 16:46:33 +04:00
/*
* Continue until end of string is reached , a whitespace is encountered ,
* or width is exceeded
*/
for ( i = 0 ;
( ( width = = NO_WIDTH ) | | ( i < width ) ) & &
( ! ( ( self - > current = = EOF ) | | isspace ( self - > current ) ) ) ;
)
{
size = TrioReadWideChar ( self , & target [ i ] , flags , 1 ) ;
if ( size = = 0 )
break ; /* for */
i + = size ;
}
if ( target )
2002-01-19 18:40:18 +03:00
target [ i ] = WCONST ( ' \0 ' ) ;
2001-06-05 16:46:33 +04:00
return TRUE ;
}
# endif /* TRIO_WIDECHAR */
2001-03-27 16:47:33 +04:00
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioReadGroup
2001-03-27 16:47:33 +04:00
*
* FIXME : characterclass does not work with multibyte characters
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE BOOLEAN_T
2002-09-26 02:44:43 +04:00
TrioReadGroup
TRIO_ARGS5 ( ( self , target , characterclass , flags , width ) ,
trio_class_t * self ,
char * target ,
int * characterclass ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width )
2001-03-27 16:47:33 +04:00
{
2001-04-21 20:57:29 +04:00
int ch ;
2001-03-27 16:47:33 +04:00
int i ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > InStream ) ) ;
ch = self - > current ;
for ( i = 0 ;
( ( width = = NO_WIDTH ) | | ( i < width ) ) & &
( ! ( ( ch = = EOF ) | |
( ( ( flags & FLAGS_EXCLUDE ) ! = 0 ) ^ ( characterclass [ ch ] = = 0 ) ) ) ) ;
i + + )
{
if ( target )
target [ i ] = ( char ) ch ;
self - > InStream ( self , & ch ) ;
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( target )
target [ i ] = NIL ;
return TRUE ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioReadDouble
2001-03-27 16:47:33 +04:00
*
* FIXME :
* add long double
2002-09-26 02:44:43 +04:00
* handle base
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE BOOLEAN_T
2002-09-26 02:44:43 +04:00
TrioReadDouble
TRIO_ARGS4 ( ( self , target , flags , width ) ,
trio_class_t * self ,
trio_pointer_t target ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags ,
2002-09-26 02:44:43 +04:00
int width )
2001-03-27 16:47:33 +04:00
{
int ch ;
2002-09-26 02:44:43 +04:00
char doubleString [ 512 ] ;
2001-03-27 16:47:33 +04:00
int index = 0 ;
int start ;
2001-04-21 20:57:29 +04:00
int j ;
2001-06-05 16:46:33 +04:00
BOOLEAN_T isHex = FALSE ;
2001-03-27 16:47:33 +04:00
2002-09-26 02:44:43 +04:00
doubleString [ 0 ] = 0 ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
if ( ( width = = NO_WIDTH ) | | ( width > ( int ) sizeof ( doubleString ) - 1 ) )
2001-03-27 16:47:33 +04:00
width = sizeof ( doubleString ) - 1 ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
TrioSkipWhitespaces ( self ) ;
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
/*
2002-01-19 18:40:18 +03:00
* Read entire double number from stream . trio_to_double requires
* a string as input , but InStream can be anything , so we have to
2001-03-27 16:47:33 +04:00
* collect all characters .
*/
ch = self - > current ;
if ( ( ch = = ' + ' ) | | ( ch = = ' - ' ) )
{
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
2001-03-27 16:47:33 +04:00
self - > InStream ( self , & ch ) ;
width - - ;
}
start = index ;
switch ( ch )
{
case ' n ' :
case ' N ' :
/* Not-a-number */
if ( index ! = 0 )
break ;
/* FALLTHROUGH */
case ' i ' :
case ' I ' :
/* Infinity */
while ( isalpha ( ch ) & & ( index - start < width ) )
{
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
2001-03-27 16:47:33 +04:00
self - > InStream ( self , & ch ) ;
}
doubleString [ index ] = NIL ;
/* Case insensitive string comparison */
2002-01-19 18:40:18 +03:00
if ( trio_equal ( & doubleString [ start ] , INFINITE_UPPER ) | |
trio_equal ( & doubleString [ start ] , LONG_INFINITE_UPPER ) )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
if ( flags & FLAGS_LONGDOUBLE )
{
if ( ( start = = 1 ) & & ( doubleString [ 0 ] = = ' - ' ) )
{
* ( ( trio_long_double_t * ) target ) = trio_ninf ( ) ;
}
else
{
* ( ( trio_long_double_t * ) target ) = trio_pinf ( ) ;
}
}
else
{
if ( ( start = = 1 ) & & ( doubleString [ 0 ] = = ' - ' ) )
{
* ( ( double * ) target ) = trio_ninf ( ) ;
}
else
{
* ( ( double * ) target ) = trio_pinf ( ) ;
}
}
2001-03-27 16:47:33 +04:00
return TRUE ;
}
2002-01-19 18:40:18 +03:00
if ( trio_equal ( doubleString , NAN_UPPER ) )
2001-03-27 16:47:33 +04:00
{
2002-01-19 18:40:18 +03:00
/* NaN must not have a preceeding + nor - */
2002-09-26 02:44:43 +04:00
if ( flags & FLAGS_LONGDOUBLE )
{
* ( ( trio_long_double_t * ) target ) = trio_nan ( ) ;
}
else
{
* ( ( double * ) target ) = trio_nan ( ) ;
}
2001-03-27 16:47:33 +04:00
return TRUE ;
}
return FALSE ;
2002-09-26 02:44:43 +04:00
case ' 0 ' :
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
self - > InStream ( self , & ch ) ;
2003-04-03 19:28:28 +04:00
if ( trio_to_upper ( ch ) = = ' X ' )
2001-06-05 16:46:33 +04:00
{
isHex = TRUE ;
doubleString [ index + + ] = ( char ) ch ;
self - > InStream ( self , & ch ) ;
}
2002-09-26 02:44:43 +04:00
break ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
default :
break ;
2001-06-05 16:46:33 +04:00
}
2012-09-11 09:26:36 +04:00
2001-04-21 20:57:29 +04:00
while ( ( ch ! = EOF ) & & ( index - start < width ) )
2001-03-27 16:47:33 +04:00
{
/* Integer part */
2001-06-05 16:46:33 +04:00
if ( isHex ? isxdigit ( ch ) : isdigit ( ch ) )
2001-04-21 20:57:29 +04:00
{
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
2001-04-21 20:57:29 +04:00
self - > InStream ( self , & ch ) ;
}
else if ( flags & FLAGS_QUOTE )
{
/* Compare with thousands separator */
for ( j = 0 ; internalThousandSeparator [ j ] & & self - > current ; j + + )
{
if ( internalThousandSeparator [ j ] ! = self - > current )
break ;
self - > InStream ( self , & ch ) ;
}
if ( internalThousandSeparator [ j ] )
break ; /* Mismatch */
else
continue ; /* Match */
}
else
break ; /* while */
2001-03-27 16:47:33 +04:00
}
if ( ch = = ' . ' )
{
/* Decimal part */
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
2001-03-27 16:47:33 +04:00
self - > InStream ( self , & ch ) ;
2001-06-05 16:46:33 +04:00
while ( ( isHex ? isxdigit ( ch ) : isdigit ( ch ) ) & &
( index - start < width ) )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
2001-03-27 16:47:33 +04:00
self - > InStream ( self , & ch ) ;
}
2003-04-03 19:28:28 +04:00
if ( isHex ? ( trio_to_upper ( ch ) = = ' P ' ) : ( trio_to_upper ( ch ) = = ' E ' ) )
2001-03-27 16:47:33 +04:00
{
/* Exponent */
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
2001-03-27 16:47:33 +04:00
self - > InStream ( self , & ch ) ;
if ( ( ch = = ' + ' ) | | ( ch = = ' - ' ) )
{
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
2001-03-27 16:47:33 +04:00
self - > InStream ( self , & ch ) ;
}
2003-04-03 19:28:28 +04:00
while ( isdigit ( ch ) & & ( index - start < width ) )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
doubleString [ index + + ] = ( char ) ch ;
2001-03-27 16:47:33 +04:00
self - > InStream ( self , & ch ) ;
}
}
}
if ( ( index = = start ) | | ( * doubleString = = NIL ) )
return FALSE ;
2002-09-26 02:44:43 +04:00
doubleString [ index ] = 0 ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( flags & FLAGS_LONGDOUBLE )
2002-09-26 02:44:43 +04:00
{
* ( ( trio_long_double_t * ) target ) = trio_to_long_double ( doubleString , NULL ) ;
}
2001-03-27 16:47:33 +04:00
else
{
2002-09-26 02:44:43 +04:00
* ( ( double * ) target ) = trio_to_double ( doubleString , NULL ) ;
2001-03-27 16:47:33 +04:00
}
return TRUE ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioReadPointer
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE BOOLEAN_T
2002-09-26 02:44:43 +04:00
TrioReadPointer
TRIO_ARGS3 ( ( self , target , flags ) ,
trio_class_t * self ,
trio_pointer_t * target ,
2003-04-03 19:28:28 +04:00
trio_flags_t flags )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
trio_uintmax_t number ;
2002-01-19 18:40:18 +03:00
char buffer [ sizeof ( internalNullString ) ] ;
2001-03-27 16:47:33 +04:00
flags | = ( FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING ) ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( TrioReadNumber ( self ,
& number ,
flags ,
POINTER_WIDTH ,
BASE_HEX ) )
{
2001-04-21 20:57:29 +04:00
/*
* The strange assignment of number is a workaround for a compiler
* warning
*/
2001-03-27 16:47:33 +04:00
if ( target )
2001-04-21 20:57:29 +04:00
* target = ( char * ) 0 + number ;
2001-03-27 16:47:33 +04:00
return TRUE ;
}
else if ( TrioReadString ( self ,
( flags & FLAGS_IGNORE )
? NULL
: buffer ,
0 ,
2002-01-19 18:40:18 +03:00
sizeof ( internalNullString ) - 1 ) )
2012-09-11 09:26:36 +04:00
{
2002-01-19 18:40:18 +03:00
if ( trio_equal_case ( buffer , internalNullString ) )
2001-03-27 16:47:33 +04:00
{
if ( target )
* target = NULL ;
return TRUE ;
}
}
return FALSE ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioScanProcess
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioScanProcess
TRIO_ARGS3 ( ( data , format , parameters ) ,
trio_class_t * data ,
TRIO_CONST char * format ,
trio_parameter_t * parameters )
2001-03-27 16:47:33 +04:00
{
2001-06-05 16:46:33 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2001-03-27 16:47:33 +04:00
int charlen ;
2002-01-19 18:40:18 +03:00
int cnt ;
2001-03-27 16:47:33 +04:00
# endif
int assignment ;
int ch ;
int index ; /* Index of format string */
int i ; /* Index of current parameter */
2003-04-03 19:28:28 +04:00
trio_flags_t flags ;
2001-03-27 16:47:33 +04:00
int width ;
int base ;
2002-09-26 02:44:43 +04:00
trio_pointer_t pointer ;
2001-03-27 16:47:33 +04:00
assignment = 0 ;
i = 0 ;
index = 0 ;
data - > InStream ( data , & ch ) ;
2001-06-05 16:46:33 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2002-09-26 02:44:43 +04:00
( void ) mblen ( NULL , 0 ) ;
2001-03-27 16:47:33 +04:00
# endif
while ( format [ index ] )
{
2001-06-05 16:46:33 +04:00
# if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
2001-03-27 16:47:33 +04:00
if ( ! isascii ( format [ index ] ) )
{
charlen = mblen ( & format [ index ] , MB_LEN_MAX ) ;
2002-09-26 02:44:43 +04:00
if ( charlen ! = - 1 )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
/* Compare multibyte characters in format string */
for ( cnt = 0 ; cnt < charlen - 1 ; cnt + + )
2001-03-27 16:47:33 +04:00
{
2002-09-26 02:44:43 +04:00
if ( ch ! = format [ index + cnt ] )
{
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
}
data - > InStream ( data , & ch ) ;
2001-03-27 16:47:33 +04:00
}
2002-09-26 02:44:43 +04:00
continue ; /* while characters left in formatting string */
2001-03-27 16:47:33 +04:00
}
}
2001-06-05 16:46:33 +04:00
# endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
if ( ( EOF = = ch ) & & ( parameters [ i ] . type ! = FORMAT_COUNT ) )
{
return ( assignment > 0 ) ? assignment : EOF ;
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( CHAR_IDENTIFIER = = format [ index ] )
{
if ( CHAR_IDENTIFIER = = format [ index + 1 ] )
{
/* Two % in format matches one % in input stream */
if ( CHAR_IDENTIFIER = = ch )
{
data - > InStream ( data , & ch ) ;
index + = 2 ;
continue ; /* while format chars left */
}
else
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
}
/* Skip the parameter entries */
while ( parameters [ i ] . type = = FORMAT_PARAMETER )
i + + ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
flags = parameters [ i ] . flags ;
/* Find width */
width = parameters [ i ] . width ;
if ( flags & FLAGS_WIDTH_PARAMETER )
{
/* Get width from parameter list */
2001-04-21 20:57:29 +04:00
width = ( int ) parameters [ width ] . data . number . as_signed ;
2001-03-27 16:47:33 +04:00
}
/* Find base */
base = parameters [ i ] . base ;
if ( flags & FLAGS_BASE_PARAMETER )
{
/* Get base from parameter list */
2001-04-21 20:57:29 +04:00
base = ( int ) parameters [ base ] . data . number . as_signed ;
2001-03-27 16:47:33 +04:00
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
switch ( parameters [ i ] . type )
{
case FORMAT_INT :
{
2001-06-05 16:46:33 +04:00
trio_uintmax_t number ;
2001-03-27 16:47:33 +04:00
if ( 0 = = base )
base = BASE_DECIMAL ;
if ( ! TrioReadNumber ( data ,
& number ,
flags ,
width ,
base ) )
return assignment ;
2002-09-26 02:44:43 +04:00
2001-03-27 16:47:33 +04:00
if ( ! ( flags & FLAGS_IGNORE ) )
{
2002-09-26 02:44:43 +04:00
assignment + + ;
2001-03-27 16:47:33 +04:00
pointer = parameters [ i ] . data . pointer ;
# if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
if ( flags & FLAGS_SIZE_T )
* ( size_t * ) pointer = ( size_t ) number ;
else
# endif
# if defined(QUALIFIER_PTRDIFF_T)
if ( flags & FLAGS_PTRDIFF_T )
* ( ptrdiff_t * ) pointer = ( ptrdiff_t ) number ;
else
# endif
# if defined(QUALIFIER_INTMAX_T)
if ( flags & FLAGS_INTMAX_T )
2001-06-05 16:46:33 +04:00
* ( trio_intmax_t * ) pointer = ( trio_intmax_t ) number ;
2001-03-27 16:47:33 +04:00
else
# endif
if ( flags & FLAGS_QUAD )
2001-06-05 16:46:33 +04:00
* ( trio_ulonglong_t * ) pointer = ( trio_ulonglong_t ) number ;
2001-03-27 16:47:33 +04:00
else if ( flags & FLAGS_LONG )
* ( long int * ) pointer = ( long int ) number ;
else if ( flags & FLAGS_SHORT )
* ( short int * ) pointer = ( short int ) number ;
else
* ( int * ) pointer = ( int ) number ;
}
}
break ; /* FORMAT_INT */
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
case FORMAT_STRING :
2001-06-05 16:46:33 +04:00
# if TRIO_WIDECHAR
if ( flags & FLAGS_WIDECHAR )
{
if ( ! TrioReadWideString ( data ,
( flags & FLAGS_IGNORE )
? NULL
: parameters [ i ] . data . wstring ,
flags ,
width ) )
return assignment ;
}
else
# endif
{
if ( ! TrioReadString ( data ,
( flags & FLAGS_IGNORE )
? NULL
: parameters [ i ] . data . string ,
flags ,
width ) )
return assignment ;
}
2002-09-26 02:44:43 +04:00
if ( ! ( flags & FLAGS_IGNORE ) )
assignment + + ;
2001-03-27 16:47:33 +04:00
break ; /* FORMAT_STRING */
2002-09-26 02:44:43 +04:00
2001-03-27 16:47:33 +04:00
case FORMAT_DOUBLE :
2002-09-26 02:44:43 +04:00
{
trio_pointer_t pointer ;
2001-03-27 16:47:33 +04:00
2002-09-26 02:44:43 +04:00
if ( flags & FLAGS_IGNORE )
{
pointer = NULL ;
}
else
{
pointer = ( flags & FLAGS_LONGDOUBLE )
? ( trio_pointer_t ) parameters [ i ] . data . longdoublePointer
: ( trio_pointer_t ) parameters [ i ] . data . doublePointer ;
}
if ( ! TrioReadDouble ( data , pointer , flags , width ) )
{
return assignment ;
}
if ( ! ( flags & FLAGS_IGNORE ) )
{
assignment + + ;
}
break ; /* FORMAT_DOUBLE */
}
2001-03-27 16:47:33 +04:00
case FORMAT_GROUP :
{
int characterclass [ MAX_CHARACTER_CLASS + 1 ] ;
int rc ;
2001-06-05 16:46:33 +04:00
/* Skip over modifiers */
while ( format [ index ] ! = SPECIFIER_GROUP )
{
index + + ;
}
/* Skip over group specifier */
index + + ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
memset ( characterclass , 0 , sizeof ( characterclass ) ) ;
2001-06-05 16:46:33 +04:00
rc = TrioGetCharacterClass ( format ,
& index ,
& flags ,
2001-03-27 16:47:33 +04:00
characterclass ) ;
if ( rc < 0 )
return rc ;
if ( ! TrioReadGroup ( data ,
( flags & FLAGS_IGNORE )
? NULL
: parameters [ i ] . data . string ,
characterclass ,
flags ,
parameters [ i ] . width ) )
return assignment ;
2002-09-26 02:44:43 +04:00
if ( ! ( flags & FLAGS_IGNORE ) )
assignment + + ;
2001-03-27 16:47:33 +04:00
}
break ; /* FORMAT_GROUP */
2002-09-26 02:44:43 +04:00
2001-03-27 16:47:33 +04:00
case FORMAT_COUNT :
pointer = parameters [ i ] . data . pointer ;
if ( NULL ! = pointer )
{
2002-09-26 02:44:43 +04:00
int count = data - > committed ;
if ( ch ! = EOF )
count - - ; /* a character is read, but is not consumed yet */
2001-03-27 16:47:33 +04:00
# if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
if ( flags & FLAGS_SIZE_T )
2002-09-26 02:44:43 +04:00
* ( size_t * ) pointer = ( size_t ) count ;
2001-03-27 16:47:33 +04:00
else
# endif
# if defined(QUALIFIER_PTRDIFF_T)
if ( flags & FLAGS_PTRDIFF_T )
2002-09-26 02:44:43 +04:00
* ( ptrdiff_t * ) pointer = ( ptrdiff_t ) count ;
2001-03-27 16:47:33 +04:00
else
# endif
# if defined(QUALIFIER_INTMAX_T)
if ( flags & FLAGS_INTMAX_T )
2002-09-26 02:44:43 +04:00
* ( trio_intmax_t * ) pointer = ( trio_intmax_t ) count ;
2001-03-27 16:47:33 +04:00
else
# endif
if ( flags & FLAGS_QUAD )
{
2002-09-26 02:44:43 +04:00
* ( trio_ulonglong_t * ) pointer = ( trio_ulonglong_t ) count ;
2001-03-27 16:47:33 +04:00
}
else if ( flags & FLAGS_LONG )
{
2002-09-26 02:44:43 +04:00
* ( long int * ) pointer = ( long int ) count ;
2001-03-27 16:47:33 +04:00
}
else if ( flags & FLAGS_SHORT )
{
2002-09-26 02:44:43 +04:00
* ( short int * ) pointer = ( short int ) count ;
2001-03-27 16:47:33 +04:00
}
else
{
2002-09-26 02:44:43 +04:00
* ( int * ) pointer = ( int ) count ;
2001-03-27 16:47:33 +04:00
}
}
break ; /* FORMAT_COUNT */
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
case FORMAT_CHAR :
2001-06-05 16:46:33 +04:00
# if TRIO_WIDECHAR
if ( flags & FLAGS_WIDECHAR )
{
if ( TrioReadWideChar ( data ,
( flags & FLAGS_IGNORE )
? NULL
: parameters [ i ] . data . wstring ,
flags ,
2002-09-26 02:44:43 +04:00
( width = = NO_WIDTH ) ? 1 : width ) = = 0 )
2001-06-05 16:46:33 +04:00
return assignment ;
}
else
# endif
{
if ( TrioReadChar ( data ,
( flags & FLAGS_IGNORE )
? NULL
: parameters [ i ] . data . string ,
flags ,
2002-09-26 02:44:43 +04:00
( width = = NO_WIDTH ) ? 1 : width ) = = 0 )
2001-06-05 16:46:33 +04:00
return assignment ;
}
2002-09-26 02:44:43 +04:00
if ( ! ( flags & FLAGS_IGNORE ) )
assignment + + ;
2001-03-27 16:47:33 +04:00
break ; /* FORMAT_CHAR */
2002-09-26 02:44:43 +04:00
2001-03-27 16:47:33 +04:00
case FORMAT_POINTER :
if ( ! TrioReadPointer ( data ,
( flags & FLAGS_IGNORE )
? NULL
2002-09-26 02:44:43 +04:00
: ( trio_pointer_t * ) parameters [ i ] . data . pointer ,
2001-03-27 16:47:33 +04:00
flags ) )
return assignment ;
2002-09-26 02:44:43 +04:00
if ( ! ( flags & FLAGS_IGNORE ) )
assignment + + ;
2001-03-27 16:47:33 +04:00
break ; /* FORMAT_POINTER */
2002-09-26 02:44:43 +04:00
2001-03-27 16:47:33 +04:00
case FORMAT_PARAMETER :
break ; /* FORMAT_PARAMETER */
2002-09-26 02:44:43 +04:00
2001-03-27 16:47:33 +04:00
default :
return TRIO_ERROR_RETURN ( TRIO_EINVAL , index ) ;
}
ch = data - > current ;
index = parameters [ i ] . indexAfterSpecifier ;
i + + ;
}
else /* Not an % identifier */
{
if ( isspace ( ( int ) format [ index ] ) )
{
/* Whitespaces may match any amount of whitespaces */
ch = TrioSkipWhitespaces ( data ) ;
}
else if ( ch = = format [ index ] )
{
data - > InStream ( data , & ch ) ;
}
else
2002-01-19 18:40:18 +03:00
return assignment ;
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
index + + ;
}
}
return assignment ;
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioScan
*/
TRIO_PRIVATE int
2002-09-26 02:44:43 +04:00
TrioScan
TRIO_ARGS6 ( ( source , sourceSize , InStream , format , arglist , argarray ) ,
trio_pointer_t source ,
size_t sourceSize ,
void ( * InStream ) TRIO_PROTO ( ( trio_class_t * , int * ) ) ,
TRIO_CONST char * format ,
2013-12-12 11:04:43 +04:00
TRIO_VA_LIST_PTR arglist ,
2002-09-26 02:44:43 +04:00
trio_pointer_t * argarray )
2002-01-19 18:40:18 +03:00
{
int status ;
trio_parameter_t parameters [ MAX_PARAMETERS ] ;
trio_class_t data ;
assert ( VALID ( InStream ) ) ;
assert ( VALID ( format ) ) ;
memset ( & data , 0 , sizeof ( data ) ) ;
data . InStream = InStream ;
2002-09-26 02:44:43 +04:00
data . location = ( trio_pointer_t ) source ;
2002-01-19 18:40:18 +03:00
data . max = sourceSize ;
data . error = 0 ;
# if defined(USE_LOCALE)
if ( NULL = = internalLocaleValues )
{
TrioSetLocale ( ) ;
}
# endif
2012-09-11 09:26:36 +04:00
2002-01-19 18:40:18 +03:00
status = TrioParse ( TYPE_SCAN , format , parameters , arglist , argarray ) ;
if ( status < 0 )
return status ;
status = TrioScanProcess ( & data , format , parameters ) ;
if ( data . error ! = 0 )
{
status = data . error ;
}
return status ;
}
/*************************************************************************
* TrioInStreamFile
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioInStreamFile
TRIO_ARGS2 ( ( self , intPointer ) ,
trio_class_t * self ,
int * intPointer )
2001-03-27 16:47:33 +04:00
{
2014-07-14 17:22:07 +04:00
FILE * file ;
2001-03-27 16:47:33 +04:00
assert ( VALID ( self ) ) ;
2014-07-14 17:22:07 +04:00
assert ( VALID ( self - > location ) ) ;
2001-03-27 16:47:33 +04:00
assert ( VALID ( file ) ) ;
2014-07-14 17:22:07 +04:00
file = ( FILE * ) self - > location ;
2001-03-27 16:47:33 +04:00
self - > current = fgetc ( file ) ;
2002-01-19 18:40:18 +03:00
if ( self - > current = = EOF )
{
self - > error = ( ferror ( file ) )
? TRIO_ERROR_RETURN ( TRIO_ERRNO , 0 )
: TRIO_ERROR_RETURN ( TRIO_EOF , 0 ) ;
}
2002-09-26 02:44:43 +04:00
else
{
self - > processed + + ;
self - > committed + + ;
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( VALID ( intPointer ) )
{
* intPointer = self - > current ;
}
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioInStreamFileDescriptor
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioInStreamFileDescriptor
TRIO_ARGS2 ( ( self , intPointer ) ,
trio_class_t * self ,
int * intPointer )
2001-03-27 16:47:33 +04:00
{
2014-07-14 17:22:07 +04:00
int fd ;
2001-03-27 16:47:33 +04:00
int size ;
unsigned char input ;
assert ( VALID ( self ) ) ;
2014-07-14 17:22:07 +04:00
assert ( VALID ( self - > location ) ) ;
fd = * ( ( int * ) self - > location ) ;
2001-03-27 16:47:33 +04:00
size = read ( fd , & input , sizeof ( char ) ) ;
2002-01-19 18:40:18 +03:00
if ( size = = - 1 )
{
self - > error = TRIO_ERROR_RETURN ( TRIO_ERRNO , 0 ) ;
self - > current = EOF ;
}
else
{
self - > current = ( size = = 0 ) ? EOF : input ;
}
2002-09-26 02:44:43 +04:00
if ( self - > current ! = EOF )
{
self - > committed + + ;
self - > processed + + ;
}
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
if ( VALID ( intPointer ) )
{
* intPointer = self - > current ;
}
}
/*************************************************************************
* TrioInStreamCustom
*/
TRIO_PRIVATE void
TrioInStreamCustom
TRIO_ARGS2 ( ( self , intPointer ) ,
trio_class_t * self ,
int * intPointer )
{
trio_custom_t * data ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > location ) ) ;
data = ( trio_custom_t * ) self - > location ;
self - > current = ( data - > stream . in = = NULL )
? NIL
: ( data - > stream . in ) ( data - > closure ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
if ( self - > current = = NIL )
{
self - > current = EOF ;
}
else
{
self - > processed + + ;
self - > committed + + ;
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( VALID ( intPointer ) )
{
* intPointer = self - > current ;
}
}
/*************************************************************************
2002-01-19 18:40:18 +03:00
* TrioInStreamString
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PRIVATE void
2002-09-26 02:44:43 +04:00
TrioInStreamString
TRIO_ARGS2 ( ( self , intPointer ) ,
trio_class_t * self ,
int * intPointer )
2001-03-27 16:47:33 +04:00
{
unsigned char * * buffer ;
assert ( VALID ( self ) ) ;
assert ( VALID ( self - > location ) ) ;
buffer = ( unsigned char * * ) self - > location ;
self - > current = ( * buffer ) [ 0 ] ;
if ( self - > current = = NIL )
2002-09-26 02:44:43 +04:00
{
self - > current = EOF ;
}
else
{
( * buffer ) + + ;
self - > processed + + ;
self - > committed + + ;
}
2012-09-11 09:26:36 +04:00
2001-03-27 16:47:33 +04:00
if ( VALID ( intPointer ) )
{
* intPointer = self - > current ;
}
}
2002-01-19 18:40:18 +03:00
/*************************************************************************
*
* Formatted scanning functions
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined(TRIO_DOCUMENTATION)
# include "doc / doc_scanf.h"
# endif
/** @addtogroup Scanf
@ {
*/
2001-03-27 16:47:33 +04:00
/*************************************************************************
2001-04-21 20:57:29 +04:00
* scanf
*/
2002-01-19 18:40:18 +03:00
/**
Scan characters from standard input stream .
@ param format Formatting string .
@ param . . . Arguments .
@ return Number of scanned characters .
*/
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_scanf
TRIO_VARGS2 ( ( format , va_alist ) ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
status = TrioScan ( ( trio_pointer_t ) stdin , 0 ,
TrioInStreamFile ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vscanf
TRIO_ARGS2 ( ( format , args ) ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioScan ( ( trio_pointer_t ) stdin , 0 ,
TrioInStreamFile ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_scanfv
TRIO_ARGS2 ( ( format , args ) ,
TRIO_CONST char * format ,
trio_pointer_t * args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioScan ( ( trio_pointer_t ) stdin , 0 ,
TrioInStreamFile ,
format , NULL , args ) ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* fscanf
*/
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_fscanf
TRIO_VARGS3 ( ( file , format , va_alist ) ,
FILE * file ,
2002-01-19 18:40:18 +03:00
TRIO_CONST char * format ,
2002-09-26 02:44:43 +04:00
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
assert ( VALID ( file ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
status = TrioScan ( ( trio_pointer_t ) file , 0 ,
TrioInStreamFile ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vfscanf
TRIO_ARGS3 ( ( file , format , args ) ,
FILE * file ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( file ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioScan ( ( trio_pointer_t ) file , 0 ,
TrioInStreamFile ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_fscanfv
TRIO_ARGS3 ( ( file , format , args ) ,
FILE * file ,
TRIO_CONST char * format ,
trio_pointer_t * args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( file ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioScan ( ( trio_pointer_t ) file , 0 ,
TrioInStreamFile ,
format , NULL , args ) ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* dscanf
*/
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_dscanf
TRIO_VARGS3 ( ( fd , format , va_alist ) ,
int fd ,
2002-01-19 18:40:18 +03:00
TRIO_CONST char * format ,
2002-09-26 02:44:43 +04:00
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
int status ;
va_list args ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
status = TrioScan ( ( trio_pointer_t ) & fd , 0 ,
TrioInStreamFileDescriptor ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-04-21 20:57:29 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vdscanf
TRIO_ARGS3 ( ( fd , format , args ) ,
int fd ,
TRIO_CONST char * format ,
va_list args )
{
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioScan ( ( trio_pointer_t ) & fd , 0 ,
TrioInStreamFileDescriptor ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
}
TRIO_PUBLIC int
trio_dscanfv
TRIO_ARGS3 ( ( fd , format , args ) ,
int fd ,
TRIO_CONST char * format ,
trio_pointer_t * args )
{
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioScan ( ( trio_pointer_t ) & fd , 0 ,
TrioInStreamFileDescriptor ,
format , NULL , args ) ;
}
/*************************************************************************
* cscanf
*/
TRIO_PUBLIC int
trio_cscanf
TRIO_VARGS4 ( ( stream , closure , format , va_alist ) ,
trio_instream_t stream ,
trio_pointer_t closure ,
TRIO_CONST char * format ,
TRIO_VA_DECL )
2001-04-21 20:57:29 +04:00
{
2002-09-26 02:44:43 +04:00
int status ;
va_list args ;
trio_custom_t data ;
assert ( VALID ( stream ) ) ;
2001-04-21 20:57:29 +04:00
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
data . stream . in = stream ;
data . closure = closure ;
2013-12-12 11:04:43 +04:00
status = TrioScan ( & data , 0 , TrioInStreamCustom , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
return status ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vcscanf
TRIO_ARGS4 ( ( stream , closure , format , args ) ,
trio_instream_t stream ,
trio_pointer_t closure ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
2002-09-26 02:44:43 +04:00
trio_custom_t data ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
assert ( VALID ( stream ) ) ;
2001-04-21 20:57:29 +04:00
assert ( VALID ( format ) ) ;
2002-09-26 02:44:43 +04:00
data . stream . in = stream ;
data . closure = closure ;
2013-12-12 11:04:43 +04:00
return TrioScan ( & data , 0 , TrioInStreamCustom , format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
}
TRIO_PUBLIC int
trio_cscanfv
TRIO_ARGS4 ( ( stream , closure , format , args ) ,
trio_instream_t stream ,
trio_pointer_t closure ,
TRIO_CONST char * format ,
trio_pointer_t * args )
{
trio_custom_t data ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
assert ( VALID ( stream ) ) ;
assert ( VALID ( format ) ) ;
data . stream . in = stream ;
data . closure = closure ;
return TrioScan ( & data , 0 , TrioInStreamCustom , format , NULL , args ) ;
2001-04-21 20:57:29 +04:00
}
/*************************************************************************
* sscanf
2001-03-27 16:47:33 +04:00
*/
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_sscanf
TRIO_VARGS3 ( ( buffer , format , va_alist ) ,
TRIO_CONST char * buffer ,
2002-01-19 18:40:18 +03:00
TRIO_CONST char * format ,
2002-09-26 02:44:43 +04:00
TRIO_VA_DECL )
2001-03-27 16:47:33 +04:00
{
int status ;
va_list args ;
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
TRIO_VA_START ( args , format ) ;
status = TrioScan ( ( trio_pointer_t ) & buffer , 0 ,
TrioInStreamString ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2002-09-26 02:44:43 +04:00
TRIO_VA_END ( args ) ;
2001-03-27 16:47:33 +04:00
return status ;
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_vsscanf
TRIO_ARGS3 ( ( buffer , format , args ) ,
TRIO_CONST char * buffer ,
TRIO_CONST char * format ,
va_list args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioScan ( ( trio_pointer_t ) & buffer , 0 ,
TrioInStreamString ,
2013-12-12 11:04:43 +04:00
format , TRIO_VA_LIST_ADDR ( args ) , NULL ) ;
2001-04-21 20:57:29 +04:00
}
2002-01-19 18:40:18 +03:00
TRIO_PUBLIC int
2002-09-26 02:44:43 +04:00
trio_sscanfv
TRIO_ARGS3 ( ( buffer , format , args ) ,
TRIO_CONST char * buffer ,
TRIO_CONST char * format ,
trio_pointer_t * args )
2001-04-21 20:57:29 +04:00
{
assert ( VALID ( buffer ) ) ;
assert ( VALID ( format ) ) ;
2012-09-11 09:26:36 +04:00
2002-09-26 02:44:43 +04:00
return TrioScan ( ( trio_pointer_t ) & buffer , 0 ,
TrioInStreamString ,
format , NULL , args ) ;
2001-04-21 20:57:29 +04:00
}
2001-06-05 16:46:33 +04:00
2002-01-19 18:40:18 +03:00
/** @} End of Scanf documentation module */
2002-09-26 02:44:43 +04:00
/*************************************************************************
* trio_strerror
*/
TRIO_PUBLIC TRIO_CONST char *
trio_strerror
TRIO_ARGS1 ( ( errorcode ) ,
int errorcode )
{
/* Textual versions of the error codes */
switch ( TRIO_ERROR_CODE ( errorcode ) )
{
case TRIO_EOF :
return " End of file " ;
case TRIO_EINVAL :
return " Invalid argument " ;
case TRIO_ETOOMANY :
return " Too many arguments " ;
case TRIO_EDBLREF :
return " Double reference " ;
case TRIO_EGAP :
return " Reference gap " ;
case TRIO_ENOMEM :
return " Out of memory " ;
case TRIO_ERANGE :
return " Invalid range " ;
case TRIO_ECUSTOM :
return " Custom error " ;
default :
return " Unknown " ;
}
}