Upgraded to trio baseline 1.4
diff --git a/trio.c b/trio.c
index 241d6c2..ea772ba 100644
--- a/trio.c
+++ b/trio.c
@@ -27,7 +27,6 @@
/*
* TODO:
* - Scan is probably too permissive about its modifiers.
- * - Add hex-float to TrioReadDouble.
* - C escapes in %#[] ?
* - C99 support has not been properly tested.
* - Multibyte characters (done for format parsing, except scan groups)
@@ -39,130 +38,241 @@
* %as or %a[ it is interpreted as the alloc modifier, otherwise as
* the C99 hex-float. This means that you cannot scan %as as a hex-float
* immediately followed by an 's'.
+ * - Scanning of collating symbols.
*/
static const char rcsid[] = "@(#)$Id$";
-#if defined(unix) || defined(__xlC__) /* AIX xlC workaround */
-# define PLATFORM_UNIX
-#elif defined(AMIGA) && defined(__GNUC__)
-# define PLATFORM_UNIX
-#endif
-
/*************************************************************************
- * Include files
+ * Trio include files
*/
-
#include "trio.h"
#include "triop.h"
#include "strio.h"
-#if !defined(DEBUG) && !defined(NDEBUG)
-# define NDEBUG
-#endif
-#include <assert.h>
-#include <ctype.h>
-#include <math.h>
-#include <limits.h>
-#include <float.h>
-#include <stdarg.h>
-#include <errno.h>
-#if defined(TRIO_C99)
-# include <stdint.h>
-#endif
-#if defined(PLATFORM_UNIX)
-# include <unistd.h>
-# include <locale.h>
-# define USE_LOCALE
-#endif
-
-#if defined(_MSC_VER)
-#include <io.h>
-#define read _read
-#define write _write
-#endif /* _MSC_VER */
-
-/*************************************************************************
- * Generic definitions
- */
-
-#ifndef NULL
-# define NULL 0
-#endif
-#define NIL ((char)0)
-#ifdef __cplusplus
-# undef TRUE
-# undef FALSE
-# define TRUE true
-# define FALSE false
-# define BOOLEAN_T bool
-#else
-# ifndef FALSE
-# define FALSE (1 == 0)
-# define TRUE (! FALSE)
-# endif
-# define BOOLEAN_T int
-#endif
-
-/* mincore() can be used for debugging purposes */
-#define VALID(x) (NULL != (x))
-
/*
* Encode the error code and the position. This is decoded
* with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
*/
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
#else
# define TRIO_ERROR_RETURN(x,y) (-1)
#endif
-/*************************************************************************
- * Internal definitions
- */
-#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX)
-# define USE_MULTIBYTE
+/*************************************************************************
+ * Platform and compiler support detection
+ */
+#if defined(unix) || defined(__xlC__) || defined(_AIX) || defined(__QNX__)
+# define PLATFORM_UNIX
+#elif defined(AMIGA) && defined(__GNUC__)
+# define PLATFORM_UNIX
+#elif defined(WIN32) || defined(_WIN32) || defined(_MSC_VER)
+# define PLATFORM_WIN32
+# define TRIO_MSVC_5 1100
#endif
-#if !defined(USE_LONGLONG)
-# if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-# define USE_LONGLONG
-# elif defined(__SUNPRO_C)
-# define USE_LONGLONG
-# elif defined(_LONG_LONG) || defined(_LONGLONG)
-# define USE_LONGLONG
+#if defined(__STDC__) && defined(__STDC_VERSION__)
+# if (__STDC_VERSION__ >= 199409L)
+# define TRIO_COMPILER_SUPPORTS_ISO94
+# endif
+# if (__STDC_VERSION__ >= 199901L)
+# define TRIO_COMPILER_SUPPORTS_C99
+# endif
+#endif
+
+#if defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)
+# define TRIO_COMPILER_SUPPORTS_UNIX98
+#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
+# endif
+#endif
+
+
+/*************************************************************************
+ * Generic definitions
+ */
+
+#if !(defined(DEBUG) || defined(NDEBUG))
+# define NDEBUG
+#endif
+#include <assert.h>
+#include <ctype.h>
+#if !defined(TRIO_COMPILER_SUPPORTS_C99)
+# define isblank(x) (((x)==32) || ((x)==9))
+#endif
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <errno.h>
+
+#ifndef NULL
+# define NULL 0
+#endif
+#define NIL ((char)0)
+#ifndef FALSE
+# define FALSE (1 == 0)
+# define TRUE (! FALSE)
+#endif
+#define BOOLEAN_T int
+
+/* mincore() can be used for debugging purposes */
+#define VALID(x) (NULL != (x))
+
+/* xlC crashes on log10(0) */
+#define guarded_log10(x) (((x) == 0.0) ? -HUGE_VAL : log10(x))
+#define guarded_log16(x) (guarded_log10(x) / log10(16.0))
+
+
+/*************************************************************************
+ * Platform specific definitions
+ */
+#if defined(PLATFORM_UNIX)
+# include <unistd.h>
+# include <signal.h>
+# include <locale.h>
+# define USE_LOCALE
+#endif /* PLATFORM_UNIX */
+#if defined(PLATFORM_WIN32)
+# include <io.h>
+# define read _read
+# define write _write
+#endif /* PLATFORM_WIN32 */
+
+#if TRIO_WIDECHAR
+# if defined(TRIO_COMPILER_SUPPORTS_ISO94)
+# include <wchar.h>
+# include <wctype.h>
+# else
+typedef char wchar_t;
+typedef int 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)
+# define iswlower(x) islower(x)
+# define iswprint(x) isprint(x)
+# define iswpunct(x) ispunct(x)
+# define iswspace(x) isspace(x)
+# define iswupper(x) isupper(x)
+# define iswxdigit(x) isxdigit(x)
+# endif
+#endif
+
+
+/*************************************************************************
+ * Compiler dependent definitions
+ */
+
+/* Support for long long */
+#ifndef __cplusplus
+# if !defined(USE_LONGLONG)
+# if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+# define USE_LONGLONG
+# elif defined(__SUNPRO_C)
+# define USE_LONGLONG
+# elif defined(_LONG_LONG) || defined(_LONGLONG)
+# define USE_LONGLONG
+# endif
# endif
#endif
/* The extra long numbers */
#if defined(USE_LONGLONG)
-# define LONGLONG long long
-# define ULONGLONG unsigned long long
+typedef signed long long int trio_longlong_t;
+typedef unsigned long long int trio_ulonglong_t;
+#elif defined(_MSC_VER)
+# if (_MSC_VER >= TRIO_MSVC_5)
+typedef signed __int64 trio_longlong_t;
+typedef unsigned __int64 trio_ulonglong_t;
+# else
+typedef signed long int trio_longlong_t;
+typedef unsigned long int trio_ulonglong_t;
+# endif
#else
-# define LONGLONG long
-# define ULONGLONG unsigned long
+typedef signed long int trio_longlong_t;
+typedef unsigned long int trio_ulonglong_t;
#endif
-/* The longest possible integer */
-#if defined(TRIO_C99)
-# define LONGEST uintmax_t
-# define SLONGEST intmax_t
+/* Maximal and fixed integer types */
+#if defined(TRIO_COMPILER_SUPPORTS_C99)
+# include <stdint.h>
+typedef intmax_t trio_intmax_t;
+typedef uintmax_t trio_uintmax_t;
+typedef int8_t trio_int8_t;
+typedef int16_t trio_int16_t;
+typedef int32_t trio_int32_t;
+typedef int64_t trio_int64_t;
+#elif defined(TRIO_COMPILER_SUPPORTS_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(_MSC_VER) && (_MSC_VER >= TRIO_MSVC_5)
+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
-# define LONGEST ULONGLONG
-# define SLONGEST LONGLONG
+typedef trio_longlong_t trio_intmax_t;
+typedef trio_ulonglong_t trio_uintmax_t;
+# if defined(TRIO_INT8_T)
+typedef TRIO_INT8_T trio_int8_t;
+# else
+typedef signed char trio_int8_t;
+# endif
+# if defined(TRIO_INT16_T)
+typedef TRIO_INT16_T trio_int16_t;
+# else
+typedef signed short trio_int16_t;
+# endif
+# if defined(TRIO_INT32_T)
+typedef TRIO_INT32_T trio_int32_t;
+# else
+typedef signed int trio_int32_t;
+# endif
+# if defined(TRIO_INT64_T)
+typedef TRIO_INT64_T trio_int64_t;
+# else
+typedef trio_longlong_t trio_int64_t;
+# endif
#endif
-/* The maximal number of digits are for base 2 */
-#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT + 1)
+
+/*************************************************************************
+ * Internal definitions
+ */
+
+/* Long double sizes */
+#ifdef LDBL_DIG
+# define MAX_MANTISSA_DIGITS LDBL_DIG
+# define MAX_EXPONENT_DIGITS 4
+#else
+# define MAX_MANTISSA_DIGITS DBL_DIG
+# define MAX_EXPONENT_DIGITS 3
+#endif
+
+/* 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(void *) * CHAR_BIT / 4)
/* Infinite and Not-A-Number for floating-point */
-#define USE_NON_NUMBERS
-#ifndef NAN
-# define NAN (cos(HUGE_VAL))
-#endif
#define INFINITE_LOWER "inf"
#define INFINITE_UPPER "INF"
#define LONG_INFINITE_LOWER "infinite"
@@ -206,12 +316,14 @@
FLAGS_ALLOC = 2 * FLAGS_WIDECHAR,
FLAGS_IGNORE = 2 * FLAGS_ALLOC,
FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE,
- FLAGS_SIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER,
+ FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER,
+ FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER,
/* Reused flags */
FLAGS_EXCLUDE = FLAGS_SHORT,
FLAGS_USER_DEFINED = FLAGS_IGNORE,
/* Compounded flags */
FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
+ FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT,
NO_POSITION = -1,
NO_WIDTH = 0,
@@ -236,7 +348,7 @@
MAX_USER_DATA = 256,
/* Maximal length of locale separator strings */
- MAX_LOCALE_SEPARATOR_LENGTH = 64,
+ MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX,
/* Maximal number of integers in grouping */
MAX_LOCALE_GROUPS = 64
};
@@ -253,10 +365,10 @@
#define FORMAT_COUNT 6
#define FORMAT_PARAMETER 7
#define FORMAT_GROUP 8
-#if defined(TRIO_GNU)
+#if TRIO_GNU
# define FORMAT_ERRNO 9
#endif
-#if defined(TRIO_EXTENSION)
+#if TRIO_EXTENSION
# define FORMAT_USER_DEFINED 10
#endif
@@ -300,7 +412,7 @@
* o Octal
* p Pointer
* s String
- * S Widechar string (wchar_t)
+ * S Widechar string (wchar_t *)
* u Unsigned
* x Hex
* X Hex
@@ -329,18 +441,18 @@
#define SPECIFIER_GROUP '['
#define SPECIFIER_UNGROUP ']'
#define SPECIFIER_COUNT 'n'
-#if defined(TRIO_UNIX98)
+#if TRIO_UNIX98
# define SPECIFIER_CHAR_UPPER 'C'
# define SPECIFIER_STRING_UPPER 'S'
#endif
-#if defined(TRIO_C99)
+#if TRIO_C99
# define SPECIFIER_HEXFLOAT 'a'
# define SPECIFIER_HEXFLOAT_UPPER 'A'
#endif
-#if defined(TRIO_GNU)
+#if TRIO_GNU
# define SPECIFIER_ERRNO 'm'
#endif
-#if defined(TRIO_EXTENSION)
+#if TRIO_EXTENSION
# define SPECIFIER_BINARY 'b'
# define SPECIFIER_BINARY_UPPER 'B'
# define SPECIFIER_USER_DEFINED_BEGIN '<'
@@ -428,6 +540,14 @@
*
* ! Sticky
* @ Parameter (for both print and scan)
+ *
+ * I n-bit Integer
+ * Numbers:
+ * The following options exists
+ * I8 = 8-bit integer
+ * I16 = 16-bit integer
+ * I32 = 32-bit integer
+ * I64 = 64-bit integer
*/
#define QUALIFIER_POSITION '$'
#define QUALIFIER_SHORT 'h'
@@ -440,26 +560,30 @@
#define QUALIFIER_DOT '.'
#define QUALIFIER_STAR '*'
#define QUALIFIER_CIRCUMFLEX '^'
-#if defined(TRIO_C99)
+#if TRIO_C99
# define QUALIFIER_SIZE_T 'z'
# define QUALIFIER_PTRDIFF_T 't'
# define QUALIFIER_INTMAX_T 'j'
#endif
-#if defined(TRIO_BSD) || defined(TRIO_GNU)
+#if TRIO_BSD || TRIO_GNU
# define QUALIFIER_QUAD 'q'
#endif
-#if defined(TRIO_GNU)
+#if TRIO_GNU
# define QUALIFIER_SIZE_T_UPPER 'Z'
#endif
-#if defined(TRIO_MISC)
+#if TRIO_MISC
# define QUALIFIER_WIDECHAR 'w'
#endif
-#if defined(TRIO_EXTENSION)
+#if TRIO_MICROSOFT
+# define QUALIFIER_FIXED_SIZE 'I'
+#endif
+#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 */
#endif
@@ -478,10 +602,13 @@
int indexAfterSpecifier;
union {
char *string;
+#if TRIO_WIDECHAR
+ wchar_t *wstring;
+#endif
void *pointer;
union {
- SLONGEST as_signed;
- LONGEST as_unsigned;
+ trio_uintmax_t as_signed;
+ trio_intmax_t as_unsigned;
} number;
double doubleNumber;
double *doublePointer;
@@ -496,7 +623,7 @@
/* General trio "class" */
typedef struct _trio_T {
- const void *location;
+ void *location;
void (*OutStream)(struct _trio_T *, int);
void (*InStream)(struct _trio_T *, int *);
/*
@@ -545,16 +672,22 @@
* UNIX98 says "in a locale where the radix character is not defined,
* the radix character defaults to a period (.)"
*/
-static char internalDecimalPoint[MAX_LOCALE_SEPARATOR_LENGTH] = ".";
-static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH] = ",";
+static char internalDecimalPoint[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
+static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
static const char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static const char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-static userdef_T *internalUserDef = NULL;
static BOOLEAN_T internalDigitsUnconverted = TRUE;
static int internalDigitArray[128];
+#if TRIO_EXTENSION
+static BOOLEAN_T internalCollationUnconverted = TRUE;
+static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
+#endif
+static volatile trio_callback_t internalEnterCriticalRegion = NULL;
+static volatile trio_callback_t internalLeaveCriticalRegion = NULL;
+static userdef_T *internalUserDef = NULL;
/*************************************************************************
@@ -639,6 +772,9 @@
#if defined(QUALIFIER_PARAM)
case QUALIFIER_PARAM:
#endif
+#if defined(QUALIFIER_FIXED_SIZE)
+ case QUALIFIER_FIXED_SIZE:
+#endif
return TRUE;
default:
return FALSE;
@@ -646,6 +782,33 @@
}
/*************************************************************************
+ * TrioGenerateNan [private]
+ *
+ * Calculating NaN portably is difficult. Some compilers will emit
+ * warnings about divide by zero, and others will simply fail to
+ * generate a NaN.
+ */
+static double
+TrioGenerateNaN(void)
+{
+#if defined(TRIO_COMPILER_SUPPORTS_C99)
+ return nan(NULL);
+#elif defined(DBL_QNAN)
+ return DBL_QNAN;
+#elif defined(PLATFORM_UNIX)
+ double value;
+ void (*signal_handler)(int);
+
+ signal_handler = signal(SIGFPE, SIG_IGN);
+ value = 0.0 / 0.0;
+ signal(SIGFPE, signal_handler);
+ return value;
+#else
+ return 0.0 / 0.0;
+#endif
+}
+
+/*************************************************************************
* TrioIsNan [private]
*/
static int
@@ -688,23 +851,29 @@
TrioSetLocale(void)
{
internalLocaleValues = (struct lconv *)localeconv();
- if (StrLength(internalLocaleValues->decimal_point) > 0)
+ if (internalLocaleValues)
{
- StrCopyMax(internalDecimalPoint,
- sizeof(internalDecimalPoint),
- internalLocaleValues->decimal_point);
- }
- if (StrLength(internalLocaleValues->thousands_sep) > 0)
- {
- StrCopyMax(internalThousandSeparator,
- sizeof(internalThousandSeparator),
- internalLocaleValues->thousands_sep);
- }
- if (StrLength(internalLocaleValues->grouping) > 0)
- {
- StrCopyMax(internalGrouping,
- sizeof(internalGrouping),
- internalLocaleValues->grouping);
+ if ((internalLocaleValues->decimal_point) &&
+ (internalLocaleValues->decimal_point[0] != NIL))
+ {
+ StrCopyMax(internalDecimalPoint,
+ sizeof(internalDecimalPoint),
+ internalLocaleValues->decimal_point);
+ }
+ if ((internalLocaleValues->thousands_sep) &&
+ (internalLocaleValues->thousands_sep[0] != NIL))
+ {
+ StrCopyMax(internalThousandSeparator,
+ sizeof(internalThousandSeparator),
+ internalLocaleValues->thousands_sep);
+ }
+ if ((internalLocaleValues->grouping) &&
+ (internalLocaleValues->grouping[0] != NIL))
+ {
+ StrCopyMax(internalGrouping,
+ sizeof(internalGrouping),
+ internalLocaleValues->grouping);
+ }
}
}
#endif /* defined(USE_LOCALE) */
@@ -747,15 +916,22 @@
{
userdef_T *def;
+ if (internalEnterCriticalRegion)
+ (void)internalEnterCriticalRegion(NULL);
+
for (def = internalUserDef; def; def = def->next)
{
/* Case-sensitive string comparison */
if (StrEqualCase(def->name, name))
- return def;
+ break;
if (prev)
*prev = def;
}
+
+ if (internalLeaveCriticalRegion)
+ (void)internalLeaveCriticalRegion(NULL);
+
return def;
}
@@ -772,7 +948,7 @@
va_list arglist,
void **argarray)
{
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
/* Count the number of times a parameter is referenced */
unsigned short usedEntries[MAX_PARAMETERS];
#endif
@@ -804,7 +980,7 @@
char *tmpformat;
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
/*
* The 'parameters' array is not initialized, but we need to
* know which entries we have used.
@@ -814,13 +990,13 @@
index = 0;
parameterPosition = 0;
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
mblen(NULL, 0);
#endif
while (format[index])
{
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
if (! isascii(format[index]))
{
/*
@@ -831,7 +1007,7 @@
index += (charlen > 0) ? charlen : 1;
continue; /* while */
}
-#endif /* defined(USE_MULTIBYTE) */
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
if (CHAR_IDENTIFIER == format[index++])
{
if (CHAR_IDENTIFIER == format[index])
@@ -1058,7 +1234,7 @@
case QUALIFIER_SIZE_T:
flags |= FLAGS_SIZE_T;
/* Modify flags for later truncation of number */
- if (sizeof(size_t) == sizeof(ULONGLONG))
+ if (sizeof(size_t) == sizeof(trio_ulonglong_t))
flags |= FLAGS_QUAD;
else if (sizeof(size_t) == sizeof(long))
flags |= FLAGS_LONG;
@@ -1068,7 +1244,7 @@
#if defined(QUALIFIER_PTRDIFF_T)
case QUALIFIER_PTRDIFF_T:
flags |= FLAGS_PTRDIFF_T;
- if (sizeof(ptrdiff_t) == sizeof(ULONGLONG))
+ if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
flags |= FLAGS_QUAD;
else if (sizeof(ptrdiff_t) == sizeof(long))
flags |= FLAGS_LONG;
@@ -1078,9 +1254,9 @@
#if defined(QUALIFIER_INTMAX_T)
case QUALIFIER_INTMAX_T:
flags |= FLAGS_INTMAX_T;
- if (sizeof(intmax_t) == sizeof(ULONGLONG))
+ if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
flags |= FLAGS_QUAD;
- else if (sizeof(intmax_t) == sizeof(long))
+ else if (sizeof(trio_intmax_t) == sizeof(long))
flags |= FLAGS_LONG;
break;
#endif
@@ -1091,6 +1267,45 @@
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;
@@ -1117,7 +1332,7 @@
#if defined(QUALIFIER_VARSIZE)
case QUALIFIER_VARSIZE:
- flags |= FLAGS_SIZE_PARAMETER;
+ flags |= FLAGS_VARSIZE_PARAMETER;
parameterPosition++;
if (positional)
varsize = parameterPosition;
@@ -1143,7 +1358,7 @@
*/
if (flags & FLAGS_WIDTH_PARAMETER)
{
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
usedEntries[width] += 1;
#endif
parameters[pos].type = FORMAT_PARAMETER;
@@ -1152,7 +1367,7 @@
}
if (flags & FLAGS_PRECISION_PARAMETER)
{
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
usedEntries[precision] += 1;
#endif
parameters[pos].type = FORMAT_PARAMETER;
@@ -1161,16 +1376,16 @@
}
if (flags & FLAGS_BASE_PARAMETER)
{
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
usedEntries[base] += 1;
#endif
parameters[pos].type = FORMAT_PARAMETER;
indices[base] = pos;
base = pos++;
}
- if (flags & FLAGS_SIZE_PARAMETER)
+ if (flags & FLAGS_VARSIZE_PARAMETER)
{
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
usedEntries[varsize] += 1;
#endif
parameters[pos].type = FORMAT_PARAMETER;
@@ -1184,30 +1399,57 @@
{
#if defined(SPECIFIER_CHAR_UPPER)
case SPECIFIER_CHAR_UPPER:
- flags |= FLAGS_LONG;
+ 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;
#if defined(SPECIFIER_STRING_UPPER)
case SPECIFIER_STRING_UPPER:
- flags |= FLAGS_LONG;
+ flags |= FLAGS_WIDECHAR;
/* FALLTHROUGH */
#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;
- while (format[index])
+ 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_UNGROUP)
- break; /* while */
+ if (format[index] == SPECIFIER_GROUP)
+ {
+ depth++;
+ }
+ else if (format[index] == SPECIFIER_UNGROUP)
+ {
+ if (--depth <= 0)
+ {
+ index++;
+ break;
+ }
+ }
+ index++;
}
}
break;
@@ -1328,7 +1570,7 @@
parameters[pos].flags = FLAGS_USER_DEFINED;
/* Adjust parameters for insertion of new one */
pos++;
-# if defined(TRIO_ERRORS)
+# if TRIO_ERRORS
usedEntries[currentParam] += 1;
# endif
parameters[pos].type = FORMAT_USER_DEFINED;
@@ -1370,7 +1612,7 @@
return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
}
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
/* Count the number of times this entry has been used */
usedEntries[currentParam] += 1;
#endif
@@ -1415,7 +1657,7 @@
for (num = 0; num <= maxParam; num++)
{
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
if (usedEntries[num] != 1)
{
if (usedEntries[num] == 0) /* gap detected */
@@ -1460,16 +1702,27 @@
{
case FORMAT_GROUP:
case FORMAT_STRING:
- parameters[i].data.string = (arglist != NULL)
- ? va_arg(arglist, char *)
- : (char *)(argarray[num]);
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ parameters[i].data.wstring = (argarray == NULL)
+ ? va_arg(arglist, wchar_t *)
+ : (wchar_t *)(argarray[num]);
+ }
+ else
+#endif
+ {
+ parameters[i].data.string = (argarray == NULL)
+ ? va_arg(arglist, char *)
+ : (char *)(argarray[num]);
+ }
break;
case FORMAT_POINTER:
case FORMAT_COUNT:
case FORMAT_USER_DEFINED:
case FORMAT_UNKNOWN:
- parameters[i].data.pointer = (arglist != NULL)
+ parameters[i].data.pointer = (argarray == NULL)
? va_arg(arglist, void *)
: argarray[num];
break;
@@ -1478,44 +1731,54 @@
case FORMAT_INT:
if (TYPE_SCAN == type)
{
- if (arglist != NULL)
+ if (argarray == NULL)
parameters[i].data.pointer =
- (LONGEST *)va_arg(arglist, void *);
+ (trio_uintmax_t *)va_arg(arglist, void *);
else
{
if (parameters[i].type == FORMAT_CHAR)
parameters[i].data.pointer =
- (LONGEST *)((char *)argarray[num]);
+ (trio_uintmax_t *)((char *)argarray[num]);
else if (parameters[i].flags & FLAGS_SHORT)
parameters[i].data.pointer =
- (LONGEST *)((short *)argarray[num]);
+ (trio_uintmax_t *)((short *)argarray[num]);
else
parameters[i].data.pointer =
- (LONGEST *)((int *)argarray[num]);
+ (trio_uintmax_t *)((int *)argarray[num]);
}
}
else
{
-#if defined(QUALIFIER_VARSIZE)
- if (parameters[i].flags & FLAGS_SIZE_PARAMETER)
+#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
+ if ((parameters[i].flags & FLAGS_VARSIZE_PARAMETER) ||
+ (parameters[i].flags & FLAGS_FIXED_SIZE))
{
- /*
- * Variable sizes are mapped onto the fixed sizes, in
- * accordance with integer promotion.
- *
- * Please note that this may not be portable, as we
- * only guess the size, not the layout of the numbers.
- * For example, if int is little-endian, and long is
- * big-endian, then this will fail.
- */
+ if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
+ {
+ /*
+ * Variable sizes are mapped onto the fixed sizes, in
+ * accordance with integer promotion.
+ *
+ * Please note that this may not be portable, as we
+ * only guess the size, not the layout of the numbers.
+ * For example, if int is little-endian, and long is
+ * big-endian, then this will fail.
+ */
+ varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
+ }
+ else
+ {
+ /* Used for the I<bits> modifiers */
+ varsize = parameters[i].varsize;
+ }
parameters[i].flags &= ~FLAGS_ALL_VARSIZES;
- varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
+
if (varsize <= (int)sizeof(int))
;
else if (varsize <= (int)sizeof(long))
parameters[i].flags |= FLAGS_LONG;
#if defined(QUALIFIER_INTMAX_T)
- else if (varsize <= (int)sizeof(LONGLONG))
+ else if (varsize <= (int)sizeof(trio_longlong_t))
parameters[i].flags |= FLAGS_QUAD;
else
parameters[i].flags |= FLAGS_INTMAX_T;
@@ -1527,45 +1790,45 @@
#endif /* defined(QUALIFIER_VARSIZE) */
#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
if (parameters[i].flags & FLAGS_SIZE_T)
- parameters[i].data.number.as_unsigned = (arglist != NULL)
- ? (LONGEST)va_arg(arglist, size_t)
- : (LONGEST)(*((size_t *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(arglist, size_t)
+ : (trio_uintmax_t)(*((size_t *)argarray[num]));
else
#endif
#if defined(QUALIFIER_PTRDIFF_T)
if (parameters[i].flags & FLAGS_PTRDIFF_T)
- parameters[i].data.number.as_unsigned = (arglist != NULL)
- ? (LONGEST)va_arg(arglist, ptrdiff_t)
- : (LONGEST)(*((ptrdiff_t *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t)
+ : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
else
#endif
#if defined(QUALIFIER_INTMAX_T)
if (parameters[i].flags & FLAGS_INTMAX_T)
- parameters[i].data.number.as_unsigned = (arglist != NULL)
- ? (LONGEST)va_arg(arglist, intmax_t)
- : (LONGEST)(*((intmax_t *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (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 = (arglist != NULL)
- ? (LONGEST)va_arg(arglist, ULONGLONG)
- : (LONGEST)(*((ULONGLONG *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (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 = (arglist != NULL)
- ? (LONGEST)va_arg(arglist, long)
- : (LONGEST)(*((long *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(arglist, long)
+ : (trio_uintmax_t)(*((long *)argarray[num]));
else
{
- if (arglist != NULL)
- parameters[i].data.number.as_unsigned = (LONGEST)va_arg(arglist, int);
+ if (argarray == NULL)
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int);
else
{
if (parameters[i].type == FORMAT_CHAR)
- parameters[i].data.number.as_unsigned = (LONGEST)(*((char *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num]));
else if (parameters[i].flags & FLAGS_SHORT)
- parameters[i].data.number.as_unsigned = (LONGEST)(*((short *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num]));
else
- parameters[i].data.number.as_unsigned = (LONGEST)(*((int *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num]));
}
}
}
@@ -1577,25 +1840,25 @@
* whereas the rest (width, precision, base) uses an integer.
*/
if (parameters[i].flags & FLAGS_USER_DEFINED)
- parameters[i].data.pointer = (arglist != NULL)
+ parameters[i].data.pointer = (argarray == NULL)
? va_arg(arglist, void *)
: argarray[num];
else
- parameters[i].data.number.as_unsigned = (arglist != NULL)
- ? (LONGEST)va_arg(arglist, int)
- : (LONGEST)(*((int *)argarray[num]));
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(arglist, int)
+ : (trio_uintmax_t)(*((int *)argarray[num]));
break;
case FORMAT_DOUBLE:
if (TYPE_SCAN == type)
{
if (parameters[i].flags & FLAGS_LONG)
- parameters[i].data.longdoublePointer = (arglist != NULL)
+ parameters[i].data.longdoublePointer = (argarray == NULL)
? va_arg(arglist, long double *)
: (long double *)((long double *)argarray[num]);
else
{
- if (arglist != NULL)
+ if (argarray == NULL)
parameters[i].data.doublePointer =
va_arg(arglist, double *);
else
@@ -1612,12 +1875,12 @@
else
{
if (parameters[i].flags & FLAGS_LONG)
- parameters[i].data.longdoubleNumber = (arglist != NULL)
+ parameters[i].data.longdoubleNumber = (argarray == NULL)
? va_arg(arglist, long double)
: (long double)(*((long double *)argarray[num]));
else
{
- if (arglist != NULL)
+ if (argarray == NULL)
parameters[i].data.longdoubleNumber = (long double)va_arg(arglist, double);
else
{
@@ -1661,16 +1924,14 @@
*/
static void
TrioWriteNumber(trio_T *self,
- SLONGEST number,
+ trio_uintmax_t number,
unsigned long flags,
int width,
int precision,
int base)
{
BOOLEAN_T isNegative;
- char buffer[MAX_CHARS_IN(LONGEST)
- * MAX_LOCALE_SEPARATOR_LENGTH
- * MAX_LOCALE_GROUPS];
+ char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
char *bufferend;
char *pointer;
const char *digits;
@@ -1687,13 +1948,14 @@
digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
- if (flags & FLAGS_UNSIGNED)
- isNegative = FALSE;
- else if ((isNegative = (((SLONGEST)number) < 0)))
+ isNegative = (flags & FLAGS_UNSIGNED)
+ ? FALSE
+ : ((trio_intmax_t)number < 0);
+ if (isNegative)
number = -number;
if (flags & FLAGS_QUAD)
- number &= (ULONGLONG)-1;
+ number &= (trio_ulonglong_t)-1;
else if (flags & FLAGS_LONG)
number &= (unsigned long)-1;
else
@@ -1841,6 +2103,60 @@
}
/*************************************************************************
+ * TrioWriteStringCharacter [private]
+ *
+ * Description:
+ * Output a single character of a string
+ */
+static void
+TrioWriteStringCharacter(trio_T *self,
+ int ch,
+ unsigned long flags)
+{
+ if (flags & FLAGS_ALTERNATIVE)
+ {
+ if (! (isprint(ch) || isspace(ch)))
+ {
+ /*
+ * Non-printable characters are converted to C escapes or
+ * \number, if no C escape exists.
+ */
+ self->OutStream(self, CHAR_BACKSLASH);
+ switch (ch)
+ {
+ case '\007': self->OutStream(self, 'a'); break;
+ case '\b': self->OutStream(self, 'b'); break;
+ case '\f': self->OutStream(self, 'f'); break;
+ case '\n': self->OutStream(self, 'n'); break;
+ case '\r': self->OutStream(self, 'r'); break;
+ case '\t': self->OutStream(self, 't'); break;
+ case '\v': self->OutStream(self, 'v'); break;
+ case '\\': self->OutStream(self, '\\'); break;
+ default:
+ self->OutStream(self, 'x');
+ TrioWriteNumber(self, (trio_intmax_t)ch,
+ FLAGS_UNSIGNED | FLAGS_NILPADDING,
+ 2, 2, BASE_HEX);
+ break;
+ }
+ }
+ else if (ch == CHAR_BACKSLASH)
+ {
+ self->OutStream(self, CHAR_BACKSLASH);
+ self->OutStream(self, CHAR_BACKSLASH);
+ }
+ else
+ {
+ self->OutStream(self, ch);
+ }
+ }
+ else
+ {
+ self->OutStream(self, ch);
+ }
+}
+
+/*************************************************************************
* TrioWriteString [private]
*
* Description:
@@ -1890,48 +2206,8 @@
while (length-- > 0)
{
/* The ctype parameters must be an unsigned char (or EOF) */
- ch = (unsigned char)(*string++);
- if (flags & FLAGS_ALTERNATIVE)
- {
- if (! (isprint(ch) || isspace(ch)))
- {
- /*
- * Non-printable characters are converted to C escapes or
- * \number, if no C escape exists.
- */
- self->OutStream(self, CHAR_BACKSLASH);
- switch (ch)
- {
- case '\a': self->OutStream(self, 'a'); break;
- case '\b': self->OutStream(self, 'b'); break;
- case '\f': self->OutStream(self, 'f'); break;
- case '\n': self->OutStream(self, 'n'); break;
- case '\r': self->OutStream(self, 'r'); break;
- case '\t': self->OutStream(self, 't'); break;
- case '\v': self->OutStream(self, 'v'); break;
- case '\\': self->OutStream(self, '\\'); break;
- default:
- self->OutStream(self, 'x');
- TrioWriteNumber(self, (SLONGEST)ch,
- FLAGS_UNSIGNED | FLAGS_NILPADDING,
- 2, 2, BASE_HEX);
- break;
- }
- }
- else if (ch == CHAR_BACKSLASH)
- {
- self->OutStream(self, CHAR_BACKSLASH);
- self->OutStream(self, CHAR_BACKSLASH);
- }
- else
- {
- self->OutStream(self, ch);
- }
- }
- else
- {
- self->OutStream(self, ch);
- }
+ ch = (int)((unsigned char)(*string++));
+ TrioWriteStringCharacter(self, ch, flags);
}
if (flags & FLAGS_LEFTADJUST)
@@ -1944,6 +2220,111 @@
}
/*************************************************************************
+ * TrioWriteWideStringCharacter [private]
+ *
+ * Description:
+ * Output a wide string as a multi-byte sequence
+ */
+#if TRIO_WIDECHAR
+static int
+TrioWriteWideStringCharacter(trio_T *self,
+ wchar_t wch,
+ unsigned long flags,
+ int width)
+{
+ int size;
+ int i;
+ int ch;
+ char *string;
+ char buffer[MB_LEN_MAX + 1];
+
+ if (width == NO_WIDTH)
+ width = sizeof(buffer);
+
+ size = wctomb(buffer, wch);
+ if ((size <= 0) || (size > width) || (buffer[0] == NIL))
+ return 0;
+
+ string = buffer;
+ i = size;
+ while ((width >= i) && (width-- > 0) && (i-- > 0))
+ {
+ /* The ctype parameters must be an unsigned char (or EOF) */
+ ch = (int)((unsigned char)(*string++));
+ TrioWriteStringCharacter(self, ch, flags);
+ }
+ return size;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
+ * TrioWriteString [private]
+ *
+ * Description:
+ * Output a wide character string as a multi-byte string
+ */
+#if TRIO_WIDECHAR
+static void
+TrioWriteWideString(trio_T *self,
+ const wchar_t *wstring,
+ unsigned long flags,
+ int width,
+ int precision)
+{
+ int length;
+ int size;
+
+ assert(VALID(self));
+ assert(VALID(self->OutStream));
+
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ mblen(NULL, 0);
+#endif
+
+ if (wstring == NULL)
+ {
+ TrioWriteString(self, NULL, flags, width, precision);
+ return;
+ }
+
+ if (NO_PRECISION == precision)
+ {
+ length = INT_MAX;
+ }
+ else
+ {
+ length = precision;
+ width -= length;
+ }
+
+ if (flags & FLAGS_QUOTE)
+ self->OutStream(self, CHAR_QUOTE);
+
+ if (! (flags & FLAGS_LEFTADJUST))
+ {
+ while (width-- > 0)
+ self->OutStream(self, CHAR_ADJUST);
+ }
+
+ while (length > 0)
+ {
+ size = TrioWriteWideStringCharacter(self, *wstring++, flags, length);
+ if (size == 0)
+ break; /* while */
+ length -= size;
+ }
+
+ if (flags & FLAGS_LEFTADJUST)
+ {
+ while (width-- > 0)
+ self->OutStream(self, CHAR_ADJUST);
+ }
+ if (flags & FLAGS_QUOTE)
+ self->OutStream(self, CHAR_QUOTE);
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
* TrioWriteDouble [private]
*/
static void
@@ -1957,7 +2338,6 @@
int charsPerThousand;
int length;
double number;
- double precisionPower;
double workNumber;
int integerDigits;
int fractionDigits;
@@ -1970,18 +2350,16 @@
BOOLEAN_T isExponentNegative = FALSE;
BOOLEAN_T isHex;
const char *digits;
- char numberBuffer[MAX_CHARS_IN(double)
- * MAX_LOCALE_SEPARATOR_LENGTH
- * MAX_LOCALE_GROUPS];
+ char numberBuffer[MAX_MANTISSA_DIGITS
+ * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
char *numberPointer;
- char exponentBuffer[MAX_CHARS_IN(double)];
+ char exponentBuffer[MAX_EXPONENT_DIGITS + 1];
char *exponentPointer = NULL;
int groupingIndex;
char *work;
int i;
BOOLEAN_T onlyzero;
-
- int set_precision = precision;
+ int zeroes = 0;
assert(VALID(self));
assert(VALID(self->OutStream));
@@ -1989,7 +2367,6 @@
number = (double)longdoubleNumber;
-#if defined(USE_NON_NUMBERS)
/* Look for infinite numbers and non-a-number first */
switch (TrioIsInfinite(number))
{
@@ -2024,7 +2401,6 @@
flags, width, precision);
return;
}
-#endif /* defined(USE_NON_NUMBERS) */
/* Normal numbers */
digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
@@ -2033,26 +2409,39 @@
if (precision == NO_PRECISION)
precision = FLT_DIG;
- precisionPower = pow(10.0, (double)precision);
isNegative = (number < 0.0);
if (isNegative)
number = -number;
-
+
if ((flags & FLAGS_FLOAT_G) || isHex)
{
- if ((number < 1.0e-4) || (number > precisionPower))
- flags |= FLAGS_FLOAT_E;
-#if defined(TRIO_UNIX98)
if (precision == 0)
precision = 1;
-#endif
+
+ if ((number < 1.0e-4) || (number > pow(10.0, (double)precision)))
+ {
+ /* Use scientific notation */
+ flags |= FLAGS_FLOAT_E;
+ }
+ else if (number < 1.0)
+ {
+ /*
+ * Use normal notation. If the integer part of the number is
+ * zero, then adjust the precision to include leading fractional
+ * zeros.
+ */
+ workNumber = fabs(guarded_log10(number));
+ if (workNumber - floor(workNumber) < 0.001)
+ workNumber--;
+ zeroes = (int)floor(workNumber);
+ }
}
if (flags & FLAGS_FLOAT_E)
{
/* Scale the number */
- workNumber = log10(number);
+ workNumber = guarded_log10(number);
if (workNumber == -HUGE_VAL)
{
exponent = 0;
@@ -2078,16 +2467,30 @@
* and number of fractional digits for others
*/
integerDigits = (floor(number) > DBL_EPSILON)
- ? 1 + (int)log10(floor(number))
+ ? 1 + (int)guarded_log10(floor(number))
: 1;
- fractionDigits = (flags & FLAGS_FLOAT_G)
+ fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
? precision - integerDigits
- : precision;
- number = floor(0.5 + number * pow(10.0, (double)fractionDigits));
- if ((int)log10(number) + 1 > integerDigits + fractionDigits)
+ : zeroes + precision;
+
+ number = floor(0.5 + number * pow(dblBase, (double)fractionDigits));
+ workNumber = (isHex
+ ? guarded_log16(0.5 + number)
+ : guarded_log10(0.5 + number));
+ if ((int)workNumber + 1 > integerDigits + fractionDigits)
{
- /* Adjust if number was rounded up one digit (ie. 99 to 100) */
- integerDigits++;
+ if (flags & FLAGS_FLOAT_E)
+ {
+ /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
+ exponent--;
+ uExponent -= (isExponentNegative) ? 1 : -1;
+ number /= dblBase;
+ }
+ else
+ {
+ /* Adjust if number was rounded up one digit (ie. 99 to 100) */
+ integerDigits++;
+ }
}
/* Build the fraction part */
@@ -2099,13 +2502,14 @@
*(--numberPointer) = digits[(int)fmod(number, dblBase)];
number = floor(number / dblBase);
- if((set_precision == NO_PRECISION) || (flags & FLAGS_ALTERNATIVE)) {
- /* Prune trailing zeroes */
- if (numberPointer[0] != digits[0])
- onlyzero = FALSE;
- else if (onlyzero && (numberPointer[0] == digits[0]))
- numberPointer++;
- }
+ if ((flags & FLAGS_FLOAT_G) && !(flags & FLAGS_ALTERNATIVE))
+ {
+ /* Prune trailing zeroes */
+ if (numberPointer[0] != digits[0])
+ onlyzero = FALSE;
+ else if (onlyzero && (numberPointer[0] == digits[0]))
+ numberPointer++;
+ }
else
onlyzero = FALSE;
}
@@ -2188,9 +2592,8 @@
if (isNegative || (flags & FLAGS_SHOWSIGN))
expectedWidth += sizeof("-") - 1;
if (exponentDigits > 0)
- expectedWidth += exponentDigits + sizeof("E+") - 1;
- if (isExponentNegative)
- expectedWidth += sizeof('-') - 1;
+ expectedWidth += exponentDigits +
+ ((exponentDigits > 1) ? sizeof("E+") : sizeof("E+0")) - 1;
if (isHex)
expectedWidth += sizeof("0X") - 1;
@@ -2248,6 +2651,11 @@
? ((flags & FLAGS_UPPER) ? 'P' : 'p')
: ((flags & FLAGS_UPPER) ? 'E' : 'e'));
self->OutStream(self, (isExponentNegative) ? '-' : '+');
+
+ /* The exponent must contain at least two digits */
+ if (exponentDigits == 1)
+ self->OutStream(self, '0');
+
for (i = 0; i < exponentDigits; i++)
{
self->OutStream(self, exponentPointer[i + 1]);
@@ -2272,7 +2680,7 @@
parameter_T *parameters)
{
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
int charlen;
#endif
int i;
@@ -2286,13 +2694,13 @@
index = 0;
i = 0;
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
mblen(NULL, 0);
#endif
while (format[index])
{
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
if (! isascii(format[index]))
{
charlen = mblen(&format[index], MB_LEN_MAX);
@@ -2302,7 +2710,7 @@
}
continue; /* while */
}
-#endif /* defined(USE_MULTIBYTE) */
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
if (CHAR_IDENTIFIER == format[index])
{
if (CHAR_IDENTIFIER == format[index + 1])
@@ -2359,9 +2767,19 @@
while (--width > 0)
data->OutStream(data, CHAR_ADJUST);
}
-
- data->OutStream(data,
- (char)parameters[i].data.number.as_signed);
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ TrioWriteWideStringCharacter(data,
+ (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)
{
@@ -2396,11 +2814,24 @@
break; /* FORMAT_DOUBLE */
case FORMAT_STRING:
- TrioWriteString(data,
- parameters[i].data.string,
- flags,
- width,
- precision);
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ TrioWriteWideString(data,
+ parameters[i].data.wstring,
+ flags,
+ width,
+ precision);
+ }
+ else
+#endif
+ {
+ TrioWriteString(data,
+ parameters[i].data.string,
+ flags,
+ width,
+ precision);
+ }
break; /* FORMAT_STRING */
case FORMAT_POINTER:
@@ -2434,12 +2865,12 @@
#endif
#if defined(QUALIFIER_INTMAX_T)
if (flags & FLAGS_INTMAX_T)
- *(intmax_t *)pointer = (intmax_t)data->committed;
+ *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
else
#endif
if (flags & FLAGS_QUAD)
{
- *(ULONGLONG int *)pointer = (ULONGLONG)data->committed;
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
}
else if (flags & FLAGS_LONG)
{
@@ -2474,7 +2905,7 @@
{
data->OutStream(data, '#');
TrioWriteNumber(data,
- (SLONGEST)parameters[i].data.errorNumber,
+ (trio_intmax_t)parameters[i].data.errorNumber,
flags,
width,
precision,
@@ -2566,7 +2997,6 @@
assert(VALID(OutStream));
assert(VALID(format));
- assert(VALID(arglist) || VALID(argarray));
memset(&data, 0, sizeof(data));
data.OutStream = OutStream;
@@ -2686,7 +3116,7 @@
if (infop->buffer == NULL)
{
/* Start with a reasonable size */
- infop->buffer = (char *)malloc(DYNAMIC_START_SIZE);
+ infop->buffer = (char *)TRIO_MALLOC(DYNAMIC_START_SIZE);
if (infop->buffer == NULL)
return; /* fail */
@@ -2699,7 +3129,7 @@
char *newptr;
/* Allocate increasing chunks */
- newptr = (char *)realloc(infop->buffer, infop->allocated * 2);
+ newptr = (char *)TRIO_REALLOC(infop->buffer, infop->allocated * 2);
if (newptr == NULL)
return;
@@ -2708,7 +3138,7 @@
infop->allocated *= 2;
}
- infop->buffer[self->committed] = output;
+ infop->buffer[self->committed] = (char)output;
self->committed++;
self->processed++;
@@ -2738,7 +3168,6 @@
va_list args)
{
assert(VALID(format));
- assert(VALID(args));
return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
}
@@ -2747,10 +3176,11 @@
trio_printfv(const char *format,
void ** args)
{
+ va_list dummy;
+
assert(VALID(format));
- assert(VALID(args));
- return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
+ return TrioFormat(stdout, 0, TrioOutStreamFile, format, dummy, args);
}
/*************************************************************************
@@ -2780,7 +3210,6 @@
{
assert(VALID(file));
assert(VALID(format));
- assert(VALID(args));
return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
}
@@ -2790,11 +3219,12 @@
const char *format,
void ** args)
{
+ va_list dummy;
+
assert(VALID(file));
assert(VALID(format));
- assert(VALID(args));
- return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
+ return TrioFormat(file, 0, TrioOutStreamFile, format, dummy, args);
}
/*************************************************************************
@@ -2822,7 +3252,6 @@
va_list args)
{
assert(VALID(format));
- assert(VALID(args));
return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
}
@@ -2832,10 +3261,11 @@
const char *format,
void **args)
{
- assert(VALID(format));
- assert(VALID(args));
+ va_list dummy;
- return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
+ assert(VALID(format));
+
+ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, dummy, args);
}
/*************************************************************************
@@ -2868,7 +3298,6 @@
assert(VALID(buffer));
assert(VALID(format));
- assert(VALID(args));
status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
*buffer = NIL;
@@ -2881,12 +3310,12 @@
void **args)
{
int status;
+ va_list dummy;
assert(VALID(buffer));
assert(VALID(format));
- assert(VALID(args));
- status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, dummy, args);
*buffer = NIL;
return status;
}
@@ -2925,7 +3354,6 @@
assert(VALID(buffer));
assert(VALID(format));
- assert(VALID(args));
status = TrioFormat(&buffer, bufferSize > 0 ? bufferSize - 1 : 0,
TrioOutStreamStringMax, format, args, NULL);
@@ -2941,13 +3369,13 @@
void **args)
{
int status;
+ va_list dummy;
assert(VALID(buffer));
assert(VALID(format));
- assert(VALID(args));
status = TrioFormat(&buffer, bufferSize > 0 ? bufferSize - 1 : 0,
- TrioOutStreamStringMax, format, NULL, args);
+ TrioOutStreamStringMax, format, dummy, args);
if (bufferSize > 0)
*buffer = NIL;
return status;
@@ -2993,7 +3421,6 @@
size_t buf_len;
assert(VALID(buffer));
assert(VALID(format));
- assert(VALID(args));
buf_len = strlen(buffer);
buffer = &buffer[buf_len];
@@ -3040,7 +3467,6 @@
struct dynamicBuffer info;
assert(VALID(format));
- assert(VALID(args));
info.buffer = NULL;
info.length = 0;
@@ -3083,7 +3509,7 @@
* no memory has been allocated, but we must to allocate and return an
* empty string.
*/
- info.buffer = (char *)malloc(sizeof(char));
+ info.buffer = (char *)TRIO_MALLOC(sizeof(char));
if (info.buffer == NULL) {
*result = NULL;
return TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
@@ -3104,7 +3530,6 @@
struct dynamicBuffer info;
assert(VALID(format));
- assert(VALID(args));
info.buffer = NULL;
info.length = 0;
@@ -3116,7 +3541,7 @@
return status;
}
if (info.length == 0) {
- info.buffer = (char *)malloc(sizeof(char));
+ info.buffer = (char *)TRIO_MALLOC(sizeof(char));
if (info.buffer == NULL) {
*result = NULL;
return TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
@@ -3151,6 +3576,20 @@
if (name)
{
+ /* Handle built-in namespaces */
+ if (name[0] == ':')
+ {
+ if (StrEqual(name, ":enter"))
+ {
+ internalEnterCriticalRegion = callback;
+ }
+ else if (StrEqual(name, ":leave"))
+ {
+ internalLeaveCriticalRegion = callback;
+ }
+ return NULL;
+ }
+
/* Bail out if namespace is too long */
if (StrLength(name) >= MAX_USER_NAME)
return NULL;
@@ -3161,9 +3600,12 @@
return NULL;
}
- def = (userdef_T *)malloc(sizeof(userdef_T));
+ def = (userdef_T *)TRIO_MALLOC(sizeof(userdef_T));
if (def)
{
+ if (internalEnterCriticalRegion)
+ (void)internalEnterCriticalRegion(NULL);
+
if (name)
{
/* Link into internal list */
@@ -3178,6 +3620,9 @@
? NULL
: StrDuplicate(name);
def->next = NULL;
+
+ if (internalLeaveCriticalRegion)
+ (void)internalLeaveCriticalRegion(NULL);
}
return def;
}
@@ -3199,14 +3644,20 @@
def = TrioFindNamespace(self->name, &prev);
if (def)
{
+ if (internalEnterCriticalRegion)
+ (void)internalEnterCriticalRegion(NULL);
+
if (prev == NULL)
internalUserDef = NULL;
else
prev->next = def->next;
+
+ if (internalLeaveCriticalRegion)
+ (void)internalLeaveCriticalRegion(NULL);
}
StrFree(self->name);
}
- free(self);
+ TRIO_FREE(self);
}
/*************************************************************************
@@ -3510,7 +3961,7 @@
/*************************************************************************
* trio_get_largest / trio_set_largest [public]
*/
-#if defined(TRIO_C99)
+#if TRIO_C99
int
trio_get_largest(void *ref)
{
@@ -3531,7 +3982,6 @@
/*************************************************************************
* trio_get_ptrdiff / trio_set_ptrdiff [public]
*/
-#if defined(TRIO_C99)
int
trio_get_ptrdiff(void *ref)
{
@@ -3547,12 +3997,11 @@
else
((reference_T *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
}
-#endif
/*************************************************************************
* trio_get_size / trio_set_size [public]
*/
-#if defined(TRIO_C99)
+#if TRIO_C99
int
trio_get_size(void *ref)
{
@@ -3580,7 +4029,7 @@
reference_T *self = (reference_T *)ref;
TrioWriteNumber(self->data,
- (SLONGEST)number,
+ (trio_intmax_t)number,
self->parameter->flags,
self->parameter->width,
self->parameter->precision,
@@ -3597,7 +4046,7 @@
reference_T *self = (reference_T *)ref;
TrioWriteNumber(self->data,
- (SLONGEST)number,
+ (trio_intmax_t)number,
self->parameter->flags | FLAGS_UNSIGNED,
self->parameter->width,
self->parameter->precision,
@@ -3646,7 +4095,7 @@
{
reference_T *self = (reference_T *)ref;
unsigned long flags;
- LONGLONG number;
+ trio_uintmax_t number;
if (NULL == pointer)
{
@@ -3663,14 +4112,14 @@
* optimising compiler). The (char *) casting is done
* to please ANSI C++.
*/
- number = (ULONGLONG)((char *)pointer - (char *)0);
+ number = (trio_uintmax_t)((char *)pointer - (char *)0);
/* Shrink to size of pointer */
- number &= (ULONGLONG)-1;
+ number &= (trio_uintmax_t)-1;
flags = self->parameter->flags;
flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE |
FLAGS_NILPADDING);
TrioWriteNumber(self->data,
- number,
+ (trio_intmax_t)number,
flags,
POINTER_WIDTH,
NO_PRECISION,
@@ -3718,9 +4167,11 @@
const char *format,
void **argarray)
{
+ va_list dummy;
+
assert(VALID(format));
- return TrioFormatRef((reference_T *)ref, format, NULL, argarray);
+ return TrioFormatRef((reference_T *)ref, format, dummy, argarray);
}
@@ -3748,6 +4199,37 @@
}
/*************************************************************************
+ * TrioGetCollation [private]
+ */
+#if TRIO_EXTENSION
+static void
+TrioGetCollation()
+{
+ int i;
+ int j;
+ int k;
+ char first[2];
+ char second[2];
+
+ /* This is computational expensive */
+ first[1] = NIL;
+ second[1] = NIL;
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ {
+ k = 0;
+ first[0] = (char)i;
+ for (j = 0; j < MAX_CHARACTER_CLASS; j++)
+ {
+ second[0] = (char)j;
+ if (StrEqualLocale(first, second))
+ internalCollationArray[i][k++] = (char)j;
+ }
+ internalCollationArray[i][k] = NIL;
+ }
+}
+#endif
+
+/*************************************************************************
* TrioGetCharacterClass [private]
*
* FIXME:
@@ -3756,7 +4238,7 @@
static int
TrioGetCharacterClass(const char *format,
int *indexPointer,
- int *flagsPointer,
+ unsigned long *flagsPointer,
int *characterclass)
{
int index = *indexPointer;
@@ -3793,7 +4275,7 @@
}
/* Collect characters */
for (ch = format[index];
- ch != SPECIFIER_UNGROUP && ch != NIL;
+ (ch != SPECIFIER_UNGROUP) && (ch != NIL);
ch = format[++index])
{
switch (ch)
@@ -3832,103 +4314,170 @@
ch = range_end;
break;
-
- case QUALIFIER_COLON: /* Character class expressions */
- if (StrEqualMax(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
- &format[index]))
+#if TRIO_EXTENSION
+
+ case SPECIFIER_GROUP:
+
+ switch (format[index + 1])
{
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (isalnum(i))
- characterclass[i]++;
- index += sizeof(CLASS_ALNUM) - 1;
- }
- else if (StrEqualMax(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (isalpha(i))
- characterclass[i]++;
- index += sizeof(CLASS_ALPHA) - 1;
- }
- else if (StrEqualMax(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (iscntrl(i))
- characterclass[i]++;
- index += sizeof(CLASS_CNTRL) - 1;
- }
- else if (StrEqualMax(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (isdigit(i))
- characterclass[i]++;
- index += sizeof(CLASS_DIGIT) - 1;
- }
- else if (StrEqualMax(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (isgraph(i))
- characterclass[i]++;
- index += sizeof(CLASS_GRAPH) - 1;
- }
- else if (StrEqualMax(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (islower(i))
- characterclass[i]++;
- index += sizeof(CLASS_LOWER) - 1;
- }
- else if (StrEqualMax(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (isprint(i))
- characterclass[i]++;
- index += sizeof(CLASS_PRINT) - 1;
- }
- else if (StrEqualMax(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (ispunct(i))
- characterclass[i]++;
- index += sizeof(CLASS_PUNCT) - 1;
- }
- else if (StrEqualMax(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (isspace(i))
- characterclass[i]++;
- index += sizeof(CLASS_SPACE) - 1;
- }
- else if (StrEqualMax(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (isupper(i))
- characterclass[i]++;
- index += sizeof(CLASS_UPPER) - 1;
- }
- else if (StrEqualMax(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
- &format[index]))
- {
- for (i = 0; i < MAX_CHARACTER_CLASS; i++)
- if (isxdigit(i))
- characterclass[i]++;
- index += sizeof(CLASS_XDIGIT) - 1;
- }
- else
- {
+ case QUALIFIER_DOT: /* Collating symbol */
+ /*
+ * FIXME: This will be easier to implement when multibyte
+ * characters have been implemented. Until now, we ignore
+ * this feature.
+ */
+ for (i = index + 2; ; i++)
+ {
+ if (format[i] == NIL)
+ /* Error in syntax */
+ return -1;
+ else if (format[i] == QUALIFIER_DOT)
+ break; /* for */
+ }
+ if (format[++i] != SPECIFIER_UNGROUP)
+ return -1;
+
+ index = i;
+ break;
+
+ case QUALIFIER_EQUAL: /* Equivalence class expressions */
+ {
+ unsigned int j;
+ unsigned int k;
+
+ if (internalCollationUnconverted)
+ {
+ /* Lazy evalutation of collation array */
+ TrioGetCollation();
+ internalCollationUnconverted = FALSE;
+ }
+ for (i = index + 2; ; i++)
+ {
+ if (format[i] == NIL)
+ /* Error in syntax */
+ return -1;
+ else if (format[i] == QUALIFIER_EQUAL)
+ break; /* for */
+ else
+ {
+ /* Mark any equivalent character */
+ k = (unsigned int)format[i];
+ for (j = 0; internalCollationArray[k][j] != NIL; j++)
+ characterclass[(int)internalCollationArray[k][j]]++;
+ }
+ }
+ if (format[++i] != SPECIFIER_UNGROUP)
+ return -1;
+
+ index = i;
+ }
+ break;
+
+ case QUALIFIER_COLON: /* Character class expressions */
+
+ if (StrEqualMax(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isalnum(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_ALNUM) - 1;
+ }
+ else if (StrEqualMax(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isalpha(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_ALPHA) - 1;
+ }
+ else if (StrEqualMax(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (iscntrl(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_CNTRL) - 1;
+ }
+ else if (StrEqualMax(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isdigit(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_DIGIT) - 1;
+ }
+ else if (StrEqualMax(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isgraph(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_GRAPH) - 1;
+ }
+ else if (StrEqualMax(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (islower(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_LOWER) - 1;
+ }
+ else if (StrEqualMax(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isprint(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_PRINT) - 1;
+ }
+ else if (StrEqualMax(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (ispunct(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_PUNCT) - 1;
+ }
+ else if (StrEqualMax(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isspace(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_SPACE) - 1;
+ }
+ else if (StrEqualMax(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isupper(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_UPPER) - 1;
+ }
+ else if (StrEqualMax(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isxdigit(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_XDIGIT) - 1;
+ }
+ else
+ {
+ characterclass[(int)ch]++;
+ }
+ break;
+
+ default:
characterclass[(int)ch]++;
+ break;
}
break;
-
+
+#endif /* TRIO_EXTENSION */
+
default:
characterclass[(int)ch]++;
break;
@@ -3945,12 +4494,12 @@
*/
static BOOLEAN_T
TrioReadNumber(trio_T *self,
- LONGEST *target,
- int flags,
+ trio_uintmax_t *target,
+ unsigned long flags,
int width,
int base)
{
- LONGEST number = 0;
+ trio_uintmax_t number = 0;
int digit;
int count;
BOOLEAN_T isNegative = FALSE;
@@ -3960,6 +4509,18 @@
assert(VALID(self->InStream));
assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE));
+ if (internalDigitsUnconverted)
+ {
+ /* Lazy evaluation of digits array */
+ memset(internalDigitArray, -1, sizeof(internalDigitArray));
+ for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++)
+ {
+ internalDigitArray[(int)internalDigitsLower[j]] = j;
+ internalDigitArray[(int)internalDigitsUpper[j]] = j;
+ }
+ internalDigitsUnconverted = FALSE;
+ }
+
TrioSkipWhitespaces(self);
if (!(flags & FLAGS_UNSIGNED))
@@ -4057,12 +4618,15 @@
/*************************************************************************
* TrioReadChar [private]
*/
-static BOOLEAN_T
+static int
TrioReadChar(trio_T *self,
char *target,
+ unsigned long flags,
int width)
{
int i;
+ char ch;
+ trio_uintmax_t number;
assert(VALID(self));
assert(VALID(self->InStream));
@@ -4071,11 +4635,48 @@
(self->current != EOF) && (i < width);
i++)
{
- if (target)
- target[i] = self->current;
+ ch = (char)self->current;
self->InStream(self, NULL);
+ if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH))
+ {
+ switch (self->current)
+ {
+ case '\\': ch = '\\'; break;
+ case 'a': ch = '\007'; break;
+ case 'b': ch = '\b'; break;
+ case 'f': ch = '\f'; break;
+ case 'n': ch = '\n'; break;
+ case 'r': ch = '\r'; break;
+ case 't': ch = '\t'; break;
+ case 'v': ch = '\v'; break;
+ default:
+ if (isdigit(self->current))
+ {
+ /* Read octal number */
+ if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL))
+ return 0;
+ ch = (char)number;
+ }
+ else if (toupper(self->current) == 'X')
+ {
+ /* Read hexadecimal number */
+ self->InStream(self, NULL);
+ if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX))
+ return 0;
+ ch = (char)number;
+ }
+ else
+ {
+ ch = (char)self->current;
+ }
+ break;
+ }
+ }
+
+ if (target)
+ target[i] = ch;
}
- return TRUE;
+ return i + 1;
}
/*************************************************************************
@@ -4084,12 +4685,10 @@
static BOOLEAN_T
TrioReadString(trio_T *self,
char *target,
- int flags,
+ unsigned long flags,
int width)
{
int i;
- char ch;
- LONGEST number;
assert(VALID(self));
assert(VALID(self->InStream));
@@ -4105,46 +4704,8 @@
(! ((self->current == EOF) || isspace(self->current)));
i++)
{
- ch = self->current;
- if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH))
- {
- self->InStream(self, NULL);
- switch (self->current)
- {
- case '\\': ch = '\\'; break;
- case 'a': ch = '\a'; break;
- case 'b': ch = '\b'; break;
- case 'f': ch = '\f'; break;
- case 'n': ch = '\n'; break;
- case 'r': ch = '\r'; break;
- case 't': ch = '\t'; break;
- case 'v': ch = '\v'; break;
- default:
- if (isdigit(self->current))
- {
- /* Read octal number */
- if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL))
- return FALSE;
- ch = (char)number;
- }
- else if (toupper(self->current) == 'X')
- {
- /* Read hexadecimal number */
- self->InStream(self, NULL);
- if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX))
- return FALSE;
- ch = (char)number;
- }
- else
- {
- ch = self->current;
- }
- break;
- }
- }
- if (target)
- target[i] = ch;
- self->InStream(self, NULL);
+ if (TrioReadChar(self, &target[i], flags, 1) == 0)
+ break; /* for */
}
if (target)
target[i] = NIL;
@@ -4152,6 +4713,108 @@
}
/*************************************************************************
+ * TrioReadWideChar [private]
+ */
+#if TRIO_WIDECHAR
+static int
+TrioReadWideChar(trio_T *self,
+ wchar_t *target,
+ unsigned long flags,
+ int width)
+{
+ int i;
+ int j;
+ int size;
+ int amount = 0;
+ wchar_t wch;
+ char buffer[MB_LEN_MAX + 1];
+
+ assert(VALID(self));
+ assert(VALID(self->InStream));
+
+ for (i = 0;
+ (self->current != EOF) && (i < width);
+ i++)
+ {
+ if (isascii(self->current))
+ {
+ if (TrioReadChar(self, buffer, flags, 1) == 0)
+ return 0;
+ buffer[1] = NIL;
+ }
+ else
+ {
+ /*
+ * Collect a multibyte character, by enlarging buffer until
+ * it contains a fully legal multibyte character, or the
+ * buffer is full.
+ */
+ j = 0;
+ do
+ {
+ buffer[j++] = (char)self->current;
+ buffer[j] = NIL;
+ self->InStream(self, NULL);
+ }
+ while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j));
+ }
+ if (target)
+ {
+ size = mbtowc(&wch, buffer, sizeof(buffer));
+ if (size > 0)
+ target[i] = wch;
+ }
+ amount += size;
+ self->InStream(self, NULL);
+ }
+ return amount;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
+ * TrioReadWideString [private]
+ */
+#if TRIO_WIDECHAR
+static BOOLEAN_T
+TrioReadWideString(trio_T *self,
+ wchar_t *target,
+ unsigned long flags,
+ int width)
+{
+ int i;
+ int size;
+
+ assert(VALID(self));
+ assert(VALID(self->InStream));
+
+ TrioSkipWhitespaces(self);
+
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ mblen(NULL, 0);
+#endif
+
+ /*
+ * Continue until end of string is reached, a whitespace is encountered,
+ * or width is exceeded
+ */
+ for (i = 0;
+ ((width == NO_WIDTH) || (i < width)) &&
+ (! ((self->current == EOF) || isspace(self->current)));
+ )
+ {
+ size = TrioReadWideChar(self, &target[i], flags, 1);
+ if (size == 0)
+ break; /* for */
+
+ i += size;
+ }
+ if (target)
+ target[i] = L'\0';
+ return TRUE;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
* TrioReadGroup [private]
*
* FIXME: characterclass does not work with multibyte characters
@@ -4160,7 +4823,7 @@
TrioReadGroup(trio_T *self,
char *target,
int *characterclass,
- int flags,
+ unsigned long flags,
int width)
{
int ch;
@@ -4190,13 +4853,12 @@
* TrioReadDouble [private]
*
* FIXME:
- * add hex-float format
* add long double
*/
static BOOLEAN_T
TrioReadDouble(trio_T *self,
double *target,
- int flags,
+ unsigned long flags,
int width)
{
int ch;
@@ -4204,6 +4866,7 @@
int index = 0;
int start;
int j;
+ BOOLEAN_T isHex = FALSE;
if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1))
width = sizeof(doubleString) - 1;
@@ -4218,13 +4881,12 @@
ch = self->current;
if ((ch == '+') || (ch == '-'))
{
- doubleString[index++] = ch;
+ doubleString[index++] = (char)ch;
self->InStream(self, &ch);
width--;
}
start = index;
-#if defined(USE_NON_NUMBERS)
switch (ch)
{
case 'n':
@@ -4238,7 +4900,7 @@
/* Infinity */
while (isalpha(ch) && (index - start < width))
{
- doubleString[index++] = ch;
+ doubleString[index++] = (char)ch;
self->InStream(self, &ch);
}
doubleString[index] = NIL;
@@ -4255,7 +4917,7 @@
if (StrEqual(doubleString, NAN_LOWER))
{
/* NaN must not have a preceeding + nor - */
- *target = NAN;
+ *target = TrioGenerateNaN();
return TRUE;
}
return FALSE;
@@ -4263,14 +4925,24 @@
default:
break;
}
-#endif /* defined(USE_NON_NUMBERS) */
+ if (ch == '0')
+ {
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ if (toupper(ch) == 'X')
+ {
+ isHex = TRUE;
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ }
while ((ch != EOF) && (index - start < width))
{
/* Integer part */
- if (isdigit(ch))
+ if (isHex ? isxdigit(ch) : isdigit(ch))
{
- doubleString[index++] = ch;
+ doubleString[index++] = (char)ch;
self->InStream(self, &ch);
}
else if (flags & FLAGS_QUOTE)
@@ -4294,26 +4966,28 @@
if (ch == '.')
{
/* Decimal part */
- doubleString[index++] = ch;
+ doubleString[index++] = (char)ch;
self->InStream(self, &ch);
- while (isdigit(ch) && (index - start < width))
+ while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
+ (index - start < width))
{
- doubleString[index++] = ch;
+ doubleString[index++] = (char)ch;
self->InStream(self, &ch);
}
- if ((ch == 'e') || (ch == 'E'))
+ if (isHex ? (toupper(ch) == 'P') : (toupper(ch) == 'E'))
{
/* Exponent */
- doubleString[index++] = ch;
+ doubleString[index++] = (char)ch;
self->InStream(self, &ch);
if ((ch == '+') || (ch == '-'))
{
- doubleString[index++] = ch;
+ doubleString[index++] = (char)ch;
self->InStream(self, &ch);
}
- while (isdigit(ch) && (index - start < width))
+ while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
+ (index - start < width))
{
- doubleString[index++] = ch;
+ doubleString[index++] = (char)ch;
self->InStream(self, &ch);
}
}
@@ -4323,7 +4997,8 @@
return FALSE;
if (flags & FLAGS_LONGDOUBLE)
-/* *longdoublePointer = StrToLongDouble()*/;
+/* *longdoublePointer = StrToLongDouble()*/
+ return FALSE; /* FIXME: Remove when long double is implemented */
else
{
*target = StrToDouble(doubleString, NULL);
@@ -4337,9 +5012,9 @@
static BOOLEAN_T
TrioReadPointer(trio_T *self,
void **target,
- int flags)
+ unsigned long flags)
{
- LONGEST number;
+ trio_uintmax_t number;
char buffer[sizeof(null)];
flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING);
@@ -4386,7 +5061,7 @@
va_list arglist,
void **argarray)
{
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
int charlen;
#endif
int status;
@@ -4398,19 +5073,18 @@
int cnt;
int index; /* Index of format string */
int i; /* Index of current parameter */
- int flags;
+ unsigned long flags;
int width;
int base;
void *pointer;
assert(VALID(InStream));
assert(VALID(format));
- assert(VALID(arglist) || VALID(argarray));
memset(&internalData, 0, sizeof(internalData));
data = &internalData;
data->InStream = InStream;
- data->location = source;
+ data->location = (void *)source;
data->max = sourceSize;
#if defined(USE_LOCALE)
@@ -4419,16 +5093,6 @@
TrioSetLocale();
}
#endif
- if (internalDigitsUnconverted)
- {
- memset(internalDigitArray, -1, sizeof(internalDigitArray));
- for (i = 0; i < (int)sizeof(internalDigitsLower) - 1; i++)
- {
- internalDigitArray[(int)internalDigitsLower[i]] = i;
- internalDigitArray[(int)internalDigitsUpper[i]] = i;
- }
- internalDigitsUnconverted = FALSE;
- }
status = TrioPreprocess(TYPE_SCAN, format, parameters, arglist, argarray);
if (status < 0)
@@ -4439,13 +5103,13 @@
index = 0;
data->InStream(data, &ch);
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
mblen(NULL, 0);
#endif
while (format[index])
{
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
if (! isascii(format[index]))
{
charlen = mblen(&format[index], MB_LEN_MAX);
@@ -4460,7 +5124,7 @@
}
continue; /* while */
}
-#endif /* defined(USE_MULTIBYTE) */
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
if (EOF == ch)
return EOF;
@@ -4503,7 +5167,7 @@
{
case FORMAT_INT:
{
- LONGEST number;
+ trio_uintmax_t number;
if (0 == base)
base = BASE_DECIMAL;
@@ -4531,11 +5195,11 @@
#endif
#if defined(QUALIFIER_INTMAX_T)
if (flags & FLAGS_INTMAX_T)
- *(intmax_t *)pointer = (intmax_t)number;
+ *(trio_intmax_t *)pointer = (trio_intmax_t)number;
else
#endif
if (flags & FLAGS_QUAD)
- *(ULONGLONG int *)pointer = (ULONGLONG)number;
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
else if (flags & FLAGS_LONG)
*(long int *)pointer = (long int)number;
else if (flags & FLAGS_SHORT)
@@ -4547,13 +5211,28 @@
break; /* FORMAT_INT */
case FORMAT_STRING:
- if (!TrioReadString(data,
- (flags & FLAGS_IGNORE)
- ? NULL
- : parameters[i].data.string,
- flags,
- width))
- return assignment;
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ if (!TrioReadWideString(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.wstring,
+ flags,
+ width))
+ return assignment;
+ }
+ else
+#endif
+ {
+ if (!TrioReadString(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ flags,
+ width))
+ return assignment;
+ }
assignment++;
break; /* FORMAT_STRING */
@@ -4572,10 +5251,19 @@
{
int characterclass[MAX_CHARACTER_CLASS + 1];
int rc;
+
+ /* Skip over modifiers */
+ while (format[index] != SPECIFIER_GROUP)
+ {
+ index++;
+ }
+ /* Skip over group specifier */
+ index++;
- index += 2;
memset(characterclass, 0, sizeof(characterclass));
- rc = TrioGetCharacterClass(format, &index, &flags,
+ rc = TrioGetCharacterClass(format,
+ &index,
+ &flags,
characterclass);
if (rc < 0)
return rc;
@@ -4608,12 +5296,12 @@
#endif
#if defined(QUALIFIER_INTMAX_T)
if (flags & FLAGS_INTMAX_T)
- *(intmax_t *)pointer = (intmax_t)data->committed;
+ *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
else
#endif
if (flags & FLAGS_QUAD)
{
- *(ULONGLONG int *)pointer = (ULONGLONG)data->committed;
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
}
else if (flags & FLAGS_LONG)
{
@@ -4631,12 +5319,28 @@
break; /* FORMAT_COUNT */
case FORMAT_CHAR:
- if (!TrioReadChar(data,
- (flags & FLAGS_IGNORE)
- ? NULL
- : parameters[i].data.string,
- (width == NO_WIDTH) ? 1 : width))
- return assignment;
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ if (TrioReadWideChar(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.wstring,
+ flags,
+ (width == NO_WIDTH) ? 1 : width) > 0)
+ return assignment;
+ }
+ else
+#endif
+ {
+ if (TrioReadChar(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ flags,
+ (width == NO_WIDTH) ? 1 : width) > 0)
+ return assignment;
+ }
assignment++;
break; /* FORMAT_CHAR */
@@ -4776,7 +5480,6 @@
va_list args)
{
assert(VALID(format));
- assert(VALID(args));
return TrioScan(stdin, 0, TrioInStreamFile, format, args, NULL);
}
@@ -4785,10 +5488,11 @@
trio_scanfv(const char *format,
void **args)
{
- assert(VALID(format));
- assert(VALID(args));
+ va_list dummy;
- return TrioScan(stdin, 0, TrioInStreamFile, format, NULL, args);
+ assert(VALID(format));
+
+ return TrioScan(stdin, 0, TrioInStreamFile, format, dummy, args);
}
/*************************************************************************
@@ -4818,7 +5522,6 @@
{
assert(VALID(file));
assert(VALID(format));
- assert(VALID(args));
return TrioScan(file, 0, TrioInStreamFile, format, args, NULL);
}
@@ -4828,11 +5531,12 @@
const char *format,
void **args)
{
+ va_list dummy;
+
assert(VALID(file));
assert(VALID(format));
- assert(VALID(args));
- return TrioScan(file, 0, TrioInStreamFile, format, NULL, args);
+ return TrioScan(file, 0, TrioInStreamFile, format, dummy, args);
}
/*************************************************************************
@@ -4860,7 +5564,6 @@
va_list args)
{
assert(VALID(format));
- assert(VALID(args));
return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, args, NULL);
}
@@ -4870,10 +5573,11 @@
const char *format,
void **args)
{
- assert(VALID(format));
- assert(VALID(args));
+ va_list dummy;
- return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, NULL, args);
+ assert(VALID(format));
+
+ return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, dummy, args);
}
/*************************************************************************
@@ -4903,7 +5607,6 @@
{
assert(VALID(buffer));
assert(VALID(format));
- assert(VALID(args));
return TrioScan(&buffer, 0, TrioInStreamString, format, args, NULL);
}
@@ -4913,9 +5616,11 @@
const char *format,
void **args)
{
+ va_list dummy;
+
assert(VALID(buffer));
assert(VALID(format));
- assert(VALID(args));
- return TrioScan(&buffer, 0, TrioInStreamString, format, NULL, args);
+ return TrioScan(&buffer, 0, TrioInStreamString, format, dummy, args);
}
+