From 906ec8a0cadacfc0711b9ebeba0025f1848cea55 Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Tue, 5 Jun 2001 12:46:33 +0000 Subject: [PATCH] Upgraded to trio baseline 1.4 --- strio.c | 47 +- strio.h | 28 +- trio.c | 1805 ++++++++++++++++++++++++++++++++++++++----------------- trio.h | 17 +- triop.h | 57 +- 5 files changed, 1368 insertions(+), 586 deletions(-) diff --git a/strio.c b/strio.c index bbb2056d..f1ab5b86 100644 --- a/strio.c +++ b/strio.c @@ -22,7 +22,7 @@ static const char rcsid[] = "@(#)$Id$"; -#if defined(unix) || defined(__xlC__) +#if defined(unix) || defined(__xlC__) || defined(__QNX__) # define PLATFORM_UNIX #elif defined(WIN32) || defined(_WIN32) # define PLATFORM_WIN32 @@ -36,6 +36,7 @@ static const char rcsid[] = "@(#)$Id$"; #include "strio.h" #include +#include #include #include #include @@ -61,8 +62,13 @@ static const char rcsid[] = "@(#)$Id$"; # define USE_STRCASECMP # define USE_STRNCASECMP # define USE_STRERROR +# if defined(__QNX__) +# define strcasecmp(x,y) stricmp(x,y) +# define strncasecmp(x,y,n) strnicmp(x,y,n) +# endif #elif defined(PLATFORM_WIN32) -# define USE_STRCMPI +# define USE_STRCASECMP +# define strcasecmp(x,y) strcmpi(x,y) #endif /************************************************************************* @@ -101,7 +107,7 @@ char *StrDuplicate(const char *source) assert(VALID(source)); - target = (char *)malloc(StrLength(source) + 1); + target = StrAlloc(StrLength(source) + 1); if (target) { StrCopy(target, source); @@ -126,7 +132,7 @@ char *StrDuplicateMax(const char *source, size_t max) { len = max; } - target = (char *)malloc(len); + target = StrAlloc(len); if (target) { StrCopyMax(target, len, source); @@ -146,8 +152,6 @@ int StrEqual(const char *first, const char *second) { #if defined(USE_STRCASECMP) return (0 == strcasecmp(first, second)); -#elif defined(USE_STRCMPI) - return (0 == strcmpi(first, second)); #else while ((*first != NIL) && (*second != NIL)) { @@ -194,6 +198,21 @@ int StrEqualCaseMax(const char *first, size_t max, const char *second) return FALSE; } +/************************************************************************* + * StrEqualLocale + */ +int StrEqualLocale(const char *first, const char *second) +{ + assert(VALID(first)); + assert(VALID(second)); + +#if defined(LC_COLLATE) + return (strcoll(first, second) == 0); +#else + return StrEqual(first, second); +#endif +} + /************************************************************************* * StrEqualMax */ @@ -293,7 +312,7 @@ int StrMatch(char *string, char *pattern) { return (NIL == *pattern); } - if ((toupper(*string) != toupper(*pattern)) + if ((toupper((int)*string) != toupper((int)*pattern)) && ('?' != *pattern)) { return FALSE; @@ -435,9 +454,9 @@ double StrToDouble(const char *source, const char **endp) while (isxdigit((int)*source)) { integer *= 16; - integer += (isdigit((int)*source) ? (*source - '0') : - (isupper((int)*source) ? (*source - 'A') : - (*source - 'a'))); + integer += (isdigit((int)*source) + ? (*source - '0') + : 10 + (toupper((int)*source) - 'A')); source++; } if (*source == '.') @@ -446,9 +465,9 @@ double StrToDouble(const char *source, const char **endp) while (isxdigit((int)*source)) { fraction *= 16; - fraction += (isdigit((int)*source) ? (*source - '0') : - (isupper((int)*source) ? (*source - 'A') : - (*source - 'a'))); + fraction += (isdigit((int)*source) + ? (*source - '0') + : 10 + (toupper((int)*source) - 'A')); fracdiv *= 16; source++; } @@ -554,7 +573,7 @@ int StrToUpper(char *target) while (NIL != *target) { - *target = toupper(*target); + *target = toupper((int)*target); target++; i++; } diff --git a/strio.h b/strio.h index 3bb05dbb..68845a38 100644 --- a/strio.h +++ b/strio.h @@ -18,13 +18,20 @@ #ifndef TRIO_STRIO_H #define TRIO_STRIO_H -#include -#include -#include -#ifndef DEBUG +#if !(defined(DEBUG) || defined(NDEBUG)) # define NDEBUG #endif #include +#include +#include +#include + +#ifndef STRIO_MALLOC +# define STRIO_MALLOC(n) malloc(n) +#endif +#ifndef STRIO_FREE +# define STRIO_FREE(x) free(x) +#endif /* * StrAppend(target, source) @@ -129,13 +136,13 @@ enum { }; #if !defined(DEBUG) || defined(__DECC) +#define StrAlloc(n) (char *)STRIO_MALLOC(n) #define StrAppend(x,y) strcat((x), (y)) -#define StrAlloc(n) ((char *)calloc(1, (n))) #define StrContains(x,y) (0 != strstr((x), (y))) #define StrCopy(x,y) strcpy((x), (y)) -#define StrFree(x) free((x)) #define StrIndex(x,y) strchr((x), (y)) #define StrIndexLast(x,y) strrchr((x), (y)) +#define StrFree(x) STRIO_FREE(x) #define StrLength(x) strlen((x)) #define StrSubstring(x,y) strstr((x), (y)) #define StrTokenize(x,y) strtok((x), (y)) @@ -151,13 +158,13 @@ enum { * so it will use the un-asserted functions above for the * debugging case too. */ +#define StrAlloc(n) \ + (assert((n) > 0),\ + (char *)STRIO_MALLOC(n)) #define StrAppend(x,y) \ (assert((x) != NULL),\ assert((y) != NULL),\ strcat((x), (y))) -#define StrAlloc(n) \ - (assert((n) > 0),\ - ((char *)calloc(1, (n)))) #define StrContains(x,y) \ (assert((x) != NULL),\ assert((y) != NULL),\ @@ -174,7 +181,7 @@ enum { strrchr((x), (c))) #define StrFree(x) \ (assert((x) != NULL),\ - free((x))) + STRIO_FREE(x)) #define StrLength(x) \ (assert((x) != NULL),\ strlen((x))) @@ -204,6 +211,7 @@ char *StrDuplicateMax(const char *source, size_t max); int StrEqual(const char *first, const char *second); int StrEqualCase(const char *first, const char *second); int StrEqualCaseMax(const char *first, size_t max, const char *second); +int StrEqualLocale(const char *first, const char *second); int StrEqualMax(const char *first, size_t max, const char *second); const char *StrError(int); size_t StrFormatDateMax(char *target, size_t max, const char *format, const struct tm *datetime); diff --git a/trio.c b/trio.c index 241d6c22..ea772bac 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 -#include -#include -#include -#include -#include -#include -#if defined(TRIO_C99) -# include -#endif -#if defined(PLATFORM_UNIX) -# include -# include -# define USE_LOCALE -#endif - -#if defined(_MSC_VER) -#include -#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 +#include +#if !defined(TRIO_COMPILER_SUPPORTS_C99) +# define isblank(x) (((x)==32) || ((x)==9)) +#endif +#include +#include +#include +#include +#include +#include + +#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 +# include +# include +# define USE_LOCALE +#endif /* PLATFORM_UNIX */ +#if defined(PLATFORM_WIN32) +# include +# define read _read +# define write _write +#endif /* PLATFORM_WIN32 */ + +#if TRIO_WIDECHAR +# if defined(TRIO_COMPILER_SUPPORTS_ISO94) +# include +# include +# 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 +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 +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 @@ enum { 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 @@ enum { 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 @@ enum { #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 @@ enum { * 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 @@ enum { #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 @@ enum { * * ! 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 @@ enum { #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 @@ typedef struct { 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 @@ typedef struct { /* 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 @@ static struct lconv *internalLocaleValues = NULL; * 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; /************************************************************************* @@ -638,6 +771,9 @@ TrioIsQualifier(const char ch) #endif #if defined(QUALIFIER_PARAM) case QUALIFIER_PARAM: +#endif +#if defined(QUALIFIER_FIXED_SIZE) + case QUALIFIER_FIXED_SIZE: #endif return TRUE; default: @@ -645,6 +781,33 @@ TrioIsQualifier(const char ch) } } +/************************************************************************* + * 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] */ @@ -688,23 +851,29 @@ static void 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 @@ TrioFindNamespace(const char *name, userdef_T **prev) { 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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, #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 @@ TrioPreprocess(int type, #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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, #if defined(QUALIFIER_VARSIZE) case QUALIFIER_VARSIZE: - flags |= FLAGS_SIZE_PARAMETER; + flags |= FLAGS_VARSIZE_PARAMETER; parameterPosition++; if (positional) varsize = parameterPosition; @@ -1143,7 +1358,7 @@ TrioPreprocess(int type, */ 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 @@ TrioPreprocess(int type, } 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 @@ TrioPreprocess(int type, } 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 @@ TrioPreprocess(int type, { #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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, { 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 @@ TrioPreprocess(int type, 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 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 @@ TrioPreprocess(int type, #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 @@ TrioPreprocess(int type, * 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 @@ TrioPreprocess(int type, 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 @@ TrioPreprocess(int type, */ 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 @@ TrioWriteNumber(trio_T *self, 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 @@ -1840,6 +2102,60 @@ TrioWriteNumber(trio_T *self, } } +/************************************************************************* + * 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] * @@ -1890,48 +2206,8 @@ TrioWriteString(trio_T *self, 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) @@ -1943,6 +2219,111 @@ TrioWriteString(trio_T *self, self->OutStream(self, CHAR_QUOTE); } +/************************************************************************* + * 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] */ @@ -1957,7 +2338,6 @@ TrioWriteDouble(trio_T *self, int charsPerThousand; int length; double number; - double precisionPower; double workNumber; int integerDigits; int fractionDigits; @@ -1970,18 +2350,16 @@ TrioWriteDouble(trio_T *self, 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 @@ TrioWriteDouble(trio_T *self, number = (double)longdoubleNumber; -#if defined(USE_NON_NUMBERS) /* Look for infinite numbers and non-a-number first */ switch (TrioIsInfinite(number)) { @@ -2024,7 +2401,6 @@ TrioWriteDouble(trio_T *self, flags, width, precision); return; } -#endif /* defined(USE_NON_NUMBERS) */ /* Normal numbers */ digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; @@ -2033,26 +2409,39 @@ TrioWriteDouble(trio_T *self, 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 @@ TrioWriteDouble(trio_T *self, * 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 @@ TrioWriteDouble(trio_T *self, *(--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 @@ TrioWriteDouble(trio_T *self, 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 @@ TrioWriteDouble(trio_T *self, ? ((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 @@ TrioFormatProcess(trio_T *data, parameter_T *parameters) { -#if defined(USE_MULTIBYTE) +#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) int charlen; #endif int i; @@ -2286,13 +2694,13 @@ TrioFormatProcess(trio_T *data, 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 @@ TrioFormatProcess(trio_T *data, } 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 @@ TrioFormatProcess(trio_T *data, 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 @@ TrioFormatProcess(trio_T *data, 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 @@ TrioFormatProcess(trio_T *data, #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 @@ TrioFormatProcess(trio_T *data, { data->OutStream(data, '#'); TrioWriteNumber(data, - (SLONGEST)parameters[i].data.errorNumber, + (trio_intmax_t)parameters[i].data.errorNumber, flags, width, precision, @@ -2566,7 +2997,6 @@ TrioFormat(void *destination, assert(VALID(OutStream)); assert(VALID(format)); - assert(VALID(arglist) || VALID(argarray)); memset(&data, 0, sizeof(data)); data.OutStream = OutStream; @@ -2686,7 +3116,7 @@ TrioOutStreamStringDynamic(trio_T *self, 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 @@ TrioOutStreamStringDynamic(trio_T *self, 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 @@ TrioOutStreamStringDynamic(trio_T *self, infop->allocated *= 2; } - infop->buffer[self->committed] = output; + infop->buffer[self->committed] = (char)output; self->committed++; self->processed++; @@ -2738,7 +3168,6 @@ trio_vprintf(const char *format, va_list args) { assert(VALID(format)); - assert(VALID(args)); return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL); } @@ -2747,10 +3176,11 @@ int 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 @@ trio_vfprintf(FILE *file, { assert(VALID(file)); assert(VALID(format)); - assert(VALID(args)); return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL); } @@ -2790,11 +3219,12 @@ trio_fprintfv(FILE *file, 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 @@ trio_vdprintf(int fd, va_list args) { assert(VALID(format)); - assert(VALID(args)); return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL); } @@ -2832,10 +3261,11 @@ trio_dprintfv(int fd, 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 @@ trio_vsprintf(char *buffer, assert(VALID(buffer)); assert(VALID(format)); - assert(VALID(args)); status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL); *buffer = NIL; @@ -2881,12 +3310,12 @@ trio_sprintfv(char *buffer, 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 @@ trio_vsnprintf(char *buffer, 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 @@ trio_snprintfv(char *buffer, 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 @@ trio_vsnprintfcat(char *buffer, 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 @@ trio_vaprintf(const char *format, struct dynamicBuffer info; assert(VALID(format)); - assert(VALID(args)); info.buffer = NULL; info.length = 0; @@ -3083,7 +3509,7 @@ trio_asprintf(char **result, * 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 @@ trio_vasprintf(char **result, struct dynamicBuffer info; assert(VALID(format)); - assert(VALID(args)); info.buffer = NULL; info.length = 0; @@ -3116,7 +3541,7 @@ trio_vasprintf(char **result, 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 @@ trio_register(trio_callback_t callback, 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 @@ trio_register(trio_callback_t callback, 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 @@ trio_register(trio_callback_t callback, ? NULL : StrDuplicate(name); def->next = NULL; + + if (internalLeaveCriticalRegion) + (void)internalLeaveCriticalRegion(NULL); } return def; } @@ -3199,14 +3644,20 @@ trio_unregister(void *handle) 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_set_upper(void *ref, /************************************************************************* * 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_set_largest(void *ref, /************************************************************************* * trio_get_ptrdiff / trio_set_ptrdiff [public] */ -#if defined(TRIO_C99) int trio_get_ptrdiff(void *ref) { @@ -3547,12 +3997,11 @@ trio_set_ptrdiff(void *ref, 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 @@ trio_print_int(void *ref, 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 @@ trio_print_uint(void *ref, 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 @@ trio_print_pointer(void *ref, { reference_T *self = (reference_T *)ref; unsigned long flags; - LONGLONG number; + trio_uintmax_t number; if (NULL == pointer) { @@ -3663,14 +4112,14 @@ trio_print_pointer(void *ref, * 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 @@ trio_printv_ref(void *ref, 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); } @@ -3747,6 +4198,37 @@ TrioSkipWhitespaces(trio_T *self) return ch; } +/************************************************************************* + * 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] * @@ -3756,7 +4238,7 @@ TrioSkipWhitespaces(trio_T *self) static int TrioGetCharacterClass(const char *format, int *indexPointer, - int *flagsPointer, + unsigned long *flagsPointer, int *characterclass) { int index = *indexPointer; @@ -3793,7 +4275,7 @@ TrioGetCharacterClass(const char *format, } /* 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 @@ TrioGetCharacterClass(const char *format, ch = range_end; 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 +#if TRIO_EXTENSION + + case SPECIFIER_GROUP: + + switch (format[index + 1]) { + 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 @@ TrioGetCharacterClass(const char *format, */ 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 @@ TrioReadNumber(trio_T *self, 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 @@ TrioReadNumber(trio_T *self, /************************************************************************* * 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 @@ TrioReadChar(trio_T *self, (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 @@ TrioReadChar(trio_T *self, 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,52 +4704,116 @@ TrioReadString(trio_T *self, (! ((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; return TRUE; } +/************************************************************************* + * 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] * @@ -4160,7 +4823,7 @@ static BOOLEAN_T TrioReadGroup(trio_T *self, char *target, int *characterclass, - int flags, + unsigned long flags, int width) { int ch; @@ -4190,13 +4853,12 @@ TrioReadGroup(trio_T *self, * 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 @@ TrioReadDouble(trio_T *self, 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 @@ TrioReadDouble(trio_T *self, 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 @@ TrioReadDouble(trio_T *self, /* 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 @@ TrioReadDouble(trio_T *self, if (StrEqual(doubleString, NAN_LOWER)) { /* NaN must not have a preceeding + nor - */ - *target = NAN; + *target = TrioGenerateNaN(); return TRUE; } return FALSE; @@ -4263,14 +4925,24 @@ TrioReadDouble(trio_T *self, 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 @@ TrioReadDouble(trio_T *self, 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 @@ TrioReadDouble(trio_T *self, 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 @@ TrioReadDouble(trio_T *self, 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 @@ TrioScan(const void *source, va_list arglist, void **argarray) { -#if defined(USE_MULTIBYTE) +#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) int charlen; #endif int status; @@ -4398,19 +5073,18 @@ TrioScan(const void *source, 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 @@ TrioScan(const void *source, 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 @@ TrioScan(const void *source, 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 @@ TrioScan(const void *source, } continue; /* while */ } -#endif /* defined(USE_MULTIBYTE) */ +#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ if (EOF == ch) return EOF; @@ -4503,7 +5167,7 @@ TrioScan(const void *source, { case FORMAT_INT: { - LONGEST number; + trio_uintmax_t number; if (0 == base) base = BASE_DECIMAL; @@ -4531,11 +5195,11 @@ TrioScan(const void *source, #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 @@ TrioScan(const void *source, 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 @@ TrioScan(const void *source, { 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 @@ TrioScan(const void *source, #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 @@ TrioScan(const void *source, 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 @@ trio_vscanf(const char *format, va_list args) { assert(VALID(format)); - assert(VALID(args)); return TrioScan(stdin, 0, TrioInStreamFile, format, args, NULL); } @@ -4785,10 +5488,11 @@ int 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 @@ trio_vfscanf(FILE *file, { assert(VALID(file)); assert(VALID(format)); - assert(VALID(args)); return TrioScan(file, 0, TrioInStreamFile, format, args, NULL); } @@ -4828,11 +5531,12 @@ trio_fscanfv(FILE *file, 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 @@ trio_vdscanf(int fd, va_list args) { assert(VALID(format)); - assert(VALID(args)); return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, args, NULL); } @@ -4870,10 +5573,11 @@ trio_dscanfv(int fd, 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 @@ trio_vsscanf(const char *buffer, { assert(VALID(buffer)); assert(VALID(format)); - assert(VALID(args)); return TrioScan(&buffer, 0, TrioInStreamString, format, args, NULL); } @@ -4913,9 +5616,11 @@ trio_sscanfv(const char *buffer, 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); } + diff --git a/trio.h b/trio.h index 63b7dbde..14f2f52b 100644 --- a/trio.h +++ b/trio.h @@ -32,6 +32,15 @@ #if !defined(WITHOUT_TRIO) +#ifdef __cplusplus +extern "C" { +#endif + +/* make utility and C++ compiler in Windows NT fails to find this symbol */ +#if defined(WIN32) && !defined(isascii) +# define isascii ((unsigned)(x) < 0x80) +#endif + /* * Error codes. * @@ -44,7 +53,7 @@ enum { TRIO_EDBLREF = 4, TRIO_EGAP = 5, TRIO_ENOMEM = 6, - TRIO_ERANGE = 7, + TRIO_ERANGE = 7 }; /* Error macros */ @@ -181,6 +190,10 @@ int trio_sscanfv(const char *buffer, const char *format, void **args); #define StrFormatAlloc trio_aprintf #define StrFormatAppendMax trio_snprintfcat -#endif /* TRIO_IGNORE */ +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* WITHOUT_TRIO */ #endif /* TRIO_TRIO_H */ diff --git a/triop.h b/triop.h index 62ec0f9a..ca49fabb 100644 --- a/triop.h +++ b/triop.h @@ -26,16 +26,49 @@ #ifndef TRIO_TRIOP_H #define TRIO_TRIOP_H -#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L) -# define TRIO_C99 -#endif -#define TRIO_BSD -#define TRIO_GNU -#define TRIO_MISC -#define TRIO_UNIX98 -#define TRIO_EXTENSION -#define TRIO_ERRORS +#include +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRIO_C99 +# define TRIO_C99 1 +#endif +#ifndef TRIO_BSD +# define TRIO_BSD 1 +#endif +#ifndef TRIO_GNU +# define TRIO_GNU 1 +#endif +#ifndef TRIO_MISC +# define TRIO_MISC 1 +#endif +#ifndef TRIO_UNIX98 +# define TRIO_UNIX98 1 +#endif +#ifndef TRIO_MICROSOFT +# define TRIO_MICROSOFT 1 +#endif +#ifndef TRIO_EXTENSION +# define TRIO_EXTENSION 1 +#endif +#ifndef TRIO_WIDECHAR +# define TRIO_WIDECHAR 0 +#endif +#ifndef TRIO_ERRORS +# define TRIO_ERRORS 1 +#endif + +#ifndef TRIO_MALLOC +# define TRIO_MALLOC(n) malloc(n) +#endif +#ifndef TRIO_REALLOC +# define TRIO_REALLOC(x,n) realloc((x),(n)) +#endif +#ifndef TRIO_FREE +# define TRIO_FREE(x) free(x) +#endif typedef int (*trio_callback_t)(void *ref); @@ -76,7 +109,7 @@ int trio_get_quote(void *ref); /* ' */ void trio_set_quote(void *ref, int is_quote); int trio_get_upper(void *ref); void trio_set_upper(void *ref, int is_upper); -#if defined(TRIO_C99) +#if TRIO_C99 int trio_get_largest(void *ref); /* j */ void trio_set_largest(void *ref, int is_largest); int trio_get_ptrdiff(void *ref); /* t */ @@ -98,4 +131,8 @@ void trio_print_double(void *ref, double number); void trio_print_string(void *ref, char *string); void trio_print_pointer(void *ref, void *pointer); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* TRIO_TRIOP_H */