aboutsummaryrefslogtreecommitdiffstats
path: root/trio/trio.c
diff options
context:
space:
mode:
authorMatthias Andree <matthias.andree@gmx.de>2009-07-02 19:48:34 +0000
committerMatthias Andree <matthias.andree@gmx.de>2009-07-02 19:48:34 +0000
commitc8e1897c969ce43b551c29d65bc605f175c01263 (patch)
treed976ad001b090dbebd5ee58a4929108de7ce426d /trio/trio.c
parent33c48f99e8b28504cc68a9bd672e487422602038 (diff)
downloadfetchmail-c8e1897c969ce43b551c29d65bc605f175c01263.tar.gz
fetchmail-c8e1897c969ce43b551c29d65bc605f175c01263.tar.bz2
fetchmail-c8e1897c969ce43b551c29d65bc605f175c01263.zip
Update trio to CVS checkout of 2009-07-02.
svn path=/branches/BRANCH_6-3/; revision=5370
Diffstat (limited to 'trio/trio.c')
-rw-r--r--trio/trio.c4225
1 files changed, 2565 insertions, 1660 deletions
diff --git a/trio/trio.c b/trio/trio.c
index 8494e556..8c9d36e2 100644
--- a/trio/trio.c
+++ b/trio/trio.c
@@ -1,8 +1,8 @@
/*************************************************************************
*
- * $Id: trio.c,v 1.75 2003/03/01 15:34:01 breese Exp $
+ * $Id: trio.c,v 1.125 2009/06/23 15:46:21 breese Exp $
*
- * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
+ * Copyright (C) 1998, 2009 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
@@ -47,10 +47,71 @@
#include "triodef.h"
#include "trio.h"
#include "triop.h"
+
+#if defined(TRIO_EMBED_NAN)
+# define TRIO_PUBLIC_NAN static
+# if TRIO_FEATURE_FLOAT
+# define TRIO_FUNC_NAN
+# define TRIO_FUNC_NINF
+# define TRIO_FUNC_PINF
+# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
+# define TRIO_FUNC_ISINF
+# endif
+#endif
#include "trionan.h"
-#if !defined(TRIO_MINIMAL)
-# include "triostr.h"
+
+#if defined(TRIO_EMBED_STRING)
+# define TRIO_PUBLIC_STRING static
+# define TRIO_FUNC_LENGTH
+# define TRIO_FUNC_LENGTH_MAX
+# define TRIO_FUNC_TO_LONG
+# if TRIO_FEATURE_LOCALE
+# define TRIO_FUNC_COPY_MAX
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_XSTRING_DUPLICATE
+# endif
+# if TRIO_EXTENSION && TRIO_FEATURE_SCANF
+# define TRIO_FUNC_EQUAL_LOCALE
+# endif
+# if TRIO_FEATURE_ERRNO
+# define TRIO_FUNC_ERROR
+# endif
+# if TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF
+# define TRIO_FUNC_TO_DOUBLE
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_STRING_EXTRACT
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_STRING_TERMINATE
+# endif
+# if TRIO_FEATURE_USER_DEFINED
+# define TRIO_FUNC_DUPLICATE
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_STRING_DESTROY
+# endif
+# if TRIO_FEATURE_USER_DEFINED
+# define TRIO_FUNC_DESTROY
+# endif
+# if TRIO_FEATURE_USER_DEFINED || (TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF)
+# define TRIO_FUNC_EQUAL
+# endif
+# if TRIO_FEATURE_USER_DEFINED || TRIO_FEATURE_SCANF
+# define TRIO_FUNC_EQUAL_CASE
+# endif
+# if (TRIO_EXTENSION && TRIO_FEATURE_SCANF)
+# define TRIO_FUNC_EQUAL_MAX
+# endif
+# if TRIO_FEATURE_SCANF
+# define TRIO_FUNC_TO_UPPER
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_XSTRING_APPEND_CHAR
+# endif
#endif
+#include "triostr.h"
/**************************************************************************
*
@@ -58,19 +119,61 @@
*
*************************************************************************/
-#include <math.h>
#include <limits.h>
-#include <float.h>
+#if TRIO_FEATURE_FLOAT
+# include <math.h>
+# include <float.h>
+#endif
-#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_WIDECHAR
-# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
-# if !defined(MB_LEN_MAX)
-# define MB_LEN_MAX 6
+#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_FEATURE_WIDECHAR
+# if !defined(TRIO_PLATFORM_WINCE)
+# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
+# if !defined(MB_LEN_MAX)
+# define MB_LEN_MAX 6
+# endif
# endif
#endif
-#if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
-# define TRIO_COMPILER_SUPPORTS_MSVC_INT
+#if (TRIO_COMPILER_VISUALC - 0 >= 1100) || defined(TRIO_COMPILER_BORLAND)
+# define TRIO_COMPILER_SUPPORTS_VISUALC_INT
+#endif
+
+#if TRIO_FEATURE_FLOAT
+# if defined(PREDEF_STANDARD_C99) \
+ || defined(PREDEF_STANDARD_UNIX03)
+# if !defined(HAVE_FLOORL)
+# define HAVE_FLOORL
+# endif
+# if !defined(HAVE_CEILL)
+# define HAVE_CEILL
+# endif
+# if !defined(HAVE_POWL)
+# define HAVE_POWL
+# endif
+# if !defined(HAVE_FMODL)
+# define HAVE_FMODL
+# endif
+# if !defined(HAVE_LOG10L)
+# define HAVE_LOG10L
+# endif
+# endif
+# if defined(TRIO_COMPILER_VISUALC)
+# if defined(floorl)
+# define HAVE_FLOORL
+# endif
+# if defined(ceill)
+# define HAVE_CEILL
+# endif
+# if defined(powl)
+# define HAVE_POWL
+# endif
+# if defined(fmodl)
+# define HAVE_FMODL
+# endif
+# if defined(log10l)
+# define HAVE_LOG10L
+# endif
+# endif
#endif
/*************************************************************************
@@ -83,8 +186,8 @@
#include <assert.h>
#include <ctype.h>
-#if !defined(TRIO_COMPILER_SUPPORTS_C99)
-# define isblank(x) (((x)==32) || ((x)==9))
+#if defined(PREDEF_STANDARD_C99) && !defined(isascii)
+# define isascii(x) ((x) & 0x7F)
#endif
#if defined(TRIO_COMPILER_ANCIENT)
# include <varargs.h>
@@ -92,7 +195,11 @@
# include <stdarg.h>
#endif
#include <stddef.h>
-#include <errno.h>
+#if defined(TRIO_PLATFORM_WINCE)
+extern int errno;
+#else
+# include <errno.h>
+#endif
#ifndef NULL
# define NULL 0
@@ -107,7 +214,7 @@
/* mincore() can be used for debugging purposes */
#define VALID(x) (NULL != (x))
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
/*
* Encode the error code and the position. This is decoded
* with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
@@ -127,19 +234,26 @@ typedef unsigned long trio_flags_t;
# include <unistd.h>
# include <signal.h>
# include <locale.h>
-# define USE_LOCALE
+# if !defined(TRIO_FEATURE_LOCALE)
+# define USE_LOCALE
+# endif
#endif /* TRIO_PLATFORM_UNIX */
#if defined(TRIO_PLATFORM_VMS)
# include <unistd.h>
#endif
#if defined(TRIO_PLATFORM_WIN32)
-# include <io.h>
-# define read _read
-# define write _write
+# if defined(TRIO_PLATFORM_WINCE)
+int read(int handle, char *buffer, unsigned int length);
+int write(int handle, const char *buffer, unsigned int length);
+# else
+# include <io.h>
+# define read _read
+# define write _write
+# endif
#endif /* TRIO_PLATFORM_WIN32 */
-#if TRIO_WIDECHAR
-# if defined(TRIO_COMPILER_SUPPORTS_ISO94)
+#if TRIO_FEATURE_WIDECHAR
+# if defined(PREDEF_STANDARD_C94)
# include <wchar.h>
# include <wctype.h>
typedef wchar_t trio_wchar_t;
@@ -151,7 +265,6 @@ typedef int trio_wint_t;
# 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)
@@ -174,10 +287,18 @@ typedef int trio_wint_t;
# if !defined(USE_LONGLONG)
# if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
# define USE_LONGLONG
-# elif defined(TRIO_COMPILER_SUNPRO)
-# define USE_LONGLONG
-# elif defined(_LONG_LONG) || defined(_LONGLONG)
-# define USE_LONGLONG
+# else
+# if defined(TRIO_COMPILER_SUNPRO)
+# define USE_LONGLONG
+# else
+# if defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1400)
+# define USE_LONGLONG
+# else
+# if defined(_LONG_LONG) || defined(_LONGLONG)
+# define USE_LONGLONG
+# endif
+# endif
+# endif
# endif
# endif
#endif
@@ -186,16 +307,18 @@ typedef int trio_wint_t;
#if defined(USE_LONGLONG)
typedef signed long long int trio_longlong_t;
typedef unsigned long long int trio_ulonglong_t;
-#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
+#else
+# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT)
typedef signed __int64 trio_longlong_t;
typedef unsigned __int64 trio_ulonglong_t;
-#else
+# else
typedef TRIO_SIGNED long int trio_longlong_t;
typedef unsigned long int trio_ulonglong_t;
+# endif
#endif
/* Maximal and fixed integer types */
-#if defined(TRIO_COMPILER_SUPPORTS_C99)
+#if defined(PREDEF_STANDARD_C99)
# include <stdint.h>
typedef intmax_t trio_intmax_t;
typedef uintmax_t trio_uintmax_t;
@@ -203,100 +326,137 @@ typedef int8_t trio_int8_t;
typedef int16_t trio_int16_t;
typedef int32_t trio_int32_t;
typedef int64_t trio_int64_t;
-#elif defined(TRIO_COMPILER_SUPPORTS_UNIX98)
-# include <inttypes.h>
+#else
+# if defined(PREDEF_STANDARD_UNIX98)
+# include <inttypes.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;
-#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
+# else
+# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT)
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;
-#else
+# else
typedef trio_longlong_t trio_intmax_t;
typedef trio_ulonglong_t trio_uintmax_t;
-# if defined(TRIO_INT8_T)
+# if defined(TRIO_INT8_T)
typedef TRIO_INT8_T trio_int8_t;
-# else
+# else
typedef TRIO_SIGNED char trio_int8_t;
-# endif
-# if defined(TRIO_INT16_T)
+# endif
+# if defined(TRIO_INT16_T)
typedef TRIO_INT16_T trio_int16_t;
-# else
+# else
typedef TRIO_SIGNED short trio_int16_t;
-# endif
-# if defined(TRIO_INT32_T)
+# endif
+# if defined(TRIO_INT32_T)
typedef TRIO_INT32_T trio_int32_t;
-# else
+# else
typedef TRIO_SIGNED int trio_int32_t;
-# endif
-# if defined(TRIO_INT64_T)
+# endif
+# if defined(TRIO_INT64_T)
typedef TRIO_INT64_T trio_int64_t;
-# else
+# else
typedef trio_longlong_t trio_int64_t;
+# endif
+# endif
# endif
#endif
-#if !(defined(TRIO_COMPILER_SUPPORTS_C99) \
- || defined(TRIO_COMPILER_SUPPORTS_UNIX01))
-# define floorl(x) floor((double)(x))
-# define fmodl(x,y) fmod((double)(x),(double)(y))
-# define powl(x,y) pow((double)(x),(double)(y))
+#if defined(HAVE_FLOORL)
+# define trio_floor(x) floorl((x))
+#else
+# define trio_floor(x) floor((double)(x))
#endif
-#define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
+#if defined(HAVE_CEILL)
+# define trio_ceil(x) ceill((x))
+#else
+# define trio_ceil(x) ceil((double)(x))
+#endif
-/*************************************************************************
- * Internal Definitions
- */
+#if defined(HAVE_FMODL)
+# define trio_fmod(x,y) fmodl((x),(y))
+#else
+# define trio_fmod(x,y) fmod((double)(x),(double)(y))
+#endif
-#ifndef DECIMAL_DIG
-# define DECIMAL_DIG DBL_DIG
+#if defined(HAVE_POWL)
+# define trio_pow(x,y) powl((x),(y))
+#else
+# define trio_pow(x,y) pow((double)(x),(double)(y))
#endif
-/* Long double sizes */
-#ifdef LDBL_DIG
-# define MAX_MANTISSA_DIGITS LDBL_DIG
-# define MAX_EXPONENT_DIGITS 4
-# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
+#if defined(HAVE_LOG10L)
+# define trio_log10(x) log10l((x))
#else
-# define MAX_MANTISSA_DIGITS DECIMAL_DIG
-# define MAX_EXPONENT_DIGITS 3
-# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
+# define trio_log10(x) log10((double)(x))
#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
+#if TRIO_FEATURE_FLOAT
+# define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
#endif
+/*************************************************************************
+ * Internal Definitions
+ */
+
+#if TRIO_FEATURE_FLOAT
+
+# if !defined(DECIMAL_DIG)
+# define DECIMAL_DIG DBL_DIG
+# endif
+
+/* Long double sizes */
+# ifdef LDBL_DIG
+# define MAX_MANTISSA_DIGITS LDBL_DIG
+# define MAX_EXPONENT_DIGITS 4
+# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
+# else
+# define MAX_MANTISSA_DIGITS DECIMAL_DIG
+# define MAX_EXPONENT_DIGITS 3
+# 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
+# endif
+
+#endif /* TRIO_FEATURE_FLOAT */
+
/* The maximal number of digits is for base 2 */
#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
/* The width of a pointer. The number of bits in a hex digit is 4 */
#define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
+#if TRIO_FEATURE_FLOAT
/* Infinite and Not-A-Number for floating-point */
-#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"
+# 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"
+#endif
/* Various constants */
enum {
TYPE_PRINT = 1,
+#if TRIO_FEATURE_SCANF
TYPE_SCAN = 2,
+#endif
/* Flags. FLAGS_LAST must be less than ULONG_MAX */
FLAGS_NEW = 0,
@@ -326,8 +486,7 @@ enum {
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 = 2 * FLAGS_WIDECHAR,
FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE,
FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER,
FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER,
@@ -335,6 +494,7 @@ enum {
/* Reused flags */
FLAGS_EXCLUDE = FLAGS_SHORT,
FLAGS_USER_DEFINED = FLAGS_IGNORE,
+ FLAGS_USER_DEFINED_PARAMETER = FLAGS_IGNORE_PARAMETER,
FLAGS_ROUNDING = FLAGS_INTMAX_T,
/* Compounded flags */
FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
@@ -359,22 +519,22 @@ enum {
/* Maximal number of characters in class */
MAX_CHARACTER_CLASS = UCHAR_MAX + 1,
+#if TRIO_FEATURE_USER_DEFINED
/* Maximal string lengths for user-defined specifiers */
MAX_USER_NAME = 64,
MAX_USER_DATA = 256,
+#endif
/* Maximal length of locale separator strings */
MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX,
/* Maximal number of integers in grouping */
- MAX_LOCALE_GROUPS = 64,
-
- /* Initial size of asprintf buffer */
- DYNAMIC_START_SIZE = 32
+ MAX_LOCALE_GROUPS = 64
};
#define NO_GROUPING ((int)CHAR_MAX)
/* Fundamental formatting parameter types */
+#define FORMAT_SENTINEL -1 /* marks end of parameters array */
#define FORMAT_UNKNOWN 0
#define FORMAT_INT 1
#define FORMAT_DOUBLE 2
@@ -384,32 +544,31 @@ enum {
#define FORMAT_COUNT 6
#define FORMAT_PARAMETER 7
#define FORMAT_GROUP 8
-#if TRIO_GNU
-# define FORMAT_ERRNO 9
-#endif
-#if TRIO_EXTENSION
-# define FORMAT_USER_DEFINED 10
-#endif
+#define FORMAT_ERRNO 9
+#define FORMAT_USER_DEFINED 10
/* Character constants */
#define CHAR_IDENTIFIER '%'
+#define CHAR_ALT_IDENTIFIER '$'
#define CHAR_BACKSLASH '\\'
#define CHAR_QUOTE '\"'
#define CHAR_ADJUST ' '
+#if TRIO_EXTENSION
/* Character class expressions */
-#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:]"
+# 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:]"
+#endif
/*
* SPECIFIERS:
@@ -451,33 +610,36 @@ enum {
#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'
+#if TRIO_FEATURE_FLOAT
+# 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'
+#endif
#define SPECIFIER_POINTER 'p'
-#define SPECIFIER_GROUP '['
-#define SPECIFIER_UNGROUP ']'
+#if TRIO_FEATURE_SCANF
+# define SPECIFIER_GROUP '['
+# define SPECIFIER_UNGROUP ']'
+#endif
#define SPECIFIER_COUNT 'n'
#if TRIO_UNIX98
# define SPECIFIER_CHAR_UPPER 'C'
# define SPECIFIER_STRING_UPPER 'S'
#endif
-#if TRIO_C99
-# define SPECIFIER_HEXFLOAT 'a'
-# define SPECIFIER_HEXFLOAT_UPPER 'A'
-#endif
-#if TRIO_GNU
-# define SPECIFIER_ERRNO 'm'
-#endif
-#if TRIO_EXTENSION
+#define SPECIFIER_HEXFLOAT 'a'
+#define SPECIFIER_HEXFLOAT_UPPER 'A'
+#define SPECIFIER_ERRNO 'm'
+#if TRIO_FEATURE_BINARY
# define SPECIFIER_BINARY 'b'
# define SPECIFIER_BINARY_UPPER 'B'
+#endif
+#if TRIO_FEATURE_USER_DEFINED
# define SPECIFIER_USER_DEFINED_BEGIN '<'
# define SPECIFIER_USER_DEFINED_END '>'
# define SPECIFIER_USER_DEFINED_SEPARATOR ':'
+# define SPECIFIER_USER_DEFINED_EXTRA '|'
#endif
/*
@@ -580,31 +742,23 @@ enum {
#define QUALIFIER_DOT '.'
#define QUALIFIER_STAR '*'
#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
-#if TRIO_C99
-# define QUALIFIER_SIZE_T 'z'
-# define QUALIFIER_PTRDIFF_T 't'
-# define QUALIFIER_INTMAX_T 'j'
-#endif
-#if TRIO_BSD || TRIO_GNU
-# define QUALIFIER_QUAD 'q'
-#endif
-#if TRIO_GNU
-# define QUALIFIER_SIZE_T_UPPER 'Z'
-#endif
+#define QUALIFIER_SIZE_T 'z'
+#define QUALIFIER_PTRDIFF_T 't'
+#define QUALIFIER_INTMAX_T 'j'
+#define QUALIFIER_QUAD 'q'
+#define QUALIFIER_SIZE_T_UPPER 'Z'
#if TRIO_MISC
# define QUALIFIER_WIDECHAR 'w'
#endif
-#if TRIO_MICROSOFT
-# define QUALIFIER_FIXED_SIZE 'I'
-#endif
+#define QUALIFIER_FIXED_SIZE 'I'
+#define QUALIFIER_QUOTE '\''
+#define QUALIFIER_STICKY '!'
+#define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
+#define QUALIFIER_ROUNDING_UPPER 'R'
#if TRIO_EXTENSION
-# define QUALIFIER_QUOTE '\''
-# define QUALIFIER_STICKY '!'
-# define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
# define QUALIFIER_PARAM '@' /* Experimental */
# define QUALIFIER_COLON ':' /* For scanlists */
# define QUALIFIER_EQUAL '=' /* For scanlists */
-# define QUALIFIER_ROUNDING_UPPER 'R'
#endif
@@ -626,14 +780,20 @@ typedef struct {
int precision;
/* The base qualifier */
int base;
+ /* Base from specifier */
+ int baseSpecifier;
/* The size for the variable size qualifier */
int varsize;
- /* The marker of the end of the specifier */
- int indexAfterSpecifier;
+ /* Offset of the first character of the specifier */
+ int beginOffset;
+ /* Offset of the first character after the specifier */
+ int endOffset;
+ /* Position in the argument list that this parameter refers to */
+ int position;
/* The data from the argument list */
union {
char *string;
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
trio_wchar_t *wstring;
#endif
trio_pointer_t pointer;
@@ -641,15 +801,22 @@ typedef struct {
trio_intmax_t as_signed;
trio_uintmax_t as_unsigned;
} number;
+#if TRIO_FEATURE_FLOAT
double doubleNumber;
double *doublePointer;
trio_long_double_t longdoubleNumber;
trio_long_double_t *longdoublePointer;
+#endif
int errorNumber;
} data;
+#if TRIO_FEATURE_USER_DEFINED
/* For the user-defined specifier */
- char user_name[MAX_USER_NAME];
+ union {
+ char namespace[MAX_USER_NAME];
+ int handler; /* if flags & FLAGS_USER_DEFINED_PARAMETER */
+ } user_defined;
char user_data[MAX_USER_DATA];
+#endif
} trio_parameter_t;
/* Container for customized functions */
@@ -672,6 +839,10 @@ typedef struct _trio_class_t {
*/
void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
/*
+ * The function to undo read characters from a stream.
+ */
+ void (*UndoStream) TRIO_PROTO((struct _trio_class_t *));
+ /*
* The current location in the stream.
*/
trio_pointer_t location;
@@ -684,12 +855,17 @@ typedef struct _trio_class_t {
* if there had been sufficient space.
*/
int processed;
- /*
- * The number of characters that are actually written/read.
- * Processed and committed will only differ for the *nprintf
- * and *nscanf functions.
- */
- int committed;
+ union {
+ /*
+ * The number of characters that are actually written. Processed and
+ * committed will only differ for the *nprintf functions.
+ */
+ int committed;
+ /*
+ * The number of look-ahead characters read.
+ */
+ int cached;
+ } actually;
/*
* The upper limit of characters that may be written/read.
*/
@@ -706,12 +882,14 @@ typedef struct _trio_reference_t {
trio_parameter_t *parameter;
} trio_reference_t;
+#if TRIO_FEATURE_USER_DEFINED
/* Registered entries (for user-defined callbacks) */
typedef struct _trio_userdef_t {
struct _trio_userdef_t *next;
trio_callback_t callback;
char *name;
} trio_userdef_t;
+#endif
/*************************************************************************
*
@@ -719,15 +897,17 @@ typedef struct _trio_userdef_t {
*
*************************************************************************/
-static TRIO_CONST char rcsid[] = "@(#)$Id: trio.c,v 1.75 2003/03/01 15:34:01 breese Exp $";
+static TRIO_CONST char rcsid[] = "@(#)$Id: trio.c,v 1.125 2009/06/23 15:46:21 breese Exp $";
+#if TRIO_FEATURE_FLOAT
/*
* 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)
+# if defined(TRIO_PLATFORM_MPEIX)
static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
+# endif
#endif
static TRIO_CONST char internalNullString[] = "(nil)";
@@ -740,23 +920,29 @@ static struct lconv *internalLocaleValues = NULL;
* UNIX98 says "in a locale where the radix character is not defined,
* the radix character defaults to a period (.)"
*/
+#if TRIO_FEATURE_FLOAT || TRIO_FEATURE_LOCALE || defined(USE_LOCALE)
static int internalDecimalPointLength = 1;
-static int internalThousandSeparatorLength = 1;
static char internalDecimalPoint = '.';
static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
+#endif
+#if TRIO_FEATURE_QUOTE || TRIO_FEATURE_LOCALE || TRIO_EXTENSION
+static int internalThousandSeparatorLength = 1;
static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
+#endif
static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+#if TRIO_FEATURE_SCANF
static BOOLEAN_T internalDigitsUnconverted = TRUE;
static int internalDigitArray[128];
-#if TRIO_EXTENSION
+# if TRIO_EXTENSION
static BOOLEAN_T internalCollationUnconverted = TRUE;
static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
+# endif
#endif
-#if TRIO_EXTENSION
+#if TRIO_FEATURE_USER_DEFINED
static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL;
static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL;
static trio_userdef_t *internalUserDef = NULL;
@@ -769,10 +955,80 @@ static trio_userdef_t *internalUserDef = NULL;
*
************************************************************************/
-#if defined(TRIO_MINIMAL)
-# define TRIO_STRING_PUBLIC static
+#if defined(TRIO_EMBED_NAN)
+# include "trionan.c"
+#endif
+
+#if defined(TRIO_EMBED_STRING)
# include "triostr.c"
-#endif /* defined(TRIO_MINIMAL) */
+#endif
+
+/*************************************************************************
+ * TrioInitializeParameter
+ *
+ * Description:
+ * Initialize a trio_parameter_t struct.
+ */
+TRIO_PRIVATE void
+TrioInitializeParameter
+TRIO_ARGS1((parameter),
+ trio_parameter_t *parameter)
+{
+ parameter->type = FORMAT_UNKNOWN;
+ parameter->flags = 0;
+ parameter->width = 0;
+ parameter->precision = 0;
+ parameter->base = 0;
+ parameter->baseSpecifier = 0;
+ parameter->varsize = 0;
+ parameter->beginOffset = 0;
+ parameter->endOffset = 0;
+ parameter->position = 0;
+ parameter->data.pointer = 0;
+#if TRIO_FEATURE_USER_DEFINED
+ parameter->user_defined.handler = 0;
+ parameter->user_data[0] = 0;
+#endif
+}
+
+/*************************************************************************
+ * TrioCopyParameter
+ *
+ * Description:
+ * Copies one trio_parameter_t struct to another.
+ */
+TRIO_PRIVATE void
+TrioCopyParameter
+TRIO_ARGS2((target, source),
+ trio_parameter_t *target,
+ TRIO_CONST trio_parameter_t *source)
+{
+#if TRIO_FEATURE_USER_DEFINED
+ size_t i;
+#endif
+
+ target->type = source->type;
+ target->flags = source->flags;
+ target->width = source->width;
+ target->precision = source->precision;
+ target->base = source->base;
+ target->baseSpecifier = source->baseSpecifier;
+ target->varsize = source->varsize;
+ target->beginOffset = source->beginOffset;
+ target->endOffset = source->endOffset;
+ target->position = source->position;
+ target->data = source->data;
+
+#if TRIO_FEATURE_USER_DEFINED
+ target->user_defined = source->user_defined;
+
+ for (i = 0U; i < sizeof(target->user_data); ++i)
+ {
+ if ((target->user_data[i] = source->user_data[i]) == NIL)
+ break;
+ }
+#endif
+}
/*************************************************************************
* TrioIsQualifier
@@ -799,44 +1055,24 @@ TRIO_ARGS1((character),
case QUALIFIER_ALTERNATIVE:
case QUALIFIER_SHORT:
case QUALIFIER_LONG:
- case QUALIFIER_LONG_UPPER:
case QUALIFIER_CIRCUMFLEX:
-#if defined(QUALIFIER_SIZE_T)
+ case QUALIFIER_LONG_UPPER:
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:
#endif
-#if defined(QUALIFIER_FIXED_SIZE)
case QUALIFIER_FIXED_SIZE:
-#endif
-#if defined(QUALIFIER_ROUNDING_UPPER)
case QUALIFIER_ROUNDING_UPPER:
-#endif
return TRUE;
default:
return FALSE;
@@ -869,6 +1105,7 @@ TrioSetLocale(TRIO_NOARGS)
internalLocaleValues->decimal_point);
}
}
+# if TRIO_EXTENSION
if ((internalLocaleValues->thousands_sep) &&
(internalLocaleValues->thousands_sep[0] != NIL))
{
@@ -877,6 +1114,8 @@ TrioSetLocale(TRIO_NOARGS)
internalLocaleValues->thousands_sep);
internalThousandSeparatorLength = trio_length(internalThousandSeparator);
}
+# endif
+# if TRIO_EXTENSION
if ((internalLocaleValues->grouping) &&
(internalLocaleValues->grouping[0] != NIL))
{
@@ -884,16 +1123,17 @@ TrioSetLocale(TRIO_NOARGS)
sizeof(internalGrouping),
internalLocaleValues->grouping);
}
+# endif
}
}
#endif /* defined(USE_LOCALE) */
+#if TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE
TRIO_PRIVATE int
TrioCalcThousandSeparatorLength
TRIO_ARGS1((digits),
int digits)
{
-#if TRIO_EXTENSION
int count = 0;
int step = NO_GROUPING;
char *groupingPointer = internalGrouping;
@@ -923,17 +1163,15 @@ TRIO_ARGS1((digits),
digits -= step;
}
return count;
-#else
- return 0;
-#endif
}
+#endif /* TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE */
+#if TRIO_FEATURE_QUOTE
TRIO_PRIVATE BOOLEAN_T
TrioFollowedBySeparator
TRIO_ARGS1((position),
int position)
{
-#if TRIO_EXTENSION
int step = 0;
char *groupingPointer = internalGrouping;
@@ -956,10 +1194,8 @@ TRIO_ARGS1((position),
position -= step;
}
return (position == 0);
-#else
- return FALSE;
-#endif
}
+#endif /* TRIO_FEATURE_QUOTE */
/*************************************************************************
* TrioGetPosition
@@ -968,20 +1204,20 @@ TRIO_ARGS1((position),
*/
TRIO_PRIVATE int
TrioGetPosition
-TRIO_ARGS2((format, indexPointer),
+TRIO_ARGS2((format, offsetPointer),
TRIO_CONST char *format,
- int *indexPointer)
+ int *offsetPointer)
{
-#if TRIO_UNIX98
+#if TRIO_FEATURE_POSITIONAL
char *tmpformat;
int number = 0;
- int index = *indexPointer;
+ int offset = *offsetPointer;
- number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL);
- index = (int)(tmpformat - format);
- if ((number != 0) && (QUALIFIER_POSITION == format[index++]))
+ number = (int)trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL);
+ offset = (int)(tmpformat - format);
+ if ((number != 0) && (QUALIFIER_POSITION == format[offset++]))
{
- *indexPointer = index;
+ *offsetPointer = offset;
/*
* number is decreased by 1, because n$ starts from 1, whereas
* the array it is indexing starts from 0.
@@ -992,13 +1228,13 @@ TRIO_ARGS2((format, indexPointer),
return NO_POSITION;
}
-#if TRIO_EXTENSION
/*************************************************************************
* TrioFindNamespace
*
* Find registered user-defined specifier.
* The prev argument is used for optimization only.
*/
+#if TRIO_FEATURE_USER_DEFINED
TRIO_PRIVATE trio_userdef_t *
TrioFindNamespace
TRIO_ARGS2((name, prev),
@@ -1033,6 +1269,7 @@ TRIO_ARGS2((name, prev),
* Description:
* Calculate pow(base, exponent), where number and exponent are integers.
*/
+#if TRIO_FEATURE_FLOAT
TRIO_PRIVATE trio_long_double_t
TrioPower
TRIO_ARGS2((number, exponent),
@@ -1077,28 +1314,31 @@ TRIO_ARGS2((number, exponent),
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);
+ result = trio_pow((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 trio_pow((trio_long_double_t)number,
+ (trio_long_double_t)exponent);
}
return result;
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* TrioLogarithm
*/
-TRIO_PRIVATE double
+#if TRIO_FEATURE_FLOAT
+TRIO_PRIVATE trio_long_double_t
TrioLogarithm
TRIO_ARGS2((number, base),
- double number,
+ trio_long_double_t number,
int base)
{
- double result;
+ trio_long_double_t result;
if (number <= 0.0)
{
@@ -1109,19 +1349,21 @@ TRIO_ARGS2((number, base),
{
if (base == 10)
{
- result = log10(number);
+ result = trio_log10(number);
}
else
{
- result = log10(number) / log10((double)base);
+ result = trio_log10(number) / trio_log10((double)base);
}
}
return result;
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* TrioLogarithmBase
*/
+#if TRIO_FEATURE_FLOAT
TRIO_PRIVATE double
TrioLogarithmBase
TRIO_ARGS1((base),
@@ -1136,6 +1378,557 @@ TRIO_ARGS1((base),
default : return TrioLogarithm((double)base, 2);
}
}
+#endif /* TRIO_FEATURE_FLOAT */
+
+/*************************************************************************
+ * TrioParseQualifiers
+ *
+ * Description:
+ * Parse the qualifiers of a potential conversion specifier
+ */
+TRIO_PRIVATE int
+TrioParseQualifiers
+TRIO_ARGS4((type, format, offset, parameter),
+ int type,
+ TRIO_CONST char *format,
+ int offset,
+ trio_parameter_t *parameter)
+{
+ char ch;
+ int dots = 0; /* Count number of dots in modifier part */
+ char *tmpformat;
+
+ parameter->beginOffset = offset - 1;
+ parameter->flags = FLAGS_NEW;
+ parameter->position = TrioGetPosition(format, &offset);
+
+ /* Default values */
+ parameter->width = NO_WIDTH;
+ parameter->precision = NO_PRECISION;
+ parameter->base = NO_BASE;
+ parameter->varsize = NO_SIZE;
+
+ while (TrioIsQualifier(format[offset]))
+ {
+ ch = format[offset++];
+
+ switch (ch)
+ {
+ case QUALIFIER_SPACE:
+ parameter->flags |= FLAGS_SPACE;
+ break;
+
+ case QUALIFIER_PLUS:
+ parameter->flags |= FLAGS_SHOWSIGN;
+ break;
+
+ case QUALIFIER_MINUS:
+ parameter->flags |= FLAGS_LEFTADJUST;
+ parameter->flags &= ~FLAGS_NILPADDING;
+ break;
+
+ case QUALIFIER_ALTERNATIVE:
+ parameter->flags |= FLAGS_ALTERNATIVE;
+ break;
+
+ case QUALIFIER_DOT:
+ if (dots == 0) /* Precision */
+ {
+ dots++;
+
+ /* Skip if no precision */
+ if (QUALIFIER_DOT == format[offset])
+ break;
+
+ /* After the first dot we have the precision */
+ parameter->flags |= FLAGS_PRECISION;
+ if ((QUALIFIER_STAR == format[offset])
+#if defined(QUALIFIER_PARAM)
+ || (QUALIFIER_PARAM == format[offset])
+#endif
+ )
+ {
+ offset++;
+ parameter->flags |= FLAGS_PRECISION_PARAMETER;
+ parameter->precision = TrioGetPosition(format, &offset);
+ }
+ else
+ {
+ parameter->precision = trio_to_long(&format[offset],
+ &tmpformat,
+ BASE_DECIMAL);
+ offset = (int)(tmpformat - format);
+ }
+ }
+ else if (dots == 1) /* Base */
+ {
+ dots++;
+
+ /* After the second dot we have the base */
+ parameter->flags |= FLAGS_BASE;
+ if ((QUALIFIER_STAR == format[offset])
+#if defined(QUALIFIER_PARAM)
+ || (QUALIFIER_PARAM == format[offset])
+#endif
+ )
+ {
+ offset++;
+ parameter->flags |= FLAGS_BASE_PARAMETER;
+ parameter->base = TrioGetPosition(format, &offset);
+ }
+ else
+ {
+ parameter->base = trio_to_long(&format[offset],
+ &tmpformat,
+ BASE_DECIMAL);
+ if (parameter->base > MAX_BASE)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ offset = (int)(tmpformat - format);
+ }
+ }
+ else
+ {
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ }
+ break; /* QUALIFIER_DOT */
+
+#if defined(QUALIFIER_PARAM)
+ case QUALIFIER_PARAM:
+ parameter->type = TYPE_PRINT;
+ /* FALLTHROUGH */
+#endif
+ case QUALIFIER_STAR:
+ /* This has different meanings for print and scan */
+ if (TYPE_PRINT == type)
+ {
+ /* Read with from parameter */
+ int width = TrioGetPosition(format, &offset);
+ parameter->flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
+ if (NO_POSITION != width)
+ parameter->width = width;
+ /* else keep parameter->width = NO_WIDTH which != NO_POSITION */
+ }
+#if TRIO_FEATURE_SCANF
+ else
+ {
+ /* Scan, but do not store result */
+ parameter->flags |= FLAGS_IGNORE;
+ }
+#endif
+ break; /* QUALIFIER_STAR */
+
+ case '0':
+ if (! (parameter->flags & FLAGS_LEFTADJUST))
+ parameter->flags |= FLAGS_NILPADDING;
+ /* FALLTHROUGH */
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ parameter->flags |= FLAGS_WIDTH;
+ /*
+ * &format[offset - 1] is used to "rewind" the read
+ * character from format
+ */
+ parameter->width = trio_to_long(&format[offset - 1],
+ &tmpformat,
+ BASE_DECIMAL);
+ offset = (int)(tmpformat - format);
+ break;
+
+ case QUALIFIER_SHORT:
+ if (parameter->flags & FLAGS_SHORTSHORT)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ else if (parameter->flags & FLAGS_SHORT)
+ parameter->flags |= FLAGS_SHORTSHORT;
+ else
+ parameter->flags |= FLAGS_SHORT;
+ break;
+
+ case QUALIFIER_LONG:
+ if (parameter->flags & FLAGS_QUAD)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ else if (parameter->flags & FLAGS_LONG)
+ parameter->flags |= FLAGS_QUAD;
+ else
+ parameter->flags |= FLAGS_LONG;
+ break;
+
+#if TRIO_FEATURE_LONGDOUBLE
+ case QUALIFIER_LONG_UPPER:
+ parameter->flags |= FLAGS_LONGDOUBLE;
+ break;
+#endif
+
+#if TRIO_FEATURE_SIZE_T
+ case QUALIFIER_SIZE_T:
+ parameter->flags |= FLAGS_SIZE_T;
+ /* Modify flags for later truncation of number */
+ if (sizeof(size_t) == sizeof(trio_ulonglong_t))
+ parameter->flags |= FLAGS_QUAD;
+ else if (sizeof(size_t) == sizeof(long))
+ parameter->flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if TRIO_FEATURE_PTRDIFF_T
+ case QUALIFIER_PTRDIFF_T:
+ parameter->flags |= FLAGS_PTRDIFF_T;
+ if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
+ parameter->flags |= FLAGS_QUAD;
+ else if (sizeof(ptrdiff_t) == sizeof(long))
+ parameter->flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if TRIO_FEATURE_INTMAX_T
+ case QUALIFIER_INTMAX_T:
+ parameter->flags |= FLAGS_INTMAX_T;
+ if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
+ parameter->flags |= FLAGS_QUAD;
+ else if (sizeof(trio_intmax_t) == sizeof(long))
+ parameter->flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if TRIO_FEATURE_QUAD
+ case QUALIFIER_QUAD:
+ parameter->flags |= FLAGS_QUAD;
+ break;
+#endif
+
+#if TRIO_FEATURE_FIXED_SIZE
+ case QUALIFIER_FIXED_SIZE:
+ if (parameter->flags & FLAGS_FIXED_SIZE)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+
+ if (parameter->flags & (FLAGS_ALL_SIZES |
+ FLAGS_LONGDOUBLE |
+ FLAGS_WIDECHAR |
+ FLAGS_VARSIZE_PARAMETER))
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+
+ if ((format[offset] == '6') &&
+ (format[offset + 1] == '4'))
+ {
+ parameter->varsize = sizeof(trio_int64_t);
+ offset += 2;
+ }
+ else if ((format[offset] == '3') &&
+ (format[offset + 1] == '2'))
+ {
+ parameter->varsize = sizeof(trio_int32_t);
+ offset += 2;
+ }
+ else if ((format[offset] == '1') &&
+ (format[offset + 1] == '6'))
+ {
+ parameter->varsize = sizeof(trio_int16_t);
+ offset += 2;
+ }
+ else if (format[offset] == '8')
+ {
+ parameter->varsize = sizeof(trio_int8_t);
+ offset++;
+ }
+ else
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+
+ parameter->flags |= FLAGS_FIXED_SIZE;
+ break;
+#endif /* TRIO_FEATURE_FIXED_SIZE */
+
+#if defined(QUALIFIER_WIDECHAR)
+ case QUALIFIER_WIDECHAR:
+ parameter->flags |= FLAGS_WIDECHAR;
+ break;
+#endif
+
+#if TRIO_FEATURE_SIZE_T_UPPER
+ case QUALIFIER_SIZE_T_UPPER:
+ break;
+#endif
+
+#if TRIO_FEATURE_QUOTE
+ case QUALIFIER_QUOTE:
+ parameter->flags |= FLAGS_QUOTE;
+ break;
+#endif
+
+#if TRIO_FEATURE_STICKY
+ case QUALIFIER_STICKY:
+ parameter->flags |= FLAGS_STICKY;
+ break;
+#endif
+
+#if TRIO_FEATURE_VARSIZE
+ case QUALIFIER_VARSIZE:
+ parameter->flags |= FLAGS_VARSIZE_PARAMETER;
+ break;
+#endif
+
+#if TRIO_FEATURE_ROUNDING
+ case QUALIFIER_ROUNDING_UPPER:
+ parameter->flags |= FLAGS_ROUNDING;
+ break;
+#endif
+
+ default:
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ }
+ } /* while qualifier */
+
+ parameter->endOffset = offset;
+
+ return 0;
+}
+
+/*************************************************************************
+ * TrioParseSpecifier
+ *
+ * Description:
+ * Parse the specifier part of a potential conversion specifier
+ */
+TRIO_PRIVATE int
+TrioParseSpecifier
+TRIO_ARGS4((type, format, offset, parameter),
+ int type,
+ TRIO_CONST char *format,
+ int offset,
+ trio_parameter_t *parameter)
+{
+ parameter->baseSpecifier = NO_BASE;
+
+ switch (format[offset++])
+ {
+#if defined(SPECIFIER_CHAR_UPPER)
+ case SPECIFIER_CHAR_UPPER:
+ parameter->flags |= FLAGS_WIDECHAR;
+ /* FALLTHROUGH */
+#endif
+ case SPECIFIER_CHAR:
+ if (parameter->flags & FLAGS_LONG)
+ parameter->flags |= FLAGS_WIDECHAR;
+ else if (parameter->flags & FLAGS_SHORT)
+ parameter->flags &= ~FLAGS_WIDECHAR;
+ parameter->type = FORMAT_CHAR;
+ break;
+
+#if defined(SPECIFIER_STRING_UPPER)
+ case SPECIFIER_STRING_UPPER:
+ parameter->flags |= FLAGS_WIDECHAR;
+ /* FALLTHROUGH */
+#endif
+ case SPECIFIER_STRING:
+ if (parameter->flags & FLAGS_LONG)
+ parameter->flags |= FLAGS_WIDECHAR;
+ else if (parameter->flags & FLAGS_SHORT)
+ parameter->flags &= ~FLAGS_WIDECHAR;
+ parameter->type = FORMAT_STRING;
+ break;
+
+#if defined(SPECIFIER_GROUP)
+ case SPECIFIER_GROUP:
+ if (TYPE_SCAN == type)
+ {
+ int depth = 1;
+ parameter->type = FORMAT_GROUP;
+ if (format[offset] == QUALIFIER_CIRCUMFLEX)
+ offset++;
+ if (format[offset] == SPECIFIER_UNGROUP)
+ offset++;
+ if (format[offset] == QUALIFIER_MINUS)
+ offset++;
+ /* Skip nested brackets */
+ while (format[offset] != NIL)
+ {
+ if (format[offset] == SPECIFIER_GROUP)
+ {
+ depth++;
+ }
+ else if (format[offset] == SPECIFIER_UNGROUP)
+ {
+ if (--depth <= 0)
+ {
+ offset++;
+ break;
+ }
+ }
+ offset++;
+ }
+ }
+ break;
+#endif /* defined(SPECIFIER_GROUP) */
+
+ case SPECIFIER_INTEGER:
+ parameter->type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_UNSIGNED:
+ parameter->flags |= FLAGS_UNSIGNED;
+ parameter->type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_DECIMAL:
+ parameter->baseSpecifier = BASE_DECIMAL;
+ parameter->type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_OCTAL:
+ parameter->flags |= FLAGS_UNSIGNED;
+ parameter->baseSpecifier = BASE_OCTAL;
+ parameter->type = FORMAT_INT;
+ break;
+
+#if TRIO_FEATURE_BINARY
+ case SPECIFIER_BINARY_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_BINARY:
+ parameter->flags |= FLAGS_NILPADDING;
+ parameter->baseSpecifier = BASE_BINARY;
+ parameter->type = FORMAT_INT;
+ break;
+#endif
+
+ case SPECIFIER_HEX_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_HEX:
+ parameter->flags |= FLAGS_UNSIGNED;
+ parameter->baseSpecifier = BASE_HEX;
+ parameter->type = FORMAT_INT;
+ break;
+
+#if defined(SPECIFIER_FLOAT_E)
+# if defined(SPECIFIER_FLOAT_E_UPPER)
+ case SPECIFIER_FLOAT_E_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+# endif
+ case SPECIFIER_FLOAT_E:
+ parameter->flags |= FLAGS_FLOAT_E;
+ parameter->type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if defined(SPECIFIER_FLOAT_G)
+# if defined(SPECIFIER_FLOAT_G_UPPER)
+ case SPECIFIER_FLOAT_G_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+# endif
+ case SPECIFIER_FLOAT_G:
+ parameter->flags |= FLAGS_FLOAT_G;
+ parameter->type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if defined(SPECIFIER_FLOAT_F)
+# if defined(SPECIFIER_FLOAT_F_UPPER)
+ case SPECIFIER_FLOAT_F_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+# endif
+ case SPECIFIER_FLOAT_F:
+ parameter->type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if defined(TRIO_COMPILER_VISUALC)
+# pragma warning( push )
+# pragma warning( disable : 4127 ) /* Conditional expression is constant */
+#endif
+ case SPECIFIER_POINTER:
+ if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
+ parameter->flags |= FLAGS_QUAD;
+ else if (sizeof(trio_pointer_t) == sizeof(long))
+ parameter->flags |= FLAGS_LONG;
+ parameter->type = FORMAT_POINTER;
+ break;
+#if defined(TRIO_COMPILER_VISUALC)
+# pragma warning( pop )
+#endif
+
+ case SPECIFIER_COUNT:
+ parameter->type = FORMAT_COUNT;
+ break;
+
+#if TRIO_FEATURE_HEXFLOAT
+ case SPECIFIER_HEXFLOAT_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_HEXFLOAT:
+ parameter->baseSpecifier = BASE_HEX;
+ parameter->type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if TRIO_FEATURE_ERRNO
+ case SPECIFIER_ERRNO:
+ parameter->type = FORMAT_ERRNO;
+ break;
+#endif
+
+#if TRIO_FEATURE_USER_DEFINED
+ case SPECIFIER_USER_DEFINED_BEGIN:
+ {
+ unsigned int max;
+ int without_namespace = TRUE;
+ char* tmpformat = (char *)&format[offset];
+ int ch;
+
+ parameter->type = FORMAT_USER_DEFINED;
+ parameter->user_defined.namespace[0] = NIL;
+
+ while ((ch = format[offset]) != NIL)
+ {
+ offset++;
+ if ((ch == SPECIFIER_USER_DEFINED_END) || (ch == SPECIFIER_USER_DEFINED_EXTRA))
+ {
+ if (without_namespace)
+ /* No namespace, handler will be passed as an argument */
+ parameter->flags |= FLAGS_USER_DEFINED_PARAMETER;
+
+ /* Copy the user data */
+ max = (unsigned int)(&format[offset] - tmpformat);
+ if (max > MAX_USER_DATA)
+ max = MAX_USER_DATA;
+ trio_copy_max(parameter->user_data, max, tmpformat);
+
+ /* Skip extra data (which is only there to keep the compiler happy) */
+ while ((ch != NIL) && (ch != SPECIFIER_USER_DEFINED_END))
+ ch = format[offset++];
+
+ break; /* while */
+ }
+
+ if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
+ {
+ without_namespace = FALSE;
+ /* Copy the namespace for later looking-up */
+ max = (int)(&format[offset] - tmpformat);
+ if (max > MAX_USER_NAME)
+ max = MAX_USER_NAME;
+ trio_copy_max(parameter->user_defined.namespace, max, tmpformat);
+ tmpformat = (char *)&format[offset];
+ }
+ }
+
+ if (ch != SPECIFIER_USER_DEFINED_END)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ }
+ break;
+#endif /* TRIO_FEATURE_USER_DEFINED */
+
+ default:
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ }
+
+ parameter->endOffset = offset;
+
+ return 0;
+}
/*************************************************************************
* TrioParse
@@ -1149,25 +1942,20 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
int type,
TRIO_CONST char *format,
trio_parameter_t *parameters,
- va_list *arglist,
+ va_list arglist,
trio_pointer_t *argarray)
{
/* 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 */
- trio_flags_t flags;
- int width;
- int precision;
- int varsize;
- int base;
- int index; /* Index into formatting string */
- int dots; /* Count number of dots in modifier part */
+ int offset; /* Offset into formatting string */
BOOLEAN_T positional; /* Does the specifier have a positional? */
+#if TRIO_FEATURE_STICKY
BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */
+#endif
/*
* indices specifies the order in which the parameters must be
* read from the va_args (this is necessary to handle positionals)
@@ -1175,18 +1963,15 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
int indices[MAX_PARAMETERS];
int pos = 0;
/* Various variables */
- char ch;
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
int charlen;
#endif
int save_errno;
int i = -1;
int num;
- char *tmpformat;
+ trio_parameter_t workParameter;
+ int status;
- /* One and only one of arglist and argarray must be used */
- assert((arglist != NULL) ^ (argarray != NULL));
-
/*
* The 'parameters' array is not initialized, but we need to
* know which entries we have used.
@@ -1194,690 +1979,223 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
memset(usedEntries, 0, sizeof(usedEntries));
save_errno = errno;
- index = 0;
+ offset = 0;
parameterPosition = 0;
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
(void)mblen(NULL, 0);
#endif
- while (format[index])
+ while (format[offset])
{
+ TrioInitializeParameter(&workParameter);
+
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- if (! isascii(format[index]))
+ if (! isascii(format[offset]))
{
/*
* Multibyte characters cannot be legal specifiers or
* modifiers, so we skip over them.
*/
- charlen = mblen(&format[index], MB_LEN_MAX);
- index += (charlen > 0) ? charlen : 1;
+ charlen = mblen(&format[offset], MB_LEN_MAX);
+ offset += (charlen > 0) ? charlen : 1;
continue; /* while */
}
#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
- if (CHAR_IDENTIFIER == format[index++])
+
+ switch(format[offset++]) {
+
+ case CHAR_IDENTIFIER:
{
- if (CHAR_IDENTIFIER == format[index])
+ if (CHAR_IDENTIFIER == format[offset])
{
- index++;
+ /* skip double "%" */
+ offset++;
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;
+ status = TrioParseQualifiers(type, format, offset, &workParameter);
+ if (status < 0)
+ return status; /* Return qualifier syntax error */
- /* Default values */
- width = NO_WIDTH;
- precision = NO_PRECISION;
- base = NO_BASE;
- varsize = NO_SIZE;
-
- while (TrioIsQualifier(format[index]))
- {
- 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;
-
- /* After the first dot we have the precision */
- flags |= FLAGS_PRECISION;
- if ((QUALIFIER_STAR == format[index])
-#if defined(QUALIFIER_PARAM)
- || (QUALIFIER_PARAM == format[index])
-#endif
- )
- {
- 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
- {
- precision = trio_to_long(&format[index],
- &tmpformat,
- BASE_DECIMAL);
- index = (int)(tmpformat - format);
- }
- }
- else if (dots == 1) /* Base */
- {
- dots++;
-
- /* After the second dot we have the base */
- flags |= FLAGS_BASE;
- if ((QUALIFIER_STAR == format[index])
-#if defined(QUALIFIER_PARAM)
- || (QUALIFIER_PARAM == format[index])
-#endif
- )
- {
- 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
- {
- base = trio_to_long(&format[index],
- &tmpformat,
- BASE_DECIMAL);
- 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 */
-
-#if defined(QUALIFIER_PARAM)
- case QUALIFIER_PARAM:
- type = TYPE_PRINT;
- /* FALLTHROUGH */
-#endif
- 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
- */
- width = trio_to_long(&format[index - 1],
- &tmpformat,
- BASE_DECIMAL);
- 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 */
- if (sizeof(size_t) == sizeof(trio_ulonglong_t))
- 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;
- if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
- 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;
- if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
- flags |= FLAGS_QUAD;
- else if (sizeof(trio_intmax_t) == sizeof(long))
- flags |= FLAGS_LONG;
- break;
-#endif
-
-#if defined(QUALIFIER_QUAD)
- case QUALIFIER_QUAD:
- flags |= FLAGS_QUAD;
- break;
-#endif
-
-#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);
-
- flags |= FLAGS_FIXED_SIZE;
- break;
-#endif
-
-#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
+ status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter);
+ if (status < 0)
+ return status; /* Return specifier syntax error */
+ }
+ break;
-#if defined(QUALIFIER_QUOTE)
- case QUALIFIER_QUOTE:
- flags |= FLAGS_QUOTE;
- break;
-#endif
+#if TRIO_EXTENSION
+ case CHAR_ALT_IDENTIFIER:
+ {
+ status = TrioParseQualifiers(type, format, offset, &workParameter);
+ if (status < 0)
+ continue; /* False alert, not a user defined specifier */
-#if defined(QUALIFIER_STICKY)
- case QUALIFIER_STICKY:
- flags |= FLAGS_STICKY;
- gotSticky = TRUE;
- break;
-#endif
-
-#if defined(QUALIFIER_VARSIZE)
- case QUALIFIER_VARSIZE:
- flags |= FLAGS_VARSIZE_PARAMETER;
- parameterPosition++;
- if (positional)
- varsize = parameterPosition;
- else
- {
- varsize = currentParam;
- currentParam = varsize + 1;
- }
- if (currentParam > maxParam)
- maxParam = currentParam;
- break;
+ status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter);
+ if ((status < 0) || (FORMAT_USER_DEFINED != workParameter.type))
+ continue; /* False alert, not a user defined specifier */
+ }
+ break;
#endif
-#if defined(QUALIFIER_ROUNDING_UPPER)
- case QUALIFIER_ROUNDING_UPPER:
- flags |= FLAGS_ROUNDING;
- break;
-#endif
+ default:
+ continue; /* while */
+ }
- default:
- /* Bail out completely to make the error more obvious */
- return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
- }
- } /* while qualifier */
+ /* now handle the parsed conversion specification */
+ positional = (NO_POSITION != workParameter.position);
- /*
- * Parameters only need the type and value. The value is
- * read later.
- */
- if (flags & FLAGS_WIDTH_PARAMETER)
+ /*
+ * Parameters only need the type and value. The value is
+ * read later.
+ */
+ if (workParameter.flags & FLAGS_WIDTH_PARAMETER)
+ {
+ if (workParameter.width == NO_WIDTH)
{
- usedEntries[width] += 1;
- parameters[pos].type = FORMAT_PARAMETER;
- parameters[pos].flags = 0;
- indices[width] = pos;
- width = pos++;
+ workParameter.width = parameterPosition++;
}
- if (flags & FLAGS_PRECISION_PARAMETER)
+ else
{
- usedEntries[precision] += 1;
- parameters[pos].type = FORMAT_PARAMETER;
- parameters[pos].flags = 0;
- indices[precision] = pos;
- precision = pos++;
+ if (! positional)
+ workParameter.position = workParameter.width + 1;
}
- if (flags & FLAGS_BASE_PARAMETER)
+
+ usedEntries[workParameter.width] += 1;
+ if (workParameter.width > maxParam)
+ maxParam = workParameter.width;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[workParameter.width] = pos;
+ workParameter.width = pos++;
+ }
+ if (workParameter.flags & FLAGS_PRECISION_PARAMETER)
+ {
+ if (workParameter.precision == NO_PRECISION)
{
- usedEntries[base] += 1;
- parameters[pos].type = FORMAT_PARAMETER;
- parameters[pos].flags = 0;
- indices[base] = pos;
- base = pos++;
+ workParameter.precision = parameterPosition++;
}
- if (flags & FLAGS_VARSIZE_PARAMETER)
+ else
{
- usedEntries[varsize] += 1;
- parameters[pos].type = FORMAT_PARAMETER;
- parameters[pos].flags = 0;
- indices[varsize] = pos;
- varsize = pos++;
+ if (! positional)
+ workParameter.position = workParameter.precision + 1;
}
-
- indices[currentParam] = pos;
-
- switch (format[index++])
+
+ usedEntries[workParameter.precision] += 1;
+ if (workParameter.precision > maxParam)
+ maxParam = workParameter.precision;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[workParameter.precision] = pos;
+ workParameter.precision = pos++;
+ }
+ if (workParameter.flags & FLAGS_BASE_PARAMETER)
+ {
+ if (workParameter.base == NO_BASE)
{
-#if defined(SPECIFIER_CHAR_UPPER)
- case SPECIFIER_CHAR_UPPER:
- flags |= FLAGS_WIDECHAR;
- /* FALLTHROUGH */
-#endif
- case SPECIFIER_CHAR:
- if (flags & FLAGS_LONG)
- flags |= FLAGS_WIDECHAR;
- else if (flags & FLAGS_SHORT)
- flags &= ~FLAGS_WIDECHAR;
- parameters[pos].type = FORMAT_CHAR;
- break;
+ workParameter.base = parameterPosition++;
+ }
+ else
+ {
+ if (! positional)
+ workParameter.position = workParameter.base + 1;
+ }
-#if defined(SPECIFIER_STRING_UPPER)
- case SPECIFIER_STRING_UPPER:
- flags |= FLAGS_WIDECHAR;
- /* FALLTHROUGH */
+ usedEntries[workParameter.base] += 1;
+ if (workParameter.base > maxParam)
+ maxParam = workParameter.base;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[workParameter.base] = pos;
+ workParameter.base = pos++;
+ }
+#if TRIO_FEATURE_VARSIZE
+ if (workParameter.flags & FLAGS_VARSIZE_PARAMETER)
+ {
+ workParameter.varsize = parameterPosition++;
+
+ usedEntries[workParameter.varsize] += 1;
+ if (workParameter.varsize > maxParam)
+ maxParam = workParameter.varsize;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[workParameter.varsize] = pos;
+ workParameter.varsize = pos++;
+ }
#endif
- case SPECIFIER_STRING:
- if (flags & FLAGS_LONG)
- flags |= FLAGS_WIDECHAR;
- else if (flags & FLAGS_SHORT)
- flags &= ~FLAGS_WIDECHAR;
- parameters[pos].type = FORMAT_STRING;
- break;
-
- case SPECIFIER_GROUP:
- if (TYPE_SCAN == type)
- {
- int depth = 1;
- parameters[pos].type = FORMAT_GROUP;
- 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)
- {
- if (format[index] == SPECIFIER_GROUP)
- {
- depth++;
- }
- else if (format[index] == SPECIFIER_UNGROUP)
- {
- if (--depth <= 0)
- {
- index++;
- break;
- }
- }
- index++;
- }
- }
- break;
-
- case SPECIFIER_INTEGER:
- parameters[pos].type = FORMAT_INT;
- break;
-
- 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:
- flags |= FLAGS_UNSIGNED;
- 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;
+#if TRIO_FEATURE_USER_DEFINED
+ if (workParameter.flags & FLAGS_USER_DEFINED_PARAMETER)
+ {
+ workParameter.user_defined.handler = parameterPosition++;
+
+ usedEntries[workParameter.user_defined.handler] += 1;
+ if (workParameter.user_defined.handler > maxParam)
+ maxParam = workParameter.user_defined.handler;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = FLAGS_USER_DEFINED;
+ indices[workParameter.user_defined.handler] = pos;
+ workParameter.user_defined.handler = pos++;
+ }
#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;
+ if (NO_POSITION == workParameter.position)
+ {
+ workParameter.position = parameterPosition++;
+ }
- case SPECIFIER_FLOAT_F_UPPER:
- flags |= FLAGS_UPPER;
- /* FALLTHROUGH */
- case SPECIFIER_FLOAT_F:
- parameters[pos].type = FORMAT_DOUBLE;
- break;
+ if (workParameter.position > maxParam)
+ maxParam = workParameter.position;
- case SPECIFIER_POINTER:
- if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
- flags |= FLAGS_QUAD;
- else if (sizeof(trio_pointer_t) == sizeof(long))
- flags |= FLAGS_LONG;
- parameters[pos].type = FORMAT_POINTER;
- break;
+ if (workParameter.position >= MAX_PARAMETERS)
+ {
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_ETOOMANY, offset);
+ }
- case SPECIFIER_COUNT:
- parameters[pos].type = FORMAT_COUNT;
- break;
+ indices[workParameter.position] = pos;
-#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
+ /* Count the number of times this entry has been used */
+ usedEntries[workParameter.position] += 1;
-#if defined(FORMAT_ERRNO)
- case SPECIFIER_ERRNO:
- parameters[pos].type = FORMAT_ERRNO;
- break;
-#endif
-
-#if defined(SPECIFIER_USER_DEFINED_BEGIN)
- case SPECIFIER_USER_DEFINED_BEGIN:
- {
- unsigned int max;
- int without_namespace = TRUE;
-
- parameters[pos].type = FORMAT_USER_DEFINED;
- parameters[pos].user_name[0] = NIL;
- tmpformat = (char *)&format[index];
-
- 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;
- trio_copy_max(parameters[pos].user_data,
- max,
- tmpformat);
- 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;
- trio_copy_max(parameters[pos].user_name,
- max,
- tmpformat);
- tmpformat = (char *)&format[index];
- }
- }
- if (ch != SPECIFIER_USER_DEFINED_END)
- return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
- }
- break;
-#endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */
-
- 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;
-
- /* Find last sticky parameters */
- if (gotSticky && !(flags & FLAGS_STICKY))
+ /* Find last sticky parameters */
+#if TRIO_FEATURE_STICKY
+ if (workParameter.flags & FLAGS_STICKY)
+ {
+ gotSticky = TRUE;
+ }
+ else if (gotSticky)
+ {
+ for (i = pos - 1; i >= 0; i--)
{
- for (i = pos - 1; i >= 0; i--)
+ if (parameters[i].type == FORMAT_PARAMETER)
+ continue;
+ if ((parameters[i].flags & FLAGS_STICKY) &&
+ (parameters[i].type == workParameter.type))
{
- if (parameters[i].type == FORMAT_PARAMETER)
- continue;
- if ((parameters[i].flags & FLAGS_STICKY) &&
- (parameters[i].type == parameters[pos].type))
- {
- /* Do not overwrite current qualifiers */
- flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
- 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;
- }
+ /* Do not overwrite current qualifiers */
+ workParameter.flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
+ if (workParameter.width == NO_WIDTH)
+ workParameter.width = parameters[i].width;
+ if (workParameter.precision == NO_PRECISION)
+ workParameter.precision = parameters[i].precision;
+ if (workParameter.base == NO_BASE)
+ workParameter.base = parameters[i].base;
+ break;
}
}
-
- 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++;
-
- if (! positional)
- parameterPosition++;
-
- } /* if identifier */
-
+ }
+#endif
+
+ if (workParameter.base == NO_BASE)
+ workParameter.base = BASE_DECIMAL;
+
+ offset = workParameter.endOffset;
+
+ TrioCopyParameter(&parameters[pos++], &workParameter);
} /* while format characters left */
+ parameters[pos].type = FORMAT_SENTINEL; /* end parameter array with sentinel */
+ parameters[pos].beginOffset = offset;
+
for (num = 0; num <= maxParam; num++)
{
if (usedEntries[num] != 1)
@@ -1923,40 +2241,41 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
{
case FORMAT_GROUP:
case FORMAT_STRING:
-#if TRIO_WIDECHAR
- if (flags & FLAGS_WIDECHAR)
+#if TRIO_FEATURE_WIDECHAR
+ if (parameters[i].flags & FLAGS_WIDECHAR)
{
parameters[i].data.wstring = (argarray == NULL)
- ? va_arg(*arglist, trio_wchar_t *)
+ ? va_arg(arglist, trio_wchar_t *)
: (trio_wchar_t *)(argarray[num]);
}
else
#endif
{
parameters[i].data.string = (argarray == NULL)
- ? va_arg(*arglist, char *)
+ ? va_arg(arglist, char *)
: (char *)(argarray[num]);
}
break;
-#if defined(FORMAT_USER_DEFINED)
+#if TRIO_FEATURE_USER_DEFINED
case FORMAT_USER_DEFINED:
#endif
case FORMAT_POINTER:
case FORMAT_COUNT:
case FORMAT_UNKNOWN:
parameters[i].data.pointer = (argarray == NULL)
- ? va_arg(*arglist, trio_pointer_t )
+ ? va_arg(arglist, trio_pointer_t )
: argarray[num];
break;
case FORMAT_CHAR:
case FORMAT_INT:
+#if TRIO_FEATURE_SCANF
if (TYPE_SCAN == type)
{
if (argarray == NULL)
parameters[i].data.pointer =
- (trio_pointer_t)va_arg(*arglist, trio_pointer_t);
+ (trio_pointer_t)va_arg(arglist, trio_pointer_t);
else
{
if (parameters[i].type == FORMAT_CHAR)
@@ -1971,11 +2290,13 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
}
}
else
+#endif /* TRIO_FEATURE_SCANF */
{
-#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
+#if TRIO_FEATURE_VARSIZE || TRIO_FEATURE_FIXED_SIZE
if (parameters[i].flags
& (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE))
{
+ int varsize;
if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
{
/*
@@ -2000,7 +2321,7 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
;
else if (varsize <= (int)sizeof(long))
parameters[i].flags |= FLAGS_LONG;
-#if defined(QUALIFIER_INTMAX_T)
+#if TRIO_FEATURE_INTMAX_T
else if (varsize <= (int)sizeof(trio_longlong_t))
parameters[i].flags |= FLAGS_QUAD;
else
@@ -2010,40 +2331,40 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
parameters[i].flags |= FLAGS_QUAD;
#endif
}
-#endif /* defined(QUALIFIER_VARSIZE) */
-#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
+#endif /* TRIO_FEATURE_VARSIZE */
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
if (parameters[i].flags & FLAGS_SIZE_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, size_t)
+ ? (trio_uintmax_t)va_arg(arglist, size_t)
: (trio_uintmax_t)(*((size_t *)argarray[num]));
else
#endif
-#if defined(QUALIFIER_PTRDIFF_T)
+#if TRIO_FEATURE_PTRDIFF_T
if (parameters[i].flags & FLAGS_PTRDIFF_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, ptrdiff_t)
+ ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t)
: (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
else
#endif
-#if defined(QUALIFIER_INTMAX_T)
+#if TRIO_FEATURE_INTMAX_T
if (parameters[i].flags & FLAGS_INTMAX_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, trio_intmax_t)
+ ? (trio_uintmax_t)va_arg(arglist, trio_intmax_t)
: (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
else
#endif
if (parameters[i].flags & FLAGS_QUAD)
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, trio_ulonglong_t)
+ ? (trio_uintmax_t)va_arg(arglist, trio_ulonglong_t)
: (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
else if (parameters[i].flags & FLAGS_LONG)
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, long)
+ ? (trio_uintmax_t)va_arg(arglist, long)
: (trio_uintmax_t)(*((long *)argarray[num]));
else
{
if (argarray == NULL)
- parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(*arglist, int);
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int);
else
{
if (parameters[i].type == FORMAT_CHAR)
@@ -2064,44 +2385,47 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
*/
if (parameters[i].flags & FLAGS_USER_DEFINED)
parameters[i].data.pointer = (argarray == NULL)
- ? va_arg(*arglist, trio_pointer_t )
+ ? va_arg(arglist, trio_pointer_t )
: argarray[num];
else
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, int)
+ ? (trio_uintmax_t)va_arg(arglist, int)
: (trio_uintmax_t)(*((int *)argarray[num]));
break;
+#if TRIO_FEATURE_FLOAT
case FORMAT_DOUBLE:
+# if TRIO_FEATURE_SCANF
if (TYPE_SCAN == type)
{
if (parameters[i].flags & FLAGS_LONGDOUBLE)
parameters[i].data.longdoublePointer = (argarray == NULL)
- ? va_arg(*arglist, trio_long_double_t *)
+ ? va_arg(arglist, trio_long_double_t *)
: (trio_long_double_t *)argarray[num];
else
{
if (parameters[i].flags & FLAGS_LONG)
parameters[i].data.doublePointer = (argarray == NULL)
- ? va_arg(*arglist, double *)
+ ? va_arg(arglist, double *)
: (double *)argarray[num];
else
parameters[i].data.doublePointer = (argarray == NULL)
- ? (double *)va_arg(*arglist, float *)
+ ? (double *)va_arg(arglist, float *)
: (double *)((float *)argarray[num]);
}
}
else
+# endif /* TRIO_FEATURE_SCANF */
{
if (parameters[i].flags & FLAGS_LONGDOUBLE)
parameters[i].data.longdoubleNumber = (argarray == NULL)
- ? va_arg(*arglist, trio_long_double_t)
+ ? va_arg(arglist, trio_long_double_t)
: (trio_long_double_t)(*((trio_long_double_t *)argarray[num]));
else
{
if (argarray == NULL)
parameters[i].data.longdoubleNumber =
- (trio_long_double_t)va_arg(*arglist, double);
+ (trio_long_double_t)va_arg(arglist, double);
else
{
if (parameters[i].flags & FLAGS_SHORT)
@@ -2114,8 +2438,9 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
}
}
break;
+#endif /* TRIO_FEATURE_FLOAT */
-#if defined(FORMAT_ERRNO)
+#if TRIO_FEATURE_ERRNO
case FORMAT_ERRNO:
parameters[i].data.errorNumber = save_errno;
break;
@@ -2163,9 +2488,12 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
char *pointer;
TRIO_CONST char *digits;
int i;
+#if TRIO_FEATURE_QUOTE
int length;
char *p;
+#endif
int count;
+ int digitOffset;
assert(VALID(self));
assert(VALID(self->OutStream));
@@ -2205,11 +2533,13 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
*pointer-- = NIL;
for (i = 1; i < (int)sizeof(buffer); i++)
{
- *pointer-- = digits[number % base];
+ digitOffset = number % base;
+ *pointer-- = digits[digitOffset];
number /= base;
if (number == 0)
break;
+#if TRIO_FEATURE_QUOTE
if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
{
/*
@@ -2225,6 +2555,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
*pointer-- = *p--;
}
}
+#endif
}
if (! ignoreNumber)
@@ -2418,13 +2749,22 @@ TRIO_ARGS5((self, string, flags, width, precision),
{
string = internalNullString;
length = sizeof(internalNullString) - 1;
+#if TRIO_FEATURE_QUOTE
/* Disable quoting for the null pointer */
flags &= (~FLAGS_QUOTE);
+#endif
width = 0;
}
else
{
- length = trio_length(string);
+ if (precision == 0)
+ {
+ length = trio_length(string);
+ }
+ else
+ {
+ length = trio_length_max(string, precision);
+ }
}
if ((NO_PRECISION != precision) &&
(precision < length))
@@ -2433,8 +2773,10 @@ TRIO_ARGS5((self, string, flags, width, precision),
}
width -= length;
+#if TRIO_FEATURE_QUOTE
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
+#endif
if (! (flags & FLAGS_LEFTADJUST))
{
@@ -2454,8 +2796,10 @@ TRIO_ARGS5((self, string, flags, width, precision),
while (width-- > 0)
self->OutStream(self, CHAR_ADJUST);
}
+#if TRIO_FEATURE_QUOTE
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
+#endif
}
/*************************************************************************
@@ -2464,7 +2808,7 @@ TRIO_ARGS5((self, string, flags, width, precision),
* Description:
* Output a wide string as a multi-byte sequence
*/
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
TRIO_PRIVATE int
TrioWriteWideStringCharacter
TRIO_ARGS4((self, wch, flags, width),
@@ -2496,7 +2840,7 @@ TRIO_ARGS4((self, wch, flags, width),
}
return size;
}
-#endif /* TRIO_WIDECHAR */
+#endif /* TRIO_FEATURE_WIDECHAR */
/*************************************************************************
* TrioWriteWideString
@@ -2504,7 +2848,7 @@ TRIO_ARGS4((self, wch, flags, width),
* Description:
* Output a wide character string as a multi-byte string
*/
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
TRIO_PRIVATE void
TrioWriteWideString
TRIO_ARGS5((self, wstring, flags, width, precision),
@@ -2521,6 +2865,7 @@ TRIO_ARGS5((self, wstring, flags, width, precision),
assert(VALID(self->OutStream));
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ /* Required by TrioWriteWideStringCharacter */
(void)mblen(NULL, 0);
#endif
@@ -2540,8 +2885,10 @@ TRIO_ARGS5((self, wstring, flags, width, precision),
width -= length;
}
+#if TRIO_FEATURE_QUOTE
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
+#endif
if (! (flags & FLAGS_LEFTADJUST))
{
@@ -2562,10 +2909,12 @@ TRIO_ARGS5((self, wstring, flags, width, precision),
while (width-- > 0)
self->OutStream(self, CHAR_ADJUST);
}
+#if TRIO_FEATURE_QUOTE
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
+#endif
}
-#endif /* TRIO_WIDECHAR */
+#endif /* TRIO_FEATURE_WIDECHAR */
/*************************************************************************
* TrioWriteDouble
@@ -2582,6 +2931,7 @@ TRIO_ARGS5((self, wstring, flags, width, precision),
/* FIXME: handle all instances of constant long-double number (L)
* and *l() math functions.
*/
+#if TRIO_FEATURE_FLOAT
TRIO_PRIVATE void
TrioWriteDouble
TRIO_ARGS6((self, number, flags, width, precision, base),
@@ -2598,6 +2948,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
int integerDigits;
int fractionDigits;
int exponentDigits;
+ int workDigits;
int baseDigits;
int integerThreshold;
int fractionThreshold;
@@ -2606,24 +2957,29 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
unsigned int uExponent = 0;
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;
+ trio_long_double_t workFractionNumber;
+ trio_long_double_t workFractionAdjust;
+ int fractionDigitsInspect;
BOOLEAN_T isNegative;
BOOLEAN_T isExponentNegative = FALSE;
BOOLEAN_T requireTwoDigitExponent;
BOOLEAN_T isHex;
TRIO_CONST char *digits;
+# if TRIO_FEATURE_QUOTE
char *groupingPointer;
+# endif
int i;
- int index;
+ int offset;
BOOLEAN_T hasOnlyZeroes;
- int zeroes = 0;
+ int leadingFractionZeroes = -1;
register int trailingZeroes;
BOOLEAN_T keepTrailingZeroes;
BOOLEAN_T keepDecimalPoint;
trio_long_double_t epsilon;
+ BOOLEAN_T adjustNumber = FALSE;
assert(VALID(self));
assert(VALID(self->OutStream));
@@ -2672,21 +3028,21 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
{
baseDigits = (base == 10)
? LDBL_DIG
- : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
+ : (int)trio_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));
+ : (int)trio_floor(FLT_MANT_DIG / TrioLogarithmBase(base));
epsilon = FLT_EPSILON;
}
else
{
baseDigits = (base == BASE_DECIMAL)
? DBL_DIG
- : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base));
+ : (int)trio_floor(DBL_MANT_DIG / TrioLogarithmBase(base));
epsilon = DBL_EPSILON;
}
@@ -2699,8 +3055,12 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
( (flags & FLAGS_FLOAT_G) &&
!(flags & FLAGS_ALTERNATIVE) ) );
+# if TRIO_FEATURE_ROUNDING
if (flags & FLAGS_ROUNDING)
- precision = baseDigits;
+ {
+ precision = baseDigits;
+ }
+# endif
if (precision == NO_PRECISION)
{
@@ -2716,18 +3076,24 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
if (isNegative)
- number = -number;
+ {
+ number = -number;
+ }
if (isHex)
- flags |= FLAGS_FLOAT_E;
+ {
+ flags |= FLAGS_FLOAT_E;
+ }
+
+ reprocess:
if (flags & FLAGS_FLOAT_G)
{
if (precision == 0)
precision = 1;
- if ((number < 1.0E-4) || (number > powl(base,
- (trio_long_double_t)precision)))
+ if ( (number < 1.0E-4) ||
+ (number >= trio_pow(base, (trio_long_double_t)precision)) )
{
/* Use scientific notation */
flags |= FLAGS_FLOAT_E;
@@ -2741,9 +3107,9 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
*/
workNumber = TrioLogarithm(number, base);
workNumber = TRIO_FABS(workNumber);
- if (workNumber - floorl(workNumber) < 0.001)
+ if (workNumber - trio_floor(workNumber) < epsilon)
workNumber--;
- zeroes = (int)floorl(workNumber);
+ leadingFractionZeroes = (int)trio_floor(workNumber);
}
}
@@ -2760,63 +3126,165 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
else
{
- exponent = (int)floorl(workNumber);
- number /= powl(dblBase, (trio_long_double_t)exponent);
+ exponent = (int)trio_floor(workNumber);
+ /*
+ * The expression A * 10^-B is equivalent to A / 10^B but the former
+ * usually gives better accuracy.
+ */
+ workNumber = number * trio_pow(dblBase, (trio_long_double_t)-exponent);
+ if (trio_isinf(workNumber))
+ {
+ workNumber = number / trio_pow(dblBase, (trio_long_double_t)exponent);
+ }
+ number = workNumber;
isExponentNegative = (exponent < 0);
uExponent = (isExponentNegative) ? -exponent : exponent;
if (isHex)
uExponent *= 4; /* log16(2) */
+#if TRIO_FEATURE_QUOTE
/* No thousand separators */
flags &= ~FLAGS_QUOTE;
+#endif
}
}
- integerNumber = floorl(number);
+ integerNumber = trio_floor(number);
fractionNumber = number - integerNumber;
/*
* Truncated number.
*
- * Precision is number of significant digits for FLOAT_G
- * and number of fractional digits for others.
+ * Precision is number of significant digits for FLOAT_G and number of
+ * fractional digits for others.
*/
- integerDigits = (integerNumber > epsilon)
- ? 1 + (int)TrioLogarithm(integerNumber, base)
- : 1;
- fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
- ? precision - integerDigits
- : zeroes + precision;
+ integerDigits = 1;
+ if (integerNumber > epsilon)
+ {
+ integerDigits += (int)TrioLogarithm(integerNumber, base);
+ }
+
+ fractionDigits = precision;
+ if (flags & FLAGS_FLOAT_G)
+ {
+ if (leadingFractionZeroes > 0)
+ {
+ fractionDigits += leadingFractionZeroes;
+ }
+ if ((integerNumber > epsilon) || (number <= epsilon))
+ {
+ fractionDigits -= integerDigits;
+ }
+ }
dblFractionBase = TrioPower(base, fractionDigits);
-
- workNumber = number + 0.5 / dblFractionBase;
- if (floorl(number) != floorl(workNumber))
+
+ if (integerNumber < 1.0)
+ {
+ workNumber = number * dblFractionBase + 0.5;
+ if (trio_floor(number * dblFractionBase) != trio_floor(workNumber))
+ {
+ adjustNumber = TRUE;
+ /* Remove a leading fraction zero if fraction is rounded up */
+ if ((int)TrioLogarithm(number * dblFractionBase, base) != (int)TrioLogarithm(workNumber, base))
+ {
+ --leadingFractionZeroes;
+ }
+ }
+ workNumber /= dblFractionBase;
+ }
+ else
{
+ workNumber = number + 0.5 / dblFractionBase;
+ adjustNumber = (trio_floor(number) != trio_floor(workNumber));
+ }
+ if (adjustNumber)
+ {
+ if ((flags & FLAGS_FLOAT_G) && !(flags & FLAGS_FLOAT_E))
+ {
+ /* The adjustment may require a change to scientific notation */
+ if ( (workNumber < 1.0E-4) ||
+ (workNumber >= trio_pow(base, (trio_long_double_t)precision)) )
+ {
+ /* Use scientific notation */
+ flags |= FLAGS_FLOAT_E;
+ goto reprocess;
+ }
+ }
+
if (flags & FLAGS_FLOAT_E)
{
- /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
- exponent++;
- isExponentNegative = (exponent < 0);
- uExponent = (isExponentNegative) ? -exponent : exponent;
- if (isHex)
- uExponent *= 4; /* log16(2) */
- workNumber = (number + 0.5 / dblFractionBase) / dblBase;
- integerNumber = floorl(workNumber);
- fractionNumber = workNumber - integerNumber;
+ workDigits = 1 + TrioLogarithm(trio_floor(workNumber), base);
+ if (integerDigits == workDigits)
+ {
+ /* Adjust if the same number of digits are used */
+ number += 0.5 / dblFractionBase;
+ integerNumber = trio_floor(number);
+ fractionNumber = number - integerNumber;
+ }
+ else
+ {
+ /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
+ exponent++;
+ isExponentNegative = (exponent < 0);
+ uExponent = (isExponentNegative) ? -exponent : exponent;
+ if (isHex)
+ uExponent *= 4; /* log16(2) */
+ workNumber = (number + 0.5 / dblFractionBase) / dblBase;
+ integerNumber = trio_floor(workNumber);
+ fractionNumber = workNumber - integerNumber;
+ }
}
else
{
- /* Adjust if number was rounded up one digit (ie. 99 to 100) */
- integerNumber = floorl(number + 0.5);
- fractionNumber = 0.0;
- integerDigits = (integerNumber > epsilon)
- ? 1 + (int)TrioLogarithm(integerNumber, base)
- : 1;
+ if (workNumber > 1.0)
+ {
+ /* Adjust if number was rounded up one digit (ie. 99 to 100) */
+ integerNumber = trio_floor(workNumber);
+ fractionNumber = 0.0;
+ integerDigits = (integerNumber > epsilon)
+ ? 1 + (int)TrioLogarithm(integerNumber, base)
+ : 1;
+ if (flags & FLAGS_FLOAT_G)
+ {
+ if (flags & FLAGS_ALTERNATIVE)
+ {
+ if ((integerNumber > epsilon) || (number <= epsilon))
+ {
+ fractionDigits -= integerDigits;
+ }
+ }
+ else
+ {
+ fractionDigits = 0;
+ }
+ }
+ }
+ else
+ {
+ integerNumber = trio_floor(workNumber);
+ fractionNumber = workNumber - integerNumber;
+ if (flags & FLAGS_FLOAT_G)
+ {
+ if (flags & FLAGS_ALTERNATIVE)
+ {
+ fractionDigits = precision;
+ if (leadingFractionZeroes > 0)
+ {
+ fractionDigits += leadingFractionZeroes;
+ }
+ if ((integerNumber > epsilon) || (number <= epsilon))
+ {
+ fractionDigits -= integerDigits;
+ }
+ }
+ }
+ }
}
}
/* Estimate accuracy */
integerAdjust = fractionAdjust = 0.5;
+# if TRIO_FEATURE_ROUNDING
if (flags & FLAGS_ROUNDING)
{
if (integerDigits > baseDigits)
@@ -2837,6 +3305,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
}
else
+# endif
{
integerThreshold = INT_MAX;
fractionThreshold = INT_MAX;
@@ -2848,35 +3317,88 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
* + fraction + exponent
*/
fractionAdjust /= dblFractionBase;
- hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon);
+ hasOnlyZeroes = (trio_floor((fractionNumber + fractionAdjust) *
+ dblFractionBase) < epsilon);
keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) ||
!((precision == 0) ||
(!keepTrailingZeroes && hasOnlyZeroes)) );
+
+ expectedWidth = integerDigits + fractionDigits;
+
+ if (!keepTrailingZeroes)
+ {
+ trailingZeroes = 0;
+ workFractionNumber = fractionNumber;
+ workFractionAdjust = fractionAdjust;
+ fractionDigitsInspect = fractionDigits;
+
+ if (integerDigits > integerThreshold)
+ {
+ fractionDigitsInspect = 0;
+ }
+ else if (fractionThreshold <= fractionDigits)
+ {
+ fractionDigitsInspect = fractionThreshold + 1;
+ }
+
+ trailingZeroes = fractionDigits - fractionDigitsInspect;
+ for (i = 0; i < fractionDigitsInspect; i++)
+ {
+ workFractionNumber *= dblBase;
+ workFractionAdjust *= dblBase;
+ workNumber = trio_floor(workFractionNumber + workFractionAdjust);
+ workFractionNumber -= workNumber;
+ offset = (int)trio_fmod(workNumber, dblBase);
+ if (offset == 0)
+ {
+ trailingZeroes++;
+ }
+ else
+ {
+ trailingZeroes = 0;
+ }
+ }
+ expectedWidth -= trailingZeroes;
+ }
+
+ if (keepDecimalPoint)
+ {
+ expectedWidth += internalDecimalPointLength;
+ }
+
+#if TRIO_FEATURE_QUOTE
+ if (flags & FLAGS_QUOTE)
+ {
+ expectedWidth += TrioCalcThousandSeparatorLength(integerDigits);
+ }
+#endif
+
+ if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
+ {
+ expectedWidth += sizeof("-") - 1;
+ }
+
+ exponentDigits = 0;
if (flags & FLAGS_FLOAT_E)
{
exponentDigits = (uExponent == 0)
? 1
- : (int)ceil(TrioLogarithm((double)(uExponent + 1),
- (isHex) ? 10.0 : base));
+ : (int)trio_ceil(TrioLogarithm((double)(uExponent + 1),
+ (isHex) ? 10 : base));
}
- 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))
- expectedWidth += sizeof("-") - 1;
if (exponentDigits > 0)
- expectedWidth += exponentDigits +
- ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1);
+ {
+ expectedWidth += exponentDigits;
+ expectedWidth += (requireTwoDigitExponent
+ ? sizeof("E+0") - 1
+ : sizeof("E+") - 1);
+ }
+
if (isHex)
- expectedWidth += sizeof("0X") - 1;
+ {
+ expectedWidth += sizeof("0X") - 1;
+ }
/* Output prefixing */
if (flags & FLAGS_NILPADDING)
@@ -2925,10 +3447,10 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
/* 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));
+ workNumber = trio_floor(((integerNumber + integerAdjust)
+ / TrioPower(base, integerDigits - i - 1)));
if (i > integerThreshold)
{
/* Beyond accuracy */
@@ -2936,10 +3458,10 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
else
{
- self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]);
+ self->OutStream(self, digits[(int)trio_fmod(workNumber, dblBase)]);
}
- dblIntegerBase *= dblBase;
-
+
+#if TRIO_FEATURE_QUOTE
if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
&& TrioFollowedBySeparator(integerDigits - i))
{
@@ -2950,6 +3472,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
self->OutStream(self, *groupingPointer);
}
}
+#endif
}
/* Insert decimal point and build the fraction part */
@@ -2981,10 +3504,19 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
{
fractionNumber *= dblBase;
fractionAdjust *= dblBase;
- workNumber = floorl(fractionNumber + fractionAdjust);
- fractionNumber -= workNumber;
- index = (int)fmodl(workNumber, dblBase);
- if (index == 0)
+ workNumber = trio_floor(fractionNumber + fractionAdjust);
+ if (workNumber > fractionNumber)
+ {
+ /* fractionNumber should never become negative */
+ fractionNumber = 0.0;
+ fractionAdjust = 0.0;
+ }
+ else
+ {
+ fractionNumber -= workNumber;
+ }
+ offset = (int)trio_fmod(workNumber, dblBase);
+ if (offset == 0)
{
trailingZeroes++;
}
@@ -2996,7 +3528,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
self->OutStream(self, digits[0]);
trailingZeroes--;
}
- self->OutStream(self, digits[index]);
+ self->OutStream(self, digits[offset]);
}
}
}
@@ -3024,7 +3556,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
self->OutStream(self, '0');
if (isHex)
- base = 10.0;
+ base = 10;
exponentBase = (int)TrioPower(base, exponentDigits - 1);
for (i = 0; i < exponentDigits; i++)
{
@@ -3041,6 +3573,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
}
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* TrioFormatProcess
@@ -3055,318 +3588,318 @@ TRIO_ARGS3((data, format, parameters),
TRIO_CONST char *format,
trio_parameter_t *parameters)
{
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- int charlen;
-#endif
int i;
+#if TRIO_FEATURE_ERRNO
TRIO_CONST char *string;
+#endif
trio_pointer_t pointer;
trio_flags_t flags;
int width;
int precision;
int base;
- int index;
+ int offset;
- index = 0;
+ offset = 0;
i = 0;
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- (void)mblen(NULL, 0);
-#endif
-
- while (format[index])
+
+ for (;;)
{
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- if (! isascii(format[index]))
- {
- charlen = mblen(&format[index], MB_LEN_MAX);
- /*
- * Only valid multibyte characters are handled here. Invalid
- * multibyte characters (charlen == -1) are handled as normal
- * characters.
- */
- if (charlen != -1)
+ /* Skip the parameter entries */
+ while (parameters[i].type == FORMAT_PARAMETER)
+ i++;
+
+ /* Copy non conversion-specifier part of format string */
+ while (offset < parameters[i].beginOffset)
+ {
+ if (CHAR_IDENTIFIER == format[offset] && CHAR_IDENTIFIER == format[offset + 1])
{
- while (charlen-- > 0)
- {
- data->OutStream(data, format[index++]);
- }
- continue; /* while characters left in formatting string */
+ data->OutStream(data, CHAR_IDENTIFIER);
+ offset += 2;
+ }
+ else
+ {
+ data->OutStream(data, format[offset++]);
}
}
-#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
- if (CHAR_IDENTIFIER == format[index])
+
+ /* Abort if we reached end of format string */
+ if (parameters[i].type == FORMAT_SENTINEL)
+ break;
+
+ /* Ouput parameter */
+ flags = parameters[i].flags;
+
+ /* Find width */
+ width = parameters[i].width;
+ if (flags & FLAGS_WIDTH_PARAMETER)
{
- if (CHAR_IDENTIFIER == format[index + 1])
+ /* Get width from parameter list */
+ width = (int)parameters[width].data.number.as_signed;
+ if (width < 0)
{
- data->OutStream(data, CHAR_IDENTIFIER);
- index += 2;
+ /*
+ * A negative width is the same as the - flag and
+ * a positive width.
+ */
+ flags |= FLAGS_LEFTADJUST;
+ flags &= ~FLAGS_NILPADDING;
+ width = -width;
}
- else
- {
- /* Skip the parameter entries */
- while (parameters[i].type == FORMAT_PARAMETER)
- i++;
-
- flags = parameters[i].flags;
+ }
- /* Find width */
- width = parameters[i].width;
- if (flags & FLAGS_WIDTH_PARAMETER)
- {
- /* Get width from parameter list */
- width = (int)parameters[width].data.number.as_signed;
- if (width < 0)
- {
- /*
- * A negative width is the same as the - flag and
- * a positive width.
- */
- flags |= FLAGS_LEFTADJUST;
- flags &= ~FLAGS_NILPADDING;
- width = -width;
- }
- }
-
- /* Find precision */
- if (flags & FLAGS_PRECISION)
- {
- precision = parameters[i].precision;
- if (flags & FLAGS_PRECISION_PARAMETER)
- {
- /* Get precision from parameter list */
- precision = (int)parameters[precision].data.number.as_signed;
- if (precision < 0)
- {
- /*
- * A negative precision is the same as no
- * precision
- */
- precision = NO_PRECISION;
- }
- }
- }
- else
+ /* Find precision */
+ if (flags & FLAGS_PRECISION)
+ {
+ precision = parameters[i].precision;
+ if (flags & FLAGS_PRECISION_PARAMETER)
+ {
+ /* Get precision from parameter list */
+ precision = (int)parameters[precision].data.number.as_signed;
+ if (precision < 0)
{
+ /*
+ * A negative precision is the same as no
+ * precision
+ */
precision = NO_PRECISION;
}
+ }
+ }
+ else
+ {
+ precision = NO_PRECISION;
+ }
- /* Find base */
- base = parameters[i].base;
- if (flags & FLAGS_BASE_PARAMETER)
- {
- /* Get base from parameter list */
- base = (int)parameters[base].data.number.as_signed;
- }
-
- switch (parameters[i].type)
- {
- case FORMAT_CHAR:
- if (flags & FLAGS_QUOTE)
- data->OutStream(data, CHAR_QUOTE);
- if (! (flags & FLAGS_LEFTADJUST))
- {
- while (--width > 0)
- data->OutStream(data, CHAR_ADJUST);
- }
-#if TRIO_WIDECHAR
- if (flags & FLAGS_WIDECHAR)
- {
- TrioWriteWideStringCharacter(data,
- (trio_wchar_t)parameters[i].data.number.as_signed,
- flags,
- NO_WIDTH);
- }
- else
+ /* Find base */
+ if (NO_BASE != parameters[i].baseSpecifier)
+ {
+ /* Base from specifier has priority */
+ base = parameters[i].baseSpecifier;
+ }
+ else if (flags & FLAGS_BASE_PARAMETER)
+ {
+ /* Get base from parameter list */
+ base = parameters[i].base;
+ base = (int)parameters[base].data.number.as_signed;
+ }
+ else
+ {
+ /* Use base from format string */
+ base = parameters[i].base;
+ }
+
+ switch (parameters[i].type)
+ {
+ case FORMAT_CHAR:
+#if TRIO_FEATURE_QUOTE
+ if (flags & FLAGS_QUOTE)
+ data->OutStream(data, CHAR_QUOTE);
#endif
- {
- TrioWriteStringCharacter(data,
- (int)parameters[i].data.number.as_signed,
- flags);
- }
+ if (! (flags & FLAGS_LEFTADJUST))
+ {
+ while (--width > 0)
+ data->OutStream(data, CHAR_ADJUST);
+ }
+#if TRIO_FEATURE_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ TrioWriteWideStringCharacter(data,
+ (trio_wchar_t)parameters[i].data.number.as_signed,
+ flags,
+ NO_WIDTH);
+ }
+ else
+#endif
+ {
+ TrioWriteStringCharacter(data,
+ (int)parameters[i].data.number.as_signed,
+ flags);
+ }
- if (flags & FLAGS_LEFTADJUST)
- {
- while(--width > 0)
- data->OutStream(data, CHAR_ADJUST);
- }
- if (flags & FLAGS_QUOTE)
- data->OutStream(data, CHAR_QUOTE);
+ if (flags & FLAGS_LEFTADJUST)
+ {
+ while(--width > 0)
+ data->OutStream(data, CHAR_ADJUST);
+ }
+#if TRIO_FEATURE_QUOTE
+ if (flags & FLAGS_QUOTE)
+ data->OutStream(data, CHAR_QUOTE);
+#endif
- break; /* FORMAT_CHAR */
+ break; /* FORMAT_CHAR */
- case FORMAT_INT:
- TrioWriteNumber(data,
- parameters[i].data.number.as_unsigned,
- flags,
- width,
- precision,
- base);
+ case FORMAT_INT:
+ TrioWriteNumber(data,
+ parameters[i].data.number.as_unsigned,
+ flags,
+ width,
+ precision,
+ base);
+
+ break; /* FORMAT_INT */
- break; /* FORMAT_INT */
+#if TRIO_FEATURE_FLOAT
+ case FORMAT_DOUBLE:
+ TrioWriteDouble(data,
+ parameters[i].data.longdoubleNumber,
+ flags,
+ width,
+ precision,
+ base);
+ break; /* FORMAT_DOUBLE */
+#endif
- case FORMAT_DOUBLE:
- TrioWriteDouble(data,
- parameters[i].data.longdoubleNumber,
+ case FORMAT_STRING:
+#if TRIO_FEATURE_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ TrioWriteWideString(data,
+ parameters[i].data.wstring,
flags,
width,
- precision,
- base);
- break; /* FORMAT_DOUBLE */
-
- case FORMAT_STRING:
-#if TRIO_WIDECHAR
- if (flags & FLAGS_WIDECHAR)
- {
- TrioWriteWideString(data,
- parameters[i].data.wstring,
- flags,
- width,
- precision);
- }
- else
+ precision);
+ }
+ else
#endif
- {
- TrioWriteString(data,
- parameters[i].data.string,
- flags,
- width,
- precision);
- }
- break; /* FORMAT_STRING */
+ {
+ TrioWriteString(data,
+ parameters[i].data.string,
+ flags,
+ width,
+ precision);
+ }
+ break; /* FORMAT_STRING */
- case FORMAT_POINTER:
- {
- trio_reference_t reference;
-
- reference.data = data;
- reference.parameter = &parameters[i];
- trio_print_pointer(&reference, parameters[i].data.pointer);
- }
- break; /* FORMAT_POINTER */
+ case FORMAT_POINTER:
+ {
+ trio_reference_t reference;
- case FORMAT_COUNT:
- pointer = parameters[i].data.pointer;
- if (NULL != pointer)
- {
- /*
- * C99 paragraph 7.19.6.1.8 says "the number of
- * 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
+ reference.data = data;
+ reference.parameter = &parameters[i];
+ trio_print_pointer(&reference, parameters[i].data.pointer);
+ }
+ break; /* FORMAT_POINTER */
+
+ case FORMAT_COUNT:
+ pointer = parameters[i].data.pointer;
+ if (NULL != pointer)
+ {
+ /*
+ * C99 paragraph 7.19.6.1.8 says "the number of
+ * characters written to the output stream so far by
+ * this call", which is data->actually.committed
+ */
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
+ if (flags & FLAGS_SIZE_T)
+ *(size_t *)pointer = (size_t)data->actually.committed;
+ else
#endif
-#if defined(QUALIFIER_PTRDIFF_T)
- if (flags & FLAGS_PTRDIFF_T)
- *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed;
- else
+#if TRIO_FEATURE_PTRDIFF_T
+ if (flags & FLAGS_PTRDIFF_T)
+ *(ptrdiff_t *)pointer = (ptrdiff_t)data->actually.committed;
+ else
#endif
-#if defined(QUALIFIER_INTMAX_T)
- if (flags & FLAGS_INTMAX_T)
- *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
- else
+#if TRIO_FEATURE_INTMAX_T
+ if (flags & FLAGS_INTMAX_T)
+ *(trio_intmax_t *)pointer = (trio_intmax_t)data->actually.committed;
+ else
#endif
- if (flags & FLAGS_QUAD)
- {
- *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
- }
- 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 */
+ if (flags & FLAGS_QUAD)
+ {
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->actually.committed;
+ }
+ else if (flags & FLAGS_LONG)
+ {
+ *(long int *)pointer = (long int)data->actually.committed;
+ }
+ else if (flags & FLAGS_SHORT)
+ {
+ *(short int *)pointer = (short int)data->actually.committed;
+ }
+ else
+ {
+ *(int *)pointer = (int)data->actually.committed;
+ }
+ }
+ break; /* FORMAT_COUNT */
- case FORMAT_PARAMETER:
- break; /* FORMAT_PARAMETER */
+ case FORMAT_PARAMETER:
+ break; /* FORMAT_PARAMETER */
-#if defined(FORMAT_ERRNO)
- case FORMAT_ERRNO:
- string = trio_error(parameters[i].data.errorNumber);
- if (string)
- {
- TrioWriteString(data,
- string,
- flags,
- width,
- precision);
- }
- else
- {
- data->OutStream(data, '#');
- TrioWriteNumber(data,
- (trio_uintmax_t)parameters[i].data.errorNumber,
- flags,
- width,
- precision,
- BASE_DECIMAL);
- }
- break; /* FORMAT_ERRNO */
-#endif /* defined(FORMAT_ERRNO) */
+#if TRIO_FEATURE_ERRNO
+ case FORMAT_ERRNO:
+ string = trio_error(parameters[i].data.errorNumber);
+ if (string)
+ {
+ TrioWriteString(data,
+ string,
+ flags,
+ width,
+ precision);
+ }
+ else
+ {
+ data->OutStream(data, '#');
+ TrioWriteNumber(data,
+ (trio_uintmax_t)parameters[i].data.errorNumber,
+ flags,
+ width,
+ precision,
+ BASE_DECIMAL);
+ }
+ break; /* FORMAT_ERRNO */
+#endif /* TRIO_FEATURE_ERRNO */
+
+#if TRIO_FEATURE_USER_DEFINED
+ case FORMAT_USER_DEFINED:
+ {
+ trio_reference_t reference;
+ trio_userdef_t *def = NULL;
-#if defined(FORMAT_USER_DEFINED)
- case FORMAT_USER_DEFINED:
- {
- trio_reference_t reference;
- trio_userdef_t *def = NULL;
+ if (parameters[i].flags & FLAGS_USER_DEFINED_PARAMETER)
+ {
+ /* Use handle */
+ if ((i > 0) ||
+ (parameters[i - 1].type == FORMAT_PARAMETER))
+ def = (trio_userdef_t *)parameters[i - 1].data.pointer;
+ }
+ else
+ {
+ /* Look up namespace */
+ def = TrioFindNamespace(parameters[i].user_defined.namespace, NULL);
+ }
+ if (def)
+ {
+ reference.data = data;
+ reference.parameter = &parameters[i];
+ def->callback(&reference);
+ }
+ }
+ break;
+#endif /* TRIO_FEATURE_USER_DEFINED */
- if (parameters[i].user_name[0] == NIL)
- {
- /* Use handle */
- if ((i > 0) ||
- (parameters[i - 1].type == FORMAT_PARAMETER))
- def = (trio_userdef_t *)parameters[i - 1].data.pointer;
- }
- 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) */
-
- default:
- break;
- } /* switch parameter type */
+ default:
+ break;
+ } /* switch parameter type */
- /* Prepare for next */
- index = parameters[i].indexAfterSpecifier;
- i++;
- }
- }
- else /* not identifier */
- {
- data->OutStream(data, format[index++]);
- }
+ /* Prepare for next */
+ offset = parameters[i].endOffset;
+ i++;
}
+
return data->processed;
}
/*************************************************************************
* TrioFormatRef
*/
+#if TRIO_EXTENSION
TRIO_PRIVATE int
TrioFormatRef
TRIO_ARGS4((reference, format, arglist, argarray),
trio_reference_t *reference,
TRIO_CONST char *format,
- va_list *arglist,
+ va_list arglist,
trio_pointer_t *argarray)
{
int status;
@@ -3383,6 +3916,7 @@ TRIO_ARGS4((reference, format, arglist, argarray),
}
return status;
}
+#endif /* TRIO_EXTENSION */
/*************************************************************************
* TrioFormat
@@ -3394,7 +3928,7 @@ TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
size_t destinationSize,
void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
TRIO_CONST char *format,
- va_list *arglist,
+ va_list arglist,
trio_pointer_t *argarray)
{
int status;
@@ -3432,6 +3966,7 @@ TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
/*************************************************************************
* TrioOutStreamFile
*/
+#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
TRIO_PRIVATE void
TrioOutStreamFile
TRIO_ARGS2((self, output),
@@ -3451,13 +3986,15 @@ TRIO_ARGS2((self, output),
}
else
{
- self->committed++;
+ self->actually.committed++;
}
}
+#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
/*************************************************************************
* TrioOutStreamFileDescriptor
*/
+#if TRIO_FEATURE_FD
TRIO_PRIVATE void
TrioOutStreamFileDescriptor
TRIO_ARGS2((self, output),
@@ -3478,13 +4015,15 @@ TRIO_ARGS2((self, output),
}
else
{
- self->committed++;
+ self->actually.committed++;
}
}
+#endif /* TRIO_FEATURE_FD */
/*************************************************************************
* TrioOutStreamCustom
*/
+#if TRIO_FEATURE_CLOSURE
TRIO_PRIVATE void
TrioOutStreamCustom
TRIO_ARGS2((self, output),
@@ -3503,7 +4042,7 @@ TRIO_ARGS2((self, output),
status = (data->stream.out)(data->closure, output);
if (status >= 0)
{
- self->committed++;
+ self->actually.committed++;
}
else
{
@@ -3515,6 +4054,7 @@ TRIO_ARGS2((self, output),
}
self->processed++;
}
+#endif /* TRIO_FEATURE_CLOSURE */
/*************************************************************************
* TrioOutStreamString
@@ -3534,7 +4074,7 @@ TRIO_ARGS2((self, output),
**buffer = (char)output;
(*buffer)++;
self->processed++;
- self->committed++;
+ self->actually.committed++;
}
/*************************************************************************
@@ -3557,7 +4097,7 @@ TRIO_ARGS2((self, output),
{
**buffer = (char)output;
(*buffer)++;
- self->committed++;
+ self->actually.committed++;
}
self->processed++;
}
@@ -3565,6 +4105,7 @@ TRIO_ARGS2((self, output),
/*************************************************************************
* TrioOutStreamStringDynamic
*/
+#if TRIO_FEATURE_DYNAMICSTRING
TRIO_PRIVATE void
TrioOutStreamStringDynamic
TRIO_ARGS2((self, output),
@@ -3578,11 +4119,12 @@ TRIO_ARGS2((self, output),
{
trio_xstring_append_char((trio_string_t *)self->location,
(char)output);
- self->committed++;
+ self->actually.committed++;
}
/* The processed variable must always be increased */
self->processed++;
}
+#endif /* TRIO_FEATURE_DYNAMICSTRING */
/*************************************************************************
*
@@ -3608,6 +4150,7 @@ TRIO_ARGS2((self, output),
@param ... Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_printf
TRIO_VARGS2((format, va_alist),
@@ -3620,10 +4163,11 @@ TRIO_VARGS2((format, va_alist),
assert(VALID(format));
TRIO_VA_START(args, format);
- status = TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
+ status = TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_STDIO */
/**
Print to standard output stream.
@@ -3632,6 +4176,7 @@ TRIO_VARGS2((format, va_alist),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_vprintf
TRIO_ARGS2((format, args),
@@ -3640,8 +4185,9 @@ TRIO_ARGS2((format, args),
{
assert(VALID(format));
- return TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
+ return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
}
+#endif /* TRIO_FEATURE_STDIO */
/**
Print to standard output stream.
@@ -3650,16 +4196,20 @@ TRIO_ARGS2((format, args),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_printfv
TRIO_ARGS2((format, args),
TRIO_CONST char *format,
trio_pointer_t * args)
{
+ static va_list unused;
+
assert(VALID(format));
- return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
+ return TrioFormat(stdout, 0, TrioOutStreamFile, format, unused, args);
}
+#endif /* TRIO_FEATURE_STDIO */
/*************************************************************************
* fprintf
@@ -3673,6 +4223,7 @@ TRIO_ARGS2((format, args),
@param ... Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_fprintf
TRIO_VARGS3((file, format, va_alist),
@@ -3687,10 +4238,11 @@ TRIO_VARGS3((file, format, va_alist),
assert(VALID(format));
TRIO_VA_START(args, format);
- status = TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
+ status = TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_FILE */
/**
Print to file.
@@ -3700,6 +4252,7 @@ TRIO_VARGS3((file, format, va_alist),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_vfprintf
TRIO_ARGS3((file, format, args),
@@ -3710,8 +4263,9 @@ TRIO_ARGS3((file, format, args),
assert(VALID(file));
assert(VALID(format));
- return TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
+ return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
}
+#endif /* TRIO_FEATURE_FILE */
/**
Print to file.
@@ -3721,6 +4275,7 @@ TRIO_ARGS3((file, format, args),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_fprintfv
TRIO_ARGS3((file, format, args),
@@ -3728,11 +4283,14 @@ TRIO_ARGS3((file, format, args),
TRIO_CONST char *format,
trio_pointer_t * args)
{
+ static va_list unused;
+
assert(VALID(file));
assert(VALID(format));
- return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
+ return TrioFormat(file, 0, TrioOutStreamFile, format, unused, args);
}
+#endif /* TRIO_FEATURE_FILE */
/*************************************************************************
* dprintf
@@ -3746,6 +4304,7 @@ TRIO_ARGS3((file, format, args),
@param ... Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_dprintf
TRIO_VARGS3((fd, format, va_alist),
@@ -3759,10 +4318,11 @@ TRIO_VARGS3((fd, format, va_alist),
assert(VALID(format));
TRIO_VA_START(args, format);
- status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
+ status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_FD */
/**
Print to file descriptor.
@@ -3772,6 +4332,7 @@ TRIO_VARGS3((fd, format, va_alist),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_vdprintf
TRIO_ARGS3((fd, format, args),
@@ -3781,8 +4342,9 @@ TRIO_ARGS3((fd, format, args),
{
assert(VALID(format));
- return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
+ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
}
+#endif /* TRIO_FEATURE_FD */
/**
Print to file descriptor.
@@ -3792,6 +4354,7 @@ TRIO_ARGS3((fd, format, args),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_dprintfv
TRIO_ARGS3((fd, format, args),
@@ -3799,14 +4362,18 @@ TRIO_ARGS3((fd, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(format));
- return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
+ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, unused, args);
}
+#endif /* TRIO_FEATURE_FD */
/*************************************************************************
* cprintf
*/
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_cprintf
TRIO_VARGS4((stream, closure, format, va_alist),
@@ -3825,11 +4392,13 @@ TRIO_VARGS4((stream, closure, format, va_alist),
TRIO_VA_START(args, format);
data.stream.out = stream;
data.closure = closure;
- status = TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
+ status = TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_CLOSURE */
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_vcprintf
TRIO_ARGS4((stream, closure, format, args),
@@ -3845,9 +4414,11 @@ TRIO_ARGS4((stream, closure, format, args),
data.stream.out = stream;
data.closure = closure;
- return TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
+ return TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL);
}
+#endif /* TRIO_FEATURE_CLOSURE */
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_cprintfv
TRIO_ARGS4((stream, closure, format, args),
@@ -3856,6 +4427,7 @@ TRIO_ARGS4((stream, closure, format, args),
TRIO_CONST char *format,
void **args)
{
+ static va_list unused;
trio_custom_t data;
assert(VALID(stream));
@@ -3863,8 +4435,9 @@ TRIO_ARGS4((stream, closure, format, args),
data.stream.out = stream;
data.closure = closure;
- return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args);
+ return TrioFormat(&data, 0, TrioOutStreamCustom, format, unused, args);
}
+#endif /* TRIO_FEATURE_CLOSURE */
/*************************************************************************
* sprintf
@@ -3892,7 +4465,7 @@ TRIO_VARGS3((buffer, format, va_alist),
assert(VALID(format));
TRIO_VA_START(args, format);
- status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
*buffer = NIL; /* Terminate with NIL character */
TRIO_VA_END(args);
return status;
@@ -3918,7 +4491,7 @@ TRIO_ARGS3((buffer, format, args),
assert(VALID(buffer));
assert(VALID(format));
- status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
*buffer = NIL;
return status;
}
@@ -3938,12 +4511,13 @@ TRIO_ARGS3((buffer, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
int status;
-
+
assert(VALID(buffer));
assert(VALID(format));
- status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, unused, args);
*buffer = NIL;
return status;
}
@@ -3972,12 +4546,12 @@ TRIO_VARGS4((buffer, max, format, va_alist),
int status;
va_list args;
- assert(VALID(buffer));
+ assert(VALID(buffer) || (max == 0));
assert(VALID(format));
TRIO_VA_START(args, format);
status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
- TrioOutStreamStringMax, format, &args, NULL);
+ TrioOutStreamStringMax, format, args, NULL);
if (max > 0)
*buffer = NIL;
TRIO_VA_END(args);
@@ -4003,11 +4577,11 @@ TRIO_ARGS4((buffer, max, format, args),
{
int status;
- assert(VALID(buffer));
+ assert(VALID(buffer) || (max == 0));
assert(VALID(format));
status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
- TrioOutStreamStringMax, format, &args, NULL);
+ TrioOutStreamStringMax, format, args, NULL);
if (max > 0)
*buffer = NIL;
return status;
@@ -4030,13 +4604,14 @@ TRIO_ARGS4((buffer, max, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
int status;
- assert(VALID(buffer));
+ assert(VALID(buffer) || (max == 0));
assert(VALID(format));
status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
- TrioOutStreamStringMax, format, NULL, args);
+ TrioOutStreamStringMax, format, unused, args);
if (max > 0)
*buffer = NIL;
return status;
@@ -4047,6 +4622,7 @@ TRIO_ARGS4((buffer, max, format, args),
* Appends the new string to the buffer string overwriting the '\0'
* character at the end of buffer.
*/
+#if TRIO_EXTENSION
TRIO_PUBLIC int
trio_snprintfcat
TRIO_VARGS4((buffer, max, format, va_alist),
@@ -4068,12 +4644,14 @@ TRIO_VARGS4((buffer, max, format, va_alist),
buffer = &buffer[buf_len];
status = TrioFormat(&buffer, max - 1 - buf_len,
- TrioOutStreamStringMax, format, &args, NULL);
+ TrioOutStreamStringMax, format, args, NULL);
TRIO_VA_END(args);
*buffer = NIL;
return status;
}
+#endif
+#if TRIO_EXTENSION
TRIO_PUBLIC int
trio_vsnprintfcat
TRIO_ARGS4((buffer, max, format, args),
@@ -4091,16 +4669,17 @@ TRIO_ARGS4((buffer, max, format, args),
buf_len = trio_length(buffer);
buffer = &buffer[buf_len];
status = TrioFormat(&buffer, max - 1 - buf_len,
- TrioOutStreamStringMax, format, &args, NULL);
+ TrioOutStreamStringMax, format, args, NULL);
*buffer = NIL;
return status;
}
+#endif
/*************************************************************************
* trio_aprintf
*/
-/* Deprecated */
+#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING
TRIO_PUBLIC char *
trio_aprintf
TRIO_VARGS2((format, va_alist),
@@ -4118,7 +4697,7 @@ TRIO_VARGS2((format, va_alist),
{
TRIO_VA_START(args, format);
(void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
- format, &args, NULL);
+ format, args, NULL);
TRIO_VA_END(args);
trio_string_terminate(info);
@@ -4127,8 +4706,9 @@ TRIO_VARGS2((format, va_alist),
}
return result;
}
+#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */
-/* Deprecated */
+#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING
TRIO_PUBLIC char *
trio_vaprintf
TRIO_ARGS2((format, args),
@@ -4144,14 +4724,26 @@ TRIO_ARGS2((format, args),
if (info)
{
(void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
- format, &args, NULL);
+ format, args, NULL);
trio_string_terminate(info);
result = trio_string_extract(info);
trio_string_destroy(info);
}
return result;
}
+#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */
+
+/**
+ Allocate and print to string.
+ The memory allocated and returned by @p result must be freed by the
+ calling application.
+ @param result Output string.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of printed characters.
+ */
+#if TRIO_FEATURE_DYNAMICSTRING
TRIO_PUBLIC int
trio_asprintf
TRIO_VARGS3((result, format, va_alist),
@@ -4176,7 +4768,7 @@ TRIO_VARGS3((result, format, va_alist),
{
TRIO_VA_START(args, format);
status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
- format, &args, NULL);
+ format, args, NULL);
TRIO_VA_END(args);
if (status >= 0)
{
@@ -4187,7 +4779,19 @@ TRIO_VARGS3((result, format, va_alist),
}
return status;
}
+#endif /* TRIO_FEATURE_DYNAMICSTRING */
+/**
+ Allocate and print to string.
+ The memory allocated and returned by @p result must be freed by the
+ calling application.
+
+ @param result Output string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+#if TRIO_FEATURE_DYNAMICSTRING
TRIO_PUBLIC int
trio_vasprintf
TRIO_ARGS3((result, format, args),
@@ -4210,7 +4814,7 @@ TRIO_ARGS3((result, format, args),
else
{
status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
- format, &args, NULL);
+ format, args, NULL);
if (status >= 0)
{
trio_string_terminate(info);
@@ -4220,6 +4824,53 @@ TRIO_ARGS3((result, format, args),
}
return status;
}
+#endif /* TRIO_FEATURE_DYNAMICSTRING */
+
+/**
+ Allocate and print to string.
+ The memory allocated and returned by @p result must be freed by the
+ calling application.
+
+ @param result Output string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+#if TRIO_FEATURE_DYNAMICSTRING
+TRIO_PUBLIC int
+trio_asprintfv
+TRIO_ARGS3((result, format, args),
+ char **result,
+ TRIO_CONST char *format,
+ trio_pointer_t * args)
+{
+ static va_list unused;
+ int status;
+ trio_string_t *info;
+
+ assert(VALID(format));
+
+ *result = NULL;
+
+ info = trio_xstring_duplicate("");
+ if (info == NULL)
+ {
+ status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
+ }
+ else
+ {
+ status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
+ format, unused, args);
+ if (status >= 0)
+ {
+ trio_string_terminate(info);
+ *result = trio_string_extract(info);
+ }
+ trio_string_destroy(info);
+ }
+ return status;
+}
+#endif /* TRIO_FEATURE_DYNAMICSTRING */
/** @} End of Printf documentation module */
@@ -4237,7 +4888,7 @@ TRIO_ARGS3((result, format, args),
@{
*/
-#if TRIO_EXTENSION
+#if TRIO_FEATURE_USER_DEFINED
/*************************************************************************
* trio_register
@@ -4340,7 +4991,7 @@ TRIO_ARGS1((handle),
(void)internalEnterCriticalRegion(NULL);
if (prev == NULL)
- internalUserDef = NULL;
+ internalUserDef = internalUserDef->next;
else
prev->next = def->next;
@@ -4360,7 +5011,7 @@ trio_get_format
TRIO_ARGS1((ref),
trio_pointer_t ref)
{
-#if defined(FORMAT_USER_DEFINED)
+#if TRIO_FEATURE_USER_DEFINED
assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
#endif
@@ -4375,7 +5026,7 @@ trio_get_argument
TRIO_ARGS1((ref),
trio_pointer_t ref)
{
-#if defined(FORMAT_USER_DEFINED)
+#if TRIO_FEATURE_USER_DEFINED
assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
#endif
@@ -4495,6 +5146,7 @@ TRIO_ARGS2((ref, is_longlong),
/*************************************************************************
* trio_get_longdouble / trio_set_longdouble [public]
*/
+# if TRIO_FEATURE_FLOAT
int
trio_get_longdouble
TRIO_ARGS1((ref),
@@ -4516,6 +5168,7 @@ TRIO_ARGS2((ref, is_longdouble),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE;
}
+# endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* trio_get_short / trio_set_short [public]
@@ -4695,6 +5348,7 @@ TRIO_ARGS2((ref, is_padding),
/*************************************************************************
* trio_get_quote / trio_set_quote [public]
*/
+# if TRIO_FEATURE_QUOTE
int
trio_get_quote
TRIO_ARGS1((ref),
@@ -4716,6 +5370,7 @@ TRIO_ARGS2((ref, is_quote),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE;
}
+#endif /* TRIO_FEATURE_QUOTE */
/*************************************************************************
* trio_get_upper / trio_set_upper [public]
@@ -4745,7 +5400,7 @@ TRIO_ARGS2((ref, is_upper),
/*************************************************************************
* trio_get_largest / trio_set_largest [public]
*/
-#if TRIO_C99
+#if TRIO_FEATURE_INTMAX_T
int
trio_get_largest
TRIO_ARGS1((ref),
@@ -4767,11 +5422,12 @@ TRIO_ARGS2((ref, is_largest),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T;
}
-#endif
+#endif /* TRIO_FEATURE_INTMAX_T */
/*************************************************************************
* trio_get_ptrdiff / trio_set_ptrdiff [public]
*/
+#if TRIO_FEATURE_PTRDIFF_T
int
trio_get_ptrdiff
TRIO_ARGS1((ref),
@@ -4793,11 +5449,12 @@ TRIO_ARGS2((ref, is_ptrdiff),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
}
+#endif /* TRIO_FEATURE_PTRDIFF_T */
/*************************************************************************
* trio_get_size / trio_set_size [public]
*/
-#if TRIO_C99
+#if TRIO_FEATURE_SIZE_T
int
trio_get_size
TRIO_ARGS1((ref),
@@ -4819,7 +5476,7 @@ TRIO_ARGS2((ref, is_size),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T;
}
-#endif
+#endif /* TRIO_FEATURE_SIZE_T */
/*************************************************************************
* trio_print_int [public]
@@ -4862,6 +5519,7 @@ TRIO_ARGS2((ref, number),
/*************************************************************************
* trio_print_double [public]
*/
+#if TRIO_FEATURE_FLOAT
void
trio_print_double
TRIO_ARGS2((ref, number),
@@ -4877,6 +5535,7 @@ TRIO_ARGS2((ref, number),
self->parameter->precision,
self->parameter->base);
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* trio_print_string [public]
@@ -4885,7 +5544,7 @@ void
trio_print_string
TRIO_ARGS2((ref, string),
trio_pointer_t ref,
- char *string)
+ TRIO_CONST char *string)
{
trio_reference_t *self = (trio_reference_t *)ref;
@@ -4912,7 +5571,7 @@ TRIO_VARGS3((ref, format, va_alist),
assert(VALID(format));
TRIO_VA_START(arglist, format);
- status = TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
+ status = TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
TRIO_VA_END(arglist);
return status;
}
@@ -4929,7 +5588,7 @@ TRIO_ARGS3((ref, format, arglist),
{
assert(VALID(format));
- return TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
+ return TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
}
/*************************************************************************
@@ -4942,12 +5601,14 @@ TRIO_ARGS3((ref, format, argarray),
TRIO_CONST char *format,
trio_pointer_t *argarray)
{
+ static va_list unused;
+
assert(VALID(format));
- return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray);
+ return TrioFormatRef((trio_reference_t *)ref, format, unused, argarray);
}
-#endif /* TRIO_EXTENSION */
+#endif
/*************************************************************************
* trio_print_pointer [public]
@@ -5007,6 +5668,7 @@ TRIO_ARGS2((ref, pointer),
* string to enable multibyte characters. At most MB_LEN_MAX characters
* will be used.
*/
+#if TRIO_FEATURE_LOCALE
TRIO_PUBLIC void
trio_locale_set_decimal_point
TRIO_ARGS1((decimalPoint),
@@ -5031,28 +5693,31 @@ TRIO_ARGS1((decimalPoint),
decimalPoint);
}
}
+#endif
/*************************************************************************
* trio_locale_set_thousand_separator
*
* See trio_locale_set_decimal_point
*/
+#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION
TRIO_PUBLIC void
trio_locale_set_thousand_separator
TRIO_ARGS1((thousandSeparator),
char *thousandSeparator)
{
-#if defined(USE_LOCALE)
+# if defined(USE_LOCALE)
if (NULL == internalLocaleValues)
{
TrioSetLocale();
}
-#endif
+# endif
trio_copy_max(internalThousandSeparator,
sizeof(internalThousandSeparator),
thousandSeparator);
internalThousandSeparatorLength = trio_length(internalThousandSeparator);
}
+#endif
/*************************************************************************
* trio_locale_set_grouping
@@ -5066,21 +5731,23 @@ TRIO_ARGS1((thousandSeparator),
*
* Same order as the grouping attribute in LC_NUMERIC.
*/
+#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION
TRIO_PUBLIC void
trio_locale_set_grouping
TRIO_ARGS1((grouping),
char *grouping)
{
-#if defined(USE_LOCALE)
+# if defined(USE_LOCALE)
if (NULL == internalLocaleValues)
{
TrioSetLocale();
}
-#endif
+# endif
trio_copy_max(internalGrouping,
sizeof(internalGrouping),
grouping);
}
+#endif
/*************************************************************************
@@ -5089,6 +5756,8 @@ TRIO_ARGS1((grouping),
*
************************************************************************/
+#if TRIO_FEATURE_SCANF
+
/*************************************************************************
* TrioSkipWhitespaces
*/
@@ -5146,13 +5815,13 @@ TrioGetCollation(TRIO_NOARGS)
*/
TRIO_PRIVATE int
TrioGetCharacterClass
-TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
+TRIO_ARGS4((format, offsetPointer, flagsPointer, characterclass),
TRIO_CONST char *format,
- int *indexPointer,
+ int *offsetPointer,
trio_flags_t *flagsPointer,
int *characterclass)
{
- int index = *indexPointer;
+ int offset = *offsetPointer;
int i;
char ch;
char range_begin;
@@ -5160,34 +5829,34 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
*flagsPointer &= ~FLAGS_EXCLUDE;
- if (format[index] == QUALIFIER_CIRCUMFLEX)
+ if (format[offset] == QUALIFIER_CIRCUMFLEX)
{
*flagsPointer |= FLAGS_EXCLUDE;
- index++;
+ offset++;
}
/*
* If the ungroup character is at the beginning of the scanlist,
* it will be part of the class, and a second ungroup character
* must follow to end the group.
*/
- if (format[index] == SPECIFIER_UNGROUP)
+ if (format[offset] == SPECIFIER_UNGROUP)
{
characterclass[(int)SPECIFIER_UNGROUP]++;
- index++;
+ offset++;
}
/*
* Minus is used to specify ranges. To include minus in the class,
* it must be at the beginning of the list
*/
- if (format[index] == QUALIFIER_MINUS)
+ if (format[offset] == QUALIFIER_MINUS)
{
characterclass[(int)QUALIFIER_MINUS]++;
- index++;
+ offset++;
}
/* Collect characters */
- for (ch = format[index];
+ for (ch = format[offset];
(ch != SPECIFIER_UNGROUP) && (ch != NIL);
- ch = format[++index])
+ ch = format[++offset])
{
switch (ch)
{
@@ -5206,8 +5875,8 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
* - duplicates (although we can easily convert these
* into errors)
*/
- range_begin = format[index - 1];
- range_end = format[++index];
+ range_begin = format[offset - 1];
+ range_end = format[++offset];
if (range_end == SPECIFIER_UNGROUP)
{
/* Trailing minus is included */
@@ -5216,9 +5885,9 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
break; /* for */
}
if (range_end == NIL)
- return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
if (range_begin > range_end)
- return TRIO_ERROR_RETURN(TRIO_ERANGE, index);
+ return TRIO_ERROR_RETURN(TRIO_ERANGE, offset);
for (i = (int)range_begin; i <= (int)range_end; i++)
characterclass[i]++;
@@ -5230,7 +5899,7 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
case SPECIFIER_GROUP:
- switch (format[index + 1])
+ switch (format[offset + 1])
{
case QUALIFIER_DOT: /* Collating symbol */
/*
@@ -5238,7 +5907,7 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
* characters have been implemented. Until now, we ignore
* this feature.
*/
- for (i = index + 2; ; i++)
+ for (i = offset + 2; ; i++)
{
if (format[i] == NIL)
/* Error in syntax */
@@ -5249,7 +5918,7 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
if (format[++i] != SPECIFIER_UNGROUP)
return -1;
- index = i;
+ offset = i;
break;
case QUALIFIER_EQUAL: /* Equivalence class expressions */
@@ -5263,7 +5932,7 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
TrioGetCollation();
internalCollationUnconverted = FALSE;
}
- for (i = index + 2; ; i++)
+ for (i = offset + 2; ; i++)
{
if (format[i] == NIL)
/* Error in syntax */
@@ -5281,99 +5950,99 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
if (format[++i] != SPECIFIER_UNGROUP)
return -1;
- index = i;
+ offset = i;
}
break;
case QUALIFIER_COLON: /* Character class expressions */
if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isalnum(i))
characterclass[i]++;
- index += sizeof(CLASS_ALNUM) - 1;
+ offset += sizeof(CLASS_ALNUM) - 1;
}
else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isalpha(i))
characterclass[i]++;
- index += sizeof(CLASS_ALPHA) - 1;
+ offset += sizeof(CLASS_ALPHA) - 1;
}
else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (iscntrl(i))
characterclass[i]++;
- index += sizeof(CLASS_CNTRL) - 1;
+ offset += sizeof(CLASS_CNTRL) - 1;
}
else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isdigit(i))
characterclass[i]++;
- index += sizeof(CLASS_DIGIT) - 1;
+ offset += sizeof(CLASS_DIGIT) - 1;
}
else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isgraph(i))
characterclass[i]++;
- index += sizeof(CLASS_GRAPH) - 1;
+ offset += sizeof(CLASS_GRAPH) - 1;
}
else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (islower(i))
characterclass[i]++;
- index += sizeof(CLASS_LOWER) - 1;
+ offset += sizeof(CLASS_LOWER) - 1;
}
else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isprint(i))
characterclass[i]++;
- index += sizeof(CLASS_PRINT) - 1;
+ offset += sizeof(CLASS_PRINT) - 1;
}
else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (ispunct(i))
characterclass[i]++;
- index += sizeof(CLASS_PUNCT) - 1;
+ offset += sizeof(CLASS_PUNCT) - 1;
}
else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isspace(i))
characterclass[i]++;
- index += sizeof(CLASS_SPACE) - 1;
+ offset += sizeof(CLASS_SPACE) - 1;
}
else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isupper(i))
characterclass[i]++;
- index += sizeof(CLASS_UPPER) - 1;
+ offset += sizeof(CLASS_UPPER) - 1;
}
else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isxdigit(i))
characterclass[i]++;
- index += sizeof(CLASS_XDIGIT) - 1;
+ offset += sizeof(CLASS_XDIGIT) - 1;
}
else
{
@@ -5437,18 +6106,15 @@ TRIO_ARGS5((self, target, flags, width, base),
TrioSkipWhitespaces(self);
- if (!(flags & FLAGS_UNSIGNED))
+ /* Leading sign */
+ if (self->current == '+')
{
- /* Leading sign */
- if (self->current == '+')
- {
- self->InStream(self, NULL);
- }
- else if (self->current == '-')
- {
- self->InStream(self, NULL);
- isNegative = TRUE;
- }
+ self->InStream(self, NULL);
+ }
+ else if (self->current == '-')
+ {
+ self->InStream(self, NULL);
+ isNegative = TRUE;
}
count = self->processed;
@@ -5496,6 +6162,7 @@ TRIO_ARGS5((self, target, flags, width, base),
if ((digit == -1) || (digit >= base))
break;
}
+#if TRIO_FEATURE_QUOTE
else if (flags & FLAGS_QUOTE)
{
/* Compare with thousands separator */
@@ -5511,6 +6178,7 @@ TRIO_ARGS5((self, target, flags, width, base),
else
continue; /* Match */
}
+#endif
else
break;
@@ -5526,7 +6194,7 @@ TRIO_ARGS5((self, target, flags, width, base),
return FALSE;
if (target)
- *target = (isNegative) ? -((trio_intmax_t)number) : number;
+ *target = (isNegative) ? (trio_uintmax_t)(-((trio_intmax_t)number)) : number;
return TRUE;
}
@@ -5634,7 +6302,7 @@ TRIO_ARGS4((self, target, flags, width),
/*************************************************************************
* TrioReadWideChar
*/
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
TRIO_PRIVATE int
TrioReadWideChar
TRIO_ARGS4((self, target, flags, width),
@@ -5690,12 +6358,12 @@ TRIO_ARGS4((self, target, flags, width),
}
return amount;
}
-#endif /* TRIO_WIDECHAR */
+#endif /* TRIO_FEATURE_WIDECHAR */
/*************************************************************************
* TrioReadWideString
*/
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
TRIO_PRIVATE BOOLEAN_T
TrioReadWideString
TRIO_ARGS4((self, target, flags, width),
@@ -5713,6 +6381,7 @@ TRIO_ARGS4((self, target, flags, width),
TrioSkipWhitespaces(self);
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ /* Required by TrioReadWideChar */
(void)mblen(NULL, 0);
#endif
@@ -5735,11 +6404,13 @@ TRIO_ARGS4((self, target, flags, width),
target[i] = WCONST('\0');
return TRUE;
}
-#endif /* TRIO_WIDECHAR */
+#endif /* TRIO_FEATURE_WIDECHAR */
/*************************************************************************
* TrioReadGroup
*
+ * Reads non-empty character groups.
+ *
* FIXME: characterclass does not work with multibyte characters
*/
TRIO_PRIVATE BOOLEAN_T
@@ -5768,7 +6439,11 @@ TRIO_ARGS5((self, target, characterclass, flags, width),
target[i] = (char)ch;
self->InStream(self, &ch);
}
-
+
+ if (i == 0)
+ return FALSE;
+
+ /* Terminate the string if input saved */
if (target)
target[i] = NIL;
return TRUE;
@@ -5781,6 +6456,7 @@ TRIO_ARGS5((self, target, characterclass, flags, width),
* add long double
* handle base
*/
+#if TRIO_FEATURE_FLOAT
TRIO_PRIVATE BOOLEAN_T
TrioReadDouble
TRIO_ARGS4((self, target, flags, width),
@@ -5791,10 +6467,13 @@ TRIO_ARGS4((self, target, flags, width),
{
int ch;
char doubleString[512];
- int index = 0;
+ int offset = 0;
int start;
+# if TRIO_FEATURE_QUOTE
int j;
+# endif
BOOLEAN_T isHex = FALSE;
+ trio_long_double_t infinity;
doubleString[0] = 0;
@@ -5811,55 +6490,48 @@ TRIO_ARGS4((self, target, flags, width),
ch = self->current;
if ((ch == '+') || (ch == '-'))
{
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
width--;
}
- start = index;
+ start = offset;
switch (ch)
{
case 'n':
case 'N':
/* Not-a-number */
- if (index != 0)
+ if (offset != 0)
break;
/* FALLTHROUGH */
case 'i':
case 'I':
/* Infinity */
- while (isalpha(ch) && (index - start < width))
+ while (isalpha(ch) && (offset - start < width))
{
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
}
- doubleString[index] = NIL;
+ doubleString[offset] = NIL;
/* Case insensitive string comparison */
if (trio_equal(&doubleString[start], INFINITE_UPPER) ||
trio_equal(&doubleString[start], LONG_INFINITE_UPPER))
{
+ infinity = ((start == 1) && (doubleString[0] == '-'))
+ ? trio_ninf()
+ : trio_pinf();
if (flags & FLAGS_LONGDOUBLE)
{
- if ((start == 1) && (doubleString[0] == '-'))
- {
- *((trio_long_double_t *)target) = trio_ninf();
- }
- else
- {
- *((trio_long_double_t *)target) = trio_pinf();
- }
+ *((trio_long_double_t *)target) = infinity;
+ }
+ else if (flags & FLAGS_LONG)
+ {
+ *((double *)target) = infinity;
}
else
{
- if ((start == 1) && (doubleString[0] == '-'))
- {
- *((double *)target) = trio_ninf();
- }
- else
- {
- *((double *)target) = trio_pinf();
- }
+ *((float *)target) = infinity;
}
return TRUE;
}
@@ -5870,21 +6542,25 @@ TRIO_ARGS4((self, target, flags, width),
{
*((trio_long_double_t *)target) = trio_nan();
}
- else
+ else if (flags & FLAGS_LONG)
{
*((double *)target) = trio_nan();
}
+ else
+ {
+ *((float *)target) = trio_nan();
+ }
return TRUE;
}
return FALSE;
case '0':
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
if (trio_to_upper(ch) == 'X')
{
isHex = TRUE;
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
}
break;
@@ -5893,14 +6569,15 @@ TRIO_ARGS4((self, target, flags, width),
break;
}
- while ((ch != EOF) && (index - start < width))
+ while ((ch != EOF) && (offset - start < width))
{
/* Integer part */
if (isHex ? isxdigit(ch) : isdigit(ch))
{
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
}
+# if TRIO_FEATURE_QUOTE
else if (flags & FLAGS_QUOTE)
{
/* Compare with thousands separator */
@@ -5916,53 +6593,59 @@ TRIO_ARGS4((self, target, flags, width),
else
continue; /* Match */
}
+# endif
else
break; /* while */
}
if (ch == '.')
{
/* Decimal part */
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
- (index - start < width))
+ (offset - start < width))
{
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
}
- if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
+ }
+ if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
+ {
+ /* Exponent */
+ doubleString[offset++] = (char)ch;
+ self->InStream(self, &ch);
+ if ((ch == '+') || (ch == '-'))
{
- /* Exponent */
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ while (isdigit(ch) && (offset - start < width))
+ {
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
- if ((ch == '+') || (ch == '-'))
- {
- doubleString[index++] = (char)ch;
- self->InStream(self, &ch);
- }
- while (isdigit(ch) && (index - start < width))
- {
- doubleString[index++] = (char)ch;
- self->InStream(self, &ch);
- }
}
}
- if ((index == start) || (*doubleString == NIL))
+ if ((offset == start) || (*doubleString == NIL))
return FALSE;
- doubleString[index] = 0;
+ doubleString[offset] = 0;
if (flags & FLAGS_LONGDOUBLE)
{
*((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL);
}
- else
+ else if (flags & FLAGS_LONG)
{
*((double *)target) = trio_to_double(doubleString, NULL);
}
+ else
+ {
+ *((float *)target) = trio_to_float(doubleString, NULL);
+ }
return TRUE;
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* TrioReadPointer
@@ -5985,12 +6668,18 @@ TRIO_ARGS3((self, target, flags),
POINTER_WIDTH,
BASE_HEX))
{
- /*
- * The strange assignment of number is a workaround for a compiler
- * warning
- */
if (target)
- *target = (char *)0 + number;
+ {
+#if defined(TRIO_COMPILER_GCC) || defined(TRIO_COMPILER_MIPSPRO)
+ /*
+ * The strange assignment of number is a workaround for a compiler
+ * warning
+ */
+ *target = &((char *)0)[number];
+#else
+ *target = (trio_pointer_t)number;
+#endif
+ }
return TRUE;
}
else if (TrioReadString(self,
@@ -5999,7 +6688,7 @@ TRIO_ARGS3((self, target, flags),
: buffer,
0,
sizeof(internalNullString) - 1))
- {
+ {
if (trio_equal_case(buffer, internalNullString))
{
if (target)
@@ -6020,330 +6709,364 @@ TRIO_ARGS3((data, format, parameters),
TRIO_CONST char *format,
trio_parameter_t *parameters)
{
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- int charlen;
- int cnt;
-#endif
+ int status;
int assignment;
int ch;
- int index; /* Index of format string */
- int i; /* Index of current parameter */
+ int offset; /* Offset of format string */
+ int i; /* Offset of current parameter */
trio_flags_t flags;
int width;
int base;
trio_pointer_t pointer;
+ /* Return on empty format string */
+ if (format[0] == NIL)
+ return 0;
+
+ status = 0;
assignment = 0;
i = 0;
- index = 0;
+ offset = 0;
data->InStream(data, &ch);
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- (void)mblen(NULL, 0);
-#endif
-
- while (format[index])
+ for (;;)
{
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- if (! isascii(format[index]))
+ /* Skip the parameter entries */
+ while (parameters[i].type == FORMAT_PARAMETER)
{
- charlen = mblen(&format[index], MB_LEN_MAX);
- if (charlen != -1)
- {
- /* Compare multibyte characters in format string */
- for (cnt = 0; cnt < charlen - 1; cnt++)
- {
- if (ch != format[index + cnt])
- {
- return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
- }
- data->InStream(data, &ch);
- }
- continue; /* while characters left in formatting string */
- }
- }
-#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
-
- if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
- {
- return (assignment > 0) ? assignment : EOF;
+ assert(i <= MAX_PARAMETERS);
+ i++;
}
-
- if (CHAR_IDENTIFIER == format[index])
+
+ /* Compare non conversion-specifier part of format string */
+ while (offset < parameters[i].beginOffset)
{
- if (CHAR_IDENTIFIER == format[index + 1])
+ if ((CHAR_IDENTIFIER == format[offset]) &&
+ (CHAR_IDENTIFIER == format[offset + 1]))
{
/* Two % in format matches one % in input stream */
if (CHAR_IDENTIFIER == ch)
{
data->InStream(data, &ch);
- index += 2;
+ offset += 2;
continue; /* while format chars left */
}
else
- return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ {
+ status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ goto end;
+ }
}
-
- /* Skip the parameter entries */
- while (parameters[i].type == FORMAT_PARAMETER)
- i++;
-
- flags = parameters[i].flags;
- /* Find width */
- width = parameters[i].width;
- if (flags & FLAGS_WIDTH_PARAMETER)
+ else /* Not an % identifier */
{
- /* Get width from parameter list */
- width = (int)parameters[width].data.number.as_signed;
+ if (isspace((int)format[offset]))
+ {
+ /* Whitespaces may match any amount of whitespaces */
+ ch = TrioSkipWhitespaces(data);
+ }
+ else if (ch == format[offset])
+ {
+ data->InStream(data, &ch);
+ }
+ else
+ {
+ status = assignment;
+ goto end;
+ }
+
+ offset++;
}
- /* Find base */
+ }
+
+ if (parameters[i].type == FORMAT_SENTINEL)
+ break;
+
+ if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
+ {
+ status = (assignment > 0) ? assignment : EOF;
+ goto end;
+ }
+
+ flags = parameters[i].flags;
+
+ /* Find width */
+ width = parameters[i].width;
+ if (flags & FLAGS_WIDTH_PARAMETER)
+ {
+ /* Get width from parameter list */
+ width = (int)parameters[width].data.number.as_signed;
+ }
+
+ /* Find base */
+ if (NO_BASE != parameters[i].baseSpecifier)
+ {
+ /* Base from specifier has priority */
+ base = parameters[i].baseSpecifier;
+ }
+ else if (flags & FLAGS_BASE_PARAMETER)
+ {
+ /* Get base from parameter list */
base = parameters[i].base;
- if (flags & FLAGS_BASE_PARAMETER)
- {
- /* Get base from parameter list */
- base = (int)parameters[base].data.number.as_signed;
- }
-
- switch (parameters[i].type)
- {
- case FORMAT_INT:
- {
- trio_uintmax_t number;
+ base = (int)parameters[base].data.number.as_signed;
+ }
+ else
+ {
+ /* Use base from format string */
+ base = parameters[i].base;
+ }
+
+ switch (parameters[i].type)
+ {
+ case FORMAT_INT:
+ {
+ trio_uintmax_t number;
- if (0 == base)
- base = BASE_DECIMAL;
+ if (0 == base)
+ base = BASE_DECIMAL;
- if (!TrioReadNumber(data,
- &number,
- flags,
- width,
- base))
- return assignment;
+ if (!TrioReadNumber(data,
+ &number,
+ flags,
+ width,
+ base))
+ {
+ status = assignment;
+ goto end;
+ }
- if (!(flags & FLAGS_IGNORE))
- {
- assignment++;
+ if (!(flags & FLAGS_IGNORE))
+ {
+ assignment++;
- 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
+ pointer = parameters[i].data.pointer;
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_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
+#if TRIO_FEATURE_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)
- *(trio_intmax_t *)pointer = (trio_intmax_t)number;
- else
+#if TRIO_FEATURE_INTMAX_T
+ if (flags & FLAGS_INTMAX_T)
+ *(trio_intmax_t *)pointer = (trio_intmax_t)number;
+ else
#endif
- if (flags & FLAGS_QUAD)
- *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
- 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;
- }
+ if (flags & FLAGS_QUAD)
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
+ 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 */
-
- case FORMAT_STRING:
-#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,
+ }
+ break; /* FORMAT_INT */
+
+ case FORMAT_STRING:
+#if TRIO_FEATURE_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ if (!TrioReadWideString(data,
(flags & FLAGS_IGNORE)
? NULL
- : parameters[i].data.string,
+ : parameters[i].data.wstring,
flags,
width))
- return assignment;
+ {
+ status = assignment;
+ goto end;
}
- if (!(flags & FLAGS_IGNORE))
- assignment++;
- break; /* FORMAT_STRING */
+ }
+ else
+#endif
+ {
+ if (!TrioReadString(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ flags,
+ width))
+ {
+ status = assignment;
+ goto end;
+ }
+ }
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ break; /* FORMAT_STRING */
- case FORMAT_DOUBLE:
+#if TRIO_FEATURE_FLOAT
+ case FORMAT_DOUBLE:
+ {
+ if (flags & FLAGS_IGNORE)
{
- trio_pointer_t pointer;
-
- 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 */
+ pointer = NULL;
}
- case FORMAT_GROUP:
+ else
{
- int characterclass[MAX_CHARACTER_CLASS + 1];
- int rc;
+ pointer = (flags & FLAGS_LONGDOUBLE)
+ ? (trio_pointer_t)parameters[i].data.longdoublePointer
+ : (trio_pointer_t)parameters[i].data.doublePointer;
+ }
+ if (!TrioReadDouble(data, pointer, flags, width))
+ {
+ status = assignment;
+ goto end;
+ }
+ if (!(flags & FLAGS_IGNORE))
+ {
+ assignment++;
+ }
+ break; /* FORMAT_DOUBLE */
+ }
+#endif
- /* Skip over modifiers */
- while (format[index] != SPECIFIER_GROUP)
- {
- index++;
- }
- /* Skip over group specifier */
- index++;
-
- memset(characterclass, 0, sizeof(characterclass));
- rc = TrioGetCharacterClass(format,
- &index,
+ case FORMAT_GROUP:
+ {
+ int characterclass[MAX_CHARACTER_CLASS + 1];
+
+ /* Skip over modifiers */
+ while (format[offset] != SPECIFIER_GROUP)
+ {
+ offset++;
+ }
+ /* Skip over group specifier */
+ offset++;
+
+ memset(characterclass, 0, sizeof(characterclass));
+ status = TrioGetCharacterClass(format,
+ &offset,
&flags,
characterclass);
- if (rc < 0)
- return rc;
-
- if (!TrioReadGroup(data,
- (flags & FLAGS_IGNORE)
- ? NULL
- : parameters[i].data.string,
- characterclass,
- flags,
- parameters[i].width))
- return assignment;
- if (!(flags & FLAGS_IGNORE))
- assignment++;
+ if (status < 0)
+ goto end;
+
+ if (!TrioReadGroup(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ characterclass,
+ flags,
+ parameters[i].width))
+ {
+ status = assignment;
+ goto end;
}
- break; /* FORMAT_GROUP */
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ }
+ break; /* FORMAT_GROUP */
- case FORMAT_COUNT:
- pointer = parameters[i].data.pointer;
- if (NULL != pointer)
- {
- int count = data->committed;
- if (ch != EOF)
- count--; /* a character is read, but is not consumed yet */
-#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
- if (flags & FLAGS_SIZE_T)
- *(size_t *)pointer = (size_t)count;
- else
+ case FORMAT_COUNT:
+ pointer = parameters[i].data.pointer;
+ if (NULL != pointer)
+ {
+ int count = data->processed;
+ if (ch != EOF)
+ count--; /* a character is read, but is not consumed yet */
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
+ if (flags & FLAGS_SIZE_T)
+ *(size_t *)pointer = (size_t)count;
+ else
#endif
-#if defined(QUALIFIER_PTRDIFF_T)
- if (flags & FLAGS_PTRDIFF_T)
- *(ptrdiff_t *)pointer = (ptrdiff_t)count;
- else
+#if TRIO_FEATURE_PTRDIFF_T
+ if (flags & FLAGS_PTRDIFF_T)
+ *(ptrdiff_t *)pointer = (ptrdiff_t)count;
+ else
#endif
-#if defined(QUALIFIER_INTMAX_T)
- if (flags & FLAGS_INTMAX_T)
- *(trio_intmax_t *)pointer = (trio_intmax_t)count;
- else
+#if TRIO_FEATURE_INTMAX_T
+ if (flags & FLAGS_INTMAX_T)
+ *(trio_intmax_t *)pointer = (trio_intmax_t)count;
+ else
#endif
- if (flags & FLAGS_QUAD)
- {
- *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
- }
- else if (flags & FLAGS_LONG)
- {
- *(long int *)pointer = (long int)count;
- }
- else if (flags & FLAGS_SHORT)
- {
- *(short int *)pointer = (short int)count;
- }
- else
- {
- *(int *)pointer = (int)count;
- }
+ if (flags & FLAGS_QUAD)
+ {
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
}
- break; /* FORMAT_COUNT */
-
- case FORMAT_CHAR:
-#if TRIO_WIDECHAR
- if (flags & FLAGS_WIDECHAR)
+ else if (flags & FLAGS_LONG)
+ {
+ *(long int *)pointer = (long int)count;
+ }
+ else if (flags & FLAGS_SHORT)
{
- if (TrioReadWideChar(data,
- (flags & FLAGS_IGNORE)
- ? NULL
- : parameters[i].data.wstring,
- flags,
- (width == NO_WIDTH) ? 1 : width) == 0)
- return assignment;
+ *(short int *)pointer = (short int)count;
}
else
-#endif
{
- if (TrioReadChar(data,
+ *(int *)pointer = (int)count;
+ }
+ }
+ break; /* FORMAT_COUNT */
+
+ case FORMAT_CHAR:
+#if TRIO_FEATURE_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ if (TrioReadWideChar(data,
(flags & FLAGS_IGNORE)
? NULL
- : parameters[i].data.string,
+ : parameters[i].data.wstring,
flags,
(width == NO_WIDTH) ? 1 : width) == 0)
- return assignment;
+ {
+ status = assignment;
+ goto end;
}
- if (!(flags & FLAGS_IGNORE))
- assignment++;
- break; /* FORMAT_CHAR */
-
- case FORMAT_POINTER:
- if (!TrioReadPointer(data,
- (flags & FLAGS_IGNORE)
- ? NULL
- : (trio_pointer_t *)parameters[i].data.pointer,
- flags))
- return assignment;
- if (!(flags & FLAGS_IGNORE))
- assignment++;
- break; /* FORMAT_POINTER */
-
- case FORMAT_PARAMETER:
- break; /* FORMAT_PARAMETER */
-
- 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]))
+ else
+#endif
{
- /* Whitespaces may match any amount of whitespaces */
- ch = TrioSkipWhitespaces(data);
+ if (TrioReadChar(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ flags,
+ (width == NO_WIDTH) ? 1 : width) == 0)
+ {
+ status = assignment;
+ goto end;
+ }
}
- else if (ch == format[index])
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ break; /* FORMAT_CHAR */
+
+ case FORMAT_POINTER:
+ if (!TrioReadPointer(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : (trio_pointer_t *)parameters[i].data.pointer,
+ flags))
{
- data->InStream(data, &ch);
+ status = assignment;
+ goto end;
}
- else
- return assignment;
-
- index++;
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ break; /* FORMAT_POINTER */
+
+ case FORMAT_PARAMETER:
+ break; /* FORMAT_PARAMETER */
+
+ default:
+ status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ goto end;
}
+
+ ch = data->current;
+ offset = parameters[i].endOffset;
+ i++;
}
- return assignment;
+
+ status = assignment;
+ end:
+ if (data->UndoStream)
+ data->UndoStream(data);
+ return status;
}
/*************************************************************************
@@ -6351,12 +7074,13 @@ TRIO_ARGS3((data, format, parameters),
*/
TRIO_PRIVATE int
TrioScan
-TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
+TRIO_ARGS7((source, sourceSize, InStream, UndoStream, format, arglist, argarray),
trio_pointer_t source,
size_t sourceSize,
void (*InStream) TRIO_PROTO((trio_class_t *, int *)),
+ void (*UndoStream) TRIO_PROTO((trio_class_t *)),
TRIO_CONST char *format,
- va_list *arglist,
+ va_list arglist,
trio_pointer_t *argarray)
{
int status;
@@ -6368,6 +7092,7 @@ TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
memset(&data, 0, sizeof(data));
data.InStream = InStream;
+ data.UndoStream = UndoStream;
data.location = (trio_pointer_t)source;
data.max = sourceSize;
data.error = 0;
@@ -6378,7 +7103,7 @@ TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
TrioSetLocale();
}
#endif
-
+
status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray);
if (status < 0)
return status;
@@ -6394,6 +7119,7 @@ TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
/*************************************************************************
* TrioInStreamFile
*/
+#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
TRIO_PRIVATE void
TrioInStreamFile
TRIO_ARGS2((self, intPointer),
@@ -6405,7 +7131,9 @@ TRIO_ARGS2((self, intPointer),
assert(VALID(self));
assert(VALID(file));
- self->current = fgetc(file);
+ self->actually.cached = 0;
+
+ /* The initial value of self->current is zero */
if (self->current == EOF)
{
self->error = (ferror(file))
@@ -6415,18 +7143,46 @@ TRIO_ARGS2((self, intPointer),
else
{
self->processed++;
- self->committed++;
+ self->actually.cached++;
}
-
+
+ self->current = fgetc(file);
+
if (VALID(intPointer))
{
*intPointer = self->current;
}
}
+#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
+
+/*************************************************************************
+ * TrioUndoStreamFile
+ */
+#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
+TRIO_PRIVATE void
+TrioUndoStreamFile
+TRIO_ARGS1((self),
+ trio_class_t *self)
+{
+ FILE *file = (FILE *)self->location;
+
+ assert(VALID(self));
+ assert(VALID(file));
+
+ if (self->actually.cached > 0)
+ {
+ assert(self->actually.cached == 1);
+
+ self->current = ungetc(self->current, file);
+ self->actually.cached = 0;
+ }
+}
+#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
/*************************************************************************
* TrioInStreamFileDescriptor
*/
+#if TRIO_FEATURE_FD
TRIO_PRIVATE void
TrioInStreamFileDescriptor
TRIO_ARGS2((self, intPointer),
@@ -6439,6 +7195,8 @@ TRIO_ARGS2((self, intPointer),
assert(VALID(self));
+ self->actually.cached = 0;
+
size = read(fd, &input, sizeof(char));
if (size == -1)
{
@@ -6451,19 +7209,21 @@ TRIO_ARGS2((self, intPointer),
}
if (self->current != EOF)
{
- self->committed++;
+ self->actually.cached++;
self->processed++;
}
-
+
if (VALID(intPointer))
{
*intPointer = self->current;
}
}
+#endif /* TRIO_FEATURE_FD */
/*************************************************************************
* TrioInStreamCustom
*/
+#if TRIO_FEATURE_CLOSURE
TRIO_PRIVATE void
TrioInStreamCustom
TRIO_ARGS2((self, intPointer),
@@ -6471,16 +7231,18 @@ TRIO_ARGS2((self, intPointer),
int *intPointer)
{
trio_custom_t *data;
-
+
assert(VALID(self));
assert(VALID(self->location));
+ self->actually.cached = 0;
+
data = (trio_custom_t *)self->location;
self->current = (data->stream.in == NULL)
? NIL
: (data->stream.in)(data->closure);
-
+
if (self->current == NIL)
{
self->current = EOF;
@@ -6488,14 +7250,15 @@ TRIO_ARGS2((self, intPointer),
else
{
self->processed++;
- self->committed++;
+ self->actually.cached++;
}
-
+
if (VALID(intPointer))
{
*intPointer = self->current;
}
}
+#endif /* TRIO_FEATURE_CLOSURE */
/*************************************************************************
* TrioInStreamString
@@ -6511,6 +7274,8 @@ TRIO_ARGS2((self, intPointer),
assert(VALID(self));
assert(VALID(self->location));
+ self->actually.cached = 0;
+
buffer = (unsigned char **)self->location;
self->current = (*buffer)[0];
if (self->current == NIL)
@@ -6521,9 +7286,9 @@ TRIO_ARGS2((self, intPointer),
{
(*buffer)++;
self->processed++;
- self->committed++;
+ self->actually.cached++;
}
-
+
if (VALID(intPointer))
{
*intPointer = self->current;
@@ -6554,6 +7319,7 @@ TRIO_ARGS2((self, intPointer),
@param ... Arguments.
@return Number of scanned characters.
*/
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_scanf
TRIO_VARGS2((format, va_alist),
@@ -6568,11 +7334,21 @@ TRIO_VARGS2((format, va_alist),
TRIO_VA_START(args, format);
status = TrioScan((trio_pointer_t)stdin, 0,
TrioInStreamFile,
- format, &args, NULL);
+ TrioUndoStreamFile,
+ format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_STDIO */
+
+/**
+ Scan characters from standard input stream.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_vscanf
TRIO_ARGS2((format, args),
@@ -6583,25 +7359,49 @@ TRIO_ARGS2((format, args),
return TrioScan((trio_pointer_t)stdin, 0,
TrioInStreamFile,
- format, &args, NULL);
+ TrioUndoStreamFile,
+ format, args, NULL);
}
+#endif /* TRIO_FEATURE_STDIO */
+
+/**
+ Scan characters from standard input stream.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_scanfv
TRIO_ARGS2((format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(format));
return TrioScan((trio_pointer_t)stdin, 0,
TrioInStreamFile,
- format, NULL, args);
+ TrioUndoStreamFile,
+ format, unused, args);
}
+#endif /* TRIO_FEATURE_STDIO */
/*************************************************************************
* fscanf
*/
+
+/**
+ Scan characters from file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_fscanf
TRIO_VARGS3((file, format, va_alist),
@@ -6618,11 +7418,22 @@ TRIO_VARGS3((file, format, va_alist),
TRIO_VA_START(args, format);
status = TrioScan((trio_pointer_t)file, 0,
TrioInStreamFile,
- format, &args, NULL);
+ TrioUndoStreamFile,
+ format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_FILE */
+/**
+ Scan characters from file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_vfscanf
TRIO_ARGS3((file, format, args),
@@ -6635,9 +7446,20 @@ TRIO_ARGS3((file, format, args),
return TrioScan((trio_pointer_t)file, 0,
TrioInStreamFile,
- format, &args, NULL);
+ TrioUndoStreamFile,
+ format, args, NULL);
}
+#endif /* TRIO_FEATURE_FILE */
+/**
+ Scan characters from file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_fscanfv
TRIO_ARGS3((file, format, args),
@@ -6645,17 +7467,31 @@ TRIO_ARGS3((file, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(file));
assert(VALID(format));
return TrioScan((trio_pointer_t)file, 0,
TrioInStreamFile,
- format, NULL, args);
+ TrioUndoStreamFile,
+ format, unused, args);
}
+#endif /* TRIO_FEATURE_FILE */
/*************************************************************************
* dscanf
*/
+
+/**
+ Scan characters from file descriptor.
+
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_dscanf
TRIO_VARGS3((fd, format, va_alist),
@@ -6671,11 +7507,22 @@ TRIO_VARGS3((fd, format, va_alist),
TRIO_VA_START(args, format);
status = TrioScan((trio_pointer_t)&fd, 0,
TrioInStreamFileDescriptor,
- format, &args, NULL);
+ NULL,
+ format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_FD */
+/**
+ Scan characters from file descriptor.
+
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_vdscanf
TRIO_ARGS3((fd, format, args),
@@ -6687,9 +7534,20 @@ TRIO_ARGS3((fd, format, args),
return TrioScan((trio_pointer_t)&fd, 0,
TrioInStreamFileDescriptor,
- format, &args, NULL);
+ NULL,
+ format, args, NULL);
}
+#endif /* TRIO_FEATURE_FD */
+
+/**
+ Scan characters from file descriptor.
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_dscanfv
TRIO_ARGS3((fd, format, args),
@@ -6697,16 +7555,21 @@ TRIO_ARGS3((fd, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(format));
return TrioScan((trio_pointer_t)&fd, 0,
TrioInStreamFileDescriptor,
- format, NULL, args);
+ NULL,
+ format, unused, args);
}
+#endif /* TRIO_FEATURE_FD */
/*************************************************************************
* cscanf
*/
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_cscanf
TRIO_VARGS4((stream, closure, format, va_alist),
@@ -6725,11 +7588,13 @@ TRIO_VARGS4((stream, closure, format, va_alist),
TRIO_VA_START(args, format);
data.stream.in = stream;
data.closure = closure;
- status = TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
+ status = TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_CLOSURE */
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_vcscanf
TRIO_ARGS4((stream, closure, format, args),
@@ -6745,9 +7610,11 @@ TRIO_ARGS4((stream, closure, format, args),
data.stream.in = stream;
data.closure = closure;
- return TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
+ return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL);
}
+#endif /* TRIO_FEATURE_CLOSURE */
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_cscanfv
TRIO_ARGS4((stream, closure, format, args),
@@ -6756,6 +7623,7 @@ TRIO_ARGS4((stream, closure, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
trio_custom_t data;
assert(VALID(stream));
@@ -6763,12 +7631,22 @@ TRIO_ARGS4((stream, closure, format, args),
data.stream.in = stream;
data.closure = closure;
- return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args);
+ return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, unused, args);
}
+#endif /* TRIO_FEATURE_CLOSURE */
/*************************************************************************
* sscanf
*/
+
+/**
+ Scan characters from string.
+
+ @param buffer Input string.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of scanned characters.
+ */
TRIO_PUBLIC int
trio_sscanf
TRIO_VARGS3((buffer, format, va_alist),
@@ -6785,11 +7663,20 @@ TRIO_VARGS3((buffer, format, va_alist),
TRIO_VA_START(args, format);
status = TrioScan((trio_pointer_t)&buffer, 0,
TrioInStreamString,
- format, &args, NULL);
+ NULL,
+ format, args, NULL);
TRIO_VA_END(args);
return status;
}
+/**
+ Scan characters from string.
+
+ @param buffer Input string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
TRIO_PUBLIC int
trio_vsscanf
TRIO_ARGS3((buffer, format, args),
@@ -6802,9 +7689,18 @@ TRIO_ARGS3((buffer, format, args),
return TrioScan((trio_pointer_t)&buffer, 0,
TrioInStreamString,
- format, &args, NULL);
+ NULL,
+ format, args, NULL);
}
+/**
+ Scan characters from string.
+
+ @param buffer Input string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
TRIO_PUBLIC int
trio_sscanfv
TRIO_ARGS3((buffer, format, args),
@@ -6812,14 +7708,19 @@ TRIO_ARGS3((buffer, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(buffer));
assert(VALID(format));
return TrioScan((trio_pointer_t)&buffer, 0,
TrioInStreamString,
- format, NULL, args);
+ NULL,
+ format, unused, args);
}
+#endif /* TRIO_FEATURE_SCANF */
+
/** @} End of Scanf documentation module */
/*************************************************************************
@@ -6830,6 +7731,7 @@ trio_strerror
TRIO_ARGS1((errorcode),
int errorcode)
{
+#if TRIO_FEATURE_STRERR
/* Textual versions of the error codes */
switch (TRIO_ERROR_CODE(errorcode))
{
@@ -6852,4 +7754,7 @@ TRIO_ARGS1((errorcode),
default:
return "Unknown";
}
+#else
+ return "Unknown";
+#endif
}