From b7c29c38f507ac62cc85df9b897762fc84f05a68 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Wed, 25 Sep 2002 22:44:43 +0000 Subject: [PATCH] applied a trio update patch from Bjorn Reese which should work with MinGW * trio.c trio.h triodef.h trionan.c trionan.h triop.h triostr.c triostr.h: applied a trio update patch from Bjorn Reese which should work with MinGW Daniel --- ChangeLog | 6 + doc/FAQ.html | 2 +- doc/downloads.html | 5 +- trio.c | 2629 ++++++++++++++++++++++++++++++-------------- trio.h | 133 ++- triodef.h | 68 +- trionan.c | 189 ++-- trionan.h | 23 +- triop.h | 111 +- triostr.c | 1017 ++++++++++------- triostr.h | 144 +-- 11 files changed, 2857 insertions(+), 1470 deletions(-) diff --git a/ChangeLog b/ChangeLog index 24f596a9..fe4ae65a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Sep 26 00:31:46 CEST 2002 Daniel Veillard + + * trio.c trio.h triodef.h trionan.c trionan.h triop.h + triostr.c triostr.h: applied a trio update patch from + Bjorn Reese which should work with MinGW + Thu Sep 26 00:21:18 CEST 2002 Daniel Veillard * tree.c: improving some documentation comments diff --git a/doc/FAQ.html b/doc/FAQ.html index 34e39f50..508ddf68 100644 --- a/doc/FAQ.html +++ b/doc/FAQ.html @@ -119,7 +119,7 @@ A:link, A:visited, A:active { text-decoration: underline } Not Use libxml1, use libxml2
  • Where can I get libxml ? -

    The original distribution comes from rpmfind.net or gnome.org +

    The original distribution comes from rpmfind.net or gnome.org

    Most Linux and BSD distributions include libxml, this is probably the safer way for end-users to use libxml.

    diff --git a/doc/downloads.html b/doc/downloads.html index 7ee3639e..b04e9e99 100644 --- a/doc/downloads.html +++ b/doc/downloads.html @@ -89,9 +89,8 @@ A:link, A:visited, A:active { text-decoration: underline }

    The latest versions of libxml can be found on xmlsoft.org (Seattle, France) or on the Gnome FTP server either -as a source -archive or RPM -packages, Antonin Sprinzl also provide a mirror in Austria. (NOTE that +as a source +archive, Antonin Sprinzl also provide a mirror in Austria. (NOTE that you need both the libxml(2) and libxml(2)-devel packages installed to compile applications using libxml.) Igor Zlatkovic is now the maintainer of the Windows port, he diff --git a/trio.c b/trio.c index 1a844bcd..7593e581 100644 --- a/trio.c +++ b/trio.c @@ -28,7 +28,6 @@ * TODO: * - Scan is probably too permissive about its modifiers. * - C escapes in %#[] ? - * - C99 support has not been properly tested. * - Multibyte characters (done for format parsing, except scan groups) * - Complex numbers? (C99 _Complex) * - Boolean values? (C99 _Bool) @@ -47,19 +46,17 @@ #include "triodef.h" #include "trio.h" #include "triop.h" -#include "triostr.h" #include "trionan.h" - -/* - * Encode the error code and the position. This is decoded - * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION. - */ -#if TRIO_ERRORS -# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8))) -#else -# define TRIO_ERROR_RETURN(x,y) (-1) +#if !defined(TRIO_MINIMAL) +# include "triostr.h" #endif +/************************************************************************** + * + * Definitions + * + *************************************************************************/ + #if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_WIDECHAR # define TRIO_COMPILER_SUPPORTS_MULTIBYTE # if !defined(MB_LEN_MAX) @@ -67,7 +64,6 @@ # endif #endif - /************************************************************************* * Generic definitions */ @@ -83,7 +79,11 @@ #include #include #include -#include +#if defined(TRIO_COMPILER_ANCIENT) +# include +#else +# include +#endif #include #include @@ -100,9 +100,15 @@ /* mincore() can be used for debugging purposes */ #define VALID(x) (NULL != (x)) -/* xlC crashes on log10(0) */ -#define guarded_log10(x) (((x) == 0.0) ? trio_ninf() : log10(x)) -#define guarded_log16(x) (guarded_log10(x) / log10(16.0)) +#if TRIO_ERRORS + /* + * Encode the error code and the position. This is decoded + * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION. + */ +# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8))) +#else +# define TRIO_ERROR_RETURN(x,y) (-1) +#endif /************************************************************************* @@ -129,9 +135,11 @@ # if defined(TRIO_COMPILER_SUPPORTS_ISO94) # include # include +typedef wchar_t trio_wchar_t; +typedef wint_t trio_wint_t; # else -typedef char wchar_t; -typedef int wint_t; +typedef char trio_wchar_t; +typedef int trio_wint_t; # define WCONST(x) L ## x # define WEOF EOF # define iswalnum(x) isalnum(x) @@ -180,7 +188,7 @@ typedef signed long int trio_longlong_t; typedef unsigned long int trio_ulonglong_t; # endif #else -typedef signed long int trio_longlong_t; +typedef TRIO_SIGNED long int trio_longlong_t; typedef unsigned long int trio_ulonglong_t; #endif @@ -214,17 +222,17 @@ 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; +typedef TRIO_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; +typedef TRIO_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; +typedef TRIO_SIGNED int trio_int32_t; # endif # if defined(TRIO_INT64_T) typedef TRIO_INT64_T trio_int64_t; @@ -233,24 +241,47 @@ typedef trio_longlong_t trio_int64_t; # endif #endif +#if !(defined(TRIO_COMPILER_SUPPORTS_C99) \ + || defined(TRIO_COMPILER_SUPPORTS_UNIX01)) +# define floorl(x) floor((double)(x)) +# define fmodl(x,y) fmod((double)(x),(double)(y)) +# define powl(x,y) pow((double)(x),(double)(y)) +#endif + +#define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x)) /************************************************************************* - * Internal definitions + * Internal Definitions */ +#ifndef DECIMAL_DIG +# define DECIMAL_DIG DBL_DIG +#endif + /* Long double sizes */ #ifdef LDBL_DIG # define MAX_MANTISSA_DIGITS LDBL_DIG # define MAX_EXPONENT_DIGITS 4 +# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP #else -# define MAX_MANTISSA_DIGITS DBL_DIG +# define MAX_MANTISSA_DIGITS DECIMAL_DIG # define MAX_EXPONENT_DIGITS 3 +# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP +#endif + +#if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG) +# undef LDBL_DIG +# undef LDBL_MANT_DIG +# undef LDBL_EPSILON +# define LDBL_DIG DBL_DIG +# define LDBL_MANT_DIG DBL_MANT_DIG +# define LDBL_EPSILON DBL_EPSILON #endif /* 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) +#define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4) /* Infinite and Not-A-Number for floating-point */ #define INFINITE_LOWER "inf" @@ -301,6 +332,7 @@ enum { /* Reused flags */ FLAGS_EXCLUDE = FLAGS_SHORT, FLAGS_USER_DEFINED = FLAGS_IGNORE, + FLAGS_ROUNDING = FLAGS_INTMAX_T, /* 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, @@ -310,6 +342,7 @@ enum { NO_PRECISION = -1, NO_SIZE = -1, + /* Do not change these */ NO_BASE = -1, MIN_BASE = 2, MAX_BASE = 36, @@ -362,18 +395,18 @@ enum { #define CHAR_ADJUST ' ' /* Character class expressions */ -#define CLASS_ALNUM ":alnum:" -#define CLASS_ALPHA ":alpha:" -#define CLASS_BLANK ":blank:" -#define CLASS_CNTRL ":cntrl:" -#define CLASS_DIGIT ":digit:" -#define CLASS_GRAPH ":graph:" -#define CLASS_LOWER ":lower:" -#define CLASS_PRINT ":print:" -#define CLASS_PUNCT ":punct:" -#define CLASS_SPACE ":space:" -#define CLASS_UPPER ":upper:" -#define CLASS_XDIGIT ":xdigit:" +#define CLASS_ALNUM "[:alnum:]" +#define CLASS_ALPHA "[:alpha:]" +#define CLASS_BLANK "[:blank:]" +#define CLASS_CNTRL "[:cntrl:]" +#define CLASS_DIGIT "[:digit:]" +#define CLASS_GRAPH "[:graph:]" +#define CLASS_LOWER "[:lower:]" +#define CLASS_PRINT "[:print:]" +#define CLASS_PUNCT "[:punct:]" +#define CLASS_SPACE "[:space:]" +#define CLASS_UPPER "[:upper:]" +#define CLASS_XDIGIT "[:xdigit:]" /* * SPECIFIERS: @@ -543,7 +576,7 @@ enum { #define QUALIFIER_MINUS '-' #define QUALIFIER_DOT '.' #define QUALIFIER_STAR '*' -#define QUALIFIER_CIRCUMFLEX '^' +#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */ #if TRIO_C99 # define QUALIFIER_SIZE_T 'z' # define QUALIFIER_PTRDIFF_T 't' @@ -568,12 +601,15 @@ enum { # define QUALIFIER_PARAM '@' /* Experimental */ # define QUALIFIER_COLON ':' /* For scanlists */ # define QUALIFIER_EQUAL '=' /* For scanlists */ +# define QUALIFIER_ROUNDING_UPPER 'R' #endif /************************************************************************* - * Internal structures - */ + * + * Internal Structures + * + *************************************************************************/ /* Parameters */ typedef struct { @@ -595,17 +631,17 @@ typedef struct { union { char *string; #if TRIO_WIDECHAR - wchar_t *wstring; + trio_wchar_t *wstring; #endif - void *pointer; + trio_pointer_t pointer; union { - trio_uintmax_t as_signed; - trio_intmax_t as_unsigned; + trio_intmax_t as_signed; + trio_uintmax_t as_unsigned; } number; double doubleNumber; double *doublePointer; - long double longdoubleNumber; - long double *longdoublePointer; + trio_long_double_t longdoubleNumber; + trio_long_double_t *longdoublePointer; int errorNumber; } data; /* For the user-defined specifier */ @@ -613,20 +649,29 @@ typedef struct { char user_data[MAX_USER_DATA]; } trio_parameter_t; +/* Container for customized functions */ +typedef struct { + union { + trio_outstream_t out; + trio_instream_t in; + } stream; + trio_pointer_t closure; +} trio_custom_t; + /* General trio "class" */ typedef struct _trio_class_t { /* * The function to write characters to a stream. */ - void (*OutStream)(struct _trio_class_t *, int); + void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int)); /* * The function to read characters from a stream. */ - void (*InStream)(struct _trio_class_t *, int *); + void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *)); /* * The current location in the stream. */ - void *location; + trio_pointer_t location; /* * The character currently being processed. */ @@ -667,8 +712,10 @@ typedef struct _trio_userdef_t { /************************************************************************* - * Internal variables - */ + * + * Internal Variables + * + *************************************************************************/ static TRIO_CONST char rcsid[] = "@(#)$Id$"; @@ -678,7 +725,7 @@ static TRIO_CONST char rcsid[] = "@(#)$Id$"; * e.g: va_arg(arg_ptr, long double) */ #if defined(TRIO_PLATFORM_MPEIX) -static TRIO_CONST long double ___dummy_long_double = 0; +static TRIO_CONST trio_long_double_t ___dummy_long_double = 0; #endif static TRIO_CONST char internalNullString[] = "(nil)"; @@ -691,7 +738,10 @@ 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 + 1] = "."; +static int internalDecimalPointLength = 1; +static int internalThousandSeparatorLength = 1; +static char internalDecimalPoint = '.'; +static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = "."; static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ","; static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING }; @@ -704,38 +754,23 @@ static BOOLEAN_T internalCollationUnconverted = TRUE; static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS]; #endif +#if TRIO_EXTENSION static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL; static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL; static trio_userdef_t *internalUserDef = NULL; +#endif /************************************************************************* - * trio_strerror - */ -TRIO_PUBLIC TRIO_CONST char * -trio_strerror(int errorcode) -{ - /* Textual versions of the error codes */ - switch (TRIO_ERROR_CODE(errorcode)) - { - case TRIO_EOF: - return "End of file"; - case TRIO_EINVAL: - return "Invalid argument"; - case TRIO_ETOOMANY: - return "Too many arguments"; - case TRIO_EDBLREF: - return "Double reference"; - case TRIO_EGAP: - return "Reference gap"; - case TRIO_ENOMEM: - return "Out of memory"; - case TRIO_ERANGE: - return "Invalid range"; - default: - return "Unknown"; - } -} + * + * Internal Functions + * + ************************************************************************/ + +#if defined(TRIO_MINIMAL) +# define TRIO_STRING_PUBLIC static +# include "triostr.c" +#endif /* defined(TRIO_MINIMAL) */ /************************************************************************* * TrioIsQualifier @@ -745,10 +780,12 @@ trio_strerror(int errorcode) * QUALIFIER_POSITION must not be added. */ TRIO_PRIVATE BOOLEAN_T -TrioIsQualifier(TRIO_CONST char ch) +TrioIsQualifier +TRIO_ARGS1((character), + TRIO_CONST char character) { /* QUALIFIER_POSITION is not included */ - switch (ch) + switch (character) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -794,6 +831,9 @@ TrioIsQualifier(TRIO_CONST char ch) #endif #if defined(QUALIFIER_FIXED_SIZE) case QUALIFIER_FIXED_SIZE: +#endif +#if defined(QUALIFIER_ROUNDING_UPPER) + case QUALIFIER_ROUNDING_UPPER: #endif return TRUE; default: @@ -805,8 +845,8 @@ TrioIsQualifier(TRIO_CONST char ch) * TrioSetLocale */ #if defined(USE_LOCALE) -TRIO_PUBLIC void -TrioSetLocale(void) +TRIO_PRIVATE void +TrioSetLocale(TRIO_NOARGS) { internalLocaleValues = (struct lconv *)localeconv(); if (internalLocaleValues) @@ -814,9 +854,18 @@ TrioSetLocale(void) if ((internalLocaleValues->decimal_point) && (internalLocaleValues->decimal_point[0] != NIL)) { - trio_copy_max(internalDecimalPoint, - sizeof(internalDecimalPoint), - internalLocaleValues->decimal_point); + internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point); + if (internalDecimalPointLength == 1) + { + internalDecimalPoint = internalLocaleValues->decimal_point[0]; + } + else + { + internalDecimalPoint = NIL; + trio_copy_max(internalDecimalPointString, + sizeof(internalDecimalPointString), + internalLocaleValues->decimal_point); + } } if ((internalLocaleValues->thousands_sep) && (internalLocaleValues->thousands_sep[0] != NIL)) @@ -824,6 +873,7 @@ TrioSetLocale(void) trio_copy_max(internalThousandSeparator, sizeof(internalThousandSeparator), internalLocaleValues->thousands_sep); + internalThousandSeparatorLength = trio_length(internalThousandSeparator); } if ((internalLocaleValues->grouping) && (internalLocaleValues->grouping[0] != NIL)) @@ -836,15 +886,91 @@ TrioSetLocale(void) } #endif /* defined(USE_LOCALE) */ +TRIO_PRIVATE int +TrioCalcThousandSeparatorLength +TRIO_ARGS1((digits), + int digits) +{ +#if TRIO_EXTENSION + int count = 0; + int step = NO_GROUPING; + char *groupingPointer = internalGrouping; + + while (digits > 0) + { + if (*groupingPointer == CHAR_MAX) + { + /* Disable grouping */ + break; /* while */ + } + else if (*groupingPointer == 0) + { + /* Repeat last group */ + if (step == NO_GROUPING) + { + /* Error in locale */ + break; /* while */ + } + } + else + { + step = *groupingPointer++; + } + if (digits > step) + count += internalThousandSeparatorLength; + digits -= step; + } + return count; +#else + return 0; +#endif +} + +TRIO_PRIVATE BOOLEAN_T +TrioFollowedBySeparator +TRIO_ARGS1((position), + int position) +{ +#if TRIO_EXTENSION + int step = 0; + char *groupingPointer = internalGrouping; + + position--; + if (position == 0) + return FALSE; + while (position > 0) + { + if (*groupingPointer == CHAR_MAX) + { + /* Disable grouping */ + break; /* while */ + } + else if (*groupingPointer != 0) + { + step = *groupingPointer++; + } + if (step == 0) + break; + position -= step; + } + return (position == 0); +#else + return FALSE; +#endif +} + /************************************************************************* * TrioGetPosition * * Get the %n$ position. */ TRIO_PRIVATE int -TrioGetPosition(TRIO_CONST char *format, - int *indexPointer) +TrioGetPosition +TRIO_ARGS2((format, indexPointer), + TRIO_CONST char *format, + int *indexPointer) { +#if TRIO_UNIX98 char *tmpformat; int number = 0; int index = *indexPointer; @@ -860,17 +986,22 @@ TrioGetPosition(TRIO_CONST char *format, */ return number - 1; } +#endif return NO_POSITION; } +#if TRIO_EXTENSION /************************************************************************* * TrioFindNamespace * * Find registered user-defined specifier. - * The prev argument is used for optimisation only. + * The prev argument is used for optimization only. */ TRIO_PRIVATE trio_userdef_t * -TrioFindNamespace(TRIO_CONST char *name, trio_userdef_t **prev) +TrioFindNamespace +TRIO_ARGS2((name, prev), + TRIO_CONST char *name, + trio_userdef_t **prev) { trio_userdef_t *def; @@ -892,6 +1023,117 @@ TrioFindNamespace(TRIO_CONST char *name, trio_userdef_t **prev) return def; } +#endif + +/************************************************************************* + * TrioPower + * + * Description: + * Calculate pow(base, exponent), where number and exponent are integers. + */ +TRIO_PRIVATE trio_long_double_t +TrioPower +TRIO_ARGS2((number, exponent), + int number, + int exponent) +{ + trio_long_double_t result; + + if (number == 10) + { + switch (exponent) + { + /* Speed up calculation of common cases */ + case 0: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1); + break; + case 1: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0); + break; + case 2: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1); + break; + case 3: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2); + break; + case 4: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3); + break; + case 5: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4); + break; + case 6: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5); + break; + case 7: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6); + break; + case 8: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7); + break; + case 9: + result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8); + break; + default: + result = powl((trio_long_double_t)number, + (trio_long_double_t)exponent); + break; + } + } + else + { + return powl((trio_long_double_t)number, (trio_long_double_t)exponent); + } + return result; +} + +/************************************************************************* + * TrioLogarithm + */ +TRIO_PRIVATE double +TrioLogarithm +TRIO_ARGS2((number, base), + double number, + int base) +{ + double result; + + if (number <= 0.0) + { + /* xlC crashes on log(0) */ + result = (number == 0.0) ? trio_ninf() : trio_nan(); + } + else + { + if (base == 10) + { + result = log10(number); + } + else + { + result = log10(number) / log10((double)base); + } + } + return result; +} + +/************************************************************************* + * TrioLogarithmBase + */ +TRIO_PRIVATE double +TrioLogarithmBase +TRIO_ARGS1((base), + int base) +{ + switch (base) + { + case BASE_BINARY : return 1.0; + case BASE_OCTAL : return 3.0; + case BASE_DECIMAL: return 3.321928094887362345; + case BASE_HEX : return 4.0; + default : return TrioLogarithm((double)base, 2); + } +} /************************************************************************* * TrioParse @@ -900,16 +1142,16 @@ TrioFindNamespace(TRIO_CONST char *name, trio_userdef_t **prev) * Parse the format string */ TRIO_PRIVATE int -TrioParse(int type, - TRIO_CONST char *format, - trio_parameter_t *parameters, - va_list arglist, - void **argarray) +TrioParse +TRIO_ARGS5((type, format, parameters, arglist, argarray), + int type, + TRIO_CONST char *format, + trio_parameter_t *parameters, + va_list *arglist, + trio_pointer_t *argarray) { -#if TRIO_ERRORS /* Count the number of times a parameter is referenced */ unsigned short usedEntries[MAX_PARAMETERS]; -#endif /* Parameter counters */ int parameterPosition; int currentParam; @@ -923,7 +1165,7 @@ TrioParse(int type, int index; /* Index into formatting string */ int dots; /* Count number of dots in modifier part */ BOOLEAN_T positional; /* Does the specifier have a positional? */ - BOOLEAN_T got_sticky = FALSE; /* Are there any sticky modifiers at all? */ + BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */ /* * indices specifies the order in which the parameters must be * read from the va_args (this is necessary to handle positionals) @@ -935,23 +1177,25 @@ TrioParse(int type, #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) int charlen; #endif + int save_errno; int i = -1; int num; char *tmpformat; - -#if TRIO_ERRORS + /* One and only one of arglist and argarray must be used */ + assert((arglist != NULL) ^ (argarray != NULL)); + /* * The 'parameters' array is not initialized, but we need to * know which entries we have used. */ memset(usedEntries, 0, sizeof(usedEntries)); -#endif + save_errno = errno; index = 0; parameterPosition = 0; #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - mblen(NULL, 0); + (void)mblen(NULL, 0); #endif while (format[index]) @@ -1034,8 +1278,11 @@ TrioParse(int type, /* After the first dot we have the precision */ flags |= FLAGS_PRECISION; - if ((QUALIFIER_STAR == format[index]) || - (QUALIFIER_PARAM == format[index])) + if ((QUALIFIER_STAR == format[index]) +#if defined(QUALIFIER_PARAM) + || (QUALIFIER_PARAM == format[index]) +#endif + ) { index++; flags |= FLAGS_PRECISION_PARAMETER; @@ -1076,8 +1323,11 @@ TrioParse(int type, /* After the second dot we have the base */ flags |= FLAGS_BASE; - if ((QUALIFIER_STAR == format[index]) || - (QUALIFIER_PARAM == format[index])) + if ((QUALIFIER_STAR == format[index]) +#if defined(QUALIFIER_PARAM) + || (QUALIFIER_PARAM == format[index]) +#endif + ) { index++; flags |= FLAGS_BASE_PARAMETER; @@ -1119,9 +1369,11 @@ TrioParse(int type, } break; /* QUALIFIER_DOT */ +#if defined(QUALIFIER_PARAM) case QUALIFIER_PARAM: type = TYPE_PRINT; /* FALLTHROUGH */ +#endif case QUALIFIER_STAR: /* This has different meanings for print and scan */ if (TYPE_PRINT == type) @@ -1292,7 +1544,7 @@ TrioParse(int type, #if defined(QUALIFIER_STICKY) case QUALIFIER_STICKY: flags |= FLAGS_STICKY; - got_sticky = TRUE; + gotSticky = TRUE; break; #endif @@ -1312,6 +1564,12 @@ TrioParse(int type, break; #endif +#if defined(QUALIFIER_ROUNDING_UPPER) + case QUALIFIER_ROUNDING_UPPER: + flags |= FLAGS_ROUNDING; + break; +#endif + default: /* Bail out completely to make the error more obvious */ return TRIO_ERROR_RETURN(TRIO_EINVAL, index); @@ -1324,9 +1582,7 @@ TrioParse(int type, */ if (flags & FLAGS_WIDTH_PARAMETER) { -#if TRIO_ERRORS usedEntries[width] += 1; -#endif parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = 0; indices[width] = pos; @@ -1334,9 +1590,7 @@ TrioParse(int type, } if (flags & FLAGS_PRECISION_PARAMETER) { -#if TRIO_ERRORS usedEntries[precision] += 1; -#endif parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = 0; indices[precision] = pos; @@ -1344,9 +1598,7 @@ TrioParse(int type, } if (flags & FLAGS_BASE_PARAMETER) { -#if TRIO_ERRORS usedEntries[base] += 1; -#endif parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = 0; indices[base] = pos; @@ -1354,9 +1606,7 @@ TrioParse(int type, } if (flags & FLAGS_VARSIZE_PARAMETER) { -#if TRIO_ERRORS usedEntries[varsize] += 1; -#endif parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = 0; indices[varsize] = pos; @@ -1492,6 +1742,10 @@ TrioParse(int type, break; case SPECIFIER_POINTER: + if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t)) + flags |= FLAGS_QUAD; + else if (sizeof(trio_pointer_t) == sizeof(long)) + flags |= FLAGS_LONG; parameters[pos].type = FORMAT_POINTER; break; @@ -1540,9 +1794,7 @@ TrioParse(int type, parameters[pos].flags = FLAGS_USER_DEFINED; /* Adjust parameters for insertion of new one */ pos++; -# if TRIO_ERRORS usedEntries[currentParam] += 1; -# endif parameters[pos].type = FORMAT_USER_DEFINED; currentParam++; indices[currentParam] = pos; @@ -1582,13 +1834,11 @@ TrioParse(int type, return TRIO_ERROR_RETURN(TRIO_EINVAL, index); } -#if TRIO_ERRORS /* Count the number of times this entry has been used */ usedEntries[currentParam] += 1; -#endif /* Find last sticky parameters */ - if (got_sticky && !(flags & FLAGS_STICKY)) + if (gotSticky && !(flags & FLAGS_STICKY)) { for (i = pos - 1; i >= 0; i--) { @@ -1627,7 +1877,6 @@ TrioParse(int type, for (num = 0; num <= maxParam; num++) { -#if TRIO_ERRORS if (usedEntries[num] != 1) { if (usedEntries[num] == 0) /* gap detected */ @@ -1635,7 +1884,6 @@ TrioParse(int type, else /* double references detected */ return TRIO_ERROR_RETURN(TRIO_EDBLREF, num); } -#endif i = indices[num]; @@ -1676,24 +1924,26 @@ TrioParse(int type, if (flags & FLAGS_WIDECHAR) { parameters[i].data.wstring = (argarray == NULL) - ? va_arg(arglist, wchar_t *) - : (wchar_t *)(argarray[num]); + ? va_arg(*arglist, trio_wchar_t *) + : (trio_wchar_t *)(argarray[num]); } else #endif { parameters[i].data.string = (argarray == NULL) - ? va_arg(arglist, char *) + ? va_arg(*arglist, char *) : (char *)(argarray[num]); } break; +#if defined(FORMAT_USER_DEFINED) + case FORMAT_USER_DEFINED: +#endif case FORMAT_POINTER: case FORMAT_COUNT: - case FORMAT_USER_DEFINED: case FORMAT_UNKNOWN: parameters[i].data.pointer = (argarray == NULL) - ? va_arg(arglist, void *) + ? va_arg(*arglist, trio_pointer_t ) : argarray[num]; break; @@ -1703,18 +1953,18 @@ TrioParse(int type, { if (argarray == NULL) parameters[i].data.pointer = - (trio_uintmax_t *)va_arg(arglist, void *); + (trio_pointer_t)va_arg(*arglist, trio_pointer_t); else { if (parameters[i].type == FORMAT_CHAR) parameters[i].data.pointer = - (trio_uintmax_t *)((char *)argarray[num]); + (trio_pointer_t)((char *)argarray[num]); else if (parameters[i].flags & FLAGS_SHORT) parameters[i].data.pointer = - (trio_uintmax_t *)((short *)argarray[num]); + (trio_pointer_t)((short *)argarray[num]); else parameters[i].data.pointer = - (trio_uintmax_t *)((int *)argarray[num]); + (trio_pointer_t)((int *)argarray[num]); } } else @@ -1761,36 +2011,36 @@ TrioParse(int type, #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) if (parameters[i].flags & FLAGS_SIZE_T) parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(arglist, size_t) + ? (trio_uintmax_t)va_arg(*arglist, size_t) : (trio_uintmax_t)(*((size_t *)argarray[num])); else #endif #if defined(QUALIFIER_PTRDIFF_T) if (parameters[i].flags & FLAGS_PTRDIFF_T) parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t) + ? (trio_uintmax_t)va_arg(*arglist, ptrdiff_t) : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num])); else #endif #if defined(QUALIFIER_INTMAX_T) if (parameters[i].flags & FLAGS_INTMAX_T) parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(arglist, trio_intmax_t) + ? (trio_uintmax_t)va_arg(*arglist, trio_intmax_t) : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num])); else #endif if (parameters[i].flags & FLAGS_QUAD) parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(arglist, trio_ulonglong_t) + ? (trio_uintmax_t)va_arg(*arglist, trio_ulonglong_t) : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num])); else if (parameters[i].flags & FLAGS_LONG) parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(arglist, long) + ? (trio_uintmax_t)va_arg(*arglist, long) : (trio_uintmax_t)(*((long *)argarray[num])); else { if (argarray == NULL) - parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int); + parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(*arglist, int); else { if (parameters[i].type == FORMAT_CHAR) @@ -1811,56 +2061,52 @@ TrioParse(int type, */ if (parameters[i].flags & FLAGS_USER_DEFINED) parameters[i].data.pointer = (argarray == NULL) - ? va_arg(arglist, void *) + ? va_arg(*arglist, trio_pointer_t ) : argarray[num]; else parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(arglist, int) + ? (trio_uintmax_t)va_arg(*arglist, int) : (trio_uintmax_t)(*((int *)argarray[num])); break; case FORMAT_DOUBLE: if (TYPE_SCAN == type) { - if (parameters[i].flags & FLAGS_LONG) + if (parameters[i].flags & FLAGS_LONGDOUBLE) parameters[i].data.longdoublePointer = (argarray == NULL) - ? va_arg(arglist, long double *) - : (long double *)((long double *)argarray[num]); + ? va_arg(*arglist, trio_long_double_t *) + : (trio_long_double_t *)argarray[num]; else { - if (argarray == NULL) - parameters[i].data.doublePointer = - va_arg(arglist, double *); - else - { - if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.doublePointer = - (double *)((float *)argarray[num]); - else - parameters[i].data.doublePointer = - (double *)((double *)argarray[num]); - } + if (parameters[i].flags & FLAGS_LONG) + parameters[i].data.doublePointer = (argarray == NULL) + ? va_arg(*arglist, double *) + : (double *)argarray[num]; + else + parameters[i].data.doublePointer = (argarray == NULL) + ? (double *)va_arg(*arglist, float *) + : (double *)((float *)argarray[num]); } } else { - if (parameters[i].flags & FLAGS_LONG) + if (parameters[i].flags & FLAGS_LONGDOUBLE) parameters[i].data.longdoubleNumber = (argarray == NULL) - ? va_arg(arglist, long double) - : (long double)(*((long double *)argarray[num])); + ? va_arg(*arglist, trio_long_double_t) + : (trio_long_double_t)(*((trio_long_double_t *)argarray[num])); else { if (argarray == NULL) parameters[i].data.longdoubleNumber = - (long double)va_arg(arglist, double); + (trio_long_double_t)va_arg(*arglist, double); else { if (parameters[i].flags & FLAGS_SHORT) parameters[i].data.longdoubleNumber = - (long double)(*((float *)argarray[num])); + (trio_long_double_t)(*((float *)argarray[num])); else parameters[i].data.longdoubleNumber = - (long double)(long double)(*((double *)argarray[num])); + (trio_long_double_t)(*((double *)argarray[num])); } } } @@ -1868,7 +2114,7 @@ TrioParse(int type, #if defined(FORMAT_ERRNO) case FORMAT_ERRNO: - parameters[i].data.errorNumber = errno; + parameters[i].data.errorNumber = save_errno; break; #endif @@ -1896,12 +2142,14 @@ TrioParse(int type, * of the dependencies of the flags. */ TRIO_PRIVATE void -TrioWriteNumber(trio_class_t *self, - trio_uintmax_t number, - unsigned long flags, - int width, - int precision, - int base) +TrioWriteNumber +TRIO_ARGS6((self, number, flags, width, precision, base), + trio_class_t *self, + trio_uintmax_t number, + unsigned long flags, + int width, + int precision, + int base) { BOOLEAN_T isNegative; char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1]; @@ -1911,8 +2159,6 @@ TrioWriteNumber(trio_class_t *self, int i; int length; char *p; - int charsPerThousand; - int groupingIndex; int count; assert(VALID(self)); @@ -1920,12 +2166,14 @@ TrioWriteNumber(trio_class_t *self, assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; + if (base == NO_BASE) + base = BASE_DECIMAL; isNegative = (flags & FLAGS_UNSIGNED) ? FALSE : ((trio_intmax_t)number < 0); if (isNegative) - number = -number; + number = -((trio_intmax_t)number); if (flags & FLAGS_QUAD) number &= (trio_ulonglong_t)-1; @@ -1937,8 +2185,6 @@ TrioWriteNumber(trio_class_t *self, /* Build number */ pointer = bufferend = &buffer[sizeof(buffer) - 1]; *pointer-- = NIL; - charsPerThousand = (int)internalGrouping[0]; - groupingIndex = 1; for (i = 1; i < (int)sizeof(buffer); i++) { *pointer-- = digits[number % base]; @@ -1946,35 +2192,20 @@ TrioWriteNumber(trio_class_t *self, if (number == 0) break; - if ((flags & FLAGS_QUOTE) - && (charsPerThousand != NO_GROUPING) - && (i % charsPerThousand == 0)) + if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1)) { /* * We are building the number from the least significant * to the most significant digit, so we have to copy the * thousand separator backwards */ - length = trio_length(internalThousandSeparator); + length = internalThousandSeparatorLength; if (((int)(pointer - buffer) - length) > 0) { p = &internalThousandSeparator[length - 1]; while (length-- > 0) *pointer-- = *p--; } - - /* Advance to next grouping number */ - switch (internalGrouping[groupingIndex]) - { - case CHAR_MAX: /* Disable grouping */ - charsPerThousand = NO_GROUPING; - break; - case 0: /* Repeat last group */ - break; - default: - charsPerThousand = (int)internalGrouping[groupingIndex++]; - break; - } } } @@ -2082,13 +2313,15 @@ TrioWriteNumber(trio_class_t *self, * Output a single character of a string */ TRIO_PRIVATE void -TrioWriteStringCharacter(trio_class_t *self, - int ch, - unsigned long flags) +TrioWriteStringCharacter +TRIO_ARGS3((self, ch, flags), + trio_class_t *self, + int ch, + unsigned long flags) { if (flags & FLAGS_ALTERNATIVE) { - if (! (isprint(ch) || isspace(ch))) + if (! isprint(ch)) { /* * Non-printable characters are converted to C escapes or @@ -2107,7 +2340,7 @@ TrioWriteStringCharacter(trio_class_t *self, case '\\': self->OutStream(self, '\\'); break; default: self->OutStream(self, 'x'); - TrioWriteNumber(self, (trio_intmax_t)ch, + TrioWriteNumber(self, (trio_uintmax_t)ch, FLAGS_UNSIGNED | FLAGS_NILPADDING, 2, 2, BASE_HEX); break; @@ -2136,11 +2369,13 @@ TrioWriteStringCharacter(trio_class_t *self, * Output a string */ TRIO_PRIVATE void -TrioWriteString(trio_class_t *self, - TRIO_CONST char *string, - unsigned long flags, - int width, - int precision) +TrioWriteString +TRIO_ARGS5((self, string, flags, width, precision), + trio_class_t *self, + TRIO_CONST char *string, + unsigned long flags, + int width, + int precision) { int length; int ch; @@ -2200,10 +2435,12 @@ TrioWriteString(trio_class_t *self, */ #if TRIO_WIDECHAR TRIO_PRIVATE int -TrioWriteWideStringCharacter(trio_class_t *self, - wchar_t wch, - unsigned long flags, - int width) +TrioWriteWideStringCharacter +TRIO_ARGS4((self, wch, flags, width), + trio_class_t *self, + trio_wchar_t wch, + unsigned long flags, + int width) { int size; int i; @@ -2238,11 +2475,13 @@ TrioWriteWideStringCharacter(trio_class_t *self, */ #if TRIO_WIDECHAR TRIO_PRIVATE void -TrioWriteWideString(trio_class_t *self, - TRIO_CONST wchar_t *wstring, - unsigned long flags, - int width, - int precision) +TrioWriteWideString +TRIO_ARGS5((self, wstring, flags, width, precision), + trio_class_t *self, + TRIO_CONST trio_wchar_t *wstring, + unsigned long flags, + int width, + int precision) { int length; int size; @@ -2251,7 +2490,7 @@ TrioWriteWideString(trio_class_t *self, assert(VALID(self->OutStream)); #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - mblen(NULL, 0); + (void)mblen(NULL, 0); #endif if (wstring == NULL) @@ -2299,100 +2538,155 @@ TrioWriteWideString(trio_class_t *self, /************************************************************************* * TrioWriteDouble + * + * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm + * + * "5.2.4.2.2 paragraph #4 + * + * The accuracy [...] is implementation defined, as is the accuracy + * of the conversion between floating-point internal representations + * and string representations performed by the libray routine in + * " + */ +/* FIXME: handle all instances of constant long-double number (L) + * and *l() math functions. */ TRIO_PRIVATE void -TrioWriteDouble(trio_class_t *self, - long double longdoubleNumber, - unsigned long flags, - int width, - int precision, - int base) +TrioWriteDouble +TRIO_ARGS6((self, number, flags, width, precision, base), + trio_class_t *self, + trio_long_double_t number, + unsigned long flags, + int width, + int precision, + int base) { - int charsPerThousand; - int length; - double number; - double workNumber; + trio_long_double_t integerNumber; + trio_long_double_t fractionNumber; + trio_long_double_t workNumber; int integerDigits; int fractionDigits; int exponentDigits; + int baseDigits; + int integerThreshold; + int fractionThreshold; int expectedWidth; - int exponent; + int exponent = 0; unsigned int uExponent = 0; - double dblBase; + int exponentBase; + trio_long_double_t dblBase; + trio_long_double_t dblIntegerBase; + trio_long_double_t dblFractionBase; + trio_long_double_t integerAdjust; + trio_long_double_t fractionAdjust; BOOLEAN_T isNegative; BOOLEAN_T isExponentNegative = FALSE; + BOOLEAN_T requireTwoDigitExponent; BOOLEAN_T isHex; TRIO_CONST char *digits; - char numberBuffer[MAX_MANTISSA_DIGITS - * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1]; - char *numberPointer; - char exponentBuffer[MAX_EXPONENT_DIGITS + 1]; - char *exponentPointer = NULL; - int groupingIndex; - char *work; + char *groupingPointer; int i; - BOOLEAN_T onlyzero; + int index; + BOOLEAN_T hasOnlyZeroes; int zeroes = 0; + register int trailingZeroes; + BOOLEAN_T keepTrailingZeroes; + BOOLEAN_T keepDecimalPoint; + trio_long_double_t epsilon; assert(VALID(self)); assert(VALID(self->OutStream)); - assert(base == BASE_DECIMAL || base == BASE_HEX); + assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); - number = (double)longdoubleNumber; - - /* Look for infinite numbers and non-a-number first */ - switch (trio_isinf(number)) - { - case 1: - /* Positive infinity */ - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? INFINITE_UPPER - : INFINITE_LOWER, - flags, width, precision); - return; - - case -1: - /* Negative infinity */ - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? "-" INFINITE_UPPER - : "-" INFINITE_LOWER, - flags, width, precision); - return; - - default: - /* Finitude */ - break; - } - if (trio_isnan(number)) + /* Determine sign and look for special quantities */ + switch (trio_fpclassify_and_signbit(number, &isNegative)) { + case TRIO_FP_NAN: TrioWriteString(self, (flags & FLAGS_UPPER) ? NAN_UPPER : NAN_LOWER, flags, width, precision); return; + + case TRIO_FP_INFINITE: + if (isNegative) + { + /* Negative infinity */ + TrioWriteString(self, + (flags & FLAGS_UPPER) + ? "-" INFINITE_UPPER + : "-" INFINITE_LOWER, + flags, width, precision); + return; + } + else + { + /* Positive infinity */ + TrioWriteString(self, + (flags & FLAGS_UPPER) + ? INFINITE_UPPER + : INFINITE_LOWER, + flags, width, precision); + return; + } + + default: + /* Finitude */ + break; + } + + /* Normal numbers */ + if (flags & FLAGS_LONGDOUBLE) + { + baseDigits = (base == 10) + ? LDBL_DIG + : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base)); + epsilon = LDBL_EPSILON; + } + else if (flags & FLAGS_SHORT) + { + baseDigits = (base == BASE_DECIMAL) + ? FLT_DIG + : (int)floor(FLT_MANT_DIG / TrioLogarithmBase(base)); + epsilon = FLT_EPSILON; + } + else + { + baseDigits = (base == BASE_DECIMAL) + ? DBL_DIG + : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base)); + epsilon = DBL_EPSILON; } - /* Normal numbers */ digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; isHex = (base == BASE_HEX); - dblBase = (double)base; + if (base == NO_BASE) + base = BASE_DECIMAL; + dblBase = (trio_long_double_t)base; + keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) || + ( (flags & FLAGS_FLOAT_G) && + !(flags & FLAGS_ALTERNATIVE) ) ); + + if (flags & FLAGS_ROUNDING) + precision = baseDigits; if (precision == NO_PRECISION) precision = FLT_DIG; - isNegative = (number < 0.0); if (isNegative) number = -number; - if ((flags & FLAGS_FLOAT_G) || isHex) + if (isHex) + flags |= FLAGS_FLOAT_E; + + if (flags & FLAGS_FLOAT_G) { if (precision == 0) precision = 1; - if ((number < 1.0e-4) || (number > pow(10.0, (double)precision))) + if ((number < 1.0E-4) || (number > powl(base, + (trio_long_double_t)precision))) { /* Use scientific notation */ flags |= FLAGS_FLOAT_E; @@ -2404,17 +2698,18 @@ TrioWriteDouble(trio_class_t *self, * zero, then adjust the precision to include leading fractional * zeros. */ - workNumber = fabs(guarded_log10(number)); - if (workNumber - floor(workNumber) < 0.001) + workNumber = TrioLogarithm(number, base); + workNumber = TRIO_FABS(workNumber); + if (workNumber - floorl(workNumber) < 0.001) workNumber--; - zeroes = (int)floor(workNumber); + zeroes = (int)floorl(workNumber); } } if (flags & FLAGS_FLOAT_E) { /* Scale the number */ - workNumber = guarded_log10(number); + workNumber = TrioLogarithm(number, base); if (trio_isinf(workNumber) == -1) { exponent = 0; @@ -2424,8 +2719,8 @@ TrioWriteDouble(trio_class_t *self, } else { - exponent = (int)floor(workNumber); - number /= pow(10.0, (double)exponent); + exponent = (int)floorl(workNumber); + number /= powl(dblBase, (trio_long_double_t)exponent); isExponentNegative = (exponent < 0); uExponent = (isExponentNegative) ? -exponent : exponent; /* No thousand separators */ @@ -2433,140 +2728,107 @@ TrioWriteDouble(trio_class_t *self, } } + integerNumber = floorl(number); + fractionNumber = number - integerNumber; + /* * Truncated number. * - * precision is number of significant digits for FLOAT_G - * and number of fractional digits for others + * Precision is number of significant digits for FLOAT_G + * and number of fractional digits for others. */ - integerDigits = (floor(number) > DBL_EPSILON) - ? 1 + (int)guarded_log10(floor(number)) + integerDigits = (integerNumber > epsilon) + ? 1 + (int)TrioLogarithm(integerNumber, base) : 1; fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0)) ? precision - integerDigits : zeroes + precision; + + dblFractionBase = TrioPower(base, fractionDigits); - 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) + workNumber = number + 0.5 / dblFractionBase; + if (floorl(number) != floorl(workNumber)) { 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; + exponent++; + isExponentNegative = (exponent < 0); + uExponent = (isExponentNegative) ? -exponent : exponent; + workNumber = (number + 0.5 / dblFractionBase) / dblBase; + integerNumber = floorl(workNumber); + fractionNumber = workNumber - integerNumber; } else { /* Adjust if number was rounded up one digit (ie. 99 to 100) */ - integerDigits++; + integerNumber = floorl(number + 0.5); + fractionNumber = 0.0; + integerDigits = (integerNumber > epsilon) + ? 1 + (int)TrioLogarithm(integerNumber, base) + : 1; } } - - /* Build the fraction part */ - numberPointer = &numberBuffer[sizeof(numberBuffer) - 1]; - *numberPointer = NIL; - onlyzero = TRUE; - for (i = 0; i < fractionDigits; i++) - { - *(--numberPointer) = digits[(int)fmod(number, dblBase)]; - number = floor(number / dblBase); - 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++; - } + /* Estimate accuracy */ + integerAdjust = fractionAdjust = 0.5; + if (flags & FLAGS_ROUNDING) + { + if (integerDigits > baseDigits) + { + integerThreshold = baseDigits; + fractionDigits = 0; + dblFractionBase = 1.0; + fractionThreshold = 0; + precision = 0; /* Disable decimal-point */ + integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1); + fractionAdjust = 0.0; + } else - onlyzero = FALSE; - } - - /* Insert decimal point */ - if ((flags & FLAGS_ALTERNATIVE) || ((fractionDigits > 0) && !onlyzero)) - { - i = trio_length(internalDecimalPoint); - while (i> 0) { - *(--numberPointer) = internalDecimalPoint[--i]; + integerThreshold = integerDigits; + fractionThreshold = fractionDigits - integerThreshold; + fractionAdjust = 1.0; } } - /* Insert the integer part and thousand separators */ - charsPerThousand = (int)internalGrouping[0]; - groupingIndex = 1; - for (i = 1; i < integerDigits + 1; i++) + else { - *(--numberPointer) = digits[(int)fmod(number, dblBase)]; - number = floor(number / dblBase); - if (number < DBL_EPSILON) - break; - - if ((i > 0) - && ((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE) - && (charsPerThousand != NO_GROUPING) - && (i % charsPerThousand == 0)) - { - /* - * We are building the number from the least significant - * to the most significant digit, so we have to copy the - * thousand separator backwards - */ - length = trio_length(internalThousandSeparator); - integerDigits += length; - if (((int)(numberPointer - numberBuffer) - length) > 0) - { - work = &internalThousandSeparator[length - 1]; - while (length-- > 0) - *(--numberPointer) = *work--; - } - - /* Advance to next grouping number */ - if (charsPerThousand != NO_GROUPING) - { - switch (internalGrouping[groupingIndex]) - { - case CHAR_MAX: /* Disable grouping */ - charsPerThousand = NO_GROUPING; - break; - case 0: /* Repeat last group */ - break; - default: - charsPerThousand = (int)internalGrouping[groupingIndex++]; - break; - } - } - } + integerThreshold = INT_MAX; + fractionThreshold = INT_MAX; } - /* Build the exponent */ - exponentDigits = 0; - if (flags & FLAGS_FLOAT_E) - { - exponentPointer = &exponentBuffer[sizeof(exponentBuffer) - 1]; - *exponentPointer-- = NIL; - do { - *exponentPointer-- = digits[uExponent % base]; - uExponent /= base; - exponentDigits++; - } while (uExponent); - } - /* * Calculate expected width. * sign + integer part + thousands separators + decimal point * + fraction + exponent */ - expectedWidth = trio_length(numberPointer); - if (isNegative || (flags & FLAGS_SHOWSIGN)) + fractionAdjust /= dblFractionBase; + hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon); + keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) || + !((precision == 0) || + (!keepTrailingZeroes && hasOnlyZeroes)) ); + if (flags & FLAGS_FLOAT_E) + { + exponentDigits = (uExponent == 0) + ? 1 + : (int)ceil(TrioLogarithm((double)(uExponent + 1), base)); + } + else + exponentDigits = 0; + requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1)); + + expectedWidth = integerDigits + fractionDigits + + (keepDecimalPoint + ? internalDecimalPointLength + : 0) + + ((flags & FLAGS_QUOTE) + ? TrioCalcThousandSeparatorLength(integerDigits) + : 0); + if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) expectedWidth += sizeof("-") - 1; if (exponentDigits > 0) expectedWidth += exponentDigits + - ((exponentDigits > 1) ? sizeof("E+") : sizeof("E+0")) - 1; + ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1); if (isHex) expectedWidth += sizeof("0X") - 1; @@ -2578,6 +2840,8 @@ TrioWriteDouble(trio_class_t *self, self->OutStream(self, '-'); else if (flags & FLAGS_SHOWSIGN) self->OutStream(self, '+'); + else if (flags & FLAGS_SPACE) + self->OutStream(self, ' '); if (isHex) { self->OutStream(self, '0'); @@ -2605,17 +2869,101 @@ TrioWriteDouble(trio_class_t *self, self->OutStream(self, '-'); else if (flags & FLAGS_SHOWSIGN) self->OutStream(self, '+'); + else if (flags & FLAGS_SPACE) + self->OutStream(self, ' '); if (isHex) { self->OutStream(self, '0'); self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); } } - /* Output number */ - for (i = 0; numberPointer[i]; i++) + + /* Output the integer part and thousand separators */ + dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1); + for (i = 0; i < integerDigits; i++) { - self->OutStream(self, numberPointer[i]); + workNumber = floorl(((integerNumber + integerAdjust) * dblIntegerBase)); + if (i > integerThreshold) + { + /* Beyond accuracy */ + self->OutStream(self, digits[0]); + } + else + { + self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]); + } + dblIntegerBase *= dblBase; + + if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE) + && TrioFollowedBySeparator(integerDigits - i)) + { + for (groupingPointer = internalThousandSeparator; + *groupingPointer != NIL; + groupingPointer++) + { + self->OutStream(self, *groupingPointer); + } + } } + + /* Insert decimal point and build the fraction part */ + trailingZeroes = 0; + + if (keepDecimalPoint) + { + if (internalDecimalPoint) + { + self->OutStream(self, internalDecimalPoint); + } + else + { + for (i = 0; i < internalDecimalPointLength; i++) + { + self->OutStream(self, internalDecimalPointString[i]); + } + } + } + + for (i = 0; i < fractionDigits; i++) + { + if ((integerDigits > integerThreshold) || (i > fractionThreshold)) + { + /* Beyond accuracy */ + trailingZeroes++; + } + else + { + fractionNumber *= dblBase; + fractionAdjust *= dblBase; + workNumber = floorl(fractionNumber + fractionAdjust); + fractionNumber -= workNumber; + index = (int)fmodl(workNumber, dblBase); + if (index == 0) + { + trailingZeroes++; + } + else + { + while (trailingZeroes > 0) + { + /* Not trailing zeroes after all */ + self->OutStream(self, digits[0]); + trailingZeroes--; + } + self->OutStream(self, digits[index]); + } + } + } + + if (keepTrailingZeroes) + { + while (trailingZeroes > 0) + { + self->OutStream(self, digits[0]); + trailingZeroes--; + } + } + /* Output exponent */ if (exponentDigits > 0) { @@ -2626,12 +2974,14 @@ TrioWriteDouble(trio_class_t *self, self->OutStream(self, (isExponentNegative) ? '-' : '+'); /* The exponent must contain at least two digits */ - if (exponentDigits == 1) + if (requireTwoDigitExponent) self->OutStream(self, '0'); + exponentBase = (int)TrioPower(base, exponentDigits - 1); for (i = 0; i < exponentDigits; i++) { - self->OutStream(self, exponentPointer[i + 1]); + self->OutStream(self, digits[(uExponent / exponentBase) % base]); + exponentBase /= base; } } /* Output trailing spaces */ @@ -2651,17 +3001,18 @@ TrioWriteDouble(trio_class_t *self, * This is the main engine for formatting output */ TRIO_PRIVATE int -TrioFormatProcess(trio_class_t *data, - TRIO_CONST char *format, - trio_parameter_t *parameters) - +TrioFormatProcess +TRIO_ARGS3((data, format, parameters), + trio_class_t *data, + TRIO_CONST char *format, + trio_parameter_t *parameters) { #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) int charlen; #endif int i; TRIO_CONST char *string; - void *pointer; + trio_pointer_t pointer; unsigned long flags; int width; int precision; @@ -2671,7 +3022,7 @@ TrioFormatProcess(trio_class_t *data, index = 0; i = 0; #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - mblen(NULL, 0); + (void)mblen(NULL, 0); #endif while (format[index]) @@ -2680,11 +3031,19 @@ TrioFormatProcess(trio_class_t *data, if (! isascii(format[index])) { charlen = mblen(&format[index], MB_LEN_MAX); - while (charlen-- > 0) + /* + * Only valid multibyte characters are handled here. Invalid + * multibyte characters (charlen == -1) are handled as normal + * characters. + */ + if (charlen != -1) { - data->OutStream(data, format[index++]); + while (charlen-- > 0) + { + data->OutStream(data, format[index++]); + } + continue; /* while characters left in formatting string */ } - continue; /* while */ } #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ if (CHAR_IDENTIFIER == format[index]) @@ -2747,7 +3106,7 @@ TrioFormatProcess(trio_class_t *data, if (flags & FLAGS_WIDECHAR) { TrioWriteWideStringCharacter(data, - (wchar_t)parameters[i].data.number.as_signed, + (trio_wchar_t)parameters[i].data.number.as_signed, flags, NO_WIDTH); } @@ -2770,11 +3129,8 @@ TrioFormatProcess(trio_class_t *data, break; /* FORMAT_CHAR */ case FORMAT_INT: - if (base == NO_BASE) - base = BASE_DECIMAL; - TrioWriteNumber(data, - parameters[i].data.number.as_signed, + parameters[i].data.number.as_unsigned, flags, width, precision, @@ -2883,7 +3239,7 @@ TrioFormatProcess(trio_class_t *data, { data->OutStream(data, '#'); TrioWriteNumber(data, - (trio_intmax_t)parameters[i].data.errorNumber, + (trio_uintmax_t)parameters[i].data.errorNumber, flags, width, precision, @@ -2940,10 +3296,12 @@ TrioFormatProcess(trio_class_t *data, * TrioFormatRef */ TRIO_PRIVATE int -TrioFormatRef(trio_reference_t *reference, - TRIO_CONST char *format, - va_list arglist, - void **argarray) +TrioFormatRef +TRIO_ARGS4((reference, format, arglist, argarray), + trio_reference_t *reference, + TRIO_CONST char *format, + va_list *arglist, + trio_pointer_t *argarray) { int status; trio_parameter_t parameters[MAX_PARAMETERS]; @@ -2964,12 +3322,14 @@ TrioFormatRef(trio_reference_t *reference, * TrioFormat */ TRIO_PRIVATE int -TrioFormat(void *destination, +TrioFormat +TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray), + trio_pointer_t destination, size_t destinationSize, - void (*OutStream)(trio_class_t *, int), + void (*OutStream) TRIO_PROTO((trio_class_t *, int)), TRIO_CONST char *format, - va_list arglist, - void **argarray) + va_list *arglist, + trio_pointer_t *argarray) { int status; trio_class_t data; @@ -3007,14 +3367,17 @@ TrioFormat(void *destination, * TrioOutStreamFile */ TRIO_PRIVATE void -TrioOutStreamFile(trio_class_t *self, - int output) +TrioOutStreamFile +TRIO_ARGS2((self, output), + trio_class_t *self, + int output) { - FILE *file = (FILE *)self->location; + FILE *file; assert(VALID(self)); - assert(VALID(file)); + assert(VALID(self->location)); + file = (FILE *)self->location; self->processed++; if (fputc(output, file) == EOF) { @@ -3030,14 +3393,17 @@ TrioOutStreamFile(trio_class_t *self, * TrioOutStreamFileDescriptor */ TRIO_PRIVATE void -TrioOutStreamFileDescriptor(trio_class_t *self, - int output) +TrioOutStreamFileDescriptor +TRIO_ARGS2((self, output), + trio_class_t *self, + int output) { - int fd = *((int *)self->location); + int fd; char ch; assert(VALID(self)); + fd = *((int *)self->location); ch = (char)output; self->processed++; if (write(fd, &ch, sizeof(char)) == -1) @@ -3050,18 +3416,55 @@ TrioOutStreamFileDescriptor(trio_class_t *self, } } +/************************************************************************* + * TrioOutStreamCustom + */ +TRIO_PRIVATE void +TrioOutStreamCustom +TRIO_ARGS2((self, output), + trio_class_t *self, + int output) +{ + int status; + trio_custom_t *data; + + assert(VALID(self)); + assert(VALID(self->location)); + + data = (trio_custom_t *)self->location; + if (data->stream.out) + { + status = (data->stream.out)(data->closure, output); + if (status >= 0) + { + self->committed++; + } + else + { + if (self->error == 0) + { + self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status); + } + } + } + self->processed++; +} + /************************************************************************* * TrioOutStreamString */ TRIO_PRIVATE void -TrioOutStreamString(trio_class_t *self, - int output) +TrioOutStreamString +TRIO_ARGS2((self, output), + trio_class_t *self, + int output) { - char **buffer = (char **)self->location; + char **buffer; assert(VALID(self)); - assert(VALID(buffer)); + assert(VALID(self->location)); + buffer = (char **)self->location; **buffer = (char)output; (*buffer)++; self->processed++; @@ -3072,14 +3475,17 @@ TrioOutStreamString(trio_class_t *self, * TrioOutStreamStringMax */ TRIO_PRIVATE void -TrioOutStreamStringMax(trio_class_t *self, - int output) +TrioOutStreamStringMax +TRIO_ARGS2((self, output), + trio_class_t *self, + int output) { char **buffer; assert(VALID(self)); + assert(VALID(self->location)); + buffer = (char **)self->location; - assert(VALID(buffer)); if (self->processed < self->max) { @@ -3094,8 +3500,10 @@ TrioOutStreamStringMax(trio_class_t *self, * TrioOutStreamStringDynamic */ TRIO_PRIVATE void -TrioOutStreamStringDynamic(trio_class_t *self, - int output) +TrioOutStreamStringDynamic +TRIO_ARGS2((self, output), + trio_class_t *self, + int output) { assert(VALID(self)); assert(VALID(self->location)); @@ -3135,17 +3543,19 @@ TrioOutStreamStringDynamic(trio_class_t *self, @return Number of printed characters. */ TRIO_PUBLIC int -trio_printf(TRIO_CONST char *format, - ...) +trio_printf +TRIO_VARGS2((format, va_alist), + TRIO_CONST char *format, + TRIO_VA_DECL) { int status; va_list args; assert(VALID(format)); - va_start(args, format); - status = TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL); - va_end(args); + TRIO_VA_START(args, format); + status = TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL); + TRIO_VA_END(args); return status; } @@ -3157,12 +3567,14 @@ trio_printf(TRIO_CONST char *format, @return Number of printed characters. */ TRIO_PUBLIC int -trio_vprintf(TRIO_CONST char *format, - va_list args) +trio_vprintf +TRIO_ARGS2((format, args), + TRIO_CONST char *format, + va_list args) { assert(VALID(format)); - return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL); + return TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL); } /** @@ -3173,14 +3585,14 @@ trio_vprintf(TRIO_CONST char *format, @return Number of printed characters. */ TRIO_PUBLIC int -trio_printfv(TRIO_CONST char *format, - void ** args) +trio_printfv +TRIO_ARGS2((format, args), + TRIO_CONST char *format, + trio_pointer_t * args) { - va_list dummy; - assert(VALID(format)); - return TrioFormat(stdout, 0, TrioOutStreamFile, format, dummy, args); + return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args); } /************************************************************************* @@ -3196,9 +3608,11 @@ trio_printfv(TRIO_CONST char *format, @return Number of printed characters. */ TRIO_PUBLIC int -trio_fprintf(FILE *file, - TRIO_CONST char *format, - ...) +trio_fprintf +TRIO_VARGS3((file, format, va_alist), + FILE *file, + TRIO_CONST char *format, + TRIO_VA_DECL) { int status; va_list args; @@ -3206,9 +3620,9 @@ trio_fprintf(FILE *file, assert(VALID(file)); assert(VALID(format)); - va_start(args, format); - status = TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL); - va_end(args); + TRIO_VA_START(args, format); + status = TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL); + TRIO_VA_END(args); return status; } @@ -3221,14 +3635,16 @@ trio_fprintf(FILE *file, @return Number of printed characters. */ TRIO_PUBLIC int -trio_vfprintf(FILE *file, - TRIO_CONST char *format, - va_list args) +trio_vfprintf +TRIO_ARGS3((file, format, args), + FILE *file, + TRIO_CONST char *format, + va_list args) { assert(VALID(file)); assert(VALID(format)); - return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL); + return TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL); } /** @@ -3240,16 +3656,16 @@ trio_vfprintf(FILE *file, @return Number of printed characters. */ TRIO_PUBLIC int -trio_fprintfv(FILE *file, - TRIO_CONST char *format, - void ** args) +trio_fprintfv +TRIO_ARGS3((file, format, args), + FILE *file, + TRIO_CONST char *format, + trio_pointer_t * args) { - va_list dummy; - assert(VALID(file)); assert(VALID(format)); - return TrioFormat(file, 0, TrioOutStreamFile, format, dummy, args); + return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args); } /************************************************************************* @@ -3265,18 +3681,20 @@ trio_fprintfv(FILE *file, @return Number of printed characters. */ TRIO_PUBLIC int -trio_dprintf(int fd, - TRIO_CONST char *format, - ...) +trio_dprintf +TRIO_VARGS3((fd, format, va_alist), + int fd, + TRIO_CONST char *format, + TRIO_VA_DECL) { int status; va_list args; assert(VALID(format)); - va_start(args, format); - status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL); - va_end(args); + TRIO_VA_START(args, format); + status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL); + TRIO_VA_END(args); return status; } @@ -3289,13 +3707,15 @@ trio_dprintf(int fd, @return Number of printed characters. */ TRIO_PUBLIC int -trio_vdprintf(int fd, - TRIO_CONST char *format, - va_list args) +trio_vdprintf +TRIO_ARGS3((fd, format, args), + int fd, + TRIO_CONST char *format, + va_list args) { assert(VALID(format)); - return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL); + return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL); } /** @@ -3307,15 +3727,77 @@ trio_vdprintf(int fd, @return Number of printed characters. */ TRIO_PUBLIC int -trio_dprintfv(int fd, - TRIO_CONST char *format, - void **args) +trio_dprintfv +TRIO_ARGS3((fd, format, args), + int fd, + TRIO_CONST char *format, + trio_pointer_t *args) { - va_list dummy; - assert(VALID(format)); - return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, dummy, args); + return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args); +} + +/************************************************************************* + * cprintf + */ +TRIO_PUBLIC int +trio_cprintf +TRIO_VARGS4((stream, closure, format, va_alist), + trio_outstream_t stream, + trio_pointer_t closure, + TRIO_CONST char *format, + TRIO_VA_DECL) +{ + int status; + va_list args; + trio_custom_t data; + + assert(VALID(stream)); + assert(VALID(format)); + + TRIO_VA_START(args, format); + data.stream.out = stream; + data.closure = closure; + status = TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL); + TRIO_VA_END(args); + return status; +} + +TRIO_PUBLIC int +trio_vcprintf +TRIO_ARGS4((stream, closure, format, args), + trio_outstream_t stream, + trio_pointer_t closure, + TRIO_CONST char *format, + va_list args) +{ + trio_custom_t data; + + assert(VALID(stream)); + assert(VALID(format)); + + data.stream.out = stream; + data.closure = closure; + return TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL); +} + +TRIO_PUBLIC int +trio_cprintfv +TRIO_ARGS4((stream, closure, format, args), + trio_outstream_t stream, + trio_pointer_t closure, + TRIO_CONST char *format, + void **args) +{ + trio_custom_t data; + + assert(VALID(stream)); + assert(VALID(format)); + + data.stream.out = stream; + data.closure = closure; + return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args); } /************************************************************************* @@ -3331,9 +3813,11 @@ trio_dprintfv(int fd, @return Number of printed characters. */ TRIO_PUBLIC int -trio_sprintf(char *buffer, - TRIO_CONST char *format, - ...) +trio_sprintf +TRIO_VARGS3((buffer, format, va_alist), + char *buffer, + TRIO_CONST char *format, + TRIO_VA_DECL) { int status; va_list args; @@ -3341,10 +3825,10 @@ trio_sprintf(char *buffer, assert(VALID(buffer)); assert(VALID(format)); - va_start(args, format); - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL); + TRIO_VA_START(args, format); + status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL); *buffer = NIL; /* Terminate with NIL character */ - va_end(args); + TRIO_VA_END(args); return status; } @@ -3357,16 +3841,18 @@ trio_sprintf(char *buffer, @return Number of printed characters. */ TRIO_PUBLIC int -trio_vsprintf(char *buffer, - TRIO_CONST char *format, - va_list args) +trio_vsprintf +TRIO_ARGS3((buffer, format, args), + char *buffer, + TRIO_CONST char *format, + va_list args) { int status; assert(VALID(buffer)); assert(VALID(format)); - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL); + status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL); *buffer = NIL; return status; } @@ -3380,17 +3866,18 @@ trio_vsprintf(char *buffer, @return Number of printed characters. */ TRIO_PUBLIC int -trio_sprintfv(char *buffer, - TRIO_CONST char *format, - void **args) +trio_sprintfv +TRIO_ARGS3((buffer, format, args), + char *buffer, + TRIO_CONST char *format, + trio_pointer_t *args) { int status; - va_list dummy; assert(VALID(buffer)); assert(VALID(format)); - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, dummy, args); + status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args); *buffer = NIL; return status; } @@ -3409,10 +3896,12 @@ trio_sprintfv(char *buffer, @return Number of printed characters. */ TRIO_PUBLIC int -trio_snprintf(char *buffer, - size_t max, - TRIO_CONST char *format, - ...) +trio_snprintf +TRIO_VARGS4((buffer, max, format, va_alist), + char *buffer, + size_t max, + TRIO_CONST char *format, + TRIO_VA_DECL) { int status; va_list args; @@ -3420,12 +3909,12 @@ trio_snprintf(char *buffer, assert(VALID(buffer)); assert(VALID(format)); - va_start(args, format); + TRIO_VA_START(args, format); status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, args, NULL); + TrioOutStreamStringMax, format, &args, NULL); if (max > 0) *buffer = NIL; - va_end(args); + TRIO_VA_END(args); return status; } @@ -3439,10 +3928,12 @@ trio_snprintf(char *buffer, @return Number of printed characters. */ TRIO_PUBLIC int -trio_vsnprintf(char *buffer, - size_t max, - TRIO_CONST char *format, - va_list args) +trio_vsnprintf +TRIO_ARGS4((buffer, max, format, args), + char *buffer, + size_t max, + TRIO_CONST char *format, + va_list args) { int status; @@ -3450,7 +3941,7 @@ trio_vsnprintf(char *buffer, assert(VALID(format)); status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, args, NULL); + TrioOutStreamStringMax, format, &args, NULL); if (max > 0) *buffer = NIL; return status; @@ -3466,19 +3957,20 @@ trio_vsnprintf(char *buffer, @return Number of printed characters. */ TRIO_PUBLIC int -trio_snprintfv(char *buffer, - size_t max, - TRIO_CONST char *format, - void **args) +trio_snprintfv +TRIO_ARGS4((buffer, max, format, args), + char *buffer, + size_t max, + TRIO_CONST char *format, + trio_pointer_t *args) { int status; - va_list dummy; assert(VALID(buffer)); assert(VALID(format)); status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, dummy, args); + TrioOutStreamStringMax, format, NULL, args); if (max > 0) *buffer = NIL; return status; @@ -3490,16 +3982,18 @@ trio_snprintfv(char *buffer, * character at the end of buffer. */ TRIO_PUBLIC int -trio_snprintfcat(char *buffer, - size_t max, - TRIO_CONST char *format, - ...) +trio_snprintfcat +TRIO_VARGS4((buffer, max, format, va_alist), + char *buffer, + size_t max, + TRIO_CONST char *format, + TRIO_VA_DECL) { int status; va_list args; size_t buf_len; - va_start(args, format); + TRIO_VA_START(args, format); assert(VALID(buffer)); assert(VALID(format)); @@ -3508,27 +4002,30 @@ trio_snprintfcat(char *buffer, buffer = &buffer[buf_len]; status = TrioFormat(&buffer, max - 1 - buf_len, - TrioOutStreamStringMax, format, args, NULL); - va_end(args); + TrioOutStreamStringMax, format, &args, NULL); + TRIO_VA_END(args); *buffer = NIL; return status; } TRIO_PUBLIC int -trio_vsnprintfcat(char *buffer, - size_t max, - TRIO_CONST char *format, - va_list args) +trio_vsnprintfcat +TRIO_ARGS4((buffer, max, format, args), + char *buffer, + size_t max, + TRIO_CONST char *format, + va_list args) { int status; size_t buf_len; + assert(VALID(buffer)); assert(VALID(format)); buf_len = trio_length(buffer); buffer = &buffer[buf_len]; status = TrioFormat(&buffer, max - 1 - buf_len, - TrioOutStreamStringMax, format, args, NULL); + TrioOutStreamStringMax, format, &args, NULL); *buffer = NIL; return status; } @@ -3539,8 +4036,10 @@ trio_vsnprintfcat(char *buffer, /* Deprecated */ TRIO_PUBLIC char * -trio_aprintf(TRIO_CONST char *format, - ...) +trio_aprintf +TRIO_VARGS2((format, va_alist), + TRIO_CONST char *format, + TRIO_VA_DECL) { va_list args; trio_string_t *info; @@ -3551,10 +4050,10 @@ trio_aprintf(TRIO_CONST char *format, info = trio_xstring_duplicate(""); if (info) { - va_start(args, format); + TRIO_VA_START(args, format); (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, args, NULL); - va_end(args); + format, &args, NULL); + TRIO_VA_END(args); trio_string_terminate(info); result = trio_string_extract(info); @@ -3565,8 +4064,10 @@ trio_aprintf(TRIO_CONST char *format, /* Deprecated */ TRIO_PUBLIC char * -trio_vaprintf(TRIO_CONST char *format, - va_list args) +trio_vaprintf +TRIO_ARGS2((format, args), + TRIO_CONST char *format, + va_list args) { trio_string_t *info; char *result = NULL; @@ -3577,7 +4078,7 @@ trio_vaprintf(TRIO_CONST char *format, if (info) { (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, args, NULL); + format, &args, NULL); trio_string_terminate(info); result = trio_string_extract(info); trio_string_destroy(info); @@ -3586,9 +4087,11 @@ trio_vaprintf(TRIO_CONST char *format, } TRIO_PUBLIC int -trio_asprintf(char **result, - TRIO_CONST char *format, - ...) +trio_asprintf +TRIO_VARGS3((result, format, va_alist), + char **result, + TRIO_CONST char *format, + TRIO_VA_DECL) { va_list args; int status; @@ -3605,10 +4108,10 @@ trio_asprintf(char **result, } else { - va_start(args, format); + TRIO_VA_START(args, format); status = TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, args, NULL); - va_end(args); + format, &args, NULL); + TRIO_VA_END(args); if (status >= 0) { trio_string_terminate(info); @@ -3620,9 +4123,11 @@ trio_asprintf(char **result, } TRIO_PUBLIC int -trio_vasprintf(char **result, - TRIO_CONST char *format, - va_list args) +trio_vasprintf +TRIO_ARGS3((result, format, args), + char **result, + TRIO_CONST char *format, + va_list args) { int status; trio_string_t *info; @@ -3639,7 +4144,7 @@ trio_vasprintf(char **result, else { status = TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, args, NULL); + format, &args, NULL); if (status >= 0) { trio_string_terminate(info); @@ -3658,7 +4163,6 @@ trio_vasprintf(char **result, * ************************************************************************/ - #if defined(TRIO_DOCUMENTATION) # include "doc/doc_register.h" #endif @@ -3667,6 +4171,8 @@ trio_vasprintf(char **result, @{ */ +#if TRIO_EXTENSION + /************************************************************************* * trio_register */ @@ -3678,9 +4184,11 @@ trio_vasprintf(char **result, @param name @return Handle. */ -TRIO_PUBLIC void * -trio_register(trio_callback_t callback, - TRIO_CONST char *name) +TRIO_PUBLIC trio_pointer_t +trio_register +TRIO_ARGS2((callback, name), + trio_callback_t callback, + TRIO_CONST char *name) { trio_userdef_t *def; trio_userdef_t *prev = NULL; @@ -3738,14 +4246,18 @@ trio_register(trio_callback_t callback, if (internalLeaveCriticalRegion) (void)internalLeaveCriticalRegion(NULL); } - return def; + return (trio_pointer_t)def; } -/************************************************************************* - * trio_unregister [public] +/** + Unregister an existing user-defined specifier. + + @param handle */ void -trio_unregister(void *handle) +trio_unregister +TRIO_ARGS1((handle), + trio_pointer_t handle) { trio_userdef_t *self = (trio_userdef_t *)handle; trio_userdef_t *def; @@ -3778,9 +4290,13 @@ trio_unregister(void *handle) * trio_get_format [public] */ TRIO_CONST char * -trio_get_format(void *ref) +trio_get_format +TRIO_ARGS1((ref), + trio_pointer_t ref) { +#if defined(FORMAT_USER_DEFINED) assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); +#endif return (((trio_reference_t *)ref)->parameter->user_data); } @@ -3788,10 +4304,14 @@ trio_get_format(void *ref) /************************************************************************* * trio_get_argument [public] */ -void * -trio_get_argument(void *ref) +trio_pointer_t +trio_get_argument +TRIO_ARGS1((ref), + trio_pointer_t ref) { +#if defined(FORMAT_USER_DEFINED) assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); +#endif return ((trio_reference_t *)ref)->parameter->data.pointer; } @@ -3800,14 +4320,18 @@ trio_get_argument(void *ref) * trio_get_width / trio_set_width [public] */ int -trio_get_width(void *ref) +trio_get_width +TRIO_ARGS1((ref), + trio_pointer_t ref) { return ((trio_reference_t *)ref)->parameter->width; } void -trio_set_width(void *ref, - int width) +trio_set_width +TRIO_ARGS2((ref, width), + trio_pointer_t ref, + int width) { ((trio_reference_t *)ref)->parameter->width = width; } @@ -3816,14 +4340,18 @@ trio_set_width(void *ref, * trio_get_precision / trio_set_precision [public] */ int -trio_get_precision(void *ref) +trio_get_precision +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->precision); } void -trio_set_precision(void *ref, - int precision) +trio_set_precision +TRIO_ARGS2((ref, precision), + trio_pointer_t ref, + int precision) { ((trio_reference_t *)ref)->parameter->precision = precision; } @@ -3832,14 +4360,18 @@ trio_set_precision(void *ref, * trio_get_base / trio_set_base [public] */ int -trio_get_base(void *ref) +trio_get_base +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->base); } void -trio_set_base(void *ref, - int base) +trio_set_base +TRIO_ARGS2((ref, base), + trio_pointer_t ref, + int base) { ((trio_reference_t *)ref)->parameter->base = base; } @@ -3848,14 +4380,18 @@ trio_set_base(void *ref, * trio_get_long / trio_set_long [public] */ int -trio_get_long(void *ref) +trio_get_long +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG); } void -trio_set_long(void *ref, - int is_long) +trio_set_long +TRIO_ARGS2((ref, is_long), + trio_pointer_t ref, + int is_long) { if (is_long) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG; @@ -3867,14 +4403,18 @@ trio_set_long(void *ref, * trio_get_longlong / trio_set_longlong [public] */ int -trio_get_longlong(void *ref) +trio_get_longlong +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD); } void -trio_set_longlong(void *ref, - int is_longlong) +trio_set_longlong +TRIO_ARGS2((ref, is_longlong), + trio_pointer_t ref, + int is_longlong) { if (is_longlong) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD; @@ -3886,14 +4426,18 @@ trio_set_longlong(void *ref, * trio_get_longdouble / trio_set_longdouble [public] */ int -trio_get_longdouble(void *ref) +trio_get_longdouble +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE); } void -trio_set_longdouble(void *ref, - int is_longdouble) +trio_set_longdouble +TRIO_ARGS2((ref, is_longdouble), + trio_pointer_t ref, + int is_longdouble) { if (is_longdouble) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE; @@ -3905,14 +4449,18 @@ trio_set_longdouble(void *ref, * trio_get_short / trio_set_short [public] */ int -trio_get_short(void *ref) +trio_get_short +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT); } void -trio_set_short(void *ref, - int is_short) +trio_set_short +TRIO_ARGS2((ref, is_short), + trio_pointer_t ref, + int is_short) { if (is_short) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT; @@ -3924,14 +4472,18 @@ trio_set_short(void *ref, * trio_get_shortshort / trio_set_shortshort [public] */ int -trio_get_shortshort(void *ref) +trio_get_shortshort +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT); } void -trio_set_shortshort(void *ref, - int is_shortshort) +trio_set_shortshort +TRIO_ARGS2((ref, is_shortshort), + trio_pointer_t ref, + int is_shortshort) { if (is_shortshort) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT; @@ -3943,14 +4495,18 @@ trio_set_shortshort(void *ref, * trio_get_alternative / trio_set_alternative [public] */ int -trio_get_alternative(void *ref) +trio_get_alternative +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE); } void -trio_set_alternative(void *ref, - int is_alternative) +trio_set_alternative +TRIO_ARGS2((ref, is_alternative), + trio_pointer_t ref, + int is_alternative) { if (is_alternative) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE; @@ -3962,14 +4518,18 @@ trio_set_alternative(void *ref, * trio_get_alignment / trio_set_alignment [public] */ int -trio_get_alignment(void *ref) +trio_get_alignment +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST); } void -trio_set_alignment(void *ref, - int is_leftaligned) +trio_set_alignment +TRIO_ARGS2((ref, is_leftaligned), + trio_pointer_t ref, + int is_leftaligned) { if (is_leftaligned) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST; @@ -3981,14 +4541,18 @@ trio_set_alignment(void *ref, * trio_get_spacing /trio_set_spacing [public] */ int -trio_get_spacing(void *ref) +trio_get_spacing +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE); } void -trio_set_spacing(void *ref, - int is_space) +trio_set_spacing +TRIO_ARGS2((ref, is_space), + trio_pointer_t ref, + int is_space) { if (is_space) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE; @@ -4000,14 +4564,18 @@ trio_set_spacing(void *ref, * trio_get_sign / trio_set_sign [public] */ int -trio_get_sign(void *ref) +trio_get_sign +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN); } void -trio_set_sign(void *ref, - int is_sign) +trio_set_sign +TRIO_ARGS2((ref, is_sign), + trio_pointer_t ref, + int is_sign) { if (is_sign) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN; @@ -4019,14 +4587,18 @@ trio_set_sign(void *ref, * trio_get_padding / trio_set_padding [public] */ int -trio_get_padding(void *ref) +trio_get_padding +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING); } void -trio_set_padding(void *ref, - int is_padding) +trio_set_padding +TRIO_ARGS2((ref, is_padding), + trio_pointer_t ref, + int is_padding) { if (is_padding) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING; @@ -4038,14 +4610,18 @@ trio_set_padding(void *ref, * trio_get_quote / trio_set_quote [public] */ int -trio_get_quote(void *ref) +trio_get_quote +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE); } void -trio_set_quote(void *ref, - int is_quote) +trio_set_quote +TRIO_ARGS2((ref, is_quote), + trio_pointer_t ref, + int is_quote) { if (is_quote) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE; @@ -4057,14 +4633,18 @@ trio_set_quote(void *ref, * trio_get_upper / trio_set_upper [public] */ int -trio_get_upper(void *ref) +trio_get_upper +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER); } void -trio_set_upper(void *ref, - int is_upper) +trio_set_upper +TRIO_ARGS2((ref, is_upper), + trio_pointer_t ref, + int is_upper) { if (is_upper) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER; @@ -4077,14 +4657,18 @@ trio_set_upper(void *ref, */ #if TRIO_C99 int -trio_get_largest(void *ref) +trio_get_largest +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T); } void -trio_set_largest(void *ref, - int is_largest) +trio_set_largest +TRIO_ARGS2((ref, is_largest), + trio_pointer_t ref, + int is_largest) { if (is_largest) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T; @@ -4097,14 +4681,18 @@ trio_set_largest(void *ref, * trio_get_ptrdiff / trio_set_ptrdiff [public] */ int -trio_get_ptrdiff(void *ref) +trio_get_ptrdiff +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T); } void -trio_set_ptrdiff(void *ref, - int is_ptrdiff) +trio_set_ptrdiff +TRIO_ARGS2((ref, is_ptrdiff), + trio_pointer_t ref, + int is_ptrdiff) { if (is_ptrdiff) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T; @@ -4117,14 +4705,18 @@ trio_set_ptrdiff(void *ref, */ #if TRIO_C99 int -trio_get_size(void *ref) +trio_get_size +TRIO_ARGS1((ref), + trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T); } void -trio_set_size(void *ref, - int is_size) +trio_set_size +TRIO_ARGS2((ref, is_size), + trio_pointer_t ref, + int is_size) { if (is_size) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T; @@ -4137,13 +4729,15 @@ trio_set_size(void *ref, * trio_print_int [public] */ void -trio_print_int(void *ref, - int number) +trio_print_int +TRIO_ARGS2((ref, number), + trio_pointer_t ref, + int number) { trio_reference_t *self = (trio_reference_t *)ref; TrioWriteNumber(self->data, - (trio_intmax_t)number, + (trio_uintmax_t)number, self->parameter->flags, self->parameter->width, self->parameter->precision, @@ -4154,13 +4748,15 @@ trio_print_int(void *ref, * trio_print_uint [public] */ void -trio_print_uint(void *ref, - unsigned int number) +trio_print_uint +TRIO_ARGS2((ref, number), + trio_pointer_t ref, + unsigned int number) { trio_reference_t *self = (trio_reference_t *)ref; TrioWriteNumber(self->data, - (trio_intmax_t)number, + (trio_uintmax_t)number, self->parameter->flags | FLAGS_UNSIGNED, self->parameter->width, self->parameter->precision, @@ -4171,8 +4767,10 @@ trio_print_uint(void *ref, * trio_print_double [public] */ void -trio_print_double(void *ref, - double number) +trio_print_double +TRIO_ARGS2((ref, number), + trio_pointer_t ref, + double number) { trio_reference_t *self = (trio_reference_t *)ref; @@ -4188,8 +4786,10 @@ trio_print_double(void *ref, * trio_print_string [public] */ void -trio_print_string(void *ref, - char *string) +trio_print_string +TRIO_ARGS2((ref, string), + trio_pointer_t ref, + char *string) { trio_reference_t *self = (trio_reference_t *)ref; @@ -4200,12 +4800,67 @@ trio_print_string(void *ref, self->parameter->precision); } +/************************************************************************* + * trio_print_ref [public] + */ +int +trio_print_ref +TRIO_VARGS3((ref, format, va_alist), + trio_pointer_t ref, + TRIO_CONST char *format, + TRIO_VA_DECL) +{ + int status; + va_list arglist; + + assert(VALID(format)); + + TRIO_VA_START(arglist, format); + status = TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL); + TRIO_VA_END(arglist); + return status; +} + +/************************************************************************* + * trio_vprint_ref [public] + */ +int +trio_vprint_ref +TRIO_ARGS3((ref, format, arglist), + trio_pointer_t ref, + TRIO_CONST char *format, + va_list arglist) +{ + assert(VALID(format)); + + return TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL); +} + +/************************************************************************* + * trio_printv_ref [public] + */ +int +trio_printv_ref +TRIO_ARGS3((ref, format, argarray), + trio_pointer_t ref, + TRIO_CONST char *format, + trio_pointer_t *argarray) +{ + assert(VALID(format)); + + return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray); +} + +#endif /* TRIO_EXTENSION */ + /************************************************************************* * trio_print_pointer [public] */ void -trio_print_pointer(void *ref, - void *pointer) +trio_print_pointer +TRIO_ARGS2((ref, pointer), + trio_pointer_t ref, + trio_pointer_t pointer) { trio_reference_t *self = (trio_reference_t *)ref; unsigned long flags; @@ -4223,7 +4878,7 @@ trio_print_pointer(void *ref, * The subtraction of the null pointer is a workaround * to avoid a compiler warning. The performance overhead * is negligible (and likely to be removed by an - * optimising compiler). The (char *) casting is done + * optimizing compiler). The (char *) casting is done * to please ANSI C++. */ number = (trio_uintmax_t)((char *)pointer - (char *)0); @@ -4233,7 +4888,7 @@ trio_print_pointer(void *ref, flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING); TrioWriteNumber(self->data, - (trio_intmax_t)number, + number, flags, POINTER_WIDTH, NO_PRECISION, @@ -4241,67 +4896,110 @@ trio_print_pointer(void *ref, } } -/************************************************************************* - * trio_print_ref [public] - */ -int -trio_print_ref(void *ref, - TRIO_CONST char *format, - ...) -{ - int status; - va_list arglist; - - assert(VALID(format)); - - va_start(arglist, format); - status = TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL); - va_end(arglist); - return status; -} - -/************************************************************************* - * trio_vprint_ref [public] - */ -int -trio_vprint_ref(void *ref, - TRIO_CONST char *format, - va_list arglist) -{ - assert(VALID(format)); - - return TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL); -} - -/************************************************************************* - * trio_printv_ref [public] - */ -int -trio_printv_ref(void *ref, - TRIO_CONST char *format, - void **argarray) -{ - va_list dummy; - - assert(VALID(format)); - - return TrioFormatRef((trio_reference_t *)ref, format, dummy, argarray); -} - /** @} End of UserDefined documentation module */ +/************************************************************************* + * + * LOCALES + * + ************************************************************************/ + +/************************************************************************* + * trio_locale_set_decimal_point + * + * Decimal point can only be one character. The input argument is a + * string to enable multibyte characters. At most MB_LEN_MAX characters + * will be used. + */ +TRIO_PUBLIC void +trio_locale_set_decimal_point +TRIO_ARGS1((decimalPoint), + char *decimalPoint) +{ +#if defined(USE_LOCALE) + if (NULL == internalLocaleValues) + { + TrioSetLocale(); + } +#endif + internalDecimalPointLength = trio_length(decimalPoint); + if (internalDecimalPointLength == 1) + { + internalDecimalPoint = *decimalPoint; + } + else + { + internalDecimalPoint = NIL; + trio_copy_max(internalDecimalPointString, + sizeof(internalDecimalPointString), + decimalPoint); + } +} + +/************************************************************************* + * trio_locale_set_thousand_separator + * + * See trio_locale_set_decimal_point + */ +TRIO_PUBLIC void +trio_locale_set_thousand_separator +TRIO_ARGS1((thousandSeparator), + char *thousandSeparator) +{ +#if defined(USE_LOCALE) + if (NULL == internalLocaleValues) + { + TrioSetLocale(); + } +#endif + trio_copy_max(internalThousandSeparator, + sizeof(internalThousandSeparator), + thousandSeparator); + internalThousandSeparatorLength = trio_length(internalThousandSeparator); +} + +/************************************************************************* + * trio_locale_set_grouping + * + * Array of bytes. Reversed order. + * + * CHAR_MAX : No further grouping + * 0 : Repeat last group for the remaining digits (not necessary + * as C strings are zero-terminated) + * n : Set current group to n + * + * Same order as the grouping attribute in LC_NUMERIC. + */ +TRIO_PUBLIC void +trio_locale_set_grouping +TRIO_ARGS1((grouping), + char *grouping) +{ +#if defined(USE_LOCALE) + if (NULL == internalLocaleValues) + { + TrioSetLocale(); + } +#endif + trio_copy_max(internalGrouping, + sizeof(internalGrouping), + grouping); +} + + /************************************************************************* * * SCANNING * ************************************************************************/ - /************************************************************************* * TrioSkipWhitespaces */ TRIO_PRIVATE int -TrioSkipWhitespaces(trio_class_t *self) +TrioSkipWhitespaces +TRIO_ARGS1((self), + trio_class_t *self) { int ch; @@ -4318,7 +5016,7 @@ TrioSkipWhitespaces(trio_class_t *self) */ #if TRIO_EXTENSION TRIO_PRIVATE void -TrioGetCollation(void) +TrioGetCollation(TRIO_NOARGS) { int i; int j; @@ -4351,10 +5049,12 @@ TrioGetCollation(void) * multibyte */ TRIO_PRIVATE int -TrioGetCharacterClass(TRIO_CONST char *format, - int *indexPointer, - unsigned long *flagsPointer, - int *characterclass) +TrioGetCharacterClass +TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass), + TRIO_CONST char *format, + int *indexPointer, + unsigned long *flagsPointer, + int *characterclass) { int index = *indexPointer; int i; @@ -4463,7 +5163,7 @@ TrioGetCharacterClass(TRIO_CONST char *format, if (internalCollationUnconverted) { - /* Lazy evalutation of collation array */ + /* Lazy evaluation of collation array */ TrioGetCollation(); internalCollationUnconverted = FALSE; } @@ -4608,16 +5308,19 @@ TrioGetCharacterClass(TRIO_CONST char *format, * strtoul, because we must handle 'long long' and thousand separators. */ TRIO_PRIVATE BOOLEAN_T -TrioReadNumber(trio_class_t *self, - trio_uintmax_t *target, - unsigned long flags, - int width, - int base) +TrioReadNumber +TRIO_ARGS5((self, target, flags, width, base), + trio_class_t *self, + trio_uintmax_t *target, + unsigned long flags, + int width, + int base) { trio_uintmax_t number = 0; int digit; int count; BOOLEAN_T isNegative = FALSE; + BOOLEAN_T gotNumber = FALSE; int j; assert(VALID(self)); @@ -4717,16 +5420,17 @@ TrioReadNumber(trio_class_t *self, number *= base; number += digit; + gotNumber = TRUE; /* we need at least one digit */ self->InStream(self, NULL); } /* Was anything read at all? */ - if (self->processed == count) + if (!gotNumber) return FALSE; if (target) - *target = (isNegative) ? -number : number; + *target = (isNegative) ? -((trio_intmax_t)number) : number; return TRUE; } @@ -4734,10 +5438,12 @@ TrioReadNumber(trio_class_t *self, * TrioReadChar */ TRIO_PRIVATE int -TrioReadChar(trio_class_t *self, - char *target, - unsigned long flags, - int width) +TrioReadChar +TRIO_ARGS4((self, target, flags, width), + trio_class_t *self, + char *target, + unsigned long flags, + int width) { int i; char ch; @@ -4798,10 +5504,12 @@ TrioReadChar(trio_class_t *self, * TrioReadString */ TRIO_PRIVATE BOOLEAN_T -TrioReadString(trio_class_t *self, - char *target, - unsigned long flags, - int width) +TrioReadString +TRIO_ARGS4((self, target, flags, width), + trio_class_t *self, + char *target, + unsigned long flags, + int width) { int i; @@ -4819,7 +5527,7 @@ TrioReadString(trio_class_t *self, (! ((self->current == EOF) || isspace(self->current))); i++) { - if (TrioReadChar(self, &target[i], flags, 1) == 0) + if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0) break; /* for */ } if (target) @@ -4832,16 +5540,18 @@ TrioReadString(trio_class_t *self, */ #if TRIO_WIDECHAR TRIO_PRIVATE int -TrioReadWideChar(trio_class_t *self, - wchar_t *target, - unsigned long flags, - int width) +TrioReadWideChar +TRIO_ARGS4((self, target, flags, width), + trio_class_t *self, + trio_wchar_t *target, + unsigned long flags, + int width) { int i; int j; int size; int amount = 0; - wchar_t wch; + trio_wchar_t wch; char buffer[MB_LEN_MAX + 1]; assert(VALID(self)); @@ -4891,10 +5601,12 @@ TrioReadWideChar(trio_class_t *self, */ #if TRIO_WIDECHAR TRIO_PRIVATE BOOLEAN_T -TrioReadWideString(trio_class_t *self, - wchar_t *target, - unsigned long flags, - int width) +TrioReadWideString +TRIO_ARGS4((self, target, flags, width), + trio_class_t *self, + trio_wchar_t *target, + unsigned long flags, + int width) { int i; int size; @@ -4905,7 +5617,7 @@ TrioReadWideString(trio_class_t *self, TrioSkipWhitespaces(self); #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - mblen(NULL, 0); + (void)mblen(NULL, 0); #endif /* @@ -4935,11 +5647,13 @@ TrioReadWideString(trio_class_t *self, * FIXME: characterclass does not work with multibyte characters */ TRIO_PRIVATE BOOLEAN_T -TrioReadGroup(trio_class_t *self, - char *target, - int *characterclass, - unsigned long flags, - int width) +TrioReadGroup +TRIO_ARGS5((self, target, characterclass, flags, width), + trio_class_t *self, + char *target, + int *characterclass, + unsigned long flags, + int width) { int ch; int i; @@ -4969,20 +5683,25 @@ TrioReadGroup(trio_class_t *self, * * FIXME: * add long double + * handle base */ TRIO_PRIVATE BOOLEAN_T -TrioReadDouble(trio_class_t *self, - double *target, - unsigned long flags, - int width) +TrioReadDouble +TRIO_ARGS4((self, target, flags, width), + trio_class_t *self, + trio_pointer_t target, + unsigned long flags, + int width) { int ch; - char doubleString[512] = ""; + char doubleString[512]; int index = 0; int start; int j; BOOLEAN_T isHex = FALSE; + doubleString[0] = 0; + if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1)) width = sizeof(doubleString) - 1; @@ -5024,25 +5743,46 @@ TrioReadDouble(trio_class_t *self, if (trio_equal(&doubleString[start], INFINITE_UPPER) || trio_equal(&doubleString[start], LONG_INFINITE_UPPER)) { - *target = ((start == 1 && doubleString[0] == '-')) - ? trio_ninf() - : trio_pinf(); + if (flags & FLAGS_LONGDOUBLE) + { + if ((start == 1) && (doubleString[0] == '-')) + { + *((trio_long_double_t *)target) = trio_ninf(); + } + else + { + *((trio_long_double_t *)target) = trio_pinf(); + } + } + else + { + if ((start == 1) && (doubleString[0] == '-')) + { + *((double *)target) = trio_ninf(); + } + else + { + *((double *)target) = trio_pinf(); + } + } return TRUE; } if (trio_equal(doubleString, NAN_UPPER)) { /* NaN must not have a preceeding + nor - */ - *target = trio_nan(); + if (flags & FLAGS_LONGDOUBLE) + { + *((trio_long_double_t *)target) = trio_nan(); + } + else + { + *((double *)target) = trio_nan(); + } return TRUE; } return FALSE; - - default: - break; - } - - if (ch == '0') - { + + case '0': doubleString[index++] = (char)ch; self->InStream(self, &ch); if (toupper(ch) == 'X') @@ -5051,7 +5791,12 @@ TrioReadDouble(trio_class_t *self, doubleString[index++] = (char)ch; self->InStream(self, &ch); } + break; + + default: + break; } + while ((ch != EOF) && (index - start < width)) { /* Integer part */ @@ -5110,13 +5855,16 @@ TrioReadDouble(trio_class_t *self, if ((index == start) || (*doubleString == NIL)) return FALSE; + + doubleString[index] = 0; if (flags & FLAGS_LONGDOUBLE) -/* *longdoublePointer = trio_to_long_double()*/ - return FALSE; /* FIXME: Remove when long double is implemented */ + { + *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL); + } else { - *target = trio_to_double(doubleString, NULL); + *((double *)target) = trio_to_double(doubleString, NULL); } return TRUE; } @@ -5125,9 +5873,11 @@ TrioReadDouble(trio_class_t *self, * TrioReadPointer */ TRIO_PRIVATE BOOLEAN_T -TrioReadPointer(trio_class_t *self, - void **target, - unsigned long flags) +TrioReadPointer +TRIO_ARGS3((self, target, flags), + trio_class_t *self, + trio_pointer_t *target, + unsigned long flags) { trio_uintmax_t number; char buffer[sizeof(internalNullString)]; @@ -5169,9 +5919,11 @@ TrioReadPointer(trio_class_t *self, * TrioScanProcess */ TRIO_PRIVATE int -TrioScanProcess(trio_class_t *data, - TRIO_CONST char *format, - trio_parameter_t *parameters) +TrioScanProcess +TRIO_ARGS3((data, format, parameters), + trio_class_t *data, + TRIO_CONST char *format, + trio_parameter_t *parameters) { #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) int charlen; @@ -5184,7 +5936,7 @@ TrioScanProcess(trio_class_t *data, unsigned long flags; int width; int base; - void *pointer; + trio_pointer_t pointer; assignment = 0; i = 0; @@ -5192,7 +5944,7 @@ TrioScanProcess(trio_class_t *data, data->InStream(data, &ch); #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - mblen(NULL, 0); + (void)mblen(NULL, 0); #endif while (format[index]) @@ -5201,20 +5953,26 @@ TrioScanProcess(trio_class_t *data, if (! isascii(format[index])) { charlen = mblen(&format[index], MB_LEN_MAX); - /* Compare multibyte characters in format string */ - for (cnt = 0; cnt < charlen - 1; cnt++) + if (charlen != -1) { - if (ch != format[index + cnt]) + /* Compare multibyte characters in format string */ + for (cnt = 0; cnt < charlen - 1; cnt++) { - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); + if (ch != format[index + cnt]) + { + return TRIO_ERROR_RETURN(TRIO_EINVAL, index); + } + data->InStream(data, &ch); } - data->InStream(data, &ch); + continue; /* while characters left in formatting string */ } - continue; /* while */ } #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - if (EOF == ch) - return EOF; + + if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT)) + { + return (assignment > 0) ? assignment : EOF; + } if (CHAR_IDENTIFIER == format[index]) { @@ -5266,10 +6024,11 @@ TrioScanProcess(trio_class_t *data, width, base)) return assignment; - assignment++; - + if (!(flags & FLAGS_IGNORE)) { + assignment++; + pointer = parameters[i].data.pointer; #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) if (flags & FLAGS_SIZE_T) @@ -5321,20 +6080,34 @@ TrioScanProcess(trio_class_t *data, width)) return assignment; } - assignment++; + if (!(flags & FLAGS_IGNORE)) + assignment++; break; /* FORMAT_STRING */ - - case FORMAT_DOUBLE: - if (!TrioReadDouble(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.doublePointer, - flags, - width)) - return assignment; - assignment++; - break; /* FORMAT_DOUBLE */ + case FORMAT_DOUBLE: + { + trio_pointer_t pointer; + + if (flags & FLAGS_IGNORE) + { + pointer = NULL; + } + else + { + pointer = (flags & FLAGS_LONGDOUBLE) + ? (trio_pointer_t)parameters[i].data.longdoublePointer + : (trio_pointer_t)parameters[i].data.doublePointer; + } + if (!TrioReadDouble(data, pointer, flags, width)) + { + return assignment; + } + if (!(flags & FLAGS_IGNORE)) + { + assignment++; + } + break; /* FORMAT_DOUBLE */ + } case FORMAT_GROUP: { int characterclass[MAX_CHARACTER_CLASS + 1]; @@ -5364,44 +6137,48 @@ TrioScanProcess(trio_class_t *data, flags, parameters[i].width)) return assignment; - assignment++; + if (!(flags & FLAGS_IGNORE)) + assignment++; } break; /* FORMAT_GROUP */ - + case FORMAT_COUNT: pointer = parameters[i].data.pointer; if (NULL != pointer) { + int count = data->committed; + if (ch != EOF) + count--; /* a character is read, but is not consumed yet */ #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)data->committed; + *(size_t *)pointer = (size_t)count; else #endif #if defined(QUALIFIER_PTRDIFF_T) if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed; + *(ptrdiff_t *)pointer = (ptrdiff_t)count; else #endif #if defined(QUALIFIER_INTMAX_T) if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed; + *(trio_intmax_t *)pointer = (trio_intmax_t)count; else #endif if (flags & FLAGS_QUAD) { - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed; + *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count; } else if (flags & FLAGS_LONG) { - *(long int *)pointer = (long int)data->committed; + *(long int *)pointer = (long int)count; } else if (flags & FLAGS_SHORT) { - *(short int *)pointer = (short int)data->committed; + *(short int *)pointer = (short int)count; } else { - *(int *)pointer = (int)data->committed; + *(int *)pointer = (int)count; } } break; /* FORMAT_COUNT */ @@ -5415,7 +6192,7 @@ TrioScanProcess(trio_class_t *data, ? NULL : parameters[i].data.wstring, flags, - (width == NO_WIDTH) ? 1 : width) > 0) + (width == NO_WIDTH) ? 1 : width) == 0) return assignment; } else @@ -5426,25 +6203,27 @@ TrioScanProcess(trio_class_t *data, ? NULL : parameters[i].data.string, flags, - (width == NO_WIDTH) ? 1 : width) > 0) + (width == NO_WIDTH) ? 1 : width) == 0) return assignment; } - assignment++; + if (!(flags & FLAGS_IGNORE)) + assignment++; break; /* FORMAT_CHAR */ - + case FORMAT_POINTER: if (!TrioReadPointer(data, (flags & FLAGS_IGNORE) ? NULL - : (void **)parameters[i].data.pointer, + : (trio_pointer_t *)parameters[i].data.pointer, flags)) return assignment; - assignment++; + if (!(flags & FLAGS_IGNORE)) + assignment++; break; /* FORMAT_POINTER */ - + case FORMAT_PARAMETER: break; /* FORMAT_PARAMETER */ - + default: return TRIO_ERROR_RETURN(TRIO_EINVAL, index); } @@ -5476,12 +6255,14 @@ TrioScanProcess(trio_class_t *data, * TrioScan */ TRIO_PRIVATE int -TrioScan(TRIO_CONST void *source, - size_t sourceSize, - void (*InStream)(trio_class_t *, int *), - TRIO_CONST char *format, - va_list arglist, - void **argarray) +TrioScan +TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray), + trio_pointer_t source, + size_t sourceSize, + void (*InStream) TRIO_PROTO((trio_class_t *, int *)), + TRIO_CONST char *format, + va_list *arglist, + trio_pointer_t *argarray) { int status; trio_parameter_t parameters[MAX_PARAMETERS]; @@ -5492,7 +6273,7 @@ TrioScan(TRIO_CONST void *source, memset(&data, 0, sizeof(data)); data.InStream = InStream; - data.location = (void *)source; + data.location = (trio_pointer_t)source; data.max = sourceSize; data.error = 0; @@ -5519,8 +6300,10 @@ TrioScan(TRIO_CONST void *source, * TrioInStreamFile */ TRIO_PRIVATE void -TrioInStreamFile(trio_class_t *self, - int *intPointer) +TrioInStreamFile +TRIO_ARGS2((self, intPointer), + trio_class_t *self, + int *intPointer) { FILE *file = (FILE *)self->location; @@ -5534,8 +6317,11 @@ TrioInStreamFile(trio_class_t *self, ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0) : TRIO_ERROR_RETURN(TRIO_EOF, 0); } - self->processed++; - self->committed++; + else + { + self->processed++; + self->committed++; + } if (VALID(intPointer)) { @@ -5547,8 +6333,10 @@ TrioInStreamFile(trio_class_t *self, * TrioInStreamFileDescriptor */ TRIO_PRIVATE void -TrioInStreamFileDescriptor(trio_class_t *self, - int *intPointer) +TrioInStreamFileDescriptor +TRIO_ARGS2((self, intPointer), + trio_class_t *self, + int *intPointer) { int fd = *((int *)self->location); int size; @@ -5566,8 +6354,47 @@ TrioInStreamFileDescriptor(trio_class_t *self, { self->current = (size == 0) ? EOF : input; } - self->committed++; - self->processed++; + if (self->current != EOF) + { + self->committed++; + self->processed++; + } + + if (VALID(intPointer)) + { + *intPointer = self->current; + } +} + +/************************************************************************* + * TrioInStreamCustom + */ +TRIO_PRIVATE void +TrioInStreamCustom +TRIO_ARGS2((self, intPointer), + trio_class_t *self, + int *intPointer) +{ + trio_custom_t *data; + + assert(VALID(self)); + assert(VALID(self->location)); + + data = (trio_custom_t *)self->location; + + self->current = (data->stream.in == NULL) + ? NIL + : (data->stream.in)(data->closure); + + if (self->current == NIL) + { + self->current = EOF; + } + else + { + self->processed++; + self->committed++; + } if (VALID(intPointer)) { @@ -5579,22 +6406,28 @@ TrioInStreamFileDescriptor(trio_class_t *self, * TrioInStreamString */ TRIO_PRIVATE void -TrioInStreamString(trio_class_t *self, - int *intPointer) +TrioInStreamString +TRIO_ARGS2((self, intPointer), + trio_class_t *self, + int *intPointer) { unsigned char **buffer; assert(VALID(self)); - assert(VALID(self->InStream)); assert(VALID(self->location)); buffer = (unsigned char **)self->location; self->current = (*buffer)[0]; if (self->current == NIL) - self->current = EOF; - (*buffer)++; - self->processed++; - self->committed++; + { + self->current = EOF; + } + else + { + (*buffer)++; + self->processed++; + self->committed++; + } if (VALID(intPointer)) { @@ -5627,47 +6460,59 @@ TrioInStreamString(trio_class_t *self, @return Number of scanned characters. */ TRIO_PUBLIC int -trio_scanf(TRIO_CONST char *format, - ...) +trio_scanf +TRIO_VARGS2((format, va_alist), + TRIO_CONST char *format, + TRIO_VA_DECL) { int status; va_list args; assert(VALID(format)); - va_start(args, format); - status = TrioScan(stdin, 0, TrioInStreamFile, format, args, NULL); - va_end(args); + TRIO_VA_START(args, format); + status = TrioScan((trio_pointer_t)stdin, 0, + TrioInStreamFile, + format, &args, NULL); + TRIO_VA_END(args); return status; } TRIO_PUBLIC int -trio_vscanf(TRIO_CONST char *format, - va_list args) +trio_vscanf +TRIO_ARGS2((format, args), + TRIO_CONST char *format, + va_list args) { assert(VALID(format)); - return TrioScan(stdin, 0, TrioInStreamFile, format, args, NULL); + return TrioScan((trio_pointer_t)stdin, 0, + TrioInStreamFile, + format, &args, NULL); } TRIO_PUBLIC int -trio_scanfv(TRIO_CONST char *format, - void **args) +trio_scanfv +TRIO_ARGS2((format, args), + TRIO_CONST char *format, + trio_pointer_t *args) { - va_list dummy; - assert(VALID(format)); - return TrioScan(stdin, 0, TrioInStreamFile, format, dummy, args); + return TrioScan((trio_pointer_t)stdin, 0, + TrioInStreamFile, + format, NULL, args); } /************************************************************************* * fscanf */ TRIO_PUBLIC int -trio_fscanf(FILE *file, +trio_fscanf +TRIO_VARGS3((file, format, va_alist), + FILE *file, TRIO_CONST char *format, - ...) + TRIO_VA_DECL) { int status; va_list args; @@ -5675,84 +6520,166 @@ trio_fscanf(FILE *file, assert(VALID(file)); assert(VALID(format)); - va_start(args, format); - status = TrioScan(file, 0, TrioInStreamFile, format, args, NULL); - va_end(args); + TRIO_VA_START(args, format); + status = TrioScan((trio_pointer_t)file, 0, + TrioInStreamFile, + format, &args, NULL); + TRIO_VA_END(args); return status; } TRIO_PUBLIC int -trio_vfscanf(FILE *file, - TRIO_CONST char *format, - va_list args) +trio_vfscanf +TRIO_ARGS3((file, format, args), + FILE *file, + TRIO_CONST char *format, + va_list args) { assert(VALID(file)); assert(VALID(format)); - return TrioScan(file, 0, TrioInStreamFile, format, args, NULL); + return TrioScan((trio_pointer_t)file, 0, + TrioInStreamFile, + format, &args, NULL); } TRIO_PUBLIC int -trio_fscanfv(FILE *file, - TRIO_CONST char *format, - void **args) +trio_fscanfv +TRIO_ARGS3((file, format, args), + FILE *file, + TRIO_CONST char *format, + trio_pointer_t *args) { - va_list dummy; - assert(VALID(file)); assert(VALID(format)); - return TrioScan(file, 0, TrioInStreamFile, format, dummy, args); + return TrioScan((trio_pointer_t)file, 0, + TrioInStreamFile, + format, NULL, args); } /************************************************************************* * dscanf */ TRIO_PUBLIC int -trio_dscanf(int fd, +trio_dscanf +TRIO_VARGS3((fd, format, va_alist), + int fd, TRIO_CONST char *format, - ...) + TRIO_VA_DECL) { int status; va_list args; assert(VALID(format)); - va_start(args, format); - status = TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, args, NULL); - va_end(args); + TRIO_VA_START(args, format); + status = TrioScan((trio_pointer_t)&fd, 0, + TrioInStreamFileDescriptor, + format, &args, NULL); + TRIO_VA_END(args); return status; } TRIO_PUBLIC int -trio_vdscanf(int fd, - TRIO_CONST char *format, - va_list args) +trio_vdscanf +TRIO_ARGS3((fd, format, args), + int fd, + TRIO_CONST char *format, + va_list args) { assert(VALID(format)); - return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, args, NULL); + return TrioScan((trio_pointer_t)&fd, 0, + TrioInStreamFileDescriptor, + format, &args, NULL); } TRIO_PUBLIC int -trio_dscanfv(int fd, - TRIO_CONST char *format, - void **args) +trio_dscanfv +TRIO_ARGS3((fd, format, args), + int fd, + TRIO_CONST char *format, + trio_pointer_t *args) { - va_list dummy; - assert(VALID(format)); - return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, dummy, args); + return TrioScan((trio_pointer_t)&fd, 0, + TrioInStreamFileDescriptor, + format, NULL, args); +} + +/************************************************************************* + * cscanf + */ +TRIO_PUBLIC int +trio_cscanf +TRIO_VARGS4((stream, closure, format, va_alist), + trio_instream_t stream, + trio_pointer_t closure, + TRIO_CONST char *format, + TRIO_VA_DECL) +{ + int status; + va_list args; + trio_custom_t data; + + assert(VALID(stream)); + assert(VALID(format)); + + TRIO_VA_START(args, format); + data.stream.in = stream; + data.closure = closure; + status = TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL); + TRIO_VA_END(args); + return status; +} + +TRIO_PUBLIC int +trio_vcscanf +TRIO_ARGS4((stream, closure, format, args), + trio_instream_t stream, + trio_pointer_t closure, + TRIO_CONST char *format, + va_list args) +{ + trio_custom_t data; + + assert(VALID(stream)); + assert(VALID(format)); + + data.stream.in = stream; + data.closure = closure; + return TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL); +} + +TRIO_PUBLIC int +trio_cscanfv +TRIO_ARGS4((stream, closure, format, args), + trio_instream_t stream, + trio_pointer_t closure, + TRIO_CONST char *format, + trio_pointer_t *args) +{ + trio_custom_t data; + + assert(VALID(stream)); + assert(VALID(format)); + + data.stream.in = stream; + data.closure = closure; + return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args); } /************************************************************************* * sscanf */ TRIO_PUBLIC int -trio_sscanf(TRIO_CONST char *buffer, +trio_sscanf +TRIO_VARGS3((buffer, format, va_alist), + TRIO_CONST char *buffer, TRIO_CONST char *format, - ...) + TRIO_VA_DECL) { int status; va_list args; @@ -5760,34 +6687,74 @@ trio_sscanf(TRIO_CONST char *buffer, assert(VALID(buffer)); assert(VALID(format)); - va_start(args, format); - status = TrioScan(&buffer, 0, TrioInStreamString, format, args, NULL); - va_end(args); + TRIO_VA_START(args, format); + status = TrioScan((trio_pointer_t)&buffer, 0, + TrioInStreamString, + format, &args, NULL); + TRIO_VA_END(args); return status; } TRIO_PUBLIC int -trio_vsscanf(TRIO_CONST char *buffer, - TRIO_CONST char *format, - va_list args) +trio_vsscanf +TRIO_ARGS3((buffer, format, args), + TRIO_CONST char *buffer, + TRIO_CONST char *format, + va_list args) { assert(VALID(buffer)); assert(VALID(format)); - return TrioScan(&buffer, 0, TrioInStreamString, format, args, NULL); + return TrioScan((trio_pointer_t)&buffer, 0, + TrioInStreamString, + format, &args, NULL); } TRIO_PUBLIC int -trio_sscanfv(TRIO_CONST char *buffer, - TRIO_CONST char *format, - void **args) +trio_sscanfv +TRIO_ARGS3((buffer, format, args), + TRIO_CONST char *buffer, + TRIO_CONST char *format, + trio_pointer_t *args) { - va_list dummy; - assert(VALID(buffer)); assert(VALID(format)); - return TrioScan(&buffer, 0, TrioInStreamString, format, dummy, args); + return TrioScan((trio_pointer_t)&buffer, 0, + TrioInStreamString, + format, NULL, args); } /** @} End of Scanf documentation module */ + +/************************************************************************* + * trio_strerror + */ +TRIO_PUBLIC TRIO_CONST char * +trio_strerror +TRIO_ARGS1((errorcode), + int errorcode) +{ + /* Textual versions of the error codes */ + switch (TRIO_ERROR_CODE(errorcode)) + { + case TRIO_EOF: + return "End of file"; + case TRIO_EINVAL: + return "Invalid argument"; + case TRIO_ETOOMANY: + return "Too many arguments"; + case TRIO_EDBLREF: + return "Double reference"; + case TRIO_EGAP: + return "Reference gap"; + case TRIO_ENOMEM: + return "Out of memory"; + case TRIO_ERANGE: + return "Invalid range"; + case TRIO_ECUSTOM: + return "Custom error"; + default: + return "Unknown"; + } +} diff --git a/trio.h b/trio.h index 5a38f4a7..770c6a6f 100644 --- a/trio.h +++ b/trio.h @@ -23,8 +23,14 @@ #define TRIO_TRIO_H #include -#include #include +#if defined(TRIO_COMPILER_ANCIENT) +# include +#else +# include +#endif + +#if !defined(WITHOUT_TRIO) /* * Use autoconf defines if present. Packages using trio must define @@ -34,22 +40,12 @@ # include #endif -#if !defined(WITHOUT_TRIO) +#include "triodef.h" #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 macros */ -#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF) -#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8) -#define TRIO_ERROR_NAME(x) trio_strerror(x) - /* * Error codes. * @@ -63,72 +59,95 @@ enum { TRIO_EGAP = 5, TRIO_ENOMEM = 6, TRIO_ERANGE = 7, - TRIO_ERRNO = 8 + TRIO_ERRNO = 8, + TRIO_ECUSTOM = 9 }; -const char *trio_strerror(int); +/* Error macros */ +#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF) +#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8) +#define TRIO_ERROR_NAME(x) trio_strerror(x) + +typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int)); +typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t)); + +TRIO_CONST char *trio_strerror TRIO_PROTO((int)); /************************************************************************* * Print Functions */ -int trio_printf(const char *format, ...); -int trio_vprintf(const char *format, va_list args); -int trio_printfv(const char *format, void **args); +int trio_printf TRIO_PROTO((TRIO_CONST char *format, ...)); +int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); +int trio_printfv TRIO_PROTO((TRIO_CONST char *format, void **args)); -int trio_fprintf(FILE *file, const char *format, ...); -int trio_vfprintf(FILE *file, const char *format, va_list args); -int trio_fprintfv(FILE *file, const char *format, void **args); +int trio_fprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...)); +int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); +int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); -int trio_dprintf(int fd, const char *format, ...); -int trio_vdprintf(int fd, const char *format, va_list args); -int trio_dprintfv(int fd, const char *format, void **args); +int trio_dprintf TRIO_PROTO((int fd, TRIO_CONST char *format, ...)); +int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); +int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); -/* trio_sprintf(target, format, ...) - * trio_snprintf(target, maxsize, format, ...) - * - * Build 'target' according to 'format' and succesive - * arguments. This is equal to the sprintf() and - * snprintf() functions. - */ -int trio_sprintf(char *buffer, const char *format, ...); -int trio_vsprintf(char *buffer, const char *format, va_list args); -int trio_sprintfv(char *buffer, const char *format, void **args); +int trio_cprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, + TRIO_CONST char *format, ...)); +int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, + TRIO_CONST char *format, va_list args)); +int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, + TRIO_CONST char *format, void **args)); -int trio_snprintf(char *buffer, size_t max, const char *format, ...); -int trio_vsnprintf(char *buffer, size_t bufferSize, const char *format, - va_list args); -int trio_snprintfv(char *buffer, size_t bufferSize, const char *format, - void **args); +int trio_sprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, ...)); +int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args)); +int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, void **args)); -int trio_snprintfcat(char *buffer, size_t max, const char *format, ...); -int trio_vsnprintfcat(char *buffer, size_t bufferSize, const char *format, - va_list args); +int trio_snprintf TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...)); +int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, + va_list args)); +int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, + void **args)); -char *trio_aprintf(const char *format, ...); -char *trio_vaprintf(const char *format, va_list args); +int trio_snprintfcat TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...)); +int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, + va_list args)); -int trio_asprintf(char **ret, const char *format, ...); -int trio_vasprintf(char **ret, const char *format, va_list args); +char *trio_aprintf TRIO_PROTO((TRIO_CONST char *format, ...)); +char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); + +int trio_asprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, ...)); +int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args)); /************************************************************************* * Scan Functions */ -int trio_scanf(const char *format, ...); -int trio_vscanf(const char *format, va_list args); -int trio_scanfv(const char *format, void **args); +int trio_scanf TRIO_PROTO((TRIO_CONST char *format, ...)); +int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args)); +int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args)); -int trio_fscanf(FILE *file, const char *format, ...); -int trio_vfscanf(FILE *file, const char *format, va_list args); -int trio_fscanfv(FILE *file, const char *format, void **args); +int trio_fscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...)); +int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); +int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); -int trio_dscanf(int fd, const char *format, ...); -int trio_vdscanf(int fd, const char *format, va_list args); -int trio_dscanfv(int fd, const char *format, void **args); +int trio_dscanf TRIO_PROTO((int fd, TRIO_CONST char *format, ...)); +int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); +int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); -int trio_sscanf(const char *buffer, const char *format, ...); -int trio_vsscanf(const char *buffer, const char *format, va_list args); -int trio_sscanfv(const char *buffer, const char *format, void **args); +int trio_cscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, + TRIO_CONST char *format, ...)); +int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, + TRIO_CONST char *format, va_list args)); +int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, + TRIO_CONST char *format, void **args)); + +int trio_sscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, ...)); +int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args)); +int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args)); + +/************************************************************************* + * Locale Functions + */ +void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint)); +void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator)); +void trio_locale_set_grouping TRIO_PROTO((char *grouping)); /************************************************************************* * Renaming diff --git a/triodef.h b/triodef.h index 3e12cc4c..e9b62e59 100644 --- a/triodef.h +++ b/triodef.h @@ -34,8 +34,12 @@ # define TRIO_COMPILER_XLC /* Workaround for old xlc */ #elif defined(__DECC) || defined(__DECCXX) # define TRIO_COMPILER_DECC +#elif defined(__osf__) && defined(__LANGUAGE_C__) +# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */ #elif defined(_MSC_VER) # define TRIO_COMPILER_MSVC +#elif defined(__BORLANDC__) +# define TRIO_COMPILER_BCB #endif #if defined(unix) || defined(__unix) || defined(__unix__) @@ -61,9 +65,10 @@ # define TRIO_PLATFORM_MPEIX #endif -#if defined(__STDC__) -# define TRIO_COMPILER_SUPPORTS_C90 +#if defined(__STDC__) || defined(TRIO_COMPILER_MSVC) +# define TRIO_COMPILER_SUPPORTS_C89 # if defined(__STDC_VERSION__) +# define TRIO_COMPILER_SUPPORTS_C90 # if (__STDC_VERSION__ >= 199409L) # define TRIO_COMPILER_SUPPORTS_C94 # endif @@ -84,6 +89,9 @@ # if (_XOPEN_VERSION >= 500) # define TRIO_COMPILER_SUPPORTS_UNIX98 # endif +# if (_XOPEN_VERSION >= 600) +# define TRIO_COMPILER_SUPPORTS_UNIX01 +# endif #endif /************************************************************************* @@ -97,22 +105,64 @@ # define TRIO_PRIVATE static #endif -#if defined(TRIO_COMPILER_SUPPORTS_C90) || defined(__cplusplus) -# define TRIO_CONST const -# define TRIO_VOLATILE volatile -# define TRIO_POINTER void * -# define TRIO_PROTO(x) x -#else +#if !(defined(TRIO_COMPILER_SUPPORTS_C89) || defined(__cplusplus)) +# define TRIO_COMPILER_ANCIENT +#endif + +#if defined(TRIO_COMPILER_ANCIENT) # define TRIO_CONST # define TRIO_VOLATILE -# define TRIO_POINTER char * +# define TRIO_SIGNED +typedef double trio_long_double_t; +typedef char * trio_pointer_t; +# define TRIO_SUFFIX_LONG(x) x # define TRIO_PROTO(x) () +# define TRIO_NOARGS +# define TRIO_ARGS1(list,a1) list a1; +# define TRIO_ARGS2(list,a1,a2) list a1; a2; +# define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3; +# define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4; +# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5; +# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6; +# define TRIO_VARGS2(list,a1,a2) list a1; a2 +# define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3 +# define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4 +# define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5 +# define TRIO_VA_DECL va_dcl +# define TRIO_VA_START(x,y) va_start((x)) +# define TRIO_VA_END(x) va_end(x) +#else /* ANSI C */ +# define TRIO_CONST const +# define TRIO_VOLATILE volatile +# define TRIO_SIGNED signed +typedef long double trio_long_double_t; +typedef void * trio_pointer_t; +# define TRIO_SUFFIX_LONG(x) x ## L +# define TRIO_PROTO(x) x +# define TRIO_NOARGS void +# define TRIO_ARGS1(list,a1) (a1) +# define TRIO_ARGS2(list,a1,a2) (a1,a2) +# define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3) +# define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4) +# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5) +# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6) +# define TRIO_VARGS2 TRIO_ARGS2 +# define TRIO_VARGS3 TRIO_ARGS3 +# define TRIO_VARGS4 TRIO_ARGS4 +# define TRIO_VARGS5 TRIO_ARGS5 +# define TRIO_VA_DECL ... +# define TRIO_VA_START(x,y) va_start((x),(y)) +# define TRIO_VA_END(x) va_end(x) #endif #if defined(TRIO_COMPILER_SUPPORTS_C99) || defined(__cplusplus) # define TRIO_INLINE inline #elif defined(TRIO_COMPILER_GCC) # define TRIO_INLINE __inline__ +#elif defined(TRIO_COMPILER_MSVC) +# define TRIO_INLINE _inline +#elif defined(TRIO_COMPILER_BCB) +# define TRIO_INLINE __inline #else # define TRIO_INLINE #endif diff --git a/trionan.c b/trionan.c index 6f67c5be..5d63ad78 100644 --- a/trionan.c +++ b/trionan.c @@ -29,40 +29,13 @@ * 2. Use IEEE 754 bit-patterns if possible. * 3. Use platform-specific techniques. * - * This program has been tested on the following platforms (in - * alphabetic order) - * - * OS CPU Compiler - * ------------------------------------------------- - * AIX 4.1.4 PowerPC gcc - * Darwin 1.3.7 PowerPC gcc - * FreeBSD 2.2 x86 gcc - * FreeBSD 3.3 x86 gcc - * FreeBSD 4.3 x86 gcc - * FreeBSD 4.3 Alpha gcc - * HP-UX 10.20 PA-RISC gcc - * HP-UX 10.20 PA-RISC HP C++ - * IRIX 6.5 MIPS MIPSpro C - * Linux 2.2 x86 gcc - * Linux 2.2 Alpha gcc - * Linux 2.4 IA64 gcc - * Linux 2.4 StrongARM gcc - * NetBSD 1.4 x86 gcc - * NetBSD 1.4 StrongARM gcc - * NetBSD 1.5 Alpha gcc - * OpenVMS 7.1 Alpha DEC C 6.0 - * RISC OS 4 StrongARM Norcroft C - * Solaris 2.5.1 x86 gcc - * Solaris 2.5.1 Sparc gcc - * Solaris 2.6 Sparc WorkShop 4.2 - * Solaris 8 Sparc Forte C 6 - * Tru64 4.0D Alpha gcc - * Tru64 5.1 Alpha gcc - * WinNT x86 MSVC 5.0 & 6.0 - * ************************************************************************/ -static const char rcsid[] = "@(#)$Id$"; +/* + * TODO: + * o Put all the magic into trio_fpclassify_and_signbit(), and use this from + * trio_isnan() etc. + */ /************************************************************************* * Include files @@ -102,7 +75,9 @@ static const char rcsid[] = "@(#)$Id$"; # if defined(TRIO_PLATFORM_VMS) # error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE" # else -# error "Must be compiled with option -ieee" +# if !defined(_CFE) +# error "Must be compiled with option -ieee" +# endif # endif # elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__)) # error "Must be compiled with option -mieee" @@ -128,9 +103,11 @@ static const char rcsid[] = "@(#)$Id$"; /************************************************************************* - * Data + * Constants */ +static TRIO_CONST char rcsid[] = "@(#)$Id$"; + #if defined(USE_IEEE_754) /* @@ -187,7 +164,9 @@ static TRIO_CONST unsigned char ieee_754_qnan_array[] = { * trio_make_double */ TRIO_PRIVATE double -trio_make_double(TRIO_CONST unsigned char *values) +trio_make_double +TRIO_ARGS1((values), + TRIO_CONST unsigned char *values) { TRIO_VOLATILE double result; int i; @@ -202,8 +181,10 @@ trio_make_double(TRIO_CONST unsigned char *values) * trio_is_special_quantity */ TRIO_PRIVATE int -trio_is_special_quantity(double number, - int *has_mantissa) +trio_is_special_quantity +TRIO_ARGS2((number, has_mantissa), + double number, + int *has_mantissa) { unsigned int i; unsigned char current; @@ -224,7 +205,9 @@ trio_is_special_quantity(double number, * trio_is_negative */ TRIO_PRIVATE int -trio_is_negative(double number) +trio_is_negative +TRIO_ARGS1((number), + double number) { unsigned int i; int is_negative = TRIO_FALSE; @@ -236,22 +219,33 @@ trio_is_negative(double number) return is_negative; } -TRIO_PUBLIC double -trio_nzero(void) -{ - return trio_make_double(ieee_754_negzero_array); -} - #endif /* USE_IEEE_754 */ +/** + Generate negative zero. + + @return Floating-point representation of negative zero. +*/ +TRIO_PUBLIC double +trio_nzero(TRIO_NOARGS) +{ +#if defined(USE_IEEE_754) + return trio_make_double(ieee_754_negzero_array); +#else + TRIO_VOLATILE double zero = 0.0; + + return -zero; +#endif +} + /** Generate positive infinity. @return Floating-point representation of positive infinity. */ TRIO_PUBLIC double -trio_pinf(void) +trio_pinf(TRIO_NOARGS) { /* Cache the result */ static double result = 0.0; @@ -295,7 +289,7 @@ trio_pinf(void) @return Floating-point value of negative infinity. */ TRIO_PUBLIC double -trio_ninf(void) +trio_ninf(TRIO_NOARGS) { static double result = 0.0; @@ -316,7 +310,7 @@ trio_ninf(void) @return Floating-point representation of NaN. */ TRIO_PUBLIC double -trio_nan(void) +trio_nan(TRIO_NOARGS) { /* Cache the result */ static double result = 0.0; @@ -364,9 +358,12 @@ trio_nan(void) @return Boolean value indicating whether or not the number is a NaN. */ TRIO_PUBLIC int -trio_isnan(TRIO_VOLATILE double number) +trio_isnan +TRIO_ARGS1((number), + double number) { -#if defined(isnan) || defined(TRIO_COMPILER_SUPPORTS_UNIX95) +#if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \ + || defined(TRIO_COMPILER_SUPPORTS_UNIX95) /* * C99 defines isnan() as a macro. UNIX95 defines isnan() as a * function. This function was already present in XPG4, but this @@ -407,7 +404,7 @@ trio_isnan(TRIO_VOLATILE double number) status = (/* * NaN is the only number which does not compare to itself */ - (number != number) || + ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) || /* * Fallback solution if NaN compares to NaN */ @@ -431,7 +428,9 @@ trio_isnan(TRIO_VOLATILE double number) @return 1 if positive infinity, -1 if negative infinity, 0 otherwise. */ TRIO_PUBLIC int -trio_isinf(TRIO_VOLATILE double number) +trio_isinf +TRIO_ARGS1((number), + double number) { #if defined(TRIO_COMPILER_DECC) /* @@ -441,12 +440,14 @@ trio_isinf(TRIO_VOLATILE double number) return ((fp_class(number) == FP_POS_INF) ? 1 : ((fp_class(number) == FP_NEG_INF) ? -1 : 0)); - + #elif defined(isinf) /* * C99 defines isinf() as a macro. */ - return isinf(number); + return isinf(number) + ? ((number > 0.0) ? 1 : -1) + : 0; #elif defined(TRIO_COMPILER_MSVC) /* @@ -503,9 +504,11 @@ trio_isinf(TRIO_VOLATILE double number) @return Boolean value indicating whether or not the number is a finite. */ TRIO_PUBLIC int -trio_isfinite(TRIO_VOLATILE double number) +trio_isfinite +TRIO_ARGS1((number), + double number) { -#if defined(isfinite) +#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite) /* * C99 defines isfinite() as a macro. */ @@ -538,9 +541,11 @@ trio_isfinite(TRIO_VOLATILE double number) /* * The sign of NaN is always false */ -TRIO_PRIVATE int -trio_fpclass(TRIO_VOLATILE double number, - int *is_negative) +TRIO_PUBLIC int +trio_fpclassify_and_signbit +TRIO_ARGS2((number, is_negative), + double number, + int *is_negative) { #if defined(fpclassify) && defined(signbit) /* @@ -637,7 +642,46 @@ trio_fpclass(TRIO_VOLATILE double number, *is_negative = (number < 0.0); return TRIO_FP_NORMAL; } - + +#elif defined(FP_PLUS_NORM) || defined(__hpux) + + /* + * HP-UX 9.x and 10.x have an fpclassify() function, that is different + * from the C99 fpclassify() macro supported on HP-UX 11.x. + */ + switch (fpclassify(number)) { + case FP_QNAN: + case FP_SNAN: + *is_negative = TRIO_FALSE; + return TRIO_FP_NAN; + case FP_PLUS_INF: + *is_negative = TRIO_FALSE; + return TRIO_FP_INFINITE; + case FP_MINUS_INF: + *is_negative = TRIO_TRUE; + return TRIO_FP_INFINITE; + case FP_PLUS_DENORM: + *is_negative = TRIO_FALSE; + return TRIO_FP_SUBNORMAL; + case FP_MINUS_DENORM: + *is_negative = TRIO_TRUE; + return TRIO_FP_SUBNORMAL; + case FP_PLUS_ZERO: + *is_negative = TRIO_FALSE; + return TRIO_FP_ZERO; + case FP_MINUS_ZERO: + *is_negative = TRIO_TRUE; + return TRIO_FP_ZERO; + case FP_PLUS_NORM: + *is_negative = TRIO_FALSE; + return TRIO_FP_NORMAL; + case FP_MINUS_NORM: + *is_negative = TRIO_TRUE; + return TRIO_FP_NORMAL; + default: + assert(0); + } + #else /* * Fallback solution. @@ -687,11 +731,13 @@ trio_fpclass(TRIO_VOLATILE double number, sign bit set (i.e. is negative). */ TRIO_PUBLIC int -trio_signbit(TRIO_VOLATILE double number) +trio_signbit +TRIO_ARGS1((number), + double number) { int is_negative; - (void)trio_fpclass(number, &is_negative); + (void)trio_fpclassify_and_signbit(number, &is_negative); return is_negative; } @@ -702,11 +748,13 @@ trio_signbit(TRIO_VOLATILE double number) @return Enumerable value indicating the class of @p number */ TRIO_PUBLIC int -trio_fpclassify(TRIO_VOLATILE double number) +trio_fpclassify +TRIO_ARGS1((number), + double number) { int dummy; - return trio_fpclass(number, &dummy); + return trio_fpclassify_and_signbit(number, &dummy); } @@ -723,7 +771,10 @@ trio_fpclassify(TRIO_VOLATILE double number) #if defined(STANDALONE) # include -static const char *getClassification(int type) +static TRIO_CONST char * +getClassification +TRIO_ARGS1((type) + int type) { switch (type) { case TRIO_FP_INFINITE: @@ -741,7 +792,11 @@ static const char *getClassification(int type) } } -static void print_class(const char *prefix, double number) +static void +print_class +TRIO_ARGS2((prefix, number) + TRIO_CONST char *prefix, + double number) { printf("%-6s: %s %-15s %g\n", prefix, @@ -750,13 +805,13 @@ static void print_class(const char *prefix, double number) number); } -int main(void) +int main(TRIO_NOARGS) { double my_nan; double my_pinf; double my_ninf; # if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int); + void (*signal_handler) TRIO_PROTO((int)); # endif my_nan = trio_nan(); diff --git a/trionan.h b/trionan.h index ab2102d7..bed0c120 100644 --- a/trionan.h +++ b/trionan.h @@ -35,39 +35,44 @@ enum { /* * Return NaN (Not-a-Number). */ -TRIO_PUBLIC double trio_nan(void); +TRIO_PUBLIC double trio_nan TRIO_PROTO((void)); /* * Return positive infinity. */ -TRIO_PUBLIC double trio_pinf(void); +TRIO_PUBLIC double trio_pinf TRIO_PROTO((void)); /* * Return negative infinity. */ -TRIO_PUBLIC double trio_ninf(void); +TRIO_PUBLIC double trio_ninf TRIO_PROTO((void)); +/* + * Return negative zero. + */ +TRIO_PUBLIC double trio_nzero TRIO_PROTO((TRIO_NOARGS)); + /* * If number is a NaN return non-zero, otherwise return zero. */ -TRIO_PUBLIC int trio_isnan(double number); +TRIO_PUBLIC int trio_isnan TRIO_PROTO((double number)); /* * If number is positive infinity return 1, if number is negative * infinity return -1, otherwise return 0. */ -TRIO_PUBLIC int trio_isinf(double number); +TRIO_PUBLIC int trio_isinf TRIO_PROTO((double number)); /* * If number is finite return non-zero, otherwise return zero. */ -TRIO_PUBLIC int trio_isfinite(double number); +TRIO_PUBLIC int trio_isfinite TRIO_PROTO((double number)); -TRIO_PUBLIC int trio_signbit(double number); +TRIO_PUBLIC int trio_signbit TRIO_PROTO((double number)); -TRIO_PUBLIC int trio_fpclassify(double number); +TRIO_PUBLIC int trio_fpclassify TRIO_PROTO((double number)); -TRIO_PUBLIC double trio_nzero(void); +TRIO_PUBLIC int trio_fpclassify_and_signbit TRIO_PROTO((double number, int *is_negative)); #ifdef __cplusplus } diff --git a/triop.h b/triop.h index ead673a1..8462c56f 100644 --- a/triop.h +++ b/triop.h @@ -26,8 +26,14 @@ #ifndef TRIO_TRIOP_H #define TRIO_TRIOP_H +#include "triodef.h" + #include -#include +#if defined(TRIO_COMPILER_ANCIENT) +# include +#else +# include +#endif #ifdef __cplusplus extern "C" { @@ -71,70 +77,71 @@ extern "C" { # define TRIO_FREE(x) free(x) #endif + /************************************************************************* * User-defined specifiers */ -typedef int (*trio_callback_t)(void *); +typedef int (*trio_callback_t) TRIO_PROTO((trio_pointer_t)); -void *trio_register(trio_callback_t callback, const char *name); -void trio_unregister(void *handle); +trio_pointer_t trio_register TRIO_PROTO((trio_callback_t callback, const char *name)); +void trio_unregister TRIO_PROTO((trio_pointer_t handle)); -const char *trio_get_format(void *ref); -void *trio_get_argument(void *ref); +TRIO_CONST char *trio_get_format TRIO_PROTO((trio_pointer_t ref)); +trio_pointer_t trio_get_argument TRIO_PROTO((trio_pointer_t ref)); /* Modifiers */ -int trio_get_width(void *ref); -void trio_set_width(void *ref, int width); -int trio_get_precision(void *ref); -void trio_set_precision(void *ref, int precision); -int trio_get_base(void *ref); -void trio_set_base(void *ref, int base); -int trio_get_padding(void *ref); -void trio_set_padding(void *ref, int is_padding); -int trio_get_short(void *ref); /* h */ -void trio_set_shortshort(void *ref, int is_shortshort); -int trio_get_shortshort(void *ref); /* hh */ -void trio_set_short(void *ref, int is_short); -int trio_get_long(void *ref); /* l */ -void trio_set_long(void *ref, int is_long); -int trio_get_longlong(void *ref); /* ll */ -void trio_set_longlong(void *ref, int is_longlong); -int trio_get_longdouble(void *ref); /* L */ -void trio_set_longdouble(void *ref, int is_longdouble); -int trio_get_alternative(void *ref); /* # */ -void trio_set_alternative(void *ref, int is_alternative); -int trio_get_alignment(void *ref); /* - */ -void trio_set_alignment(void *ref, int is_leftaligned); -int trio_get_spacing(void *ref); /* (space) */ -void trio_set_spacing(void *ref, int is_space); -int trio_get_sign(void *ref); /* + */ -void trio_set_sign(void *ref, int is_showsign); -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); +int trio_get_width TRIO_PROTO((trio_pointer_t ref)); +void trio_set_width TRIO_PROTO((trio_pointer_t ref, int width)); +int trio_get_precision TRIO_PROTO((trio_pointer_t ref)); +void trio_set_precision TRIO_PROTO((trio_pointer_t ref, int precision)); +int trio_get_base TRIO_PROTO((trio_pointer_t ref)); +void trio_set_base TRIO_PROTO((trio_pointer_t ref, int base)); +int trio_get_padding TRIO_PROTO((trio_pointer_t ref)); +void trio_set_padding TRIO_PROTO((trio_pointer_t ref, int is_padding)); +int trio_get_short TRIO_PROTO((trio_pointer_t ref)); /* h */ +void trio_set_shortshort TRIO_PROTO((trio_pointer_t ref, int is_shortshort)); +int trio_get_shortshort TRIO_PROTO((trio_pointer_t ref)); /* hh */ +void trio_set_short TRIO_PROTO((trio_pointer_t ref, int is_short)); +int trio_get_long TRIO_PROTO((trio_pointer_t ref)); /* l */ +void trio_set_long TRIO_PROTO((trio_pointer_t ref, int is_long)); +int trio_get_longlong TRIO_PROTO((trio_pointer_t ref)); /* ll */ +void trio_set_longlong TRIO_PROTO((trio_pointer_t ref, int is_longlong)); +int trio_get_longdouble TRIO_PROTO((trio_pointer_t ref)); /* L */ +void trio_set_longdouble TRIO_PROTO((trio_pointer_t ref, int is_longdouble)); +int trio_get_alternative TRIO_PROTO((trio_pointer_t ref)); /* # */ +void trio_set_alternative TRIO_PROTO((trio_pointer_t ref, int is_alternative)); +int trio_get_alignment TRIO_PROTO((trio_pointer_t ref)); /* - */ +void trio_set_alignment TRIO_PROTO((trio_pointer_t ref, int is_leftaligned)); +int trio_get_spacing TRIO_PROTO((trio_pointer_t ref)); /* TRIO_PROTO((space) */ +void trio_set_spacing TRIO_PROTO((trio_pointer_t ref, int is_space)); +int trio_get_sign TRIO_PROTO((trio_pointer_t ref)); /* + */ +void trio_set_sign TRIO_PROTO((trio_pointer_t ref, int is_showsign)); +int trio_get_quote TRIO_PROTO((trio_pointer_t ref)); /* ' */ +void trio_set_quote TRIO_PROTO((trio_pointer_t ref, int is_quote)); +int trio_get_upper TRIO_PROTO((trio_pointer_t ref)); +void trio_set_upper TRIO_PROTO((trio_pointer_t ref, int is_upper)); #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 */ -void trio_set_ptrdiff(void *ref, int is_ptrdiff); -int trio_get_size(void *ref); /* z / Z */ -void trio_set_size(void *ref, int is_size); +int trio_get_largest TRIO_PROTO((trio_pointer_t ref)); /* j */ +void trio_set_largest TRIO_PROTO((trio_pointer_t ref, int is_largest)); +int trio_get_ptrdiff TRIO_PROTO((trio_pointer_t ref)); /* t */ +void trio_set_ptrdiff TRIO_PROTO((trio_pointer_t ref, int is_ptrdiff)); +int trio_get_size TRIO_PROTO((trio_pointer_t ref)); /* z / Z */ +void trio_set_size TRIO_PROTO((trio_pointer_t ref, int is_size)); #endif /* Printing */ -int trio_print_ref(void *ref, const char *format, ...); -int trio_vprint_ref(void *ref, const char *format, va_list args); -int trio_printv_ref(void *ref, const char *format, void **args); +int trio_print_ref TRIO_PROTO((trio_pointer_t ref, const char *format, ...)); +int trio_vprint_ref TRIO_PROTO((trio_pointer_t ref, const char *format, va_list args)); +int trio_printv_ref TRIO_PROTO((trio_pointer_t ref, const char *format, trio_pointer_t *args)); -void trio_print_int(void *ref, int number); -void trio_print_uint(void *ref, unsigned int number); -/* void trio_print_long(void *ref, long number); */ -/* void trio_print_ulong(void *ref, unsigned long number); */ -void trio_print_double(void *ref, double number); -void trio_print_string(void *ref, char *string); -void trio_print_pointer(void *ref, void *pointer); +void trio_print_int TRIO_PROTO((trio_pointer_t ref, int number)); +void trio_print_uint TRIO_PROTO((trio_pointer_t ref, unsigned int number)); +/* void trio_print_long TRIO_PROTO((trio_pointer_t ref, long number)); */ +/* void trio_print_ulong TRIO_PROTO((trio_pointer_t ref, unsigned long number)); */ +void trio_print_double TRIO_PROTO((trio_pointer_t ref, double number)); +void trio_print_string TRIO_PROTO((trio_pointer_t ref, char *string)); +void trio_print_pointer TRIO_PROTO((trio_pointer_t ref, trio_pointer_t pointer)); #ifdef __cplusplus } /* extern "C" */ diff --git a/triostr.c b/triostr.c index 760be55c..43a30dad 100644 --- a/triostr.c +++ b/triostr.c @@ -15,8 +15,6 @@ * ************************************************************************/ -static const char rcsid[] = "@(#)$Id$"; - /************************************************************************* * Include files */ @@ -26,21 +24,33 @@ static const char rcsid[] = "@(#)$Id$"; #include #include #include +#include "triodef.h" #include "triostr.h" /************************************************************************* * Definitions */ -#ifndef NULL +#if !defined(TRIO_STRING_PUBLIC) +# define TRIO_STRING_PUBLIC TRIO_PUBLIC +#endif +#if !defined(TRIO_STRING_PRIVATE) +# define TRIO_STRING_PRIVATE TRIO_PRIVATE +#endif + +#if !defined(NULL) # define NULL 0 #endif -#define NIL ((char)0) -#ifndef FALSE +#if !defined(NIL) +# define NIL ((char)0) +#endif +#if !defined(FALSE) # define FALSE (1 == 0) # define TRUE (! FALSE) #endif -#define BOOLEAN_T int +#if !defined(BOOLEAN_T) +# define BOOLEAN_T int +#endif #if defined(TRIO_COMPILER_SUPPORTS_C99) # define USE_STRTOD @@ -73,6 +83,14 @@ struct _trio_string_t size_t allocated; }; +/************************************************************************* + * Constants + */ + +#if !defined(TRIO_MINIMAL) +static TRIO_CONST char rcsid[] = "@(#)$Id$"; +#endif + /************************************************************************* * Static String Functions */ @@ -90,8 +108,10 @@ struct _trio_string_t @param size Size of new string. @return Pointer to string, or NULL if allocation failed. */ -TRIO_PUBLIC TRIO_INLINE char * -trio_create(size_t size) +TRIO_STRING_PUBLIC char * +trio_create +TRIO_ARGS1((size), + size_t size) { return (char *)TRIO_MALLOC(size); } @@ -102,8 +122,10 @@ trio_create(size_t size) @param string String to be freed. */ -TRIO_PUBLIC TRIO_INLINE void -trio_destroy(char *string) +TRIO_STRING_PUBLIC void +trio_destroy +TRIO_ARGS1((string), + char *string) { if (string) { @@ -118,18 +140,171 @@ trio_destroy(char *string) @param string String to measure. @return Number of characters in @string. */ -TRIO_PUBLIC TRIO_INLINE size_t -trio_length(const char *string) +TRIO_STRING_PUBLIC size_t +trio_length +TRIO_ARGS1((string), + TRIO_CONST char *string) { return strlen(string); } +#if !defined(TRIO_MINIMAL) +/** + Append @p source at the end of @p target. + + @param target Target string. + @param source Source string. + @return Boolean value indicating success or failure. + + @pre @p target must point to a memory chunk with sufficient room to + contain the @p target string and @p source string. + @pre No boundary checking is performed, so insufficient memory will + result in a buffer overrun. + @post @p target will be zero terminated. +*/ +TRIO_STRING_PUBLIC int +trio_append +TRIO_ARGS2((target, source), + char *target, + TRIO_CONST char *source) +{ + assert(target); + assert(source); + + return (strcat(target, source) != NULL); +} +#endif /* !defined(TRIO_MINIMAL) */ + +#if !defined(TRIO_MINIMAL) +/** + Append at most @p max characters from @p source to @p target. + + @param target Target string. + @param max Maximum number of characters to append. + @param source Source string. + @return Boolean value indicating success or failure. + + @pre @p target must point to a memory chuck with sufficient room to + contain the @p target string and the @p source string (at most @p max + characters). + @pre No boundary checking is performed, so insufficient memory will + result in a buffer overrun. + @post @p target will be zero terminated. +*/ +TRIO_STRING_PUBLIC int +trio_append_max +TRIO_ARGS3((target, max, source), + char *target, + size_t max, + TRIO_CONST char *source) +{ + size_t length; + + assert(target); + assert(source); + + length = trio_length(target); + + if (max > length) + { + strncat(target, source, max - length - 1); + } + return TRUE; +} +#endif /* !defined(TRIO_MINIMAL) */ + + +#if !defined(TRIO_MINIMAL) +/** + Determine if a string contains a substring. + + @param string String to be searched. + @param substring String to be found. + @return Boolean value indicating success or failure. +*/ +TRIO_STRING_PUBLIC int +trio_contains +TRIO_ARGS2((string, substring), + TRIO_CONST char *string, + TRIO_CONST char *substring) +{ + assert(string); + assert(substring); + + return (0 != strstr(string, substring)); +} +#endif /* !defined(TRIO_MINIMAL) */ + + +#if !defined(TRIO_MINIMAL) +/** + Copy @p source to @p target. + + @param target Target string. + @param source Source string. + @return Boolean value indicating success or failure. + + @pre @p target must point to a memory chunk with sufficient room to + contain the @p source string. + @pre No boundary checking is performed, so insufficient memory will + result in a buffer overrun. + @post @p target will be zero terminated. +*/ +TRIO_STRING_PUBLIC int +trio_copy +TRIO_ARGS2((target, source), + char *target, + TRIO_CONST char *source) +{ + assert(target); + assert(source); + + (void)strcpy(target, source); + return TRUE; +} +#endif /* !defined(TRIO_MINIMAL) */ + + +/** + Copy at most @p max characters from @p source to @p target. + + @param target Target string. + @param max Maximum number of characters to append. + @param source Source string. + @return Boolean value indicating success or failure. + + @pre @p target must point to a memory chunk with sufficient room to + contain the @p source string (at most @p max characters). + @pre No boundary checking is performed, so insufficient memory will + result in a buffer overrun. + @post @p target will be zero terminated. +*/ +TRIO_STRING_PUBLIC int +trio_copy_max +TRIO_ARGS3((target, max, source), + char *target, + size_t max, + TRIO_CONST char *source) +{ + assert(target); + assert(source); + assert(max > 0); /* Includes != 0 */ + + (void)strncpy(target, source, max - 1); + target[max - 1] = (char)0; + return TRUE; +} + + /* * TrioDuplicateMax */ -TRIO_PRIVATE char * -TrioDuplicateMax(const char *source, size_t size) +TRIO_STRING_PRIVATE char * +TrioDuplicateMax +TRIO_ARGS2((source, size), + TRIO_CONST char *source, + size_t size) { char *target; @@ -146,137 +321,6 @@ TrioDuplicateMax(const char *source, size_t size) } -/** - Append @p source at the end of @p target. - - @param target Target string. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p target string and @p source string. - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_PUBLIC int -trio_append(char *target, - const char *source) -{ - assert(target); - assert(source); - - return (strcat(target, source) != NULL); -} - - -/** - Append at most @p max characters from @p source to @p target. - - @param target Target string. - @param max Maximum number of characters to append. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chuck with sufficient room to - contain the @p target string and the @p source string (at most @p max - characters). - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_PUBLIC int -trio_append_max(char *target, - size_t max, - const char *source) -{ - size_t length; - - assert(target); - assert(source); - - length = trio_length(target); - - if (max > length) - { - strncat(target, source, max - length - 1); - } - return TRUE; -} - - -/** - Determine if a string contains a substring. - - @param string String to be searched. - @param substring String to be found. - @return Boolean value indicating success or failure. -*/ -TRIO_PUBLIC TRIO_INLINE int -trio_contains(const char *string, - const char *substring) -{ - assert(string); - assert(substring); - - return (0 != strstr(string, substring)); -} - - -/** - Copy @p source to @p target. - - @param target Target string. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p source string. - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_PUBLIC int -trio_copy(char *target, - const char *source) -{ - assert(target); - assert(source); - - (void)strcpy(target, source); - return TRUE; -} - - -/** - Copy at most @p max characters from @p source to @p target. - - @param target Target string. - @param max Maximum number of characters to append. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p source string (at most @p max characters). - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_PUBLIC int -trio_copy_max(char *target, - size_t max, - const char *source) -{ - assert(target); - assert(source); - assert(max > 0); /* Includes != 0 */ - - (void)strncpy(target, source, max - 1); - target[max - 1] = (char)0; - return TRUE; -} - - /** Duplicate @p source. @@ -285,13 +329,16 @@ trio_copy_max(char *target, @post @p target will be zero terminated. */ -TRIO_PUBLIC char * -trio_duplicate(const char *source) +TRIO_STRING_PUBLIC char * +trio_duplicate +TRIO_ARGS1((source), + TRIO_CONST char *source) { return TrioDuplicateMax(source, trio_length(source)); } +#if !defined(TRIO_MINIMAL) /** Duplicate at most @p max characters of @p source. @@ -301,9 +348,10 @@ trio_duplicate(const char *source) @post @p target will be zero terminated. */ -TRIO_PUBLIC char * -trio_duplicate_max(const char *source, - size_t max) +TRIO_STRING_PUBLIC char * +trio_duplicate_max TRIO_ARGS2((source, max), + TRIO_CONST char *source, + size_t max) { size_t length; @@ -317,6 +365,7 @@ trio_duplicate_max(const char *source, } return TrioDuplicateMax(source, length); } +#endif /* !defined(TRIO_MINIMAL) */ /** @@ -328,9 +377,11 @@ trio_duplicate_max(const char *source, Case-insensitive comparison. */ -TRIO_PUBLIC int -trio_equal(const char *first, - const char *second) +TRIO_STRING_PUBLIC int +trio_equal +TRIO_ARGS2((first, second), + TRIO_CONST char *first, + TRIO_CONST char *second) { assert(first); assert(second); @@ -365,9 +416,11 @@ trio_equal(const char *first, Case-sensitive comparison. */ -TRIO_PUBLIC int -trio_equal_case(const char *first, - const char *second) +TRIO_STRING_PUBLIC int +trio_equal_case +TRIO_ARGS2((first, second), + TRIO_CONST char *first, + TRIO_CONST char *second) { assert(first); assert(second); @@ -380,6 +433,7 @@ trio_equal_case(const char *first, } +#if !defined(TRIO_MINIMAL) /** Compare if two strings up until the first @p max characters are equal. @@ -390,10 +444,12 @@ trio_equal_case(const char *first, Case-sensitive comparison. */ -TRIO_PUBLIC int -trio_equal_case_max(const char *first, - size_t max, - const char *second) +TRIO_STRING_PUBLIC int +trio_equal_case_max +TRIO_ARGS3((first, max, second), + TRIO_CONST char *first, + size_t max, + TRIO_CONST char *second) { assert(first); assert(second); @@ -404,6 +460,7 @@ trio_equal_case_max(const char *first, } return FALSE; } +#endif /* !defined(TRIO_MINIMAL) */ /** @@ -415,9 +472,11 @@ trio_equal_case_max(const char *first, Collating characters are considered equal. */ -TRIO_PUBLIC int -trio_equal_locale(const char *first, - const char *second) +TRIO_STRING_PUBLIC int +trio_equal_locale +TRIO_ARGS2((first, second), + TRIO_CONST char *first, + TRIO_CONST char *second) { assert(first); assert(second); @@ -440,10 +499,12 @@ trio_equal_locale(const char *first, Case-insensitive comparison. */ -TRIO_PUBLIC int -trio_equal_max(const char *first, - size_t max, - const char *second) +TRIO_STRING_PUBLIC int +trio_equal_max +TRIO_ARGS3((first, max, second), + TRIO_CONST char *first, + size_t max, + TRIO_CONST char *second) { assert(first); assert(second); @@ -478,8 +539,10 @@ trio_equal_max(const char *first, @param error_number Error number. @return Textual description of @p error_number. */ -TRIO_PUBLIC const char * -trio_error(int error_number) +TRIO_STRING_PUBLIC TRIO_CONST char * +trio_error +TRIO_ARGS1((error_number), + int error_number) { #if defined(USE_STRERROR) return strerror(error_number); @@ -489,6 +552,7 @@ trio_error(int error_number) } +#if !defined(TRIO_MINIMAL) /** Format the date/time according to @p format. @@ -501,11 +565,13 @@ trio_error(int error_number) The formatting string accepts the same specifiers as the standard C function strftime. */ -TRIO_PUBLIC size_t -trio_format_date_max(char *target, - size_t max, - const char *format, - const struct tm *datetime) +TRIO_STRING_PUBLIC size_t +trio_format_date_max +TRIO_ARGS4((target, max, format, datetime), + char *target, + size_t max, + TRIO_CONST char *format, + TRIO_CONST struct tm *datetime) { assert(target); assert(format); @@ -514,8 +580,10 @@ trio_format_date_max(char *target, return strftime(target, max, format, datetime); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Calculate a hash value for a string. @@ -526,9 +594,11 @@ trio_format_date_max(char *target, @p type can be one of the following @li @c TRIO_HASH_PLAIN Plain hash function. */ -TRIO_PUBLIC unsigned long -trio_hash(const char *string, - int type) +TRIO_STRING_PUBLIC unsigned long +trio_hash +TRIO_ARGS2((string, type), + TRIO_CONST char *string, + int type) { unsigned long value = 0L; char ch; @@ -550,8 +620,10 @@ trio_hash(const char *string, } return value; } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Find first occurrence of a character in a string. @@ -559,16 +631,20 @@ trio_hash(const char *string, @param character Character to be found. @param A pointer to the found character, or NULL if character was not found. */ -TRIO_PUBLIC TRIO_INLINE char * -trio_index(const char *string, - char character) +TRIO_STRING_PUBLIC char * +trio_index +TRIO_ARGS2((string, character), + TRIO_CONST char *string, + int character) { assert(string); return strchr(string, character); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Find last occurrence of a character in a string. @@ -576,31 +652,39 @@ trio_index(const char *string, @param character Character to be found. @param A pointer to the found character, or NULL if character was not found. */ -TRIO_PUBLIC TRIO_INLINE char * -trio_index_last(const char *string, - char character) +TRIO_STRING_PUBLIC char * +trio_index_last +TRIO_ARGS2((string, character), + TRIO_CONST char *string, + int character) { assert(string); return strchr(string, character); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Convert the alphabetic letters in the string to lower-case. @param target String to be converted. @return Number of processed characters (converted or not). */ -TRIO_PUBLIC TRIO_INLINE int -trio_lower(char *target) +TRIO_STRING_PUBLIC int +trio_lower +TRIO_ARGS1((target), + char *target) { assert(target); return trio_span_function(target, target, tolower); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Compare two strings using wildcards. @@ -614,9 +698,11 @@ trio_lower(char *target) @li @c * Match any number of characters. @li @c ? Match a single character. */ -TRIO_PUBLIC int -trio_match(const char *string, - const char *pattern) +TRIO_STRING_PUBLIC int +trio_match +TRIO_ARGS2((string, pattern), + TRIO_CONST char *string, + TRIO_CONST char *pattern) { assert(string); assert(pattern); @@ -648,8 +734,10 @@ trio_match(const char *string, return FALSE; } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Compare two strings using wildcards. @@ -663,9 +751,11 @@ trio_match(const char *string, @li @c * Match any number of characters. @li @c ? Match a single character. */ -TRIO_PUBLIC int -trio_match_case(const char *string, - const char *pattern) +TRIO_STRING_PUBLIC int +trio_match_case +TRIO_ARGS2((string, pattern), + TRIO_CONST char *string, + TRIO_CONST char *pattern) { assert(string); assert(pattern); @@ -697,8 +787,10 @@ trio_match_case(const char *string, return FALSE; } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Execute a function on each character in string. @@ -707,10 +799,12 @@ trio_match_case(const char *string, @param Function Function to be executed. @return Number of processed characters. */ -TRIO_PUBLIC size_t -trio_span_function(char *target, - const char *source, - int (*Function)(int)) +TRIO_STRING_PUBLIC size_t +trio_span_function +TRIO_ARGS3((target, source, Function), + char *target, + TRIO_CONST char *source, + int (*Function) TRIO_PROTO((int))) { size_t count = 0; @@ -725,8 +819,10 @@ trio_span_function(char *target, } return count; } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Search for a substring in a string. @@ -735,17 +831,21 @@ trio_span_function(char *target, @return Pointer to first occurrence of @p substring in @p string, or NULL if no match was found. */ -TRIO_PUBLIC TRIO_INLINE char * -trio_substring(const char *string, - const char *substring) +TRIO_STRING_PUBLIC char * +trio_substring +TRIO_ARGS2((string, substring), + TRIO_CONST char *string, + TRIO_CONST char *substring) { assert(string); assert(substring); return strstr(string, substring); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Search for a substring in the first @p max characters of a string. @@ -755,10 +855,12 @@ trio_substring(const char *string, @return Pointer to first occurrence of @p substring in @p string, or NULL if no match was found. */ -TRIO_PUBLIC char * -trio_substring_max(const char *string, - size_t max, - const char *substring) +TRIO_STRING_PUBLIC char * +trio_substring_max +TRIO_ARGS3((string, max, substring), + TRIO_CONST char *string, + size_t max, + TRIO_CONST char *substring) { size_t count; size_t size; @@ -781,8 +883,10 @@ trio_substring_max(const char *string, } return result; } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Tokenize string. @@ -792,13 +896,17 @@ trio_substring_max(const char *string, @warning @p string will be destroyed. */ -TRIO_PUBLIC TRIO_INLINE char * -trio_tokenize(char *string, const char *delimiters) +TRIO_STRING_PUBLIC char * +trio_tokenize +TRIO_ARGS2((string, delimiters), + char *string, + TRIO_CONST char *delimiters) { assert(delimiters); return strtok(string, delimiters); } +#endif /* !defined(TRIO_MINIMAL) */ /** @@ -823,29 +931,32 @@ trio_tokenize(char *string, const char *delimiters) @endverbatim */ /* FIXME: Add EBNF for hex-floats */ -TRIO_PUBLIC double -trio_to_double(const char *source, - const char **endp) +TRIO_STRING_PUBLIC trio_long_double_t +trio_to_long_double +TRIO_ARGS2((source, endp), + TRIO_CONST char *source, + char **endp) { -#if defined(USE_STRTOD) - return strtod(source, (char **)endp); +#if defined(USE_STRTOLD) + return strtold(source, endp); #else - /* Preliminary code */ int isNegative = FALSE; int isExponentNegative = FALSE; - unsigned long integer = 0; - unsigned long fraction = 0; - unsigned long fracdiv = 1; + trio_long_double_t integer = 0.0; + trio_long_double_t fraction = 0.0; unsigned long exponent = 0; - double value = 0.0; + trio_long_double_t base; + trio_long_double_t fracdiv = 1.0; + trio_long_double_t value = 0.0; /* First try hex-floats */ if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X'))) { + base = 16.0; source += 2; while (isxdigit((int)*source)) { - integer *= 16; + integer *= base; integer += (isdigit((int)*source) ? (*source - '0') : 10 + (toupper((int)*source) - 'A')); @@ -856,11 +967,10 @@ trio_to_double(const char *source, source++; while (isxdigit((int)*source)) { - fraction *= 16; - fraction += (isdigit((int)*source) - ? (*source - '0') - : 10 + (toupper((int)*source) - 'A')); - fracdiv *= 16; + fracdiv /= base; + fraction += fracdiv * (isdigit((int)*source) + ? (*source - '0') + : 10 + (toupper((int)*source) - 'A')); source++; } if ((*source == 'p') || (*source == 'P')) @@ -873,7 +983,7 @@ trio_to_double(const char *source, } while (isdigit((int)*source)) { - exponent *= 10; + exponent *= (int)base; exponent += (*source - '0'); source++; } @@ -882,6 +992,7 @@ trio_to_double(const char *source, } else /* Then try normal decimal floats */ { + base = 10.0; isNegative = (*source == '-'); /* Skip sign */ if ((*source == '+') || (*source == '-')) @@ -890,7 +1001,7 @@ trio_to_double(const char *source, /* Integer part */ while (isdigit((int)*source)) { - integer *= 10; + integer *= base; integer += (*source - '0'); source++; } @@ -900,9 +1011,8 @@ trio_to_double(const char *source, source++; /* skip decimal point */ while (isdigit((int)*source)) { - fraction *= 10; - fraction += (*source - '0'); - fracdiv *= 10; + fracdiv /= base; + fraction += (*source - '0') * fracdiv; source++; } } @@ -920,30 +1030,26 @@ trio_to_double(const char *source, source++; while (isdigit((int)*source)) { - exponent *= 10; + exponent *= (int)base; exponent += (*source - '0'); source++; } } } - value = (double)integer; - if (fraction != 0) - { - value += (double)fraction / (double)fracdiv; - } + value = integer + fraction; if (exponent != 0) { if (isExponentNegative) - value /= pow((double)10, (double)exponent); + value /= pow(base, (double)exponent); else - value *= pow((double)10, (double)exponent); + value *= pow(base, (double)exponent); } if (isNegative) value = -value; if (endp) - *endp = source; + *endp = (char *)source; return value; #endif } @@ -956,19 +1062,45 @@ trio_to_double(const char *source, @param endp Pointer to end of the converted string. @return A floating-point number. - See @ref trio_to_double. + See @ref trio_to_long_double. */ -TRIO_PUBLIC TRIO_INLINE float -trio_to_float(const char *source, - const char **endp) +TRIO_STRING_PUBLIC double +trio_to_double +TRIO_ARGS2((source, endp), + TRIO_CONST char *source, + char **endp) { -#if defined(USE_STRTOF) - return strtof(source, (char **)endp); +#if defined(USE_STRTOD) + return strtod(source, endp); #else - return (float)trio_to_double(source, endp); + return (double)trio_to_long_double(source, endp); #endif } +#if !defined(TRIO_MINIMAL) +/** + Convert string to floating-point number. + + @param source String to be converted. + @param endp Pointer to end of the converted string. + @return A floating-point number. + + See @ref trio_to_long_double. +*/ +TRIO_STRING_PUBLIC float +trio_to_float +TRIO_ARGS2((source, endp), + TRIO_CONST char *source, + char **endp) +{ +#if defined(USE_STRTOF) + return strtof(source, endp); +#else + return (float)trio_to_long_double(source, endp); +#endif +} +#endif /* !defined(TRIO_MINIMAL) */ + /** Convert string to signed integer. @@ -977,10 +1109,12 @@ trio_to_float(const char *source, @param endp Pointer to end of converted string. @param base Radix number of number. */ -TRIO_PUBLIC TRIO_INLINE long -trio_to_long(const char *string, - char **endp, - int base) +TRIO_STRING_PUBLIC long +trio_to_long +TRIO_ARGS3((string, endp, base), + TRIO_CONST char *string, + char **endp, + int base) { assert(string); assert((base >= 2) && (base <= 36)); @@ -989,6 +1123,7 @@ trio_to_long(const char *string, } +#if !defined(TRIO_MINIMAL) /** Convert string to unsigned integer. @@ -996,31 +1131,38 @@ trio_to_long(const char *string, @param endp Pointer to end of converted string. @param base Radix number of number. */ -TRIO_PUBLIC TRIO_INLINE unsigned long -trio_to_unsigned_long(const char *string, - char **endp, - int base) +TRIO_STRING_PUBLIC unsigned long +trio_to_unsigned_long +TRIO_ARGS3((string, endp, base), + TRIO_CONST char *string, + char **endp, + int base) { assert(string); assert((base >= 2) && (base <= 36)); return strtoul(string, endp, base); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /** Convert the alphabetic letters in the string to upper-case. @param target The string to be converted. @return The number of processed characters (converted or not). */ -TRIO_PUBLIC TRIO_INLINE int -trio_upper(char *target) +TRIO_STRING_PUBLIC int +trio_upper +TRIO_ARGS1((target), + char *target) { assert(target); return trio_span_function(target, target, toupper); } +#endif /* !defined(TRIO_MINIMAL) */ /** @} End of StaticStrings */ @@ -1040,8 +1182,8 @@ trio_upper(char *target) /* * TrioStringAlloc */ -TRIO_PRIVATE trio_string_t * -TrioStringAlloc(void) +TRIO_STRING_PRIVATE trio_string_t * +TrioStringAlloc(TRIO_NOARGS) { trio_string_t *self; @@ -1062,9 +1204,11 @@ TrioStringAlloc(void) * The size of the string will be increased by 'delta' characters. If * 'delta' is zero, the size will be doubled. */ -TRIO_PRIVATE BOOLEAN_T -TrioStringGrow(trio_string_t *self, - size_t delta) +TRIO_STRING_PRIVATE BOOLEAN_T +TrioStringGrow +TRIO_ARGS2((self, delta), + trio_string_t *self, + size_t delta) { BOOLEAN_T status = FALSE; char *new_content; @@ -1092,9 +1236,11 @@ TrioStringGrow(trio_string_t *self, * If 'length' is less than the original size, the original size will be * used (that is, the size of the string is never decreased). */ -TRIO_PRIVATE BOOLEAN_T -TrioStringGrowTo(trio_string_t *self, - size_t length) +TRIO_STRING_PRIVATE BOOLEAN_T +TrioStringGrowTo +TRIO_ARGS2((self, length), + trio_string_t *self, + size_t length) { length++; /* Room for terminating zero */ return (self->allocated < length) @@ -1103,14 +1249,17 @@ TrioStringGrowTo(trio_string_t *self, } +#if !defined(TRIO_MINIMAL) /** Create a new dynamic string. @param initial_size Initial size of the buffer. @return Newly allocated dynamic string, or NULL if memory allocation failed. */ -TRIO_PUBLIC trio_string_t * -trio_string_create(int initial_size) +TRIO_STRING_PUBLIC trio_string_t * +trio_string_create +TRIO_ARGS1((initial_size), + int initial_size) { trio_string_t *self; @@ -1131,6 +1280,7 @@ trio_string_create(int initial_size) } return self; } +#endif /* !defined(TRIO_MINIMAL) */ /** @@ -1138,8 +1288,10 @@ trio_string_create(int initial_size) @param self Dynamic string */ -TRIO_PUBLIC void -trio_string_destroy(trio_string_t *self) +TRIO_STRING_PUBLIC void +trio_string_destroy +TRIO_ARGS1((self), + trio_string_t *self) { assert(self); @@ -1151,6 +1303,7 @@ trio_string_destroy(trio_string_t *self) } +#if !defined(TRIO_MINIMAL) /** Get a pointer to the content. @@ -1165,8 +1318,11 @@ trio_string_destroy(trio_string_t *self) number of characters from the ending of the string, starting at the terminating zero, is returned. */ -TRIO_PUBLIC char * -trio_string_get(trio_string_t *self, int offset) +TRIO_STRING_PUBLIC char * +trio_string_get +TRIO_ARGS2((self, offset), + trio_string_t *self, + int offset) { char *result = NULL; @@ -1180,7 +1336,7 @@ trio_string_get(trio_string_t *self, int offset) } if (offset >= 0) { - if (offset > self->length) + if (offset > (int)self->length) { offset = self->length; } @@ -1197,6 +1353,7 @@ trio_string_get(trio_string_t *self, int offset) } return result; } +#endif /* !defined(TRIO_MINIMAL) */ /** @@ -1208,8 +1365,10 @@ trio_string_get(trio_string_t *self, int offset) The content is removed from the dynamic string. This enables destruction of the dynamic string without deallocation of the content. */ -TRIO_PUBLIC char * -trio_string_extract(trio_string_t *self) +TRIO_STRING_PUBLIC char * +trio_string_extract +TRIO_ARGS1((self), + trio_string_t *self) { char *result; @@ -1223,6 +1382,7 @@ trio_string_extract(trio_string_t *self) } +#if !defined(TRIO_MINIMAL) /** Set the content of the dynamic string. @@ -1236,22 +1396,27 @@ trio_string_extract(trio_string_t *self) This function will make a copy of @p buffer. You are responsible for deallocating @p buffer yourself. */ -TRIO_PUBLIC void -trio_xstring_set(trio_string_t *self, - char *buffer) +TRIO_STRING_PUBLIC void +trio_xstring_set +TRIO_ARGS2((self, buffer), + trio_string_t *self, + char *buffer) { assert(self); trio_destroy(self->content); self->content = trio_duplicate(buffer); } +#endif /* !defined(TRIO_MINIMAL) */ /* * trio_string_size */ -TRIO_PUBLIC int -trio_string_size(trio_string_t *self) +TRIO_STRING_PUBLIC int +trio_string_size +TRIO_ARGS1((self), + trio_string_t *self) { assert(self); @@ -1262,21 +1427,16 @@ trio_string_size(trio_string_t *self) /* * trio_string_terminate */ -TRIO_PUBLIC void -trio_string_terminate(trio_string_t *self) +TRIO_STRING_PUBLIC void +trio_string_terminate +TRIO_ARGS1((self), + trio_string_t *self) { - char *end; - - assert(self); - - end = trio_string_get(self, -1); - if (end) - { - *end = NIL; - } + trio_xstring_append_char(self, 0); } +#if !defined(TRIO_MINIMAL) /** Append the second string to the first. @@ -1284,9 +1444,11 @@ trio_string_terminate(trio_string_t *self) @param other Dynamic string to copy from. @return Boolean value indicating success or failure. */ -TRIO_PUBLIC int -trio_string_append(trio_string_t *self, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_append +TRIO_ARGS2((self, other), + trio_string_t *self, + trio_string_t *other) { size_t length; @@ -1303,14 +1465,18 @@ trio_string_append(trio_string_t *self, error: return FALSE; } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_append */ -TRIO_PUBLIC int -trio_xstring_append(trio_string_t *self, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_append +TRIO_ARGS2((self, other), + trio_string_t *self, + TRIO_CONST char *other) { size_t length; @@ -1327,18 +1493,21 @@ trio_xstring_append(trio_string_t *self, error: return FALSE; } +#endif /* !defined(TRIO_MINIMAL) */ /* * trio_xstring_append_char */ -TRIO_PUBLIC int -trio_xstring_append_char(trio_string_t *self, - char character) +TRIO_STRING_PUBLIC int +trio_xstring_append_char +TRIO_ARGS2((self, character), + trio_string_t *self, + char character) { assert(self); - if (self->length >= trio_string_size(self)) + if ((int)self->length >= trio_string_size(self)) { if (!TrioStringGrow(self, 0)) goto error; @@ -1352,6 +1521,7 @@ trio_xstring_append_char(trio_string_t *self, } +#if !defined(TRIO_MINIMAL) /** Search for the first occurrence of second parameter in the first. @@ -1359,37 +1529,47 @@ trio_xstring_append_char(trio_string_t *self, @param other Dynamic string to copy from. @return Boolean value indicating success or failure. */ -TRIO_PUBLIC int -trio_string_contains(trio_string_t *self, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_contains +TRIO_ARGS2((self, other), + trio_string_t *self, + trio_string_t *other) { assert(self); assert(other); return trio_contains(self->content, other->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_contains */ -TRIO_PUBLIC int -trio_xstring_contains(trio_string_t *self, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_contains +TRIO_ARGS2((self, other), + trio_string_t *self, + TRIO_CONST char *other) { assert(self); assert(other); return trio_contains(self->content, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_copy */ -TRIO_PUBLIC int -trio_string_copy(trio_string_t *self, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_copy +TRIO_ARGS2((self, other), + trio_string_t *self, + trio_string_t *other) { assert(self); assert(other); @@ -1397,14 +1577,18 @@ trio_string_copy(trio_string_t *self, self->length = 0; return trio_string_append(self, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_copy */ -TRIO_PUBLIC int -trio_xstring_copy(trio_string_t *self, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_copy +TRIO_ARGS2((self, other), + trio_string_t *self, + TRIO_CONST char *other) { assert(self); assert(other); @@ -1412,13 +1596,17 @@ trio_xstring_copy(trio_string_t *self, self->length = 0; return trio_xstring_append(self, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_duplicate */ -TRIO_PUBLIC trio_string_t * -trio_string_duplicate(trio_string_t *other) +TRIO_STRING_PUBLIC trio_string_t * +trio_string_duplicate +TRIO_ARGS1((other), + trio_string_t *other) { trio_string_t *self; @@ -1440,13 +1628,16 @@ trio_string_duplicate(trio_string_t *other) } return self; } +#endif /* !defined(TRIO_MINIMAL) */ /* * trio_xstring_duplicate */ -TRIO_PUBLIC trio_string_t * -trio_xstring_duplicate(const char *other) +TRIO_STRING_PUBLIC trio_string_t * +trio_xstring_duplicate +TRIO_ARGS1((other), + TRIO_CONST char *other) { trio_string_t *self; @@ -1470,168 +1661,215 @@ trio_xstring_duplicate(const char *other) } +#if !defined(TRIO_MINIMAL) /* * trio_string_equal */ -TRIO_PUBLIC int -trio_string_equal(trio_string_t *self, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_equal +TRIO_ARGS2((self, other), + trio_string_t *self, + trio_string_t *other) { assert(self); assert(other); return trio_equal(self->content, other->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_equal */ -TRIO_PUBLIC int -trio_xstring_equal(trio_string_t *self, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_equal +TRIO_ARGS2((self, other), + trio_string_t *self, + TRIO_CONST char *other) { assert(self); assert(other); return trio_equal(self->content, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_equal_max */ -TRIO_PUBLIC int -trio_string_equal_max(trio_string_t *self, - size_t max, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_equal_max +TRIO_ARGS3((self, max, other), + trio_string_t *self, + size_t max, + trio_string_t *other) { assert(self); assert(other); return trio_equal_max(self->content, max, other->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_equal_max */ -TRIO_PUBLIC int -trio_xstring_equal_max(trio_string_t *self, - size_t max, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_equal_max +TRIO_ARGS3((self, max, other), + trio_string_t *self, + size_t max, + TRIO_CONST char *other) { assert(self); assert(other); return trio_equal_max(self->content, max, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_equal_case */ -TRIO_PUBLIC int -trio_string_equal_case(trio_string_t *self, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_equal_case +TRIO_ARGS2((self, other), + trio_string_t *self, + trio_string_t *other) { assert(self); assert(other); return trio_equal_case(self->content, other->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_equal_case */ -TRIO_PUBLIC int -trio_xstring_equal_case(trio_string_t *self, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_equal_case +TRIO_ARGS2((self, other), + trio_string_t *self, + TRIO_CONST char *other) { assert(self); assert(other); return trio_equal_case(self->content, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_equal_case_max */ -TRIO_PUBLIC int -trio_string_equal_case_max(trio_string_t *self, - size_t max, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_equal_case_max +TRIO_ARGS3((self, max, other), + trio_string_t *self, + size_t max, + trio_string_t *other) { assert(self); assert(other); return trio_equal_case_max(self->content, max, other->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_equal_case_max */ -TRIO_PUBLIC int -trio_xstring_equal_case_max(trio_string_t *self, - size_t max, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_equal_case_max +TRIO_ARGS3((self, max, other), + trio_string_t *self, + size_t max, + TRIO_CONST char *other) { assert(self); assert(other); return trio_equal_case_max(self->content, max, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_format_data_max */ -TRIO_PUBLIC size_t -trio_string_format_date_max(trio_string_t *self, - size_t max, - const char *format, - const struct tm *datetime) +TRIO_STRING_PUBLIC size_t +trio_string_format_date_max +TRIO_ARGS4((self, max, format, datetime), + trio_string_t *self, + size_t max, + TRIO_CONST char *format, + TRIO_CONST struct tm *datetime) { assert(self); return trio_format_date_max(self->content, max, format, datetime); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_index */ -TRIO_PUBLIC char * -trio_string_index(trio_string_t *self, - int character) +TRIO_STRING_PUBLIC char * +trio_string_index +TRIO_ARGS2((self, character), + trio_string_t *self, + int character) { assert(self); return trio_index(self->content, character); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_index_last */ -TRIO_PUBLIC char * -trio_string_index_last(trio_string_t *self, - int character) +TRIO_STRING_PUBLIC char * +trio_string_index_last +TRIO_ARGS2((self, character), + trio_string_t *self, + int character) { assert(self); return trio_index_last(self->content, character); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_length */ -TRIO_PUBLIC int -trio_string_length(trio_string_t *self) +TRIO_STRING_PUBLIC int +trio_string_length +TRIO_ARGS1((self), + trio_string_t *self) { assert(self); @@ -1641,113 +1879,146 @@ trio_string_length(trio_string_t *self) } return self->length; } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_lower */ -TRIO_PUBLIC int -trio_string_lower(trio_string_t *self) +TRIO_STRING_PUBLIC int +trio_string_lower +TRIO_ARGS1((self), + trio_string_t *self) { assert(self); return trio_lower(self->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_match */ -TRIO_PUBLIC int -trio_string_match(trio_string_t *self, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_match +TRIO_ARGS2((self, other), + trio_string_t *self, + trio_string_t *other) { assert(self); assert(other); return trio_match(self->content, other->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_match */ -TRIO_PUBLIC int -trio_xstring_match(trio_string_t *self, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_match +TRIO_ARGS2((self, other), + trio_string_t *self, + TRIO_CONST char *other) { assert(self); assert(other); return trio_match(self->content, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_match_case */ -TRIO_PUBLIC int -trio_string_match_case(trio_string_t *self, - trio_string_t *other) +TRIO_STRING_PUBLIC int +trio_string_match_case +TRIO_ARGS2((self, other), + trio_string_t *self, + trio_string_t *other) { assert(self); assert(other); return trio_match_case(self->content, other->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_match_case */ -TRIO_PUBLIC int -trio_xstring_match_case(trio_string_t *self, - const char *other) +TRIO_STRING_PUBLIC int +trio_xstring_match_case +TRIO_ARGS2((self, other), + trio_string_t *self, + TRIO_CONST char *other) { assert(self); assert(other); return trio_match_case(self->content, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_substring */ -TRIO_PUBLIC char * -trio_string_substring(trio_string_t *self, - trio_string_t *other) +TRIO_STRING_PUBLIC char * +trio_string_substring +TRIO_ARGS2((self, other), + trio_string_t *self, + trio_string_t *other) { assert(self); assert(other); return trio_substring(self->content, other->content); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_xstring_substring */ -TRIO_PUBLIC char * -trio_xstring_substring(trio_string_t *self, - const char *other) +TRIO_STRING_PUBLIC char * +trio_xstring_substring +TRIO_ARGS2((self, other), + trio_string_t *self, + TRIO_CONST char *other) { assert(self); assert(other); return trio_substring(self->content, other); } +#endif /* !defined(TRIO_MINIMAL) */ +#if !defined(TRIO_MINIMAL) /* * trio_string_upper */ -TRIO_PUBLIC int -trio_string_upper(trio_string_t *self) +TRIO_STRING_PUBLIC int +trio_string_upper +TRIO_ARGS1((self), + trio_string_t *self) { assert(self); return trio_upper(self->content); } +#endif /* !defined(TRIO_MINIMAL) */ /** @} End of DynamicStrings */ diff --git a/triostr.h b/triostr.h index 94b01eef..083e2a52 100644 --- a/triostr.h +++ b/triostr.h @@ -31,42 +31,50 @@ enum { TRIO_HASH_TWOSIGNED }; +#if !defined(TRIO_STRING_PUBLIC) +# if !defined(TRIO_PUBLIC) +# define TRIO_PUBLIC +# endif +# define TRIO_STRING_PUBLIC TRIO_PUBLIC +#endif + /************************************************************************* * String functions */ -int trio_append(char *target, const char *source); -int trio_append_max(char *target, size_t max, const char *source); -int trio_contains(const char *string, const char *substring); -int trio_copy(char *target, const char *source); -int trio_copy_max(char *target, size_t max, const char *source); -char *trio_create(size_t size); -void trio_destroy(char *string); -char *trio_duplicate(const char *source); -char *trio_duplicate_max(const char *source, size_t max); -int trio_equal(const char *first, const char *second); -int trio_equal_case(const char *first, const char *second); -int trio_equal_case_max(const char *first, size_t max, const char *second); -int trio_equal_locale(const char *first, const char *second); -int trio_equal_max(const char *first, size_t max, const char *second); -const char *trio_error(int); -size_t trio_format_date_max(char *target, size_t max, const char *format, const struct tm *datetime); -unsigned long trio_hash(const char *string, int type); -char *trio_index(const char *string, char character); -char *trio_index_last(const char *string, char character); -size_t trio_length(const char *string); -int trio_lower(char *target); -int trio_match(const char *string, const char *pattern); -int trio_match_case(const char *string, const char *pattern); -size_t trio_span_function(char *target, const char *source, int (*Function)(int)); -char *trio_substring(const char *string, const char *substring); -char *trio_substring_max(const char *string, size_t max, const char *substring); -char *trio_tokenize(char *string, const char *delimiters); -float trio_to_float(const char *source, const char **endp); -double trio_to_double(const char *source, const char **endp); -long trio_to_long(const char *source, char **endp, int base); -unsigned long trio_to_unsigned_long(const char *source, char **endp, int base); -int trio_upper(char *target); +TRIO_STRING_PUBLIC int trio_append TRIO_PROTO((char *target, const char *source)); +TRIO_STRING_PUBLIC int trio_append_max TRIO_PROTO((char *target, size_t max, const char *source)); +TRIO_STRING_PUBLIC int trio_contains TRIO_PROTO((const char *string, const char *substring)); +TRIO_STRING_PUBLIC int trio_copy TRIO_PROTO((char *target, const char *source)); +TRIO_STRING_PUBLIC int trio_copy_max TRIO_PROTO((char *target, size_t max, const char *source)); +TRIO_STRING_PUBLIC char *trio_create TRIO_PROTO((size_t size)); +TRIO_STRING_PUBLIC void trio_destroy TRIO_PROTO((char *string)); +TRIO_STRING_PUBLIC char *trio_duplicate TRIO_PROTO((const char *source)); +TRIO_STRING_PUBLIC char *trio_duplicate_max TRIO_PROTO((const char *source, size_t max)); +TRIO_STRING_PUBLIC int trio_equal TRIO_PROTO((const char *first, const char *second)); +TRIO_STRING_PUBLIC int trio_equal_case TRIO_PROTO((const char *first, const char *second)); +TRIO_STRING_PUBLIC int trio_equal_case_max TRIO_PROTO((const char *first, size_t max, const char *second)); +TRIO_STRING_PUBLIC int trio_equal_locale TRIO_PROTO((const char *first, const char *second)); +TRIO_STRING_PUBLIC int trio_equal_max TRIO_PROTO((const char *first, size_t max, const char *second)); +TRIO_STRING_PUBLIC TRIO_CONST char *trio_error TRIO_PROTO((int)); +TRIO_STRING_PUBLIC size_t trio_format_date_max TRIO_PROTO((char *target, size_t max, const char *format, const struct tm *datetime)); +TRIO_STRING_PUBLIC unsigned long trio_hash TRIO_PROTO((const char *string, int type)); +TRIO_STRING_PUBLIC char *trio_index TRIO_PROTO((const char *string, int character)); +TRIO_STRING_PUBLIC char *trio_index_last TRIO_PROTO((const char *string, int character)); +TRIO_STRING_PUBLIC size_t trio_length TRIO_PROTO((const char *string)); +TRIO_STRING_PUBLIC int trio_lower TRIO_PROTO((char *target)); +TRIO_STRING_PUBLIC int trio_match TRIO_PROTO((const char *string, const char *pattern)); +TRIO_STRING_PUBLIC int trio_match_case TRIO_PROTO((const char *string, const char *pattern)); +TRIO_STRING_PUBLIC size_t trio_span_function TRIO_PROTO((char *target, const char *source, int (*Function) TRIO_PROTO((int)))); +TRIO_STRING_PUBLIC char *trio_substring TRIO_PROTO((const char *string, const char *substring)); +TRIO_STRING_PUBLIC char *trio_substring_max TRIO_PROTO((const char *string, size_t max, const char *substring)); +TRIO_STRING_PUBLIC double trio_to_double TRIO_PROTO((const char *source, char **endp)); +TRIO_STRING_PUBLIC float trio_to_float TRIO_PROTO((const char *source, char **endp)); +TRIO_STRING_PUBLIC trio_long_double_t trio_to_long_double TRIO_PROTO((const char *source, char **endp)); +TRIO_STRING_PUBLIC long trio_to_long TRIO_PROTO((const char *source, char **endp, int base)); +TRIO_STRING_PUBLIC unsigned long trio_to_unsigned_long TRIO_PROTO((const char *source, char **endp, int base)); +TRIO_STRING_PUBLIC char *trio_tokenize TRIO_PROTO((char *string, const char *delimiters)); +TRIO_STRING_PUBLIC int trio_upper TRIO_PROTO((char *target)); /************************************************************************* * Dynamic string functions @@ -77,43 +85,43 @@ int trio_upper(char *target); */ typedef struct _trio_string_t trio_string_t; -trio_string_t *trio_string_create(int initial_size); -void trio_string_destroy(trio_string_t *self); -char *trio_string_get(trio_string_t *self, int offset); -void trio_xstring_set(trio_string_t *self, char *buffer); -char *trio_string_extract(trio_string_t *self); -int trio_string_size(trio_string_t *self); -void trio_string_terminate(trio_string_t *self); +TRIO_STRING_PUBLIC trio_string_t *trio_string_create TRIO_PROTO((int initial_size)); +TRIO_STRING_PUBLIC void trio_string_destroy TRIO_PROTO((trio_string_t *self)); +TRIO_STRING_PUBLIC char *trio_string_get TRIO_PROTO((trio_string_t *self, int offset)); +TRIO_STRING_PUBLIC void trio_xstring_set TRIO_PROTO((trio_string_t *self, char *buffer)); +TRIO_STRING_PUBLIC char *trio_string_extract TRIO_PROTO((trio_string_t *self)); +TRIO_STRING_PUBLIC int trio_string_size TRIO_PROTO((trio_string_t *self)); +TRIO_STRING_PUBLIC void trio_string_terminate TRIO_PROTO((trio_string_t *self)); -int trio_string_append(trio_string_t *self, trio_string_t *other); -int trio_string_contains(trio_string_t *self, trio_string_t *other); -int trio_string_copy(trio_string_t *self, trio_string_t *other); -trio_string_t *trio_string_duplicate(trio_string_t *other); -int trio_string_equal(trio_string_t *self, trio_string_t *other); -int trio_string_equal_max(trio_string_t *self, size_t max, trio_string_t *second); -int trio_string_equal_case(trio_string_t *self, trio_string_t *other); -int trio_string_equal_case_max(trio_string_t *self, size_t max, trio_string_t *other); -size_t trio_string_format_date_max(trio_string_t *self, size_t max, const char *format, const struct tm *datetime); -char *trio_string_index(trio_string_t *self, int character); -char *trio_string_index_last(trio_string_t *self, int character); -int trio_string_length(trio_string_t *self); -int trio_string_lower(trio_string_t *self); -int trio_string_match(trio_string_t *self, trio_string_t *other); -int trio_string_match_case(trio_string_t *self, trio_string_t *other); -char *trio_string_substring(trio_string_t *self, trio_string_t *other); -int trio_string_upper(trio_string_t *self); +TRIO_STRING_PUBLIC int trio_string_append TRIO_PROTO((trio_string_t *self, trio_string_t *other)); +TRIO_STRING_PUBLIC int trio_string_contains TRIO_PROTO((trio_string_t *self, trio_string_t *other)); +TRIO_STRING_PUBLIC int trio_string_copy TRIO_PROTO((trio_string_t *self, trio_string_t *other)); +TRIO_STRING_PUBLIC trio_string_t *trio_string_duplicate TRIO_PROTO((trio_string_t *other)); +TRIO_STRING_PUBLIC int trio_string_equal TRIO_PROTO((trio_string_t *self, trio_string_t *other)); +TRIO_STRING_PUBLIC int trio_string_equal_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second)); +TRIO_STRING_PUBLIC int trio_string_equal_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); +TRIO_STRING_PUBLIC int trio_string_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other)); +TRIO_STRING_PUBLIC size_t trio_string_format_date_max TRIO_PROTO((trio_string_t *self, size_t max, const char *format, const struct tm *datetime)); +TRIO_STRING_PUBLIC char *trio_string_index TRIO_PROTO((trio_string_t *self, int character)); +TRIO_STRING_PUBLIC char *trio_string_index_last TRIO_PROTO((trio_string_t *self, int character)); +TRIO_STRING_PUBLIC int trio_string_length TRIO_PROTO((trio_string_t *self)); +TRIO_STRING_PUBLIC int trio_string_lower TRIO_PROTO((trio_string_t *self)); +TRIO_STRING_PUBLIC int trio_string_match TRIO_PROTO((trio_string_t *self, trio_string_t *other)); +TRIO_STRING_PUBLIC int trio_string_match_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); +TRIO_STRING_PUBLIC char *trio_string_substring TRIO_PROTO((trio_string_t *self, trio_string_t *other)); +TRIO_STRING_PUBLIC int trio_string_upper TRIO_PROTO((trio_string_t *self)); -int trio_xstring_append_char(trio_string_t *self, char character); -int trio_xstring_append(trio_string_t *self, const char *other); -int trio_xstring_contains(trio_string_t *self, const char *other); -int trio_xstring_copy(trio_string_t *self, const char *other); -trio_string_t *trio_xstring_duplicate(const char *other); -int trio_xstring_equal(trio_string_t *self, const char *other); -int trio_xstring_equal_max(trio_string_t *self, size_t max, const char *other); -int trio_xstring_equal_case(trio_string_t *self, const char *other); -int trio_xstring_equal_case_max(trio_string_t *self, size_t max, const char *other); -int trio_xstring_match(trio_string_t *self, const char *other); -int trio_xstring_match_case(trio_string_t *self, const char *other); -char *trio_xstring_substring(trio_string_t *self, const char *other); +TRIO_STRING_PUBLIC int trio_xstring_append_char TRIO_PROTO((trio_string_t *self, char character)); +TRIO_STRING_PUBLIC int trio_xstring_append TRIO_PROTO((trio_string_t *self, const char *other)); +TRIO_STRING_PUBLIC int trio_xstring_contains TRIO_PROTO((trio_string_t *self, const char *other)); +TRIO_STRING_PUBLIC int trio_xstring_copy TRIO_PROTO((trio_string_t *self, const char *other)); +TRIO_STRING_PUBLIC trio_string_t *trio_xstring_duplicate TRIO_PROTO((const char *other)); +TRIO_STRING_PUBLIC int trio_xstring_equal TRIO_PROTO((trio_string_t *self, const char *other)); +TRIO_STRING_PUBLIC int trio_xstring_equal_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other)); +TRIO_STRING_PUBLIC int trio_xstring_equal_case TRIO_PROTO((trio_string_t *self, const char *other)); +TRIO_STRING_PUBLIC int trio_xstring_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other)); +TRIO_STRING_PUBLIC int trio_xstring_match TRIO_PROTO((trio_string_t *self, const char *other)); +TRIO_STRING_PUBLIC int trio_xstring_match_case TRIO_PROTO((trio_string_t *self, const char *other)); +TRIO_STRING_PUBLIC char *trio_xstring_substring TRIO_PROTO((trio_string_t *self, const char *other)); #endif /* TRIO_TRIOSTR_H */