Annotation of embedaddon/libxml2/trio.c, revision 1.1

1.1     ! misho       1: /*************************************************************************
        !             2:  *
        !             3:  * $Id$
        !             4:  *
        !             5:  * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            12:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            13:  * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
        !            14:  * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
        !            15:  *
        !            16:  *************************************************************************
        !            17:  *
        !            18:  * A note to trio contributors:
        !            19:  *
        !            20:  * Avoid heap allocation at all costs to ensure that the trio functions
        !            21:  * are async-safe. The exceptions are the printf/fprintf functions, which
        !            22:  * uses fputc, and the asprintf functions and the <alloc> modifier, which
        !            23:  * by design are required to allocate form the heap.
        !            24:  *
        !            25:  ************************************************************************/
        !            26: 
        !            27: /*
        !            28:  * TODO:
        !            29:  *  - Scan is probably too permissive about its modifiers.
        !            30:  *  - C escapes in %#[] ?
        !            31:  *  - Multibyte characters (done for format parsing, except scan groups)
        !            32:  *  - Complex numbers? (C99 _Complex)
        !            33:  *  - Boolean values? (C99 _Bool)
        !            34:  *  - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used
        !            35:  *    to print the mantissa, e.g. NaN(0xc000000000000000)
        !            36:  *  - Should we support the GNU %a alloc modifier? GNU has an ugly hack
        !            37:  *    for %a, because C99 used %a for other purposes. If specified as
        !            38:  *    %as or %a[ it is interpreted as the alloc modifier, otherwise as
        !            39:  *    the C99 hex-float. This means that you cannot scan %as as a hex-float
        !            40:  *    immediately followed by an 's'.
        !            41:  *  - Scanning of collating symbols.
        !            42:  */
        !            43: 
        !            44: /*************************************************************************
        !            45:  * Trio include files
        !            46:  */
        !            47: #include "triodef.h"
        !            48: #include "trio.h"
        !            49: #include "triop.h"
        !            50: #include "trionan.h"
        !            51: #if !defined(TRIO_MINIMAL)
        !            52: # include "triostr.h"
        !            53: #endif
        !            54: 
        !            55: /**************************************************************************
        !            56:  *
        !            57:  * Definitions
        !            58:  *
        !            59:  *************************************************************************/
        !            60: 
        !            61: #include <math.h>
        !            62: #include <limits.h>
        !            63: #include <float.h>
        !            64: 
        !            65: #if (defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) \
        !            66:      || defined(USE_MULTIBYTE) || TRIO_WIDECHAR) \
        !            67:     && !defined(_WIN32_WCE)
        !            68: # define TRIO_COMPILER_SUPPORTS_MULTIBYTE
        !            69: # if !defined(MB_LEN_MAX)
        !            70: #  define MB_LEN_MAX 6
        !            71: # endif
        !            72: #endif
        !            73: 
        !            74: #if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
        !            75: # define TRIO_COMPILER_SUPPORTS_MSVC_INT
        !            76: #endif
        !            77: 
        !            78: #if defined(_WIN32_WCE)
        !            79: #include <wincecompat.h>
        !            80: #endif
        !            81: 
        !            82: /*************************************************************************
        !            83:  * Generic definitions
        !            84:  */
        !            85: 
        !            86: #if !(defined(DEBUG) || defined(NDEBUG))
        !            87: # define NDEBUG
        !            88: #endif
        !            89: 
        !            90: #include <assert.h>
        !            91: #include <ctype.h>
        !            92: #if !defined(TRIO_COMPILER_SUPPORTS_C99)
        !            93: # define isblank(x) (((x)==32) || ((x)==9))
        !            94: #endif
        !            95: #if defined(TRIO_COMPILER_ANCIENT)
        !            96: # include <varargs.h>
        !            97: #else
        !            98: # include <stdarg.h>
        !            99: #endif
        !           100: #include <stddef.h>
        !           101: 
        !           102: #ifdef HAVE_ERRNO_H
        !           103: #include <errno.h>
        !           104: #endif
        !           105: 
        !           106: #ifndef NULL
        !           107: # define NULL 0
        !           108: #endif
        !           109: #define NIL ((char)0)
        !           110: #ifndef FALSE
        !           111: # define FALSE (1 == 0)
        !           112: # define TRUE (! FALSE)
        !           113: #endif
        !           114: #define BOOLEAN_T int
        !           115: 
        !           116: /* mincore() can be used for debugging purposes */
        !           117: #define VALID(x) (NULL != (x))
        !           118: 
        !           119: #if TRIO_ERRORS
        !           120:   /*
        !           121:    * Encode the error code and the position. This is decoded
        !           122:    * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
        !           123:    */
        !           124: # define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
        !           125: #else
        !           126: # define TRIO_ERROR_RETURN(x,y) (-1)
        !           127: #endif
        !           128: 
        !           129: typedef unsigned long trio_flags_t;
        !           130: 
        !           131: 
        !           132: /*************************************************************************
        !           133:  * Platform specific definitions
        !           134:  */
        !           135: #if defined(TRIO_PLATFORM_UNIX)
        !           136: # include <unistd.h>
        !           137: # include <signal.h>
        !           138: # include <locale.h>
        !           139: # define USE_LOCALE
        !           140: #endif /* TRIO_PLATFORM_UNIX */
        !           141: #if defined(TRIO_PLATFORM_VMS)
        !           142: # include <unistd.h>
        !           143: #endif
        !           144: #if defined(TRIO_PLATFORM_WIN32)
        !           145: # if defined(_WIN32_WCE)
        !           146: #  include <wincecompat.h>
        !           147: # else
        !           148: #  include <io.h>
        !           149: #  define read _read
        !           150: #  define write _write
        !           151: # endif
        !           152: #endif /* TRIO_PLATFORM_WIN32 */
        !           153: 
        !           154: #if TRIO_WIDECHAR
        !           155: # if defined(TRIO_COMPILER_SUPPORTS_ISO94)
        !           156: #  include <wchar.h>
        !           157: #  include <wctype.h>
        !           158: typedef wchar_t trio_wchar_t;
        !           159: typedef wint_t trio_wint_t;
        !           160: # else
        !           161: typedef char trio_wchar_t;
        !           162: typedef int trio_wint_t;
        !           163: #  define WCONST(x) L ## x
        !           164: #  define WEOF EOF
        !           165: #  define iswalnum(x) isalnum(x)
        !           166: #  define iswalpha(x) isalpha(x)
        !           167: #  define iswblank(x) isblank(x)
        !           168: #  define iswcntrl(x) iscntrl(x)
        !           169: #  define iswdigit(x) isdigit(x)
        !           170: #  define iswgraph(x) isgraph(x)
        !           171: #  define iswlower(x) islower(x)
        !           172: #  define iswprint(x) isprint(x)
        !           173: #  define iswpunct(x) ispunct(x)
        !           174: #  define iswspace(x) isspace(x)
        !           175: #  define iswupper(x) isupper(x)
        !           176: #  define iswxdigit(x) isxdigit(x)
        !           177: # endif
        !           178: #endif
        !           179: 
        !           180: 
        !           181: /*************************************************************************
        !           182:  * Compiler dependent definitions
        !           183:  */
        !           184: 
        !           185: /* Support for long long */
        !           186: #ifndef __cplusplus
        !           187: # if !defined(USE_LONGLONG)
        !           188: #  if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
        !           189: #   define USE_LONGLONG
        !           190: #  elif defined(TRIO_COMPILER_SUNPRO)
        !           191: #   define USE_LONGLONG
        !           192: #  elif defined(_LONG_LONG) || defined(_LONGLONG)
        !           193: #   define USE_LONGLONG
        !           194: #  endif
        !           195: # endif
        !           196: #endif
        !           197: 
        !           198: /* The extra long numbers */
        !           199: #if defined(USE_LONGLONG)
        !           200: typedef signed long long int trio_longlong_t;
        !           201: typedef unsigned long long int trio_ulonglong_t;
        !           202: #elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
        !           203: typedef signed __int64 trio_longlong_t;
        !           204: typedef unsigned __int64 trio_ulonglong_t;
        !           205: #else
        !           206: typedef TRIO_SIGNED long int trio_longlong_t;
        !           207: typedef unsigned long int trio_ulonglong_t;
        !           208: #endif
        !           209: 
        !           210: /* Maximal and fixed integer types */
        !           211: #if defined(TRIO_COMPILER_SUPPORTS_C99)
        !           212: # include <stdint.h>
        !           213: typedef intmax_t trio_intmax_t;
        !           214: typedef uintmax_t trio_uintmax_t;
        !           215: typedef int8_t trio_int8_t;
        !           216: typedef int16_t trio_int16_t;
        !           217: typedef int32_t trio_int32_t;
        !           218: typedef int64_t trio_int64_t;
        !           219: #elif defined(TRIO_COMPILER_SUPPORTS_UNIX98)
        !           220: # include <inttypes.h>
        !           221: typedef intmax_t trio_intmax_t;
        !           222: typedef uintmax_t trio_uintmax_t;
        !           223: typedef int8_t trio_int8_t;
        !           224: typedef int16_t trio_int16_t;
        !           225: typedef int32_t trio_int32_t;
        !           226: typedef int64_t trio_int64_t;
        !           227: #elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
        !           228: typedef trio_longlong_t trio_intmax_t;
        !           229: typedef trio_ulonglong_t trio_uintmax_t;
        !           230: typedef __int8 trio_int8_t;
        !           231: typedef __int16 trio_int16_t;
        !           232: typedef __int32 trio_int32_t;
        !           233: typedef __int64 trio_int64_t;
        !           234: #else
        !           235: typedef trio_longlong_t trio_intmax_t;
        !           236: typedef trio_ulonglong_t trio_uintmax_t;
        !           237: # if defined(TRIO_INT8_T)
        !           238: typedef TRIO_INT8_T trio_int8_t;
        !           239: # else
        !           240: typedef TRIO_SIGNED char trio_int8_t;
        !           241: # endif
        !           242: # if defined(TRIO_INT16_T)
        !           243: typedef TRIO_INT16_T trio_int16_t;
        !           244: # else
        !           245: typedef TRIO_SIGNED short trio_int16_t;
        !           246: # endif
        !           247: # if defined(TRIO_INT32_T)
        !           248: typedef TRIO_INT32_T trio_int32_t;
        !           249: # else
        !           250: typedef TRIO_SIGNED int trio_int32_t;
        !           251: # endif
        !           252: # if defined(TRIO_INT64_T)
        !           253: typedef TRIO_INT64_T trio_int64_t;
        !           254: # else
        !           255: typedef trio_longlong_t trio_int64_t;
        !           256: # endif
        !           257: #endif
        !           258: 
        !           259: #if (!(defined(TRIO_COMPILER_SUPPORTS_C99) \
        !           260:  || defined(TRIO_COMPILER_SUPPORTS_UNIX01))) \
        !           261:  && !defined(_WIN32_WCE)
        !           262: # define floorl(x) floor((double)(x))
        !           263: # define fmodl(x,y) fmod((double)(x),(double)(y))
        !           264: # define powl(x,y) pow((double)(x),(double)(y))
        !           265: #endif
        !           266: 
        !           267: #define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
        !           268: 
        !           269: /*************************************************************************
        !           270:  * Internal Definitions
        !           271:  */
        !           272: 
        !           273: #ifndef DECIMAL_DIG
        !           274: # define DECIMAL_DIG DBL_DIG
        !           275: #endif
        !           276: 
        !           277: /* Long double sizes */
        !           278: #ifdef LDBL_DIG
        !           279: # define MAX_MANTISSA_DIGITS LDBL_DIG
        !           280: # define MAX_EXPONENT_DIGITS 4
        !           281: # define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
        !           282: #else
        !           283: # define MAX_MANTISSA_DIGITS DECIMAL_DIG
        !           284: # define MAX_EXPONENT_DIGITS 3
        !           285: # define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
        !           286: #endif
        !           287: 
        !           288: #if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
        !           289: # undef LDBL_DIG
        !           290: # undef LDBL_MANT_DIG
        !           291: # undef LDBL_EPSILON
        !           292: # define LDBL_DIG DBL_DIG
        !           293: # define LDBL_MANT_DIG DBL_MANT_DIG
        !           294: # define LDBL_EPSILON DBL_EPSILON
        !           295: #endif
        !           296: 
        !           297: /* The maximal number of digits is for base 2 */
        !           298: #define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
        !           299: /* The width of a pointer. The number of bits in a hex digit is 4 */
        !           300: #define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
        !           301: 
        !           302: /* Infinite and Not-A-Number for floating-point */
        !           303: #define INFINITE_LOWER "inf"
        !           304: #define INFINITE_UPPER "INF"
        !           305: #define LONG_INFINITE_LOWER "infinite"
        !           306: #define LONG_INFINITE_UPPER "INFINITE"
        !           307: #define NAN_LOWER "nan"
        !           308: #define NAN_UPPER "NAN"
        !           309: 
        !           310: /* Various constants */
        !           311: enum {
        !           312:   TYPE_PRINT = 1,
        !           313:   TYPE_SCAN  = 2,
        !           314: 
        !           315:   /* Flags. FLAGS_LAST must be less than ULONG_MAX */
        !           316:   FLAGS_NEW                 = 0,
        !           317:   FLAGS_STICKY              = 1,
        !           318:   FLAGS_SPACE               = 2 * FLAGS_STICKY,
        !           319:   FLAGS_SHOWSIGN            = 2 * FLAGS_SPACE,
        !           320:   FLAGS_LEFTADJUST          = 2 * FLAGS_SHOWSIGN,
        !           321:   FLAGS_ALTERNATIVE         = 2 * FLAGS_LEFTADJUST,
        !           322:   FLAGS_SHORT               = 2 * FLAGS_ALTERNATIVE,
        !           323:   FLAGS_SHORTSHORT          = 2 * FLAGS_SHORT,
        !           324:   FLAGS_LONG                = 2 * FLAGS_SHORTSHORT,
        !           325:   FLAGS_QUAD                = 2 * FLAGS_LONG,
        !           326:   FLAGS_LONGDOUBLE          = 2 * FLAGS_QUAD,
        !           327:   FLAGS_SIZE_T              = 2 * FLAGS_LONGDOUBLE,
        !           328:   FLAGS_PTRDIFF_T           = 2 * FLAGS_SIZE_T,
        !           329:   FLAGS_INTMAX_T            = 2 * FLAGS_PTRDIFF_T,
        !           330:   FLAGS_NILPADDING          = 2 * FLAGS_INTMAX_T,
        !           331:   FLAGS_UNSIGNED            = 2 * FLAGS_NILPADDING,
        !           332:   FLAGS_UPPER               = 2 * FLAGS_UNSIGNED,
        !           333:   FLAGS_WIDTH               = 2 * FLAGS_UPPER,
        !           334:   FLAGS_WIDTH_PARAMETER     = 2 * FLAGS_WIDTH,
        !           335:   FLAGS_PRECISION           = 2 * FLAGS_WIDTH_PARAMETER,
        !           336:   FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION,
        !           337:   FLAGS_BASE                = 2 * FLAGS_PRECISION_PARAMETER,
        !           338:   FLAGS_BASE_PARAMETER      = 2 * FLAGS_BASE,
        !           339:   FLAGS_FLOAT_E             = 2 * FLAGS_BASE_PARAMETER,
        !           340:   FLAGS_FLOAT_G             = 2 * FLAGS_FLOAT_E,
        !           341:   FLAGS_QUOTE               = 2 * FLAGS_FLOAT_G,
        !           342:   FLAGS_WIDECHAR            = 2 * FLAGS_QUOTE,
        !           343:   FLAGS_ALLOC               = 2 * FLAGS_WIDECHAR,
        !           344:   FLAGS_IGNORE              = 2 * FLAGS_ALLOC,
        !           345:   FLAGS_IGNORE_PARAMETER    = 2 * FLAGS_IGNORE,
        !           346:   FLAGS_VARSIZE_PARAMETER   = 2 * FLAGS_IGNORE_PARAMETER,
        !           347:   FLAGS_FIXED_SIZE          = 2 * FLAGS_VARSIZE_PARAMETER,
        !           348:   FLAGS_LAST                = FLAGS_FIXED_SIZE,
        !           349:   /* Reused flags */
        !           350:   FLAGS_EXCLUDE             = FLAGS_SHORT,
        !           351:   FLAGS_USER_DEFINED        = FLAGS_IGNORE,
        !           352:   FLAGS_ROUNDING            = FLAGS_INTMAX_T,
        !           353:   /* Compounded flags */
        !           354:   FLAGS_ALL_VARSIZES        = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
        !           355:   FLAGS_ALL_SIZES           = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT,
        !           356: 
        !           357:   NO_POSITION  = -1,
        !           358:   NO_WIDTH     =  0,
        !           359:   NO_PRECISION = -1,
        !           360:   NO_SIZE      = -1,
        !           361: 
        !           362:   /* Do not change these */
        !           363:   NO_BASE      = -1,
        !           364:   MIN_BASE     =  2,
        !           365:   MAX_BASE     = 36,
        !           366:   BASE_BINARY  =  2,
        !           367:   BASE_OCTAL   =  8,
        !           368:   BASE_DECIMAL = 10,
        !           369:   BASE_HEX     = 16,
        !           370: 
        !           371:   /* Maximal number of allowed parameters */
        !           372:   MAX_PARAMETERS = 64,
        !           373:   /* Maximal number of characters in class */
        !           374:   MAX_CHARACTER_CLASS = UCHAR_MAX + 1,
        !           375: 
        !           376:   /* Maximal string lengths for user-defined specifiers */
        !           377:   MAX_USER_NAME = 64,
        !           378:   MAX_USER_DATA = 256,
        !           379:   
        !           380:   /* Maximal length of locale separator strings */
        !           381:   MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX,
        !           382:   /* Maximal number of integers in grouping */
        !           383:   MAX_LOCALE_GROUPS = 64,
        !           384: 
        !           385:   /* Initial size of asprintf buffer */
        !           386:   DYNAMIC_START_SIZE = 32
        !           387: };
        !           388: 
        !           389: #define NO_GROUPING ((int)CHAR_MAX)
        !           390: 
        !           391: /* Fundamental formatting parameter types */
        !           392: #define FORMAT_UNKNOWN   0
        !           393: #define FORMAT_INT       1
        !           394: #define FORMAT_DOUBLE    2
        !           395: #define FORMAT_CHAR      3
        !           396: #define FORMAT_STRING    4
        !           397: #define FORMAT_POINTER   5
        !           398: #define FORMAT_COUNT     6
        !           399: #define FORMAT_PARAMETER 7
        !           400: #define FORMAT_GROUP     8
        !           401: #if TRIO_GNU
        !           402: # define FORMAT_ERRNO    9
        !           403: #endif
        !           404: #if TRIO_EXTENSION
        !           405: # define FORMAT_USER_DEFINED 10
        !           406: #endif
        !           407: 
        !           408: /* Character constants */
        !           409: #define CHAR_IDENTIFIER '%'
        !           410: #define CHAR_BACKSLASH '\\'
        !           411: #define CHAR_QUOTE '\"'
        !           412: #define CHAR_ADJUST ' '
        !           413: 
        !           414: /* Character class expressions */
        !           415: #define CLASS_ALNUM "[:alnum:]"
        !           416: #define CLASS_ALPHA "[:alpha:]"
        !           417: #define CLASS_BLANK "[:blank:]"
        !           418: #define CLASS_CNTRL "[:cntrl:]"
        !           419: #define CLASS_DIGIT "[:digit:]"
        !           420: #define CLASS_GRAPH "[:graph:]"
        !           421: #define CLASS_LOWER "[:lower:]"
        !           422: #define CLASS_PRINT "[:print:]"
        !           423: #define CLASS_PUNCT "[:punct:]"
        !           424: #define CLASS_SPACE "[:space:]"
        !           425: #define CLASS_UPPER "[:upper:]"
        !           426: #define CLASS_XDIGIT "[:xdigit:]"
        !           427: 
        !           428: /*
        !           429:  * SPECIFIERS:
        !           430:  *
        !           431:  *
        !           432:  * a  Hex-float
        !           433:  * A  Hex-float
        !           434:  * c  Character
        !           435:  * C  Widechar character (wint_t)
        !           436:  * d  Decimal
        !           437:  * e  Float
        !           438:  * E  Float
        !           439:  * F  Float
        !           440:  * F  Float
        !           441:  * g  Float
        !           442:  * G  Float
        !           443:  * i  Integer
        !           444:  * m  Error message
        !           445:  * n  Count
        !           446:  * o  Octal
        !           447:  * p  Pointer
        !           448:  * s  String
        !           449:  * S  Widechar string (wchar_t *)
        !           450:  * u  Unsigned
        !           451:  * x  Hex
        !           452:  * X  Hex
        !           453:  * [] Group
        !           454:  * <> User-defined
        !           455:  *
        !           456:  * Reserved:
        !           457:  *
        !           458:  * D  Binary Coded Decimal %D(length,precision) (OS/390)
        !           459:  */
        !           460: #define SPECIFIER_CHAR 'c'
        !           461: #define SPECIFIER_STRING 's'
        !           462: #define SPECIFIER_DECIMAL 'd'
        !           463: #define SPECIFIER_INTEGER 'i'
        !           464: #define SPECIFIER_UNSIGNED 'u'
        !           465: #define SPECIFIER_OCTAL 'o'
        !           466: #define SPECIFIER_HEX 'x'
        !           467: #define SPECIFIER_HEX_UPPER 'X'
        !           468: #define SPECIFIER_FLOAT_E 'e'
        !           469: #define SPECIFIER_FLOAT_E_UPPER 'E'
        !           470: #define SPECIFIER_FLOAT_F 'f'
        !           471: #define SPECIFIER_FLOAT_F_UPPER 'F'
        !           472: #define SPECIFIER_FLOAT_G 'g'
        !           473: #define SPECIFIER_FLOAT_G_UPPER 'G'
        !           474: #define SPECIFIER_POINTER 'p'
        !           475: #define SPECIFIER_GROUP '['
        !           476: #define SPECIFIER_UNGROUP ']'
        !           477: #define SPECIFIER_COUNT 'n'
        !           478: #if TRIO_UNIX98
        !           479: # define SPECIFIER_CHAR_UPPER 'C'
        !           480: # define SPECIFIER_STRING_UPPER 'S'
        !           481: #endif
        !           482: #if TRIO_C99
        !           483: # define SPECIFIER_HEXFLOAT 'a'
        !           484: # define SPECIFIER_HEXFLOAT_UPPER 'A'
        !           485: #endif
        !           486: #if TRIO_GNU
        !           487: # define SPECIFIER_ERRNO 'm'
        !           488: #endif
        !           489: #if TRIO_EXTENSION
        !           490: # define SPECIFIER_BINARY 'b'
        !           491: # define SPECIFIER_BINARY_UPPER 'B'
        !           492: # define SPECIFIER_USER_DEFINED_BEGIN '<'
        !           493: # define SPECIFIER_USER_DEFINED_END '>'
        !           494: # define SPECIFIER_USER_DEFINED_SEPARATOR ':'
        !           495: #endif
        !           496: 
        !           497: /*
        !           498:  * QUALIFIERS:
        !           499:  *
        !           500:  *
        !           501:  * Numbers = d,i,o,u,x,X
        !           502:  * Float = a,A,e,E,f,F,g,G
        !           503:  * String = s
        !           504:  * Char = c
        !           505:  *
        !           506:  *
        !           507:  * 9$ Position
        !           508:  *      Use the 9th parameter. 9 can be any number between 1 and
        !           509:  *      the maximal argument
        !           510:  *
        !           511:  * 9 Width
        !           512:  *      Set width to 9. 9 can be any number, but must not be postfixed
        !           513:  *      by '$'
        !           514:  *
        !           515:  * h  Short
        !           516:  *    Numbers:
        !           517:  *      (unsigned) short int
        !           518:  *
        !           519:  * hh Short short
        !           520:  *    Numbers:
        !           521:  *      (unsigned) char
        !           522:  *
        !           523:  * l  Long
        !           524:  *    Numbers:
        !           525:  *      (unsigned) long int
        !           526:  *    String:
        !           527:  *      as the S specifier
        !           528:  *    Char:
        !           529:  *      as the C specifier
        !           530:  *
        !           531:  * ll Long Long
        !           532:  *    Numbers:
        !           533:  *      (unsigned) long long int
        !           534:  *
        !           535:  * L  Long Double
        !           536:  *    Float
        !           537:  *      long double
        !           538:  *
        !           539:  * #  Alternative
        !           540:  *    Float:
        !           541:  *      Decimal-point is always present
        !           542:  *    String:
        !           543:  *      non-printable characters are handled as \number
        !           544:  *
        !           545:  *    Spacing
        !           546:  *
        !           547:  * +  Sign
        !           548:  *
        !           549:  * -  Alignment
        !           550:  *
        !           551:  * .  Precision
        !           552:  *
        !           553:  * *  Parameter
        !           554:  *    print: use parameter
        !           555:  *    scan: no parameter (ignore)
        !           556:  *
        !           557:  * q  Quad
        !           558:  *
        !           559:  * Z  size_t
        !           560:  *
        !           561:  * w  Widechar
        !           562:  *
        !           563:  * '  Thousands/quote
        !           564:  *    Numbers:
        !           565:  *      Integer part grouped in thousands
        !           566:  *    Binary numbers:
        !           567:  *      Number grouped in nibbles (4 bits)
        !           568:  *    String:
        !           569:  *      Quoted string
        !           570:  *
        !           571:  * j  intmax_t
        !           572:  * t  prtdiff_t
        !           573:  * z  size_t
        !           574:  *
        !           575:  * !  Sticky
        !           576:  * @  Parameter (for both print and scan)
        !           577:  *
        !           578:  * I  n-bit Integer
        !           579:  *    Numbers:
        !           580:  *      The following options exists
        !           581:  *        I8  = 8-bit integer
        !           582:  *        I16 = 16-bit integer
        !           583:  *        I32 = 32-bit integer
        !           584:  *        I64 = 64-bit integer
        !           585:  */
        !           586: #define QUALIFIER_POSITION '$'
        !           587: #define QUALIFIER_SHORT 'h'
        !           588: #define QUALIFIER_LONG 'l'
        !           589: #define QUALIFIER_LONG_UPPER 'L'
        !           590: #define QUALIFIER_ALTERNATIVE '#'
        !           591: #define QUALIFIER_SPACE ' '
        !           592: #define QUALIFIER_PLUS '+'
        !           593: #define QUALIFIER_MINUS '-'
        !           594: #define QUALIFIER_DOT '.'
        !           595: #define QUALIFIER_STAR '*'
        !           596: #define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
        !           597: #if TRIO_C99
        !           598: # define QUALIFIER_SIZE_T 'z'
        !           599: # define QUALIFIER_PTRDIFF_T 't'
        !           600: # define QUALIFIER_INTMAX_T 'j'
        !           601: #endif
        !           602: #if TRIO_BSD || TRIO_GNU
        !           603: # define QUALIFIER_QUAD 'q'
        !           604: #endif
        !           605: #if TRIO_GNU
        !           606: # define QUALIFIER_SIZE_T_UPPER 'Z'
        !           607: #endif
        !           608: #if TRIO_MISC
        !           609: # define QUALIFIER_WIDECHAR 'w'
        !           610: #endif
        !           611: #if TRIO_MICROSOFT
        !           612: # define QUALIFIER_FIXED_SIZE 'I'
        !           613: #endif
        !           614: #if TRIO_EXTENSION
        !           615: # define QUALIFIER_QUOTE '\''
        !           616: # define QUALIFIER_STICKY '!'
        !           617: # define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
        !           618: # define QUALIFIER_PARAM '@' /* Experimental */
        !           619: # define QUALIFIER_COLON ':' /* For scanlists */
        !           620: # define QUALIFIER_EQUAL '=' /* For scanlists */
        !           621: # define QUALIFIER_ROUNDING_UPPER 'R'
        !           622: #endif
        !           623: 
        !           624: 
        !           625: /*************************************************************************
        !           626:  *
        !           627:  * Internal Structures
        !           628:  *
        !           629:  *************************************************************************/
        !           630: 
        !           631: /* Parameters */
        !           632: typedef struct {
        !           633:   /* An indication of which entry in the data union is used */
        !           634:   int type;
        !           635:   /* The flags */
        !           636:   trio_flags_t flags;
        !           637:   /* The width qualifier */
        !           638:   int width;
        !           639:   /* The precision qualifier */
        !           640:   int precision;
        !           641:   /* The base qualifier */
        !           642:   int base;
        !           643:   /* The size for the variable size qualifier */
        !           644:   int varsize;
        !           645:   /* The marker of the end of the specifier */
        !           646:   int indexAfterSpecifier;
        !           647:   /* The data from the argument list */
        !           648:   union {
        !           649:     char *string;
        !           650: #if TRIO_WIDECHAR
        !           651:     trio_wchar_t *wstring;
        !           652: #endif
        !           653:     trio_pointer_t pointer;
        !           654:     union {
        !           655:       trio_intmax_t as_signed;
        !           656:       trio_uintmax_t as_unsigned;
        !           657:     } number;
        !           658:     double doubleNumber;
        !           659:     double *doublePointer;
        !           660:     trio_long_double_t longdoubleNumber;
        !           661:     trio_long_double_t *longdoublePointer;
        !           662:     int errorNumber;
        !           663:   } data;
        !           664:   /* For the user-defined specifier */
        !           665:   char user_name[MAX_USER_NAME];
        !           666:   char user_data[MAX_USER_DATA];
        !           667: } trio_parameter_t;
        !           668: 
        !           669: /* Container for customized functions */
        !           670: typedef struct {
        !           671:   union {
        !           672:     trio_outstream_t out;
        !           673:     trio_instream_t in;
        !           674:   } stream;
        !           675:   trio_pointer_t closure;
        !           676: } trio_custom_t;
        !           677: 
        !           678: /* General trio "class" */
        !           679: typedef struct _trio_class_t {
        !           680:   /*
        !           681:    * The function to write characters to a stream.
        !           682:    */
        !           683:   void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int));
        !           684:   /*
        !           685:    * The function to read characters from a stream.
        !           686:    */
        !           687:   void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
        !           688:   /*
        !           689:    * The current location in the stream.
        !           690:    */
        !           691:   trio_pointer_t location;
        !           692:   /*
        !           693:    * The character currently being processed.
        !           694:    */
        !           695:   int current;
        !           696:   /*
        !           697:    * The number of characters that would have been written/read
        !           698:    * if there had been sufficient space.
        !           699:    */
        !           700:   int processed;
        !           701:   /*
        !           702:    * The number of characters that are actually written/read.
        !           703:    * Processed and committed will only differ for the *nprintf
        !           704:    * and *nscanf functions.
        !           705:    */
        !           706:   int committed;
        !           707:   /*
        !           708:    * The upper limit of characters that may be written/read.
        !           709:    */
        !           710:   int max;
        !           711:   /*
        !           712:    * The last output error that was detected.
        !           713:    */
        !           714:   int error;
        !           715: } trio_class_t;
        !           716: 
        !           717: /* References (for user-defined callbacks) */
        !           718: typedef struct _trio_reference_t {
        !           719:   trio_class_t *data;
        !           720:   trio_parameter_t *parameter;
        !           721: } trio_reference_t;
        !           722: 
        !           723: /* Registered entries (for user-defined callbacks) */
        !           724: typedef struct _trio_userdef_t {
        !           725:   struct _trio_userdef_t *next;
        !           726:   trio_callback_t callback;
        !           727:   char *name;
        !           728: } trio_userdef_t;
        !           729: 
        !           730: /*************************************************************************
        !           731:  *
        !           732:  * Internal Variables
        !           733:  *
        !           734:  *************************************************************************/
        !           735: 
        !           736: static TRIO_CONST char rcsid[] = "@(#)$Id$";
        !           737: 
        !           738: /*
        !           739:  * Need this to workaround a parser bug in HP C/iX compiler that fails
        !           740:  * to resolves macro definitions that includes type 'long double',
        !           741:  * e.g: va_arg(arg_ptr, long double)
        !           742:  */
        !           743: #if defined(TRIO_PLATFORM_MPEIX)
        !           744: static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
        !           745: #endif
        !           746: 
        !           747: static TRIO_CONST char internalNullString[] = "(nil)";
        !           748: 
        !           749: #if defined(USE_LOCALE)
        !           750: static struct lconv *internalLocaleValues = NULL;
        !           751: #endif
        !           752: 
        !           753: /*
        !           754:  * UNIX98 says "in a locale where the radix character is not defined,
        !           755:  * the radix character defaults to a period (.)"
        !           756:  */
        !           757: static int internalDecimalPointLength = 1;
        !           758: static int internalThousandSeparatorLength = 1;
        !           759: static char internalDecimalPoint = '.';
        !           760: static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
        !           761: static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
        !           762: static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
        !           763: 
        !           764: static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
        !           765: static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        !           766: static BOOLEAN_T internalDigitsUnconverted = TRUE;
        !           767: static int internalDigitArray[128];
        !           768: #if TRIO_EXTENSION
        !           769: static BOOLEAN_T internalCollationUnconverted = TRUE;
        !           770: static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
        !           771: #endif
        !           772: 
        !           773: #if TRIO_EXTENSION
        !           774: static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL;
        !           775: static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL;
        !           776: static trio_userdef_t *internalUserDef = NULL;
        !           777: #endif
        !           778: 
        !           779: 
        !           780: /*************************************************************************
        !           781:  *
        !           782:  * Internal Functions
        !           783:  *
        !           784:  ************************************************************************/
        !           785: 
        !           786: #if defined(TRIO_MINIMAL)
        !           787: # define TRIO_STRING_PUBLIC static
        !           788: # include "triostr.c"
        !           789: #endif /* defined(TRIO_MINIMAL) */
        !           790: 
        !           791: /*************************************************************************
        !           792:  * TrioIsQualifier
        !           793:  *
        !           794:  * Description:
        !           795:  *  Remember to add all new qualifiers to this function.
        !           796:  *  QUALIFIER_POSITION must not be added.
        !           797:  */
        !           798: TRIO_PRIVATE BOOLEAN_T
        !           799: TrioIsQualifier
        !           800: TRIO_ARGS1((character),
        !           801:           TRIO_CONST char character)
        !           802: {
        !           803:   /* QUALIFIER_POSITION is not included */
        !           804:   switch (character)
        !           805:     {
        !           806:     case '0': case '1': case '2': case '3': case '4':
        !           807:     case '5': case '6': case '7': case '8': case '9':
        !           808:     case QUALIFIER_PLUS:
        !           809:     case QUALIFIER_MINUS:
        !           810:     case QUALIFIER_SPACE:
        !           811:     case QUALIFIER_DOT:
        !           812:     case QUALIFIER_STAR:
        !           813:     case QUALIFIER_ALTERNATIVE:
        !           814:     case QUALIFIER_SHORT:
        !           815:     case QUALIFIER_LONG:
        !           816:     case QUALIFIER_LONG_UPPER:
        !           817:     case QUALIFIER_CIRCUMFLEX:
        !           818: #if defined(QUALIFIER_SIZE_T)
        !           819:     case QUALIFIER_SIZE_T:
        !           820: #endif
        !           821: #if defined(QUALIFIER_PTRDIFF_T)
        !           822:     case QUALIFIER_PTRDIFF_T:
        !           823: #endif
        !           824: #if defined(QUALIFIER_INTMAX_T)
        !           825:     case QUALIFIER_INTMAX_T:
        !           826: #endif
        !           827: #if defined(QUALIFIER_QUAD)
        !           828:     case QUALIFIER_QUAD:
        !           829: #endif
        !           830: #if defined(QUALIFIER_SIZE_T_UPPER)
        !           831:     case QUALIFIER_SIZE_T_UPPER:
        !           832: #endif
        !           833: #if defined(QUALIFIER_WIDECHAR)
        !           834:     case QUALIFIER_WIDECHAR:
        !           835: #endif
        !           836: #if defined(QUALIFIER_QUOTE)
        !           837:     case QUALIFIER_QUOTE:
        !           838: #endif
        !           839: #if defined(QUALIFIER_STICKY)
        !           840:     case QUALIFIER_STICKY:
        !           841: #endif
        !           842: #if defined(QUALIFIER_VARSIZE)
        !           843:     case QUALIFIER_VARSIZE:
        !           844: #endif
        !           845: #if defined(QUALIFIER_PARAM)
        !           846:     case QUALIFIER_PARAM:
        !           847: #endif
        !           848: #if defined(QUALIFIER_FIXED_SIZE)
        !           849:     case QUALIFIER_FIXED_SIZE:
        !           850: #endif
        !           851: #if defined(QUALIFIER_ROUNDING_UPPER)
        !           852:     case QUALIFIER_ROUNDING_UPPER:
        !           853: #endif
        !           854:       return TRUE;
        !           855:     default:
        !           856:       return FALSE;
        !           857:     }
        !           858: }
        !           859: 
        !           860: /*************************************************************************
        !           861:  * TrioSetLocale
        !           862:  */
        !           863: #if defined(USE_LOCALE)
        !           864: TRIO_PRIVATE void
        !           865: TrioSetLocale(TRIO_NOARGS)
        !           866: {
        !           867:   internalLocaleValues = (struct lconv *)localeconv();
        !           868:   if (internalLocaleValues)
        !           869:     {
        !           870:       if ((internalLocaleValues->decimal_point) &&
        !           871:          (internalLocaleValues->decimal_point[0] != NIL))
        !           872:        {
        !           873:          internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point);
        !           874:          if (internalDecimalPointLength == 1)
        !           875:            {
        !           876:              internalDecimalPoint = internalLocaleValues->decimal_point[0];
        !           877:            }
        !           878:          else
        !           879:            {
        !           880:              internalDecimalPoint = NIL;
        !           881:              trio_copy_max(internalDecimalPointString,
        !           882:                            sizeof(internalDecimalPointString),
        !           883:                            internalLocaleValues->decimal_point);
        !           884:            }
        !           885:        }
        !           886:       if ((internalLocaleValues->thousands_sep) &&
        !           887:          (internalLocaleValues->thousands_sep[0] != NIL))
        !           888:        {
        !           889:          trio_copy_max(internalThousandSeparator,
        !           890:                        sizeof(internalThousandSeparator),
        !           891:                        internalLocaleValues->thousands_sep);
        !           892:          internalThousandSeparatorLength = trio_length(internalThousandSeparator);
        !           893:        }
        !           894:       if ((internalLocaleValues->grouping) &&
        !           895:          (internalLocaleValues->grouping[0] != NIL))
        !           896:        {
        !           897:          trio_copy_max(internalGrouping,
        !           898:                        sizeof(internalGrouping),
        !           899:                        internalLocaleValues->grouping);
        !           900:        }
        !           901:     }
        !           902: }
        !           903: #endif /* defined(USE_LOCALE) */
        !           904: 
        !           905: TRIO_PRIVATE int
        !           906: TrioCalcThousandSeparatorLength
        !           907: TRIO_ARGS1((digits),
        !           908:           int digits)
        !           909: {
        !           910: #if TRIO_EXTENSION
        !           911:   int count = 0;
        !           912:   int step = NO_GROUPING;
        !           913:   char *groupingPointer = internalGrouping;
        !           914: 
        !           915:   while (digits > 0)
        !           916:     {
        !           917:       if (*groupingPointer == CHAR_MAX)
        !           918:        {
        !           919:          /* Disable grouping */
        !           920:          break; /* while */
        !           921:        }
        !           922:       else if (*groupingPointer == 0)
        !           923:        {
        !           924:          /* Repeat last group */
        !           925:          if (step == NO_GROUPING)
        !           926:            {
        !           927:              /* Error in locale */
        !           928:              break; /* while */
        !           929:            }
        !           930:        }
        !           931:       else
        !           932:        {
        !           933:          step = *groupingPointer++;
        !           934:        }
        !           935:       if (digits > step)
        !           936:        count += internalThousandSeparatorLength;
        !           937:       digits -= step;
        !           938:     }
        !           939:   return count;
        !           940: #else
        !           941:   return 0;
        !           942: #endif
        !           943: }
        !           944: 
        !           945: TRIO_PRIVATE BOOLEAN_T
        !           946: TrioFollowedBySeparator
        !           947: TRIO_ARGS1((position),
        !           948:           int position)
        !           949: {
        !           950: #if TRIO_EXTENSION
        !           951:   int step = 0;
        !           952:   char *groupingPointer = internalGrouping;
        !           953: 
        !           954:   position--;
        !           955:   if (position == 0)
        !           956:     return FALSE;
        !           957:   while (position > 0)
        !           958:     {
        !           959:       if (*groupingPointer == CHAR_MAX)
        !           960:        {
        !           961:          /* Disable grouping */
        !           962:          break; /* while */
        !           963:        }
        !           964:       else if (*groupingPointer != 0)
        !           965:        {
        !           966:          step = *groupingPointer++;
        !           967:        }
        !           968:       if (step == 0)
        !           969:        break;
        !           970:       position -= step;
        !           971:     }
        !           972:   return (position == 0);
        !           973: #else
        !           974:   return FALSE;
        !           975: #endif
        !           976: }
        !           977: 
        !           978: /*************************************************************************
        !           979:  * TrioGetPosition
        !           980:  *
        !           981:  * Get the %n$ position.
        !           982:  */
        !           983: TRIO_PRIVATE int
        !           984: TrioGetPosition
        !           985: TRIO_ARGS2((format, indexPointer),
        !           986:           TRIO_CONST char *format,
        !           987:           int *indexPointer)
        !           988: {
        !           989: #if TRIO_UNIX98
        !           990:   char *tmpformat;
        !           991:   int number = 0;
        !           992:   int index = *indexPointer;
        !           993: 
        !           994:   number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL);
        !           995:   index = (int)(tmpformat - format);
        !           996:   if ((number != 0) && (QUALIFIER_POSITION == format[index++]))
        !           997:     {
        !           998:       *indexPointer = index;
        !           999:       /*
        !          1000:        * number is decreased by 1, because n$ starts from 1, whereas
        !          1001:        * the array it is indexing starts from 0.
        !          1002:        */
        !          1003:       return number - 1;
        !          1004:     }
        !          1005: #endif
        !          1006:   return NO_POSITION;
        !          1007: }
        !          1008: 
        !          1009: #if TRIO_EXTENSION
        !          1010: /*************************************************************************
        !          1011:  * TrioFindNamespace
        !          1012:  *
        !          1013:  * Find registered user-defined specifier.
        !          1014:  * The prev argument is used for optimization only.
        !          1015:  */
        !          1016: TRIO_PRIVATE trio_userdef_t *
        !          1017: TrioFindNamespace
        !          1018: TRIO_ARGS2((name, prev),
        !          1019:           TRIO_CONST char *name,
        !          1020:           trio_userdef_t **prev)
        !          1021: {
        !          1022:   trio_userdef_t *def;
        !          1023:   
        !          1024:   if (internalEnterCriticalRegion)
        !          1025:     (void)internalEnterCriticalRegion(NULL);
        !          1026:   
        !          1027:   for (def = internalUserDef; def; def = def->next)
        !          1028:     {
        !          1029:       /* Case-sensitive string comparison */
        !          1030:       if (trio_equal_case(def->name, name))
        !          1031:        break;
        !          1032:       
        !          1033:       if (prev)
        !          1034:        *prev = def;
        !          1035:     }
        !          1036:   
        !          1037:   if (internalLeaveCriticalRegion)
        !          1038:     (void)internalLeaveCriticalRegion(NULL);
        !          1039:   
        !          1040:   return def;
        !          1041: }
        !          1042: #endif
        !          1043: 
        !          1044: /*************************************************************************
        !          1045:  * TrioPower
        !          1046:  *
        !          1047:  * Description:
        !          1048:  *  Calculate pow(base, exponent), where number and exponent are integers.
        !          1049:  */
        !          1050: TRIO_PRIVATE trio_long_double_t
        !          1051: TrioPower
        !          1052: TRIO_ARGS2((number, exponent),
        !          1053:           int number,
        !          1054:           int exponent)
        !          1055: {
        !          1056:   trio_long_double_t result;
        !          1057: 
        !          1058:   if (number == 10)
        !          1059:     {
        !          1060:       switch (exponent)
        !          1061:        {
        !          1062:          /* Speed up calculation of common cases */
        !          1063:        case 0:
        !          1064:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1);
        !          1065:          break;
        !          1066:        case 1:
        !          1067:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0);
        !          1068:          break;
        !          1069:        case 2:
        !          1070:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1);
        !          1071:          break;
        !          1072:        case 3:
        !          1073:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2);
        !          1074:          break;
        !          1075:        case 4:
        !          1076:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3);
        !          1077:          break;
        !          1078:        case 5:
        !          1079:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4);
        !          1080:          break;
        !          1081:        case 6:
        !          1082:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5);
        !          1083:          break;
        !          1084:        case 7:
        !          1085:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6);
        !          1086:          break;
        !          1087:        case 8:
        !          1088:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7);
        !          1089:          break;
        !          1090:        case 9:
        !          1091:          result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8);
        !          1092:          break;
        !          1093:        default:
        !          1094:          result = powl((trio_long_double_t)number,
        !          1095:                        (trio_long_double_t)exponent);
        !          1096:          break;
        !          1097:        }
        !          1098:     }
        !          1099:   else
        !          1100:     {
        !          1101:       return powl((trio_long_double_t)number, (trio_long_double_t)exponent);
        !          1102:     }
        !          1103:   return result;
        !          1104: }
        !          1105: 
        !          1106: /*************************************************************************
        !          1107:  * TrioLogarithm
        !          1108:  */
        !          1109: TRIO_PRIVATE double
        !          1110: TrioLogarithm
        !          1111: TRIO_ARGS2((number, base),
        !          1112:           double number,
        !          1113:           int base)
        !          1114: {
        !          1115:   double result;
        !          1116: 
        !          1117:   if (number <= 0.0)
        !          1118:     {
        !          1119:       /* xlC crashes on log(0) */
        !          1120:       result = (number == 0.0) ? trio_ninf() : trio_nan();
        !          1121:     }
        !          1122:   else
        !          1123:     {
        !          1124:       if (base == 10)
        !          1125:        {
        !          1126:          result = log10(number);
        !          1127:        }
        !          1128:       else
        !          1129:        {
        !          1130:          result = log10(number) / log10((double)base);
        !          1131:        }
        !          1132:     }
        !          1133:   return result;
        !          1134: }
        !          1135: 
        !          1136: /*************************************************************************
        !          1137:  * TrioLogarithmBase
        !          1138:  */
        !          1139: TRIO_PRIVATE double
        !          1140: TrioLogarithmBase
        !          1141: TRIO_ARGS1((base),
        !          1142:           int base)
        !          1143: {
        !          1144:   switch (base)
        !          1145:     {
        !          1146:     case BASE_BINARY : return 1.0;
        !          1147:     case BASE_OCTAL  : return 3.0;
        !          1148:     case BASE_DECIMAL: return 3.321928094887362345;
        !          1149:     case BASE_HEX    : return 4.0;
        !          1150:     default          : return TrioLogarithm((double)base, 2);
        !          1151:     }
        !          1152: }
        !          1153: 
        !          1154: /*************************************************************************
        !          1155:  * TrioParse
        !          1156:  *
        !          1157:  * Description:
        !          1158:  *  Parse the format string
        !          1159:  */
        !          1160: TRIO_PRIVATE int
        !          1161: TrioParse
        !          1162: TRIO_ARGS5((type, format, parameters, arglist, argarray),
        !          1163:           int type,
        !          1164:           TRIO_CONST char *format,
        !          1165:           trio_parameter_t *parameters,
        !          1166:           va_list *arglist,
        !          1167:           trio_pointer_t *argarray)
        !          1168: {
        !          1169:   /* Count the number of times a parameter is referenced */
        !          1170:   unsigned short usedEntries[MAX_PARAMETERS];
        !          1171:   /* Parameter counters */
        !          1172:   int parameterPosition;
        !          1173:   int currentParam;
        !          1174:   int maxParam = -1;
        !          1175:   /* Utility variables */
        !          1176:   trio_flags_t flags;
        !          1177:   int width;
        !          1178:   int precision;
        !          1179:   int varsize;
        !          1180:   int base;
        !          1181:   int index;  /* Index into formatting string */
        !          1182:   int dots;  /* Count number of dots in modifier part */
        !          1183:   BOOLEAN_T positional;  /* Does the specifier have a positional? */
        !          1184:   BOOLEAN_T gotSticky = FALSE;  /* Are there any sticky modifiers at all? */
        !          1185:   /*
        !          1186:    * indices specifies the order in which the parameters must be
        !          1187:    * read from the va_args (this is necessary to handle positionals)
        !          1188:    */
        !          1189:   int indices[MAX_PARAMETERS];
        !          1190:   int pos = 0;
        !          1191:   /* Various variables */
        !          1192:   char ch;
        !          1193: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          1194:   int charlen;
        !          1195: #endif
        !          1196:   int save_errno;
        !          1197:   int i = -1;
        !          1198:   int num;
        !          1199:   char *tmpformat;
        !          1200: 
        !          1201:   /* One and only one of arglist and argarray must be used */
        !          1202:   assert((arglist != NULL) ^ (argarray != NULL));
        !          1203:   
        !          1204:   /*
        !          1205:    * The 'parameters' array is not initialized, but we need to
        !          1206:    * know which entries we have used.
        !          1207:    */
        !          1208:   memset(usedEntries, 0, sizeof(usedEntries));
        !          1209: 
        !          1210:   save_errno = errno;
        !          1211:   index = 0;
        !          1212:   parameterPosition = 0;
        !          1213: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          1214:   (void)mblen(NULL, 0);
        !          1215: #endif
        !          1216:   
        !          1217:   while (format[index])
        !          1218:     {
        !          1219: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          1220:       if (! isascii(format[index]))
        !          1221:        {
        !          1222:          /*
        !          1223:           * Multibyte characters cannot be legal specifiers or
        !          1224:           * modifiers, so we skip over them.
        !          1225:           */
        !          1226:          charlen = mblen(&format[index], MB_LEN_MAX);
        !          1227:          index += (charlen > 0) ? charlen : 1;
        !          1228:          continue; /* while */
        !          1229:        }
        !          1230: #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
        !          1231:       if (CHAR_IDENTIFIER == format[index++])
        !          1232:        {
        !          1233:          if (CHAR_IDENTIFIER == format[index])
        !          1234:            {
        !          1235:              index++;
        !          1236:              continue; /* while */
        !          1237:            }
        !          1238: 
        !          1239:          flags = FLAGS_NEW;
        !          1240:          dots = 0;
        !          1241:          currentParam = TrioGetPosition(format, &index);
        !          1242:          positional = (NO_POSITION != currentParam);
        !          1243:          if (!positional)
        !          1244:            {
        !          1245:              /* We have no positional, get the next counter */
        !          1246:              currentParam = parameterPosition;
        !          1247:            }
        !          1248:           if(currentParam >= MAX_PARAMETERS)
        !          1249:            {
        !          1250:              /* Bail out completely to make the error more obvious */
        !          1251:              return TRIO_ERROR_RETURN(TRIO_ETOOMANY, index);
        !          1252:            }
        !          1253: 
        !          1254:          if (currentParam > maxParam)
        !          1255:            maxParam = currentParam;
        !          1256: 
        !          1257:          /* Default values */
        !          1258:          width = NO_WIDTH;
        !          1259:          precision = NO_PRECISION;
        !          1260:          base = NO_BASE;
        !          1261:          varsize = NO_SIZE;
        !          1262: 
        !          1263:          while (TrioIsQualifier(format[index]))
        !          1264:            {
        !          1265:              ch = format[index++];
        !          1266: 
        !          1267:              switch (ch)
        !          1268:                {
        !          1269:                case QUALIFIER_SPACE:
        !          1270:                  flags |= FLAGS_SPACE;
        !          1271:                  break;
        !          1272: 
        !          1273:                case QUALIFIER_PLUS:
        !          1274:                  flags |= FLAGS_SHOWSIGN;
        !          1275:                  break;
        !          1276: 
        !          1277:                case QUALIFIER_MINUS:
        !          1278:                  flags |= FLAGS_LEFTADJUST;
        !          1279:                  flags &= ~FLAGS_NILPADDING;
        !          1280:                  break;
        !          1281: 
        !          1282:                case QUALIFIER_ALTERNATIVE:
        !          1283:                  flags |= FLAGS_ALTERNATIVE;
        !          1284:                  break;
        !          1285: 
        !          1286:                case QUALIFIER_DOT:
        !          1287:                  if (dots == 0) /* Precision */
        !          1288:                    {
        !          1289:                      dots++;
        !          1290: 
        !          1291:                      /* Skip if no precision */
        !          1292:                      if (QUALIFIER_DOT == format[index])
        !          1293:                        break;
        !          1294:                      
        !          1295:                      /* After the first dot we have the precision */
        !          1296:                      flags |= FLAGS_PRECISION;
        !          1297:                      if ((QUALIFIER_STAR == format[index])
        !          1298: #if defined(QUALIFIER_PARAM)
        !          1299:                          || (QUALIFIER_PARAM == format[index])
        !          1300: #endif
        !          1301:                          )
        !          1302:                        {
        !          1303:                          index++;
        !          1304:                          flags |= FLAGS_PRECISION_PARAMETER;
        !          1305: 
        !          1306:                          precision = TrioGetPosition(format, &index);
        !          1307:                          if (precision == NO_POSITION)
        !          1308:                            {
        !          1309:                              parameterPosition++;
        !          1310:                              if (positional)
        !          1311:                                precision = parameterPosition;
        !          1312:                              else
        !          1313:                                {
        !          1314:                                  precision = currentParam;
        !          1315:                                  currentParam = precision + 1;
        !          1316:                                }
        !          1317:                            }
        !          1318:                          else
        !          1319:                            {
        !          1320:                              if (! positional)
        !          1321:                                currentParam = precision + 1;
        !          1322:                              if (width > maxParam)
        !          1323:                                maxParam = precision;
        !          1324:                            }
        !          1325:                          if (currentParam > maxParam)
        !          1326:                            maxParam = currentParam;
        !          1327:                        }
        !          1328:                      else
        !          1329:                        {
        !          1330:                          precision = trio_to_long(&format[index],
        !          1331:                                                   &tmpformat,
        !          1332:                                                   BASE_DECIMAL);
        !          1333:                          index = (int)(tmpformat - format);
        !          1334:                        }
        !          1335:                    }
        !          1336:                  else if (dots == 1) /* Base */
        !          1337:                    {
        !          1338:                      dots++;
        !          1339:                      
        !          1340:                      /* After the second dot we have the base */
        !          1341:                      flags |= FLAGS_BASE;
        !          1342:                      if ((QUALIFIER_STAR == format[index])
        !          1343: #if defined(QUALIFIER_PARAM)
        !          1344:                          || (QUALIFIER_PARAM == format[index])
        !          1345: #endif
        !          1346:                          )
        !          1347:                        {
        !          1348:                          index++;
        !          1349:                          flags |= FLAGS_BASE_PARAMETER;
        !          1350:                          base = TrioGetPosition(format, &index);
        !          1351:                          if (base == NO_POSITION)
        !          1352:                            {
        !          1353:                              parameterPosition++;
        !          1354:                              if (positional)
        !          1355:                                base = parameterPosition;
        !          1356:                              else
        !          1357:                                {
        !          1358:                                  base = currentParam;
        !          1359:                                  currentParam = base + 1;
        !          1360:                                }
        !          1361:                            }
        !          1362:                          else
        !          1363:                            {
        !          1364:                              if (! positional)
        !          1365:                                currentParam = base + 1;
        !          1366:                              if (base > maxParam)
        !          1367:                                maxParam = base;
        !          1368:                            }
        !          1369:                          if (currentParam > maxParam)
        !          1370:                            maxParam = currentParam;
        !          1371:                        }
        !          1372:                      else
        !          1373:                        {
        !          1374:                          base = trio_to_long(&format[index],
        !          1375:                                              &tmpformat,
        !          1376:                                              BASE_DECIMAL);
        !          1377:                          if (base > MAX_BASE)
        !          1378:                            return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1379:                          index = (int)(tmpformat - format);
        !          1380:                        }
        !          1381:                    }
        !          1382:                  else
        !          1383:                    {
        !          1384:                      return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1385:                    }
        !          1386:                  break; /* QUALIFIER_DOT */
        !          1387: 
        !          1388: #if defined(QUALIFIER_PARAM)
        !          1389:                case QUALIFIER_PARAM:
        !          1390:                  type = TYPE_PRINT;
        !          1391:                  /* FALLTHROUGH */
        !          1392: #endif
        !          1393:                case QUALIFIER_STAR:
        !          1394:                  /* This has different meanings for print and scan */
        !          1395:                  if (TYPE_PRINT == type)
        !          1396:                    {
        !          1397:                      /* Read with from parameter */
        !          1398:                      flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
        !          1399:                      width = TrioGetPosition(format, &index);
        !          1400:                      if (width == NO_POSITION)
        !          1401:                        {
        !          1402:                          parameterPosition++;
        !          1403:                          if (positional)
        !          1404:                            width = parameterPosition;
        !          1405:                          else
        !          1406:                            {
        !          1407:                              width = currentParam;
        !          1408:                              currentParam = width + 1;
        !          1409:                            }
        !          1410:                        }
        !          1411:                      else
        !          1412:                        {
        !          1413:                          if (! positional)
        !          1414:                            currentParam = width + 1;
        !          1415:                          if (width > maxParam)
        !          1416:                            maxParam = width;
        !          1417:                        }
        !          1418:                      if (currentParam > maxParam)
        !          1419:                        maxParam = currentParam;
        !          1420:                    }
        !          1421:                  else
        !          1422:                    {
        !          1423:                      /* Scan, but do not store result */
        !          1424:                      flags |= FLAGS_IGNORE;
        !          1425:                    }
        !          1426: 
        !          1427:                  break; /* QUALIFIER_STAR */
        !          1428: 
        !          1429:                case '0':
        !          1430:                  if (! (flags & FLAGS_LEFTADJUST))
        !          1431:                    flags |= FLAGS_NILPADDING;
        !          1432:                  /* FALLTHROUGH */
        !          1433:                case '1': case '2': case '3': case '4':
        !          1434:                case '5': case '6': case '7': case '8': case '9':
        !          1435:                  flags |= FLAGS_WIDTH;
        !          1436:                  /* &format[index - 1] is used to "rewind" the read
        !          1437:                   * character from format
        !          1438:                   */
        !          1439:                  width = trio_to_long(&format[index - 1],
        !          1440:                                       &tmpformat,
        !          1441:                                       BASE_DECIMAL);
        !          1442:                  index = (int)(tmpformat - format);
        !          1443:                  break;
        !          1444: 
        !          1445:                case QUALIFIER_SHORT:
        !          1446:                  if (flags & FLAGS_SHORTSHORT)
        !          1447:                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1448:                  else if (flags & FLAGS_SHORT)
        !          1449:                    flags |= FLAGS_SHORTSHORT;
        !          1450:                  else
        !          1451:                    flags |= FLAGS_SHORT;
        !          1452:                  break;
        !          1453: 
        !          1454:                case QUALIFIER_LONG:
        !          1455:                  if (flags & FLAGS_QUAD)
        !          1456:                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1457:                  else if (flags & FLAGS_LONG)
        !          1458:                    flags |= FLAGS_QUAD;
        !          1459:                  else
        !          1460:                    flags |= FLAGS_LONG;
        !          1461:                  break;
        !          1462: 
        !          1463:                case QUALIFIER_LONG_UPPER:
        !          1464:                  flags |= FLAGS_LONGDOUBLE;
        !          1465:                  break;
        !          1466: 
        !          1467: #if defined(QUALIFIER_SIZE_T)
        !          1468:                case QUALIFIER_SIZE_T:
        !          1469:                  flags |= FLAGS_SIZE_T;
        !          1470:                  /* Modify flags for later truncation of number */
        !          1471:                  if (sizeof(size_t) == sizeof(trio_ulonglong_t))
        !          1472:                    flags |= FLAGS_QUAD;
        !          1473:                  else if (sizeof(size_t) == sizeof(long))
        !          1474:                    flags |= FLAGS_LONG;
        !          1475:                  break;
        !          1476: #endif
        !          1477: 
        !          1478: #if defined(QUALIFIER_PTRDIFF_T)
        !          1479:                case QUALIFIER_PTRDIFF_T:
        !          1480:                  flags |= FLAGS_PTRDIFF_T;
        !          1481:                  if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
        !          1482:                    flags |= FLAGS_QUAD;
        !          1483:                  else if (sizeof(ptrdiff_t) == sizeof(long))
        !          1484:                    flags |= FLAGS_LONG;
        !          1485:                  break;
        !          1486: #endif
        !          1487: 
        !          1488: #if defined(QUALIFIER_INTMAX_T)
        !          1489:                case QUALIFIER_INTMAX_T:
        !          1490:                  flags |= FLAGS_INTMAX_T;
        !          1491:                  if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
        !          1492:                    flags |= FLAGS_QUAD;
        !          1493:                  else if (sizeof(trio_intmax_t) == sizeof(long))
        !          1494:                    flags |= FLAGS_LONG;
        !          1495:                  break;
        !          1496: #endif
        !          1497: 
        !          1498: #if defined(QUALIFIER_QUAD)
        !          1499:                case QUALIFIER_QUAD:
        !          1500:                  flags |= FLAGS_QUAD;
        !          1501:                  break;
        !          1502: #endif
        !          1503: 
        !          1504: #if defined(QUALIFIER_FIXED_SIZE)
        !          1505:                case QUALIFIER_FIXED_SIZE:
        !          1506:                  if (flags & FLAGS_FIXED_SIZE)
        !          1507:                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1508: 
        !          1509:                  if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE |
        !          1510:                               FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER))
        !          1511:                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1512: 
        !          1513:                  if ((format[index] == '6') &&
        !          1514:                      (format[index + 1] == '4'))
        !          1515:                    {
        !          1516:                      varsize = sizeof(trio_int64_t);
        !          1517:                      index += 2;
        !          1518:                    }
        !          1519:                  else if ((format[index] == '3') &&
        !          1520:                           (format[index + 1] == '2'))
        !          1521:                    {
        !          1522:                      varsize = sizeof(trio_int32_t);
        !          1523:                      index += 2;
        !          1524:                    }
        !          1525:                  else if ((format[index] == '1') &&
        !          1526:                           (format[index + 1] == '6'))
        !          1527:                    {
        !          1528:                      varsize = sizeof(trio_int16_t);
        !          1529:                      index += 2;
        !          1530:                    }
        !          1531:                  else if (format[index] == '8')
        !          1532:                    {
        !          1533:                      varsize = sizeof(trio_int8_t);
        !          1534:                      index++;
        !          1535:                    }
        !          1536:                  else
        !          1537:                    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1538:                  
        !          1539:                  flags |= FLAGS_FIXED_SIZE;
        !          1540:                  break;
        !          1541: #endif
        !          1542: 
        !          1543: #if defined(QUALIFIER_WIDECHAR)
        !          1544:                case QUALIFIER_WIDECHAR:
        !          1545:                  flags |= FLAGS_WIDECHAR;
        !          1546:                  break;
        !          1547: #endif
        !          1548: 
        !          1549: #if defined(QUALIFIER_SIZE_T_UPPER)
        !          1550:                case QUALIFIER_SIZE_T_UPPER:
        !          1551:                  break;
        !          1552: #endif
        !          1553: 
        !          1554: #if defined(QUALIFIER_QUOTE)
        !          1555:                case QUALIFIER_QUOTE:
        !          1556:                  flags |= FLAGS_QUOTE;
        !          1557:                  break;
        !          1558: #endif
        !          1559: 
        !          1560: #if defined(QUALIFIER_STICKY)
        !          1561:                case QUALIFIER_STICKY:
        !          1562:                  flags |= FLAGS_STICKY;
        !          1563:                  gotSticky = TRUE;
        !          1564:                  break;
        !          1565: #endif
        !          1566:                  
        !          1567: #if defined(QUALIFIER_VARSIZE)
        !          1568:                case QUALIFIER_VARSIZE:
        !          1569:                  flags |= FLAGS_VARSIZE_PARAMETER;
        !          1570:                  parameterPosition++;
        !          1571:                  if (positional)
        !          1572:                    varsize = parameterPosition;
        !          1573:                  else
        !          1574:                    {
        !          1575:                      varsize = currentParam;
        !          1576:                      currentParam = varsize + 1;
        !          1577:                    }
        !          1578:                  if (currentParam > maxParam)
        !          1579:                    maxParam = currentParam;
        !          1580:                  break;
        !          1581: #endif
        !          1582: 
        !          1583: #if defined(QUALIFIER_ROUNDING_UPPER)
        !          1584:                case QUALIFIER_ROUNDING_UPPER:
        !          1585:                  flags |= FLAGS_ROUNDING;
        !          1586:                  break;
        !          1587: #endif
        !          1588: 
        !          1589:                default:
        !          1590:                  /* Bail out completely to make the error more obvious */
        !          1591:                   return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1592:                }
        !          1593:            } /* while qualifier */
        !          1594: 
        !          1595:          /*
        !          1596:           * Parameters only need the type and value. The value is
        !          1597:           * read later.
        !          1598:           */
        !          1599:          if (flags & FLAGS_WIDTH_PARAMETER)
        !          1600:            {
        !          1601:              usedEntries[width] += 1;
        !          1602:              parameters[pos].type = FORMAT_PARAMETER;
        !          1603:              parameters[pos].flags = 0;
        !          1604:              indices[width] = pos;
        !          1605:              width = pos++;
        !          1606:            }
        !          1607:          if (flags & FLAGS_PRECISION_PARAMETER)
        !          1608:            {
        !          1609:              usedEntries[precision] += 1;
        !          1610:              parameters[pos].type = FORMAT_PARAMETER;
        !          1611:              parameters[pos].flags = 0;
        !          1612:              indices[precision] = pos;
        !          1613:              precision = pos++;
        !          1614:            }
        !          1615:          if (flags & FLAGS_BASE_PARAMETER)
        !          1616:            {
        !          1617:              usedEntries[base] += 1;
        !          1618:              parameters[pos].type = FORMAT_PARAMETER;
        !          1619:              parameters[pos].flags = 0;
        !          1620:              indices[base] = pos;
        !          1621:              base = pos++;
        !          1622:            }
        !          1623:          if (flags & FLAGS_VARSIZE_PARAMETER)
        !          1624:            {
        !          1625:              usedEntries[varsize] += 1;
        !          1626:              parameters[pos].type = FORMAT_PARAMETER;
        !          1627:              parameters[pos].flags = 0;
        !          1628:              indices[varsize] = pos;
        !          1629:              varsize = pos++;
        !          1630:            }
        !          1631:          
        !          1632:          indices[currentParam] = pos;
        !          1633:          
        !          1634:          switch (format[index++])
        !          1635:            {
        !          1636: #if defined(SPECIFIER_CHAR_UPPER)
        !          1637:            case SPECIFIER_CHAR_UPPER:
        !          1638:              flags |= FLAGS_WIDECHAR;
        !          1639:              /* FALLTHROUGH */
        !          1640: #endif
        !          1641:            case SPECIFIER_CHAR:
        !          1642:              if (flags & FLAGS_LONG)
        !          1643:                flags |= FLAGS_WIDECHAR;
        !          1644:              else if (flags & FLAGS_SHORT)
        !          1645:                flags &= ~FLAGS_WIDECHAR;
        !          1646:              parameters[pos].type = FORMAT_CHAR;
        !          1647:              break;
        !          1648: 
        !          1649: #if defined(SPECIFIER_STRING_UPPER)
        !          1650:            case SPECIFIER_STRING_UPPER:
        !          1651:              flags |= FLAGS_WIDECHAR;
        !          1652:              /* FALLTHROUGH */
        !          1653: #endif
        !          1654:            case SPECIFIER_STRING:
        !          1655:              if (flags & FLAGS_LONG)
        !          1656:                flags |= FLAGS_WIDECHAR;
        !          1657:              else if (flags & FLAGS_SHORT)
        !          1658:                flags &= ~FLAGS_WIDECHAR;
        !          1659:              parameters[pos].type = FORMAT_STRING;
        !          1660:              break;
        !          1661: 
        !          1662:            case SPECIFIER_GROUP:
        !          1663:              if (TYPE_SCAN == type)
        !          1664:                {
        !          1665:                  int depth = 1;
        !          1666:                  parameters[pos].type = FORMAT_GROUP;
        !          1667:                  if (format[index] == QUALIFIER_CIRCUMFLEX)
        !          1668:                    index++;
        !          1669:                  if (format[index] == SPECIFIER_UNGROUP)
        !          1670:                    index++;
        !          1671:                  if (format[index] == QUALIFIER_MINUS)
        !          1672:                    index++;
        !          1673:                  /* Skip nested brackets */
        !          1674:                  while (format[index] != NIL)
        !          1675:                    {
        !          1676:                      if (format[index] == SPECIFIER_GROUP)
        !          1677:                        {
        !          1678:                          depth++;
        !          1679:                        }
        !          1680:                      else if (format[index] == SPECIFIER_UNGROUP)
        !          1681:                        {
        !          1682:                          if (--depth <= 0)
        !          1683:                            {
        !          1684:                              index++;
        !          1685:                              break;
        !          1686:                            }
        !          1687:                        }
        !          1688:                      index++;
        !          1689:                    }
        !          1690:                }
        !          1691:              break;
        !          1692:              
        !          1693:            case SPECIFIER_INTEGER:
        !          1694:              parameters[pos].type = FORMAT_INT;
        !          1695:              break;
        !          1696:              
        !          1697:            case SPECIFIER_UNSIGNED:
        !          1698:              flags |= FLAGS_UNSIGNED;
        !          1699:              parameters[pos].type = FORMAT_INT;
        !          1700:              break;
        !          1701: 
        !          1702:            case SPECIFIER_DECIMAL:
        !          1703:              /* Disable base modifier */
        !          1704:              flags &= ~FLAGS_BASE_PARAMETER;
        !          1705:              base = BASE_DECIMAL;
        !          1706:              parameters[pos].type = FORMAT_INT;
        !          1707:              break;
        !          1708: 
        !          1709:            case SPECIFIER_OCTAL:
        !          1710:              flags |= FLAGS_UNSIGNED;
        !          1711:              flags &= ~FLAGS_BASE_PARAMETER;
        !          1712:              base = BASE_OCTAL;
        !          1713:              parameters[pos].type = FORMAT_INT;
        !          1714:              break;
        !          1715: 
        !          1716: #if defined(SPECIFIER_BINARY)
        !          1717:            case SPECIFIER_BINARY_UPPER:
        !          1718:              flags |= FLAGS_UPPER;
        !          1719:              /* FALLTHROUGH */
        !          1720:            case SPECIFIER_BINARY:
        !          1721:              flags |= FLAGS_NILPADDING;
        !          1722:              flags &= ~FLAGS_BASE_PARAMETER;
        !          1723:              base = BASE_BINARY;
        !          1724:              parameters[pos].type = FORMAT_INT;
        !          1725:              break;
        !          1726: #endif
        !          1727: 
        !          1728:            case SPECIFIER_HEX_UPPER:
        !          1729:              flags |= FLAGS_UPPER;
        !          1730:              /* FALLTHROUGH */
        !          1731:            case SPECIFIER_HEX:
        !          1732:              flags |= FLAGS_UNSIGNED;
        !          1733:              flags &= ~FLAGS_BASE_PARAMETER;
        !          1734:              base = BASE_HEX;
        !          1735:              parameters[pos].type = FORMAT_INT;
        !          1736:              break;
        !          1737: 
        !          1738:            case SPECIFIER_FLOAT_E_UPPER:
        !          1739:              flags |= FLAGS_UPPER;
        !          1740:              /* FALLTHROUGH */
        !          1741:            case SPECIFIER_FLOAT_E:
        !          1742:              flags |= FLAGS_FLOAT_E;
        !          1743:              parameters[pos].type = FORMAT_DOUBLE;
        !          1744:              break;
        !          1745: 
        !          1746:            case SPECIFIER_FLOAT_G_UPPER:
        !          1747:              flags |= FLAGS_UPPER;
        !          1748:              /* FALLTHROUGH */
        !          1749:            case SPECIFIER_FLOAT_G:
        !          1750:              flags |= FLAGS_FLOAT_G;
        !          1751:              parameters[pos].type = FORMAT_DOUBLE;
        !          1752:              break;
        !          1753: 
        !          1754:            case SPECIFIER_FLOAT_F_UPPER:
        !          1755:              flags |= FLAGS_UPPER;
        !          1756:              /* FALLTHROUGH */
        !          1757:            case SPECIFIER_FLOAT_F:
        !          1758:              parameters[pos].type = FORMAT_DOUBLE;
        !          1759:              break;
        !          1760: 
        !          1761:            case SPECIFIER_POINTER:
        !          1762:              if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
        !          1763:                flags |= FLAGS_QUAD;
        !          1764:              else if (sizeof(trio_pointer_t) == sizeof(long))
        !          1765:                flags |= FLAGS_LONG;
        !          1766:              parameters[pos].type = FORMAT_POINTER;
        !          1767:              break;
        !          1768: 
        !          1769:            case SPECIFIER_COUNT:
        !          1770:              parameters[pos].type = FORMAT_COUNT;
        !          1771:              break;
        !          1772: 
        !          1773: #if defined(SPECIFIER_HEXFLOAT)
        !          1774: # if defined(SPECIFIER_HEXFLOAT_UPPER)
        !          1775:            case SPECIFIER_HEXFLOAT_UPPER:
        !          1776:              flags |= FLAGS_UPPER;
        !          1777:              /* FALLTHROUGH */
        !          1778: # endif
        !          1779:            case SPECIFIER_HEXFLOAT:
        !          1780:              base = BASE_HEX;
        !          1781:              parameters[pos].type = FORMAT_DOUBLE;
        !          1782:              break;
        !          1783: #endif
        !          1784: 
        !          1785: #if defined(FORMAT_ERRNO)
        !          1786:            case SPECIFIER_ERRNO:
        !          1787:              parameters[pos].type = FORMAT_ERRNO;
        !          1788:              break;
        !          1789: #endif
        !          1790: 
        !          1791: #if defined(SPECIFIER_USER_DEFINED_BEGIN)
        !          1792:            case SPECIFIER_USER_DEFINED_BEGIN:
        !          1793:              {
        !          1794:                unsigned int max;
        !          1795:                int without_namespace = TRUE;
        !          1796:                
        !          1797:                parameters[pos].type = FORMAT_USER_DEFINED;
        !          1798:                parameters[pos].user_name[0] = NIL;
        !          1799:                tmpformat = (char *)&format[index];
        !          1800:              
        !          1801:                while ((ch = format[index]))
        !          1802:                  {
        !          1803:                    index++;
        !          1804:                    if (ch == SPECIFIER_USER_DEFINED_END)
        !          1805:                      {
        !          1806:                        if (without_namespace)
        !          1807:                          {
        !          1808:                            /* We must get the handle first */
        !          1809:                            parameters[pos].type = FORMAT_PARAMETER;
        !          1810:                            parameters[pos].indexAfterSpecifier = index;
        !          1811:                            parameters[pos].flags = FLAGS_USER_DEFINED;
        !          1812:                            /* Adjust parameters for insertion of new one */
        !          1813:                            pos++;
        !          1814:                            usedEntries[currentParam] += 1;
        !          1815:                            parameters[pos].type = FORMAT_USER_DEFINED;
        !          1816:                            currentParam++;
        !          1817:                            indices[currentParam] = pos;
        !          1818:                            if (currentParam > maxParam)
        !          1819:                              maxParam = currentParam;
        !          1820:                          }
        !          1821:                        /* Copy the user data */
        !          1822:                        max = (unsigned int)(&format[index] - tmpformat);
        !          1823:                        if (max > MAX_USER_DATA)
        !          1824:                          max = MAX_USER_DATA;
        !          1825:                        trio_copy_max(parameters[pos].user_data,
        !          1826:                                      max,
        !          1827:                                      tmpformat);
        !          1828:                        break; /* while */
        !          1829:                      }
        !          1830:                    if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
        !          1831:                      {
        !          1832:                        without_namespace = FALSE;
        !          1833:                        /* Copy the namespace for later looking-up */
        !          1834:                        max = (int)(&format[index] - tmpformat);
        !          1835:                        if (max > MAX_USER_NAME)
        !          1836:                          max = MAX_USER_NAME;
        !          1837:                        trio_copy_max(parameters[pos].user_name,
        !          1838:                                      max,
        !          1839:                                      tmpformat);
        !          1840:                        tmpformat = (char *)&format[index];
        !          1841:                      }
        !          1842:                  }
        !          1843:                if (ch != SPECIFIER_USER_DEFINED_END)
        !          1844:                  return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1845:              }
        !          1846:              break;
        !          1847: #endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */
        !          1848:              
        !          1849:            default:
        !          1850:              /* Bail out completely to make the error more obvious */
        !          1851:               return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          1852:            }
        !          1853: 
        !          1854:          /*  Count the number of times this entry has been used */
        !          1855:          usedEntries[currentParam] += 1;
        !          1856:          
        !          1857:          /* Find last sticky parameters */
        !          1858:          if (gotSticky && !(flags & FLAGS_STICKY))
        !          1859:            {
        !          1860:              for (i = pos - 1; i >= 0; i--)
        !          1861:                {
        !          1862:                  if (parameters[i].type == FORMAT_PARAMETER)
        !          1863:                    continue;
        !          1864:                  if ((parameters[i].flags & FLAGS_STICKY) &&
        !          1865:                      (parameters[i].type == parameters[pos].type))
        !          1866:                    {
        !          1867:                      /* Do not overwrite current qualifiers */
        !          1868:                      flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
        !          1869:                      if (width == NO_WIDTH)
        !          1870:                        width = parameters[i].width;
        !          1871:                      if (precision == NO_PRECISION)
        !          1872:                        precision = parameters[i].precision;
        !          1873:                      if (base == NO_BASE)
        !          1874:                        base = parameters[i].base;
        !          1875:                      break;
        !          1876:                    }
        !          1877:                }
        !          1878:            }
        !          1879:          
        !          1880:          parameters[pos].indexAfterSpecifier = index;
        !          1881:          parameters[pos].flags = flags;
        !          1882:          parameters[pos].width = width;
        !          1883:          parameters[pos].precision = precision;
        !          1884:          parameters[pos].base = (base == NO_BASE) ? BASE_DECIMAL : base;
        !          1885:          parameters[pos].varsize = varsize;
        !          1886:          pos++;
        !          1887:          
        !          1888:          if (! positional)
        !          1889:            parameterPosition++;
        !          1890:          
        !          1891:        } /* if identifier */
        !          1892:       
        !          1893:     } /* while format characters left */
        !          1894: 
        !          1895:   for (num = 0; num <= maxParam; num++)
        !          1896:     {
        !          1897:       if (usedEntries[num] != 1)
        !          1898:        {
        !          1899:          if (usedEntries[num] == 0) /* gap detected */
        !          1900:            return TRIO_ERROR_RETURN(TRIO_EGAP, num);
        !          1901:          else /* double references detected */
        !          1902:            return TRIO_ERROR_RETURN(TRIO_EDBLREF, num);
        !          1903:        }
        !          1904:       
        !          1905:       i = indices[num];
        !          1906: 
        !          1907:       /*
        !          1908:        * FORMAT_PARAMETERS are only present if they must be read,
        !          1909:        * so it makes no sense to check the ignore flag (besides,
        !          1910:        * the flags variable is not set for that particular type)
        !          1911:        */
        !          1912:       if ((parameters[i].type != FORMAT_PARAMETER) &&
        !          1913:          (parameters[i].flags & FLAGS_IGNORE))
        !          1914:        continue; /* for all arguments */
        !          1915: 
        !          1916:       /*
        !          1917:        * The stack arguments are read according to ANSI C89
        !          1918:        * default argument promotions:
        !          1919:        *
        !          1920:        *  char           = int
        !          1921:        *  short          = int
        !          1922:        *  unsigned char  = unsigned int
        !          1923:        *  unsigned short = unsigned int
        !          1924:        *  float          = double
        !          1925:        *
        !          1926:        * In addition to the ANSI C89 these types are read (the
        !          1927:        * default argument promotions of C99 has not been
        !          1928:        * considered yet)
        !          1929:        *
        !          1930:        *  long long
        !          1931:        *  long double
        !          1932:        *  size_t
        !          1933:        *  ptrdiff_t
        !          1934:        *  intmax_t
        !          1935:        */
        !          1936:       switch (parameters[i].type)
        !          1937:        {
        !          1938:        case FORMAT_GROUP:
        !          1939:        case FORMAT_STRING:
        !          1940: #if TRIO_WIDECHAR
        !          1941:          if (flags & FLAGS_WIDECHAR)
        !          1942:            {
        !          1943:              parameters[i].data.wstring = (argarray == NULL)
        !          1944:                ? va_arg(*arglist, trio_wchar_t *)
        !          1945:                : (trio_wchar_t *)(argarray[num]);
        !          1946:            }
        !          1947:          else
        !          1948: #endif
        !          1949:            {
        !          1950:              parameters[i].data.string = (argarray == NULL)
        !          1951:                ? va_arg(*arglist, char *)
        !          1952:                : (char *)(argarray[num]);
        !          1953:            }
        !          1954:          break;
        !          1955: 
        !          1956: #if defined(FORMAT_USER_DEFINED)
        !          1957:        case FORMAT_USER_DEFINED:
        !          1958: #endif
        !          1959:        case FORMAT_POINTER:
        !          1960:        case FORMAT_COUNT:
        !          1961:        case FORMAT_UNKNOWN:
        !          1962:          parameters[i].data.pointer = (argarray == NULL)
        !          1963:            ? va_arg(*arglist, trio_pointer_t )
        !          1964:            : argarray[num];
        !          1965:          break;
        !          1966: 
        !          1967:        case FORMAT_CHAR:
        !          1968:        case FORMAT_INT:
        !          1969:          if (TYPE_SCAN == type)
        !          1970:            {
        !          1971:               if (argarray == NULL)
        !          1972:                 parameters[i].data.pointer = 
        !          1973:                   (trio_pointer_t)va_arg(*arglist, trio_pointer_t);
        !          1974:               else
        !          1975:                 {
        !          1976:                   if (parameters[i].type == FORMAT_CHAR)
        !          1977:                     parameters[i].data.pointer =
        !          1978:                       (trio_pointer_t)((char *)argarray[num]);
        !          1979:                   else if (parameters[i].flags & FLAGS_SHORT)
        !          1980:                     parameters[i].data.pointer =
        !          1981:                       (trio_pointer_t)((short *)argarray[num]);
        !          1982:                   else
        !          1983:                     parameters[i].data.pointer =
        !          1984:                       (trio_pointer_t)((int *)argarray[num]);
        !          1985:                 }
        !          1986:            }
        !          1987:          else
        !          1988:            {
        !          1989: #if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
        !          1990:              if (parameters[i].flags
        !          1991:                  & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE))
        !          1992:                {
        !          1993:                  if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
        !          1994:                    {
        !          1995:                      /*
        !          1996:                       * Variable sizes are mapped onto the fixed sizes, in
        !          1997:                       * accordance with integer promotion.
        !          1998:                       *
        !          1999:                       * Please note that this may not be portable, as we
        !          2000:                       * only guess the size, not the layout of the numbers.
        !          2001:                       * For example, if int is little-endian, and long is
        !          2002:                       * big-endian, then this will fail.
        !          2003:                       */
        !          2004:                      varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
        !          2005:                    }
        !          2006:                  else
        !          2007:                    {
        !          2008:                      /* Used for the I<bits> modifiers */
        !          2009:                      varsize = parameters[i].varsize;
        !          2010:                    }
        !          2011:                  parameters[i].flags &= ~FLAGS_ALL_VARSIZES;
        !          2012:                  
        !          2013:                  if (varsize <= (int)sizeof(int))
        !          2014:                    ;
        !          2015:                  else if (varsize <= (int)sizeof(long))
        !          2016:                    parameters[i].flags |= FLAGS_LONG;
        !          2017: #if defined(QUALIFIER_INTMAX_T)
        !          2018:                  else if (varsize <= (int)sizeof(trio_longlong_t))
        !          2019:                    parameters[i].flags |= FLAGS_QUAD;
        !          2020:                  else
        !          2021:                    parameters[i].flags |= FLAGS_INTMAX_T;
        !          2022: #else
        !          2023:                  else
        !          2024:                    parameters[i].flags |= FLAGS_QUAD;
        !          2025: #endif
        !          2026:                }
        !          2027: #endif /* defined(QUALIFIER_VARSIZE) */
        !          2028: #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
        !          2029:              if (parameters[i].flags & FLAGS_SIZE_T)
        !          2030:                parameters[i].data.number.as_unsigned = (argarray == NULL)
        !          2031:                  ? (trio_uintmax_t)va_arg(*arglist, size_t)
        !          2032:                  : (trio_uintmax_t)(*((size_t *)argarray[num]));
        !          2033:              else
        !          2034: #endif
        !          2035: #if defined(QUALIFIER_PTRDIFF_T)
        !          2036:              if (parameters[i].flags & FLAGS_PTRDIFF_T)
        !          2037:                parameters[i].data.number.as_unsigned = (argarray == NULL)
        !          2038:                  ? (trio_uintmax_t)va_arg(*arglist, ptrdiff_t)
        !          2039:                  : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
        !          2040:              else
        !          2041: #endif
        !          2042: #if defined(QUALIFIER_INTMAX_T)
        !          2043:              if (parameters[i].flags & FLAGS_INTMAX_T)
        !          2044:                parameters[i].data.number.as_unsigned = (argarray == NULL)
        !          2045:                  ? (trio_uintmax_t)va_arg(*arglist, trio_intmax_t)
        !          2046:                  : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
        !          2047:              else
        !          2048: #endif
        !          2049:              if (parameters[i].flags & FLAGS_QUAD)
        !          2050:                parameters[i].data.number.as_unsigned = (argarray == NULL)
        !          2051:                  ? (trio_uintmax_t)va_arg(*arglist, trio_ulonglong_t)
        !          2052:                  : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
        !          2053:              else if (parameters[i].flags & FLAGS_LONG)
        !          2054:                parameters[i].data.number.as_unsigned = (argarray == NULL)
        !          2055:                  ? (trio_uintmax_t)va_arg(*arglist, long)
        !          2056:                  : (trio_uintmax_t)(*((long *)argarray[num]));
        !          2057:              else
        !          2058:                {
        !          2059:                  if (argarray == NULL)
        !          2060:                    parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(*arglist, int);
        !          2061:                  else
        !          2062:                    {
        !          2063:                      if (parameters[i].type == FORMAT_CHAR)
        !          2064:                        parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num]));
        !          2065:                      else if (parameters[i].flags & FLAGS_SHORT)
        !          2066:                        parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num]));
        !          2067:                      else
        !          2068:                        parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num]));
        !          2069:                    }
        !          2070:                }
        !          2071:            }
        !          2072:          break;
        !          2073: 
        !          2074:        case FORMAT_PARAMETER:
        !          2075:          /*
        !          2076:           * The parameter for the user-defined specifier is a pointer,
        !          2077:           * whereas the rest (width, precision, base) uses an integer.
        !          2078:           */
        !          2079:          if (parameters[i].flags & FLAGS_USER_DEFINED)
        !          2080:            parameters[i].data.pointer = (argarray == NULL)
        !          2081:              ? va_arg(*arglist, trio_pointer_t )
        !          2082:              : argarray[num];
        !          2083:          else
        !          2084:            parameters[i].data.number.as_unsigned = (argarray == NULL)
        !          2085:              ? (trio_uintmax_t)va_arg(*arglist, int)
        !          2086:              : (trio_uintmax_t)(*((int *)argarray[num]));
        !          2087:          break;
        !          2088: 
        !          2089:        case FORMAT_DOUBLE:
        !          2090:          if (TYPE_SCAN == type)
        !          2091:            {
        !          2092:              if (parameters[i].flags & FLAGS_LONGDOUBLE)
        !          2093:                parameters[i].data.longdoublePointer = (argarray == NULL)
        !          2094:                  ? va_arg(*arglist, trio_long_double_t *)
        !          2095:                  : (trio_long_double_t *)argarray[num];
        !          2096:              else
        !          2097:                 {
        !          2098:                  if (parameters[i].flags & FLAGS_LONG)
        !          2099:                    parameters[i].data.doublePointer = (argarray == NULL)
        !          2100:                      ? va_arg(*arglist, double *)
        !          2101:                      : (double *)argarray[num];
        !          2102:                  else
        !          2103:                    parameters[i].data.doublePointer = (argarray == NULL)
        !          2104:                      ? (double *)va_arg(*arglist, float *)
        !          2105:                      : (double *)((float *)argarray[num]);
        !          2106:                 }
        !          2107:            }
        !          2108:          else
        !          2109:            {
        !          2110:              if (parameters[i].flags & FLAGS_LONGDOUBLE)
        !          2111:                parameters[i].data.longdoubleNumber = (argarray == NULL)
        !          2112:                  ? va_arg(*arglist, trio_long_double_t)
        !          2113:                  : (trio_long_double_t)(*((trio_long_double_t *)argarray[num]));
        !          2114:              else
        !          2115:                {
        !          2116:                  if (argarray == NULL)
        !          2117:                    parameters[i].data.longdoubleNumber =
        !          2118:                      (trio_long_double_t)va_arg(*arglist, double);
        !          2119:                  else
        !          2120:                    {
        !          2121:                      if (parameters[i].flags & FLAGS_SHORT)
        !          2122:                        parameters[i].data.longdoubleNumber =
        !          2123:                          (trio_long_double_t)(*((float *)argarray[num]));
        !          2124:                      else
        !          2125:                        parameters[i].data.longdoubleNumber =
        !          2126:                          (trio_long_double_t)(*((double *)argarray[num]));
        !          2127:                    }
        !          2128:                }
        !          2129:            }
        !          2130:          break;
        !          2131: 
        !          2132: #if defined(FORMAT_ERRNO)
        !          2133:        case FORMAT_ERRNO:
        !          2134:          parameters[i].data.errorNumber = save_errno;
        !          2135:          break;
        !          2136: #endif
        !          2137: 
        !          2138:        default:
        !          2139:          break;
        !          2140:        }
        !          2141:     } /* for all specifiers */
        !          2142:   return num;
        !          2143: }
        !          2144: 
        !          2145: 
        !          2146: /*************************************************************************
        !          2147:  *
        !          2148:  * FORMATTING
        !          2149:  *
        !          2150:  ************************************************************************/
        !          2151: 
        !          2152: 
        !          2153: /*************************************************************************
        !          2154:  * TrioWriteNumber
        !          2155:  *
        !          2156:  * Description:
        !          2157:  *  Output a number.
        !          2158:  *  The complexity of this function is a result of the complexity
        !          2159:  *  of the dependencies of the flags.
        !          2160:  */
        !          2161: TRIO_PRIVATE void
        !          2162: TrioWriteNumber
        !          2163: TRIO_ARGS6((self, number, flags, width, precision, base),
        !          2164:           trio_class_t *self,
        !          2165:           trio_uintmax_t number,
        !          2166:           trio_flags_t flags,
        !          2167:           int width,
        !          2168:           int precision,
        !          2169:           int base)
        !          2170: {
        !          2171:   BOOLEAN_T isNegative;
        !          2172:   BOOLEAN_T isNumberZero;
        !          2173:   BOOLEAN_T isPrecisionZero;
        !          2174:   BOOLEAN_T ignoreNumber;
        !          2175:   char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
        !          2176:   char *bufferend;
        !          2177:   char *pointer;
        !          2178:   TRIO_CONST char *digits;
        !          2179:   int i;
        !          2180:   int length;
        !          2181:   char *p;
        !          2182:   int count;
        !          2183: 
        !          2184:   assert(VALID(self));
        !          2185:   assert(VALID(self->OutStream));
        !          2186:   assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
        !          2187: 
        !          2188:   digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
        !          2189:   if (base == NO_BASE)
        !          2190:     base = BASE_DECIMAL;
        !          2191: 
        !          2192:   isNumberZero = (number == 0);
        !          2193:   isPrecisionZero = (precision == 0);
        !          2194:   ignoreNumber = (isNumberZero
        !          2195:                  && isPrecisionZero
        !          2196:                  && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL)));
        !          2197: 
        !          2198:   if (flags & FLAGS_UNSIGNED)
        !          2199:     {
        !          2200:       isNegative = FALSE;
        !          2201:       flags &= ~FLAGS_SHOWSIGN;
        !          2202:     }
        !          2203:   else
        !          2204:     {
        !          2205:       isNegative = ((trio_intmax_t)number < 0);
        !          2206:       if (isNegative)
        !          2207:        number = -((trio_intmax_t)number);
        !          2208:     }
        !          2209: 
        !          2210:   if (flags & FLAGS_QUAD)
        !          2211:     number &= (trio_ulonglong_t)-1;
        !          2212:   else if (flags & FLAGS_LONG)
        !          2213:     number &= (unsigned long)-1;
        !          2214:   else
        !          2215:     number &= (unsigned int)-1;
        !          2216:   
        !          2217:   /* Build number */
        !          2218:   pointer = bufferend = &buffer[sizeof(buffer) - 1];
        !          2219:   *pointer-- = NIL;
        !          2220:   for (i = 1; i < (int)sizeof(buffer); i++)
        !          2221:     {
        !          2222:       *pointer-- = digits[number % base];
        !          2223:       number /= base;
        !          2224:       if (number == 0)
        !          2225:        break;
        !          2226: 
        !          2227:       if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
        !          2228:        {
        !          2229:          /*
        !          2230:           * We are building the number from the least significant
        !          2231:           * to the most significant digit, so we have to copy the
        !          2232:           * thousand separator backwards
        !          2233:           */
        !          2234:          length = internalThousandSeparatorLength;
        !          2235:          if (((int)(pointer - buffer) - length) > 0)
        !          2236:            {
        !          2237:              p = &internalThousandSeparator[length - 1];
        !          2238:              while (length-- > 0)
        !          2239:                *pointer-- = *p--;
        !          2240:            }
        !          2241:        }
        !          2242:     }
        !          2243: 
        !          2244:   if (! ignoreNumber)
        !          2245:     {
        !          2246:       /* Adjust width */
        !          2247:       width -= (bufferend - pointer) - 1;
        !          2248:     }
        !          2249: 
        !          2250:   /* Adjust precision */
        !          2251:   if (NO_PRECISION != precision)
        !          2252:     {
        !          2253:       precision -= (bufferend - pointer) - 1;
        !          2254:       if (precision < 0)
        !          2255:        precision = 0;
        !          2256:       flags |= FLAGS_NILPADDING;
        !          2257:     }
        !          2258: 
        !          2259:   /* Calculate padding */
        !          2260:   count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION)))
        !          2261:     ? precision
        !          2262:     : 0;
        !          2263:   
        !          2264:   /* Adjust width further */
        !          2265:   if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
        !          2266:     width--;
        !          2267:   if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
        !          2268:     {
        !          2269:       switch (base)
        !          2270:        {
        !          2271:        case BASE_BINARY:
        !          2272:        case BASE_HEX:
        !          2273:          width -= 2;
        !          2274:          break;
        !          2275:        case BASE_OCTAL:
        !          2276:          if (!(flags & FLAGS_NILPADDING) || (count == 0))
        !          2277:            width--;
        !          2278:          break;
        !          2279:        default:
        !          2280:          break;
        !          2281:        }
        !          2282:     }
        !          2283: 
        !          2284:   /* Output prefixes spaces if needed */
        !          2285:   if (! ((flags & FLAGS_LEFTADJUST) ||
        !          2286:         ((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION))))
        !          2287:     {
        !          2288:       while (width-- > count)
        !          2289:        self->OutStream(self, CHAR_ADJUST);
        !          2290:     }
        !          2291: 
        !          2292:   /* width has been adjusted for signs and alternatives */
        !          2293:   if (isNegative)
        !          2294:     self->OutStream(self, '-');
        !          2295:   else if (flags & FLAGS_SHOWSIGN)
        !          2296:     self->OutStream(self, '+');
        !          2297:   else if (flags & FLAGS_SPACE)
        !          2298:     self->OutStream(self, ' ');
        !          2299: 
        !          2300:   /* Prefix is not written when the value is zero */
        !          2301:   if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
        !          2302:     {
        !          2303:       switch (base)
        !          2304:        {
        !          2305:        case BASE_BINARY:
        !          2306:          self->OutStream(self, '0');
        !          2307:          self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b');
        !          2308:          break;
        !          2309: 
        !          2310:        case BASE_OCTAL:
        !          2311:          if (!(flags & FLAGS_NILPADDING) || (count == 0))
        !          2312:            self->OutStream(self, '0');
        !          2313:          break;
        !          2314: 
        !          2315:        case BASE_HEX:
        !          2316:          self->OutStream(self, '0');
        !          2317:          self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
        !          2318:          break;
        !          2319: 
        !          2320:        default:
        !          2321:          break;
        !          2322:        } /* switch base */
        !          2323:     }
        !          2324: 
        !          2325:   /* Output prefixed zero padding if needed */
        !          2326:   if (flags & FLAGS_NILPADDING)
        !          2327:     {
        !          2328:       if (precision == NO_PRECISION)
        !          2329:        precision = width;
        !          2330:       while (precision-- > 0)
        !          2331:        {
        !          2332:          self->OutStream(self, '0');
        !          2333:          width--;
        !          2334:        }
        !          2335:     }
        !          2336: 
        !          2337:   if (! ignoreNumber)
        !          2338:     {
        !          2339:       /* Output the number itself */
        !          2340:       while (*(++pointer))
        !          2341:        {
        !          2342:          self->OutStream(self, *pointer);
        !          2343:        }
        !          2344:     }
        !          2345: 
        !          2346:   /* Output trailing spaces if needed */
        !          2347:   if (flags & FLAGS_LEFTADJUST)
        !          2348:     {
        !          2349:       while (width-- > 0)
        !          2350:        self->OutStream(self, CHAR_ADJUST);
        !          2351:     }
        !          2352: }
        !          2353: 
        !          2354: /*************************************************************************
        !          2355:  * TrioWriteStringCharacter
        !          2356:  *
        !          2357:  * Description:
        !          2358:  *  Output a single character of a string
        !          2359:  */
        !          2360: TRIO_PRIVATE void
        !          2361: TrioWriteStringCharacter
        !          2362: TRIO_ARGS3((self, ch, flags),
        !          2363:           trio_class_t *self,
        !          2364:           int ch,
        !          2365:           trio_flags_t flags)
        !          2366: {
        !          2367:   if (flags & FLAGS_ALTERNATIVE)
        !          2368:     {
        !          2369:       if (! isprint(ch))
        !          2370:        {
        !          2371:          /*
        !          2372:           * Non-printable characters are converted to C escapes or
        !          2373:           * \number, if no C escape exists.
        !          2374:           */
        !          2375:          self->OutStream(self, CHAR_BACKSLASH);
        !          2376:          switch (ch)
        !          2377:            {
        !          2378:            case '\007': self->OutStream(self, 'a'); break;
        !          2379:            case '\b': self->OutStream(self, 'b'); break;
        !          2380:            case '\f': self->OutStream(self, 'f'); break;
        !          2381:            case '\n': self->OutStream(self, 'n'); break;
        !          2382:            case '\r': self->OutStream(self, 'r'); break;
        !          2383:            case '\t': self->OutStream(self, 't'); break;
        !          2384:            case '\v': self->OutStream(self, 'v'); break;
        !          2385:            case '\\': self->OutStream(self, '\\'); break;
        !          2386:            default:
        !          2387:              self->OutStream(self, 'x');
        !          2388:              TrioWriteNumber(self, (trio_uintmax_t)ch,
        !          2389:                              FLAGS_UNSIGNED | FLAGS_NILPADDING,
        !          2390:                              2, 2, BASE_HEX);
        !          2391:              break;
        !          2392:            }
        !          2393:        }
        !          2394:       else if (ch == CHAR_BACKSLASH)
        !          2395:        {
        !          2396:          self->OutStream(self, CHAR_BACKSLASH);
        !          2397:          self->OutStream(self, CHAR_BACKSLASH);
        !          2398:        }
        !          2399:       else
        !          2400:        {
        !          2401:          self->OutStream(self, ch);
        !          2402:        }
        !          2403:     }
        !          2404:   else
        !          2405:     {
        !          2406:       self->OutStream(self, ch);
        !          2407:     }
        !          2408: }
        !          2409: 
        !          2410: /*************************************************************************
        !          2411:  * TrioWriteString
        !          2412:  *
        !          2413:  * Description:
        !          2414:  *  Output a string
        !          2415:  */
        !          2416: TRIO_PRIVATE void
        !          2417: TrioWriteString
        !          2418: TRIO_ARGS5((self, string, flags, width, precision),
        !          2419:           trio_class_t *self,
        !          2420:           TRIO_CONST char *string,
        !          2421:           trio_flags_t flags,
        !          2422:           int width,
        !          2423:           int precision)
        !          2424: {
        !          2425:   int length;
        !          2426:   int ch;
        !          2427: 
        !          2428:   assert(VALID(self));
        !          2429:   assert(VALID(self->OutStream));
        !          2430: 
        !          2431:   if (string == NULL)
        !          2432:     {
        !          2433:       string = internalNullString;
        !          2434:       length = sizeof(internalNullString) - 1;
        !          2435:       /* Disable quoting for the null pointer */
        !          2436:       flags &= (~FLAGS_QUOTE);
        !          2437:       width = 0;
        !          2438:     }
        !          2439:   else
        !          2440:     {
        !          2441:       length = trio_length(string);
        !          2442:     }
        !          2443:   if ((NO_PRECISION != precision) &&
        !          2444:       (precision < length))
        !          2445:     {
        !          2446:       length = precision;
        !          2447:     }
        !          2448:   width -= length;
        !          2449: 
        !          2450:   if (flags & FLAGS_QUOTE)
        !          2451:     self->OutStream(self, CHAR_QUOTE);
        !          2452: 
        !          2453:   if (! (flags & FLAGS_LEFTADJUST))
        !          2454:     {
        !          2455:       while (width-- > 0)
        !          2456:        self->OutStream(self, CHAR_ADJUST);
        !          2457:     }
        !          2458: 
        !          2459:   while (length-- > 0)
        !          2460:     {
        !          2461:       /* The ctype parameters must be an unsigned char (or EOF) */
        !          2462:       ch = (int)((unsigned char)(*string++));
        !          2463:       TrioWriteStringCharacter(self, ch, flags);
        !          2464:     }
        !          2465: 
        !          2466:   if (flags & FLAGS_LEFTADJUST)
        !          2467:     {
        !          2468:       while (width-- > 0)
        !          2469:        self->OutStream(self, CHAR_ADJUST);
        !          2470:     }
        !          2471:   if (flags & FLAGS_QUOTE)
        !          2472:     self->OutStream(self, CHAR_QUOTE);
        !          2473: }
        !          2474: 
        !          2475: /*************************************************************************
        !          2476:  * TrioWriteWideStringCharacter
        !          2477:  *
        !          2478:  * Description:
        !          2479:  *  Output a wide string as a multi-byte sequence
        !          2480:  */
        !          2481: #if TRIO_WIDECHAR
        !          2482: TRIO_PRIVATE int
        !          2483: TrioWriteWideStringCharacter
        !          2484: TRIO_ARGS4((self, wch, flags, width),
        !          2485:           trio_class_t *self,
        !          2486:           trio_wchar_t wch,
        !          2487:           trio_flags_t flags,
        !          2488:           int width)
        !          2489: {
        !          2490:   int size;
        !          2491:   int i;
        !          2492:   int ch;
        !          2493:   char *string;
        !          2494:   char buffer[MB_LEN_MAX + 1];
        !          2495: 
        !          2496:   if (width == NO_WIDTH)
        !          2497:     width = sizeof(buffer);
        !          2498:   
        !          2499:   size = wctomb(buffer, wch);
        !          2500:   if ((size <= 0) || (size > width) || (buffer[0] == NIL))
        !          2501:     return 0;
        !          2502: 
        !          2503:   string = buffer;
        !          2504:   i = size;
        !          2505:   while ((width >= i) && (width-- > 0) && (i-- > 0))
        !          2506:     {
        !          2507:       /* The ctype parameters must be an unsigned char (or EOF) */
        !          2508:       ch = (int)((unsigned char)(*string++));
        !          2509:       TrioWriteStringCharacter(self, ch, flags);
        !          2510:     }
        !          2511:   return size;
        !          2512: }
        !          2513: #endif /* TRIO_WIDECHAR */
        !          2514: 
        !          2515: /*************************************************************************
        !          2516:  * TrioWriteWideString
        !          2517:  *
        !          2518:  * Description:
        !          2519:  *  Output a wide character string as a multi-byte string
        !          2520:  */
        !          2521: #if TRIO_WIDECHAR
        !          2522: TRIO_PRIVATE void
        !          2523: TrioWriteWideString
        !          2524: TRIO_ARGS5((self, wstring, flags, width, precision),
        !          2525:           trio_class_t *self,
        !          2526:           TRIO_CONST trio_wchar_t *wstring,
        !          2527:           trio_flags_t flags,
        !          2528:           int width,
        !          2529:           int precision)
        !          2530: {
        !          2531:   int length;
        !          2532:   int size;
        !          2533: 
        !          2534:   assert(VALID(self));
        !          2535:   assert(VALID(self->OutStream));
        !          2536: 
        !          2537: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          2538:   (void)mblen(NULL, 0);
        !          2539: #endif
        !          2540:   
        !          2541:   if (wstring == NULL)
        !          2542:     {
        !          2543:       TrioWriteString(self, NULL, flags, width, precision);
        !          2544:       return;
        !          2545:     }
        !          2546:   
        !          2547:   if (NO_PRECISION == precision)
        !          2548:     {
        !          2549:       length = INT_MAX;
        !          2550:     }
        !          2551:   else
        !          2552:     {
        !          2553:       length = precision;
        !          2554:       width -= length;
        !          2555:     }
        !          2556: 
        !          2557:   if (flags & FLAGS_QUOTE)
        !          2558:     self->OutStream(self, CHAR_QUOTE);
        !          2559: 
        !          2560:   if (! (flags & FLAGS_LEFTADJUST))
        !          2561:     {
        !          2562:       while (width-- > 0)
        !          2563:        self->OutStream(self, CHAR_ADJUST);
        !          2564:     }
        !          2565: 
        !          2566:   while (length > 0)
        !          2567:     {
        !          2568:       size = TrioWriteWideStringCharacter(self, *wstring++, flags, length);
        !          2569:       if (size == 0)
        !          2570:        break; /* while */
        !          2571:       length -= size;
        !          2572:     }
        !          2573: 
        !          2574:   if (flags & FLAGS_LEFTADJUST)
        !          2575:     {
        !          2576:       while (width-- > 0)
        !          2577:        self->OutStream(self, CHAR_ADJUST);
        !          2578:     }
        !          2579:   if (flags & FLAGS_QUOTE)
        !          2580:     self->OutStream(self, CHAR_QUOTE);
        !          2581: }
        !          2582: #endif /* TRIO_WIDECHAR */
        !          2583: 
        !          2584: /*************************************************************************
        !          2585:  * TrioWriteDouble
        !          2586:  *
        !          2587:  * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm
        !          2588:  *
        !          2589:  * "5.2.4.2.2 paragraph #4
        !          2590:  *
        !          2591:  *  The accuracy [...] is implementation defined, as is the accuracy
        !          2592:  *  of the conversion between floating-point internal representations
        !          2593:  *  and string representations performed by the libray routine in
        !          2594:  *  <stdio.h>"
        !          2595:  */
        !          2596: /* FIXME: handle all instances of constant long-double number (L)
        !          2597:  *   and *l() math functions.
        !          2598:  */
        !          2599: TRIO_PRIVATE void
        !          2600: TrioWriteDouble
        !          2601: TRIO_ARGS6((self, number, flags, width, precision, base),
        !          2602:           trio_class_t *self,
        !          2603:           trio_long_double_t number,
        !          2604:           trio_flags_t flags,
        !          2605:           int width,
        !          2606:           int precision,
        !          2607:           int base)
        !          2608: {
        !          2609:   trio_long_double_t integerNumber;
        !          2610:   trio_long_double_t fractionNumber;
        !          2611:   trio_long_double_t workNumber;
        !          2612:   int integerDigits;
        !          2613:   int fractionDigits;
        !          2614:   int exponentDigits;
        !          2615:   int baseDigits;
        !          2616:   int integerThreshold;
        !          2617:   int fractionThreshold;
        !          2618:   int expectedWidth;
        !          2619:   int exponent = 0;
        !          2620:   unsigned int uExponent = 0;
        !          2621:   int exponentBase;
        !          2622:   trio_long_double_t dblBase;
        !          2623:   trio_long_double_t dblIntegerBase;
        !          2624:   trio_long_double_t dblFractionBase;
        !          2625:   trio_long_double_t integerAdjust;
        !          2626:   trio_long_double_t fractionAdjust;
        !          2627:   BOOLEAN_T isNegative;
        !          2628:   BOOLEAN_T isExponentNegative = FALSE;
        !          2629:   BOOLEAN_T requireTwoDigitExponent;
        !          2630:   BOOLEAN_T isHex;
        !          2631:   TRIO_CONST char *digits;
        !          2632:   char *groupingPointer;
        !          2633:   int i;
        !          2634:   int index;
        !          2635:   BOOLEAN_T hasOnlyZeroes;
        !          2636:   int zeroes = 0;
        !          2637:   register int trailingZeroes;
        !          2638:   BOOLEAN_T keepTrailingZeroes;
        !          2639:   BOOLEAN_T keepDecimalPoint;
        !          2640:   trio_long_double_t epsilon;
        !          2641:   
        !          2642:   assert(VALID(self));
        !          2643:   assert(VALID(self->OutStream));
        !          2644:   assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
        !          2645: 
        !          2646:   /* Determine sign and look for special quantities */
        !          2647:   switch (trio_fpclassify_and_signbit(number, &isNegative))
        !          2648:     {
        !          2649:     case TRIO_FP_NAN:
        !          2650:       TrioWriteString(self,
        !          2651:                      (flags & FLAGS_UPPER)
        !          2652:                      ? NAN_UPPER
        !          2653:                      : NAN_LOWER,
        !          2654:                      flags, width, precision);
        !          2655:       return;
        !          2656:       
        !          2657:     case TRIO_FP_INFINITE:
        !          2658:       if (isNegative)
        !          2659:        {
        !          2660:          /* Negative infinity */
        !          2661:          TrioWriteString(self,
        !          2662:                          (flags & FLAGS_UPPER)
        !          2663:                          ? "-" INFINITE_UPPER
        !          2664:                          : "-" INFINITE_LOWER,
        !          2665:                          flags, width, precision);
        !          2666:          return;
        !          2667:        }
        !          2668:       else
        !          2669:        {
        !          2670:          /* Positive infinity */
        !          2671:          TrioWriteString(self,
        !          2672:                          (flags & FLAGS_UPPER)
        !          2673:                          ? INFINITE_UPPER
        !          2674:                          : INFINITE_LOWER,
        !          2675:                          flags, width, precision);
        !          2676:          return;
        !          2677:        }
        !          2678: 
        !          2679:     default:
        !          2680:       /* Finitude */
        !          2681:       break;
        !          2682:     }
        !          2683:   
        !          2684:   /* Normal numbers */
        !          2685:   if (flags & FLAGS_LONGDOUBLE)
        !          2686:     {
        !          2687:       baseDigits = (base == 10)
        !          2688:        ? LDBL_DIG
        !          2689:        : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
        !          2690:       epsilon = LDBL_EPSILON;
        !          2691:     }
        !          2692:   else if (flags & FLAGS_SHORT)
        !          2693:     {
        !          2694:       baseDigits = (base == BASE_DECIMAL)
        !          2695:        ? FLT_DIG
        !          2696:        : (int)floor(FLT_MANT_DIG / TrioLogarithmBase(base));
        !          2697:       epsilon = FLT_EPSILON;
        !          2698:     }
        !          2699:   else
        !          2700:     {
        !          2701:       baseDigits = (base == BASE_DECIMAL)
        !          2702:        ? DBL_DIG
        !          2703:        : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base));
        !          2704:       epsilon = DBL_EPSILON;
        !          2705:     }
        !          2706: 
        !          2707:   digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
        !          2708:   isHex = (base == BASE_HEX);
        !          2709:   if (base == NO_BASE)
        !          2710:     base = BASE_DECIMAL;
        !          2711:   dblBase = (trio_long_double_t)base;
        !          2712:   keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) ||
        !          2713:                          ( (flags & FLAGS_FLOAT_G) &&
        !          2714:                            !(flags & FLAGS_ALTERNATIVE) ) );
        !          2715: 
        !          2716:   if (flags & FLAGS_ROUNDING)
        !          2717:     precision = baseDigits;
        !          2718: 
        !          2719:   if (precision == NO_PRECISION)
        !          2720:     {
        !          2721:       if (isHex)
        !          2722:        {
        !          2723:          keepTrailingZeroes = FALSE;
        !          2724:          precision = FLT_MANT_DIG;
        !          2725:        }
        !          2726:       else
        !          2727:        {
        !          2728:          precision = FLT_DIG;
        !          2729:        }
        !          2730:     }
        !          2731:   
        !          2732:   if (isNegative)
        !          2733:     number = -number;
        !          2734: 
        !          2735:   if (isHex)
        !          2736:     flags |= FLAGS_FLOAT_E;
        !          2737:   
        !          2738:   if (flags & FLAGS_FLOAT_G)
        !          2739:     {
        !          2740:       if (precision == 0)
        !          2741:        precision = 1;
        !          2742: 
        !          2743:       if ((number < 1.0E-4) || (number > powl(base,
        !          2744:                                              (trio_long_double_t)precision)))
        !          2745:        {
        !          2746:          /* Use scientific notation */
        !          2747:          flags |= FLAGS_FLOAT_E;
        !          2748:        }
        !          2749:       else if (number < 1.0)
        !          2750:        {
        !          2751:          /*
        !          2752:           * Use normal notation. If the integer part of the number is
        !          2753:           * zero, then adjust the precision to include leading fractional
        !          2754:           * zeros.
        !          2755:           */
        !          2756:          workNumber = TrioLogarithm(number, base);
        !          2757:          workNumber = TRIO_FABS(workNumber);
        !          2758:          if (workNumber - floorl(workNumber) < 0.001)
        !          2759:            workNumber--;
        !          2760:          zeroes = (int)floorl(workNumber);
        !          2761:        }
        !          2762:     }
        !          2763: 
        !          2764:   if (flags & FLAGS_FLOAT_E)
        !          2765:     {
        !          2766:       /* Scale the number */
        !          2767:       workNumber = TrioLogarithm(number, base);
        !          2768:       if (trio_isinf(workNumber) == -1)
        !          2769:        {
        !          2770:          exponent = 0;
        !          2771:          /* Undo setting */
        !          2772:          if (flags & FLAGS_FLOAT_G)
        !          2773:            flags &= ~FLAGS_FLOAT_E;
        !          2774:        }
        !          2775:       else
        !          2776:        {
        !          2777:          exponent = (int)floorl(workNumber);
        !          2778:          number /= powl(dblBase, (trio_long_double_t)exponent);
        !          2779:          isExponentNegative = (exponent < 0);
        !          2780:          uExponent = (isExponentNegative) ? -exponent : exponent;
        !          2781:          if (isHex)
        !          2782:            uExponent *= 4; /* log16(2) */
        !          2783:          /* No thousand separators */
        !          2784:          flags &= ~FLAGS_QUOTE;
        !          2785:        }
        !          2786:     }
        !          2787: 
        !          2788:   integerNumber = floorl(number);
        !          2789:   fractionNumber = number - integerNumber;
        !          2790:   
        !          2791:   /*
        !          2792:    * Truncated number.
        !          2793:    *
        !          2794:    * Precision is number of significant digits for FLOAT_G
        !          2795:    * and number of fractional digits for others.
        !          2796:    */
        !          2797:   integerDigits = (integerNumber > epsilon)
        !          2798:     ? 1 + (int)TrioLogarithm(integerNumber, base)
        !          2799:     : 1;
        !          2800:   fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
        !          2801:     ? precision - integerDigits
        !          2802:     : zeroes + precision;
        !          2803: 
        !          2804:   dblFractionBase = TrioPower(base, fractionDigits);
        !          2805:   
        !          2806:   workNumber = number + 0.5 / dblFractionBase;
        !          2807:   if (floorl(number) != floorl(workNumber))
        !          2808:     {
        !          2809:       if (flags & FLAGS_FLOAT_E)
        !          2810:        {
        !          2811:          /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
        !          2812:          exponent++;
        !          2813:          isExponentNegative = (exponent < 0);
        !          2814:          uExponent = (isExponentNegative) ? -exponent : exponent;
        !          2815:          if (isHex)
        !          2816:            uExponent *= 4; /* log16(2) */
        !          2817:          workNumber = (number + 0.5 / dblFractionBase) / dblBase;
        !          2818:          integerNumber = floorl(workNumber);
        !          2819:          fractionNumber = workNumber - integerNumber;
        !          2820:        }
        !          2821:       else
        !          2822:        {
        !          2823:          /* Adjust if number was rounded up one digit (ie. 99 to 100) */
        !          2824:          integerNumber = floorl(number + 0.5);
        !          2825:          fractionNumber = 0.0;
        !          2826:          integerDigits = (integerNumber > epsilon)
        !          2827:            ? 1 + (int)TrioLogarithm(integerNumber, base)
        !          2828:            : 1;
        !          2829:        }
        !          2830:     }
        !          2831: 
        !          2832:   /* Estimate accuracy */
        !          2833:   integerAdjust = fractionAdjust = 0.5;
        !          2834:   if (flags & FLAGS_ROUNDING)
        !          2835:     {
        !          2836:       if (integerDigits > baseDigits)
        !          2837:        {
        !          2838:          integerThreshold = baseDigits;
        !          2839:          fractionDigits = 0;
        !          2840:          dblFractionBase = 1.0;
        !          2841:          fractionThreshold = 0;
        !          2842:          precision = 0; /* Disable decimal-point */
        !          2843:          integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1);
        !          2844:          fractionAdjust = 0.0;
        !          2845:        }
        !          2846:       else
        !          2847:        {
        !          2848:          integerThreshold = integerDigits;
        !          2849:          fractionThreshold = fractionDigits - integerThreshold;
        !          2850:          fractionAdjust = 1.0;
        !          2851:        }
        !          2852:     }
        !          2853:   else
        !          2854:     {
        !          2855:       integerThreshold = INT_MAX;
        !          2856:       fractionThreshold = INT_MAX;
        !          2857:     }
        !          2858:   
        !          2859:   /*
        !          2860:    * Calculate expected width.
        !          2861:    *  sign + integer part + thousands separators + decimal point
        !          2862:    *  + fraction + exponent
        !          2863:    */
        !          2864:   fractionAdjust /= dblFractionBase;
        !          2865:   hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon);
        !          2866:   keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) ||
        !          2867:                       !((precision == 0) ||
        !          2868:                         (!keepTrailingZeroes && hasOnlyZeroes)) );
        !          2869:   if (flags & FLAGS_FLOAT_E)
        !          2870:     {
        !          2871:       exponentDigits = (uExponent == 0)
        !          2872:        ? 1
        !          2873:        : (int)ceil(TrioLogarithm((double)(uExponent + 1),
        !          2874:                                  (isHex) ? 10.0 : base));
        !          2875:     }
        !          2876:   else
        !          2877:     exponentDigits = 0;
        !          2878:   requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1));
        !          2879: 
        !          2880:   expectedWidth = integerDigits + fractionDigits
        !          2881:     + (keepDecimalPoint
        !          2882:        ? internalDecimalPointLength
        !          2883:        : 0)
        !          2884:     + ((flags & FLAGS_QUOTE)
        !          2885:        ? TrioCalcThousandSeparatorLength(integerDigits)
        !          2886:        : 0);
        !          2887:   if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
        !          2888:     expectedWidth += sizeof("-") - 1;
        !          2889:   if (exponentDigits > 0)
        !          2890:     expectedWidth += exponentDigits +
        !          2891:       ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1);
        !          2892:   if (isHex)
        !          2893:     expectedWidth += sizeof("0X") - 1;
        !          2894:   
        !          2895:   /* Output prefixing */
        !          2896:   if (flags & FLAGS_NILPADDING)
        !          2897:     {
        !          2898:       /* Leading zeros must be after sign */
        !          2899:       if (isNegative)
        !          2900:        self->OutStream(self, '-');
        !          2901:       else if (flags & FLAGS_SHOWSIGN)
        !          2902:        self->OutStream(self, '+');
        !          2903:       else if (flags & FLAGS_SPACE)
        !          2904:        self->OutStream(self, ' ');
        !          2905:       if (isHex)
        !          2906:        {
        !          2907:          self->OutStream(self, '0');
        !          2908:          self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
        !          2909:        }
        !          2910:       if (!(flags & FLAGS_LEFTADJUST))
        !          2911:        {
        !          2912:          for (i = expectedWidth; i < width; i++)
        !          2913:            {
        !          2914:              self->OutStream(self, '0');
        !          2915:            }
        !          2916:        }
        !          2917:     }
        !          2918:   else
        !          2919:     {
        !          2920:       /* Leading spaces must be before sign */
        !          2921:       if (!(flags & FLAGS_LEFTADJUST))
        !          2922:        {
        !          2923:          for (i = expectedWidth; i < width; i++)
        !          2924:            {
        !          2925:              self->OutStream(self, CHAR_ADJUST);
        !          2926:            }
        !          2927:        }
        !          2928:       if (isNegative)
        !          2929:        self->OutStream(self, '-');
        !          2930:       else if (flags & FLAGS_SHOWSIGN)
        !          2931:        self->OutStream(self, '+');
        !          2932:       else if (flags & FLAGS_SPACE)
        !          2933:        self->OutStream(self, ' ');
        !          2934:       if (isHex)
        !          2935:        {
        !          2936:          self->OutStream(self, '0');
        !          2937:          self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
        !          2938:        }
        !          2939:     }
        !          2940:   
        !          2941:   /* Output the integer part and thousand separators */
        !          2942:   dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1);
        !          2943:   for (i = 0; i < integerDigits; i++)
        !          2944:     {
        !          2945:       workNumber = floorl(((integerNumber + integerAdjust) * dblIntegerBase));
        !          2946:       if (i > integerThreshold)
        !          2947:        {
        !          2948:          /* Beyond accuracy */
        !          2949:          self->OutStream(self, digits[0]);
        !          2950:        }
        !          2951:       else
        !          2952:        {
        !          2953:          self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]);
        !          2954:        }
        !          2955:       dblIntegerBase *= dblBase;
        !          2956:       
        !          2957:       if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
        !          2958:          && TrioFollowedBySeparator(integerDigits - i))
        !          2959:        {
        !          2960:          for (groupingPointer = internalThousandSeparator;
        !          2961:               *groupingPointer != NIL;
        !          2962:               groupingPointer++)
        !          2963:            {
        !          2964:              self->OutStream(self, *groupingPointer);
        !          2965:            }
        !          2966:        }
        !          2967:     }
        !          2968:   
        !          2969:   /* Insert decimal point and build the fraction part */
        !          2970:   trailingZeroes = 0;
        !          2971: 
        !          2972:   if (keepDecimalPoint)
        !          2973:     {
        !          2974:       if (internalDecimalPoint)
        !          2975:        {
        !          2976:          self->OutStream(self, internalDecimalPoint);
        !          2977:        }
        !          2978:       else
        !          2979:        {
        !          2980:          for (i = 0; i < internalDecimalPointLength; i++)
        !          2981:            {
        !          2982:              self->OutStream(self, internalDecimalPointString[i]);
        !          2983:            }
        !          2984:        }
        !          2985:     }
        !          2986: 
        !          2987:   for (i = 0; i < fractionDigits; i++)
        !          2988:     {
        !          2989:       if ((integerDigits > integerThreshold) || (i > fractionThreshold))
        !          2990:        {
        !          2991:          /* Beyond accuracy */
        !          2992:          trailingZeroes++;
        !          2993:        }
        !          2994:       else
        !          2995:        {
        !          2996:          fractionNumber *= dblBase;
        !          2997:          fractionAdjust *= dblBase;
        !          2998:          workNumber = floorl(fractionNumber + fractionAdjust);
        !          2999:          fractionNumber -= workNumber;
        !          3000:          index = (int)fmodl(workNumber, dblBase);
        !          3001:          if (index == 0)
        !          3002:            {
        !          3003:              trailingZeroes++;
        !          3004:            }
        !          3005:          else
        !          3006:            {
        !          3007:              while (trailingZeroes > 0)
        !          3008:                {
        !          3009:                  /* Not trailing zeroes after all */
        !          3010:                  self->OutStream(self, digits[0]);
        !          3011:                  trailingZeroes--;
        !          3012:                }
        !          3013:              self->OutStream(self, digits[index]);
        !          3014:            }
        !          3015:        }
        !          3016:     }
        !          3017:   
        !          3018:   if (keepTrailingZeroes)
        !          3019:     {
        !          3020:       while (trailingZeroes > 0)
        !          3021:        {
        !          3022:          self->OutStream(self, digits[0]);
        !          3023:          trailingZeroes--;
        !          3024:        }
        !          3025:     }
        !          3026:   
        !          3027:   /* Output exponent */
        !          3028:   if (exponentDigits > 0)
        !          3029:     {
        !          3030:       self->OutStream(self,
        !          3031:                      isHex
        !          3032:                      ? ((flags & FLAGS_UPPER) ? 'P' : 'p')
        !          3033:                      : ((flags & FLAGS_UPPER) ? 'E' : 'e'));
        !          3034:       self->OutStream(self, (isExponentNegative) ? '-' : '+');
        !          3035: 
        !          3036:       /* The exponent must contain at least two digits */
        !          3037:       if (requireTwoDigitExponent)
        !          3038:         self->OutStream(self, '0');
        !          3039: 
        !          3040:       if (isHex)
        !          3041:        base = 10.0;
        !          3042:       exponentBase = (int)TrioPower(base, exponentDigits - 1);
        !          3043:       for (i = 0; i < exponentDigits; i++)
        !          3044:        {
        !          3045:          self->OutStream(self, digits[(uExponent / exponentBase) % base]);
        !          3046:          exponentBase /= base;
        !          3047:        }
        !          3048:     }
        !          3049:   /* Output trailing spaces */
        !          3050:   if (flags & FLAGS_LEFTADJUST)
        !          3051:     {
        !          3052:       for (i = expectedWidth; i < width; i++)
        !          3053:        {
        !          3054:          self->OutStream(self, CHAR_ADJUST);
        !          3055:        }
        !          3056:     }
        !          3057: }
        !          3058: 
        !          3059: /*************************************************************************
        !          3060:  * TrioFormatProcess
        !          3061:  *
        !          3062:  * Description:
        !          3063:  *  This is the main engine for formatting output
        !          3064:  */
        !          3065: TRIO_PRIVATE int
        !          3066: TrioFormatProcess
        !          3067: TRIO_ARGS3((data, format, parameters),
        !          3068:           trio_class_t *data,
        !          3069:           TRIO_CONST char *format,
        !          3070:           trio_parameter_t *parameters)
        !          3071: {
        !          3072: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          3073:   int charlen;
        !          3074: #endif
        !          3075:   int i;
        !          3076:   TRIO_CONST char *string;
        !          3077:   trio_pointer_t pointer;
        !          3078:   trio_flags_t flags;
        !          3079:   int width;
        !          3080:   int precision;
        !          3081:   int base;
        !          3082:   int index;
        !          3083:   
        !          3084:   index = 0;
        !          3085:   i = 0;
        !          3086: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          3087:   (void)mblen(NULL, 0);
        !          3088: #endif
        !          3089:   
        !          3090:   while (format[index])
        !          3091:     {
        !          3092: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          3093:       if (! isascii(format[index]))
        !          3094:        {
        !          3095:          charlen = mblen(&format[index], MB_LEN_MAX);
        !          3096:          /*
        !          3097:           * Only valid multibyte characters are handled here. Invalid
        !          3098:           * multibyte characters (charlen == -1) are handled as normal
        !          3099:           * characters.
        !          3100:           */
        !          3101:          if (charlen != -1)
        !          3102:            {
        !          3103:              while (charlen-- > 0)
        !          3104:                {
        !          3105:                  data->OutStream(data, format[index++]);
        !          3106:                }
        !          3107:              continue; /* while characters left in formatting string */
        !          3108:            }
        !          3109:        }
        !          3110: #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
        !          3111:       if (CHAR_IDENTIFIER == format[index])
        !          3112:        {
        !          3113:          if (CHAR_IDENTIFIER == format[index + 1])
        !          3114:            {
        !          3115:              data->OutStream(data, CHAR_IDENTIFIER);
        !          3116:              index += 2;
        !          3117:            }
        !          3118:          else
        !          3119:            {
        !          3120:              /* Skip the parameter entries */
        !          3121:              while (parameters[i].type == FORMAT_PARAMETER)
        !          3122:                i++;
        !          3123:              
        !          3124:              flags = parameters[i].flags;
        !          3125: 
        !          3126:              /* Find width */
        !          3127:              width = parameters[i].width;
        !          3128:              if (flags & FLAGS_WIDTH_PARAMETER)
        !          3129:                {
        !          3130:                  /* Get width from parameter list */
        !          3131:                  width = (int)parameters[width].data.number.as_signed;
        !          3132:                  if (width < 0)
        !          3133:                    {
        !          3134:                      /*
        !          3135:                       * A negative width is the same as the - flag and
        !          3136:                       * a positive width.
        !          3137:                       */
        !          3138:                      flags |= FLAGS_LEFTADJUST;
        !          3139:                      flags &= ~FLAGS_NILPADDING;
        !          3140:                      width = -width;
        !          3141:                    }
        !          3142:                }
        !          3143:              
        !          3144:              /* Find precision */
        !          3145:              if (flags & FLAGS_PRECISION)
        !          3146:                {
        !          3147:                  precision = parameters[i].precision;
        !          3148:                  if (flags & FLAGS_PRECISION_PARAMETER)
        !          3149:                    {
        !          3150:                      /* Get precision from parameter list */
        !          3151:                      precision = (int)parameters[precision].data.number.as_signed;
        !          3152:                      if (precision < 0)
        !          3153:                        {
        !          3154:                          /*
        !          3155:                           * A negative precision is the same as no
        !          3156:                           * precision
        !          3157:                           */
        !          3158:                          precision = NO_PRECISION;
        !          3159:                        }
        !          3160:                    }
        !          3161:                }
        !          3162:              else
        !          3163:                {
        !          3164:                  precision = NO_PRECISION;
        !          3165:                }
        !          3166: 
        !          3167:              /* Find base */
        !          3168:              base = parameters[i].base;
        !          3169:              if (flags & FLAGS_BASE_PARAMETER)
        !          3170:                {
        !          3171:                  /* Get base from parameter list */
        !          3172:                  base = (int)parameters[base].data.number.as_signed;
        !          3173:                }
        !          3174:              
        !          3175:              switch (parameters[i].type)
        !          3176:                {
        !          3177:                case FORMAT_CHAR:
        !          3178:                  if (flags & FLAGS_QUOTE)
        !          3179:                    data->OutStream(data, CHAR_QUOTE);
        !          3180:                  if (! (flags & FLAGS_LEFTADJUST))
        !          3181:                    {
        !          3182:                      while (--width > 0)
        !          3183:                        data->OutStream(data, CHAR_ADJUST);
        !          3184:                    }
        !          3185: #if TRIO_WIDECHAR
        !          3186:                  if (flags & FLAGS_WIDECHAR)
        !          3187:                    {
        !          3188:                      TrioWriteWideStringCharacter(data,
        !          3189:                                                   (trio_wchar_t)parameters[i].data.number.as_signed,
        !          3190:                                                   flags,
        !          3191:                                                   NO_WIDTH);
        !          3192:                    }
        !          3193:                  else
        !          3194: #endif
        !          3195:                    {
        !          3196:                      TrioWriteStringCharacter(data,
        !          3197:                                               (int)parameters[i].data.number.as_signed,
        !          3198:                                               flags);
        !          3199:                    }
        !          3200: 
        !          3201:                  if (flags & FLAGS_LEFTADJUST)
        !          3202:                    {
        !          3203:                      while(--width > 0)
        !          3204:                        data->OutStream(data, CHAR_ADJUST);
        !          3205:                    }
        !          3206:                  if (flags & FLAGS_QUOTE)
        !          3207:                    data->OutStream(data, CHAR_QUOTE);
        !          3208: 
        !          3209:                  break; /* FORMAT_CHAR */
        !          3210: 
        !          3211:                case FORMAT_INT:
        !          3212:                  TrioWriteNumber(data,
        !          3213:                                  parameters[i].data.number.as_unsigned,
        !          3214:                                  flags,
        !          3215:                                  width,
        !          3216:                                  precision,
        !          3217:                                  base);
        !          3218: 
        !          3219:                  break; /* FORMAT_INT */
        !          3220: 
        !          3221:                case FORMAT_DOUBLE:
        !          3222:                  TrioWriteDouble(data,
        !          3223:                                  parameters[i].data.longdoubleNumber,
        !          3224:                                  flags,
        !          3225:                                  width,
        !          3226:                                  precision,
        !          3227:                                  base);
        !          3228:                  break; /* FORMAT_DOUBLE */
        !          3229: 
        !          3230:                case FORMAT_STRING:
        !          3231: #if TRIO_WIDECHAR
        !          3232:                  if (flags & FLAGS_WIDECHAR)
        !          3233:                    {
        !          3234:                      TrioWriteWideString(data,
        !          3235:                                          parameters[i].data.wstring,
        !          3236:                                          flags,
        !          3237:                                          width,
        !          3238:                                          precision);
        !          3239:                    }
        !          3240:                  else
        !          3241: #endif
        !          3242:                    {
        !          3243:                      TrioWriteString(data,
        !          3244:                                      parameters[i].data.string,
        !          3245:                                      flags,
        !          3246:                                      width,
        !          3247:                                      precision);
        !          3248:                    }
        !          3249:                  break; /* FORMAT_STRING */
        !          3250: 
        !          3251:                case FORMAT_POINTER:
        !          3252:                  {
        !          3253:                    trio_reference_t reference;
        !          3254:                    
        !          3255:                    reference.data = data;
        !          3256:                    reference.parameter = &parameters[i];
        !          3257:                    trio_print_pointer(&reference, parameters[i].data.pointer);
        !          3258:                  }
        !          3259:                  break; /* FORMAT_POINTER */
        !          3260: 
        !          3261:                case FORMAT_COUNT:
        !          3262:                  pointer = parameters[i].data.pointer;
        !          3263:                  if (NULL != pointer)
        !          3264:                    {
        !          3265:                      /*
        !          3266:                       * C99 paragraph 7.19.6.1.8 says "the number of
        !          3267:                       * characters written to the output stream so far by
        !          3268:                       * this call", which is data->committed
        !          3269:                       */
        !          3270: #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
        !          3271:                      if (flags & FLAGS_SIZE_T)
        !          3272:                        *(size_t *)pointer = (size_t)data->committed;
        !          3273:                      else
        !          3274: #endif
        !          3275: #if defined(QUALIFIER_PTRDIFF_T)
        !          3276:                      if (flags & FLAGS_PTRDIFF_T)
        !          3277:                        *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed;
        !          3278:                      else
        !          3279: #endif
        !          3280: #if defined(QUALIFIER_INTMAX_T)
        !          3281:                      if (flags & FLAGS_INTMAX_T)
        !          3282:                        *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
        !          3283:                      else
        !          3284: #endif
        !          3285:                      if (flags & FLAGS_QUAD)
        !          3286:                        {
        !          3287:                          *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
        !          3288:                        }
        !          3289:                      else if (flags & FLAGS_LONG)
        !          3290:                        {
        !          3291:                          *(long int *)pointer = (long int)data->committed;
        !          3292:                        }
        !          3293:                      else if (flags & FLAGS_SHORT)
        !          3294:                        {
        !          3295:                          *(short int *)pointer = (short int)data->committed;
        !          3296:                        }
        !          3297:                      else
        !          3298:                        {
        !          3299:                          *(int *)pointer = (int)data->committed;
        !          3300:                        }
        !          3301:                    }
        !          3302:                  break; /* FORMAT_COUNT */
        !          3303: 
        !          3304:                case FORMAT_PARAMETER:
        !          3305:                  break; /* FORMAT_PARAMETER */
        !          3306: 
        !          3307: #if defined(FORMAT_ERRNO)
        !          3308:                case FORMAT_ERRNO:
        !          3309:                  string = trio_error(parameters[i].data.errorNumber);
        !          3310:                  if (string)
        !          3311:                    {
        !          3312:                      TrioWriteString(data,
        !          3313:                                      string,
        !          3314:                                      flags,
        !          3315:                                      width,
        !          3316:                                      precision);
        !          3317:                    }
        !          3318:                  else
        !          3319:                    {
        !          3320:                      data->OutStream(data, '#');
        !          3321:                      TrioWriteNumber(data,
        !          3322:                                      (trio_uintmax_t)parameters[i].data.errorNumber,
        !          3323:                                      flags,
        !          3324:                                      width,
        !          3325:                                      precision,
        !          3326:                                      BASE_DECIMAL);
        !          3327:                    }
        !          3328:                  break; /* FORMAT_ERRNO */
        !          3329: #endif /* defined(FORMAT_ERRNO) */
        !          3330: 
        !          3331: #if defined(FORMAT_USER_DEFINED)
        !          3332:                case FORMAT_USER_DEFINED:
        !          3333:                  {
        !          3334:                    trio_reference_t reference;
        !          3335:                    trio_userdef_t *def = NULL;
        !          3336: 
        !          3337:                    if (parameters[i].user_name[0] == NIL)
        !          3338:                      {
        !          3339:                        /* Use handle */
        !          3340:                        if ((i > 0) ||
        !          3341:                            (parameters[i - 1].type == FORMAT_PARAMETER))
        !          3342:                          def = (trio_userdef_t *)parameters[i - 1].data.pointer;
        !          3343:                      }
        !          3344:                    else
        !          3345:                      {
        !          3346:                        /* Look up namespace */
        !          3347:                        def = TrioFindNamespace(parameters[i].user_name, NULL);
        !          3348:                      }
        !          3349:                    if (def) {
        !          3350:                      reference.data = data;
        !          3351:                      reference.parameter = &parameters[i];
        !          3352:                      def->callback(&reference);
        !          3353:                    }
        !          3354:                  }
        !          3355:                  break;
        !          3356: #endif /* defined(FORMAT_USER_DEFINED) */
        !          3357:                  
        !          3358:                default:
        !          3359:                  break;
        !          3360:                } /* switch parameter type */
        !          3361: 
        !          3362:              /* Prepare for next */
        !          3363:              index = parameters[i].indexAfterSpecifier;
        !          3364:              i++;
        !          3365:            }
        !          3366:        }
        !          3367:       else /* not identifier */
        !          3368:        {
        !          3369:          data->OutStream(data, format[index++]);
        !          3370:        }
        !          3371:     }
        !          3372:   return data->processed;
        !          3373: }
        !          3374: 
        !          3375: /*************************************************************************
        !          3376:  * TrioFormatRef
        !          3377:  */
        !          3378: TRIO_PRIVATE int
        !          3379: TrioFormatRef
        !          3380: TRIO_ARGS4((reference, format, arglist, argarray),
        !          3381:           trio_reference_t *reference,
        !          3382:           TRIO_CONST char *format,
        !          3383:           va_list *arglist,
        !          3384:           trio_pointer_t *argarray)
        !          3385: {
        !          3386:   int status;
        !          3387:   trio_parameter_t parameters[MAX_PARAMETERS];
        !          3388: 
        !          3389:   status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
        !          3390:   if (status < 0)
        !          3391:     return status;
        !          3392: 
        !          3393:   status = TrioFormatProcess(reference->data, format, parameters);
        !          3394:   if (reference->data->error != 0)
        !          3395:     {
        !          3396:       status = reference->data->error;
        !          3397:     }
        !          3398:   return status;
        !          3399: }
        !          3400: 
        !          3401: /*************************************************************************
        !          3402:  * TrioFormat
        !          3403:  */
        !          3404: TRIO_PRIVATE int
        !          3405: TrioFormat
        !          3406: TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
        !          3407:           trio_pointer_t destination,
        !          3408:           size_t destinationSize,
        !          3409:           void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
        !          3410:           TRIO_CONST char *format,
        !          3411:           va_list *arglist,
        !          3412:           trio_pointer_t *argarray)
        !          3413: {
        !          3414:   int status;
        !          3415:   trio_class_t data;
        !          3416:   trio_parameter_t parameters[MAX_PARAMETERS];
        !          3417: 
        !          3418:   assert(VALID(OutStream));
        !          3419:   assert(VALID(format));
        !          3420: 
        !          3421:   memset(&data, 0, sizeof(data));
        !          3422:   data.OutStream = OutStream;
        !          3423:   data.location = destination;
        !          3424:   data.max = destinationSize;
        !          3425:   data.error = 0;
        !          3426: 
        !          3427: #if defined(USE_LOCALE)
        !          3428:   if (NULL == internalLocaleValues)
        !          3429:     {
        !          3430:       TrioSetLocale();
        !          3431:     }
        !          3432: #endif
        !          3433: 
        !          3434:   status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
        !          3435:   if (status < 0)
        !          3436:     return status;
        !          3437: 
        !          3438:   status = TrioFormatProcess(&data, format, parameters);
        !          3439:   if (data.error != 0)
        !          3440:     {
        !          3441:       status = data.error;
        !          3442:     }
        !          3443:   return status;
        !          3444: }
        !          3445: 
        !          3446: /*************************************************************************
        !          3447:  * TrioOutStreamFile
        !          3448:  */
        !          3449: TRIO_PRIVATE void
        !          3450: TrioOutStreamFile
        !          3451: TRIO_ARGS2((self, output),
        !          3452:           trio_class_t *self,
        !          3453:           int output)
        !          3454: {
        !          3455:   FILE *file;
        !          3456: 
        !          3457:   assert(VALID(self));
        !          3458:   assert(VALID(self->location));
        !          3459: 
        !          3460:   file = (FILE *)self->location;
        !          3461:   self->processed++;
        !          3462:   if (fputc(output, file) == EOF)
        !          3463:     {
        !          3464:       self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0);
        !          3465:     }
        !          3466:   else
        !          3467:     {
        !          3468:       self->committed++;
        !          3469:     }
        !          3470: }
        !          3471: 
        !          3472: /*************************************************************************
        !          3473:  * TrioOutStreamFileDescriptor
        !          3474:  */
        !          3475: TRIO_PRIVATE void
        !          3476: TrioOutStreamFileDescriptor
        !          3477: TRIO_ARGS2((self, output),
        !          3478:           trio_class_t *self,
        !          3479:           int output)
        !          3480: {
        !          3481:   int fd;
        !          3482:   char ch;
        !          3483: 
        !          3484:   assert(VALID(self));
        !          3485: 
        !          3486:   fd = *((int *)self->location);
        !          3487:   ch = (char)output;
        !          3488:   self->processed++;
        !          3489:   if (write(fd, &ch, sizeof(char)) == -1)
        !          3490:     {
        !          3491:       self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
        !          3492:     }
        !          3493:   else
        !          3494:     {
        !          3495:       self->committed++;
        !          3496:     }
        !          3497: }
        !          3498: 
        !          3499: /*************************************************************************
        !          3500:  * TrioOutStreamCustom
        !          3501:  */
        !          3502: TRIO_PRIVATE void
        !          3503: TrioOutStreamCustom
        !          3504: TRIO_ARGS2((self, output),
        !          3505:           trio_class_t *self,
        !          3506:           int output)
        !          3507: {
        !          3508:   int status;
        !          3509:   trio_custom_t *data;
        !          3510: 
        !          3511:   assert(VALID(self));
        !          3512:   assert(VALID(self->location));
        !          3513: 
        !          3514:   data = (trio_custom_t *)self->location;
        !          3515:   if (data->stream.out)
        !          3516:     {
        !          3517:       status = (data->stream.out)(data->closure, output);
        !          3518:       if (status >= 0)
        !          3519:        {
        !          3520:          self->committed++;
        !          3521:        }
        !          3522:       else
        !          3523:        {
        !          3524:          if (self->error == 0)
        !          3525:            {
        !          3526:              self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status);
        !          3527:            }
        !          3528:        }
        !          3529:     }
        !          3530:   self->processed++;
        !          3531: }
        !          3532: 
        !          3533: /*************************************************************************
        !          3534:  * TrioOutStreamString
        !          3535:  */
        !          3536: TRIO_PRIVATE void
        !          3537: TrioOutStreamString
        !          3538: TRIO_ARGS2((self, output),
        !          3539:           trio_class_t *self,
        !          3540:           int output)
        !          3541: {
        !          3542:   char **buffer;
        !          3543: 
        !          3544:   assert(VALID(self));
        !          3545:   assert(VALID(self->location));
        !          3546: 
        !          3547:   buffer = (char **)self->location;
        !          3548:   **buffer = (char)output;
        !          3549:   (*buffer)++;
        !          3550:   self->processed++;
        !          3551:   self->committed++;
        !          3552: }
        !          3553: 
        !          3554: /*************************************************************************
        !          3555:  * TrioOutStreamStringMax
        !          3556:  */
        !          3557: TRIO_PRIVATE void
        !          3558: TrioOutStreamStringMax
        !          3559: TRIO_ARGS2((self, output),
        !          3560:           trio_class_t *self,
        !          3561:           int output)
        !          3562: {
        !          3563:   char **buffer;
        !          3564: 
        !          3565:   assert(VALID(self));
        !          3566:   assert(VALID(self->location));
        !          3567:   
        !          3568:   buffer = (char **)self->location;
        !          3569: 
        !          3570:   if (self->processed < self->max)
        !          3571:     {
        !          3572:       **buffer = (char)output;
        !          3573:       (*buffer)++;
        !          3574:       self->committed++;
        !          3575:     }
        !          3576:   self->processed++;
        !          3577: }
        !          3578: 
        !          3579: /*************************************************************************
        !          3580:  * TrioOutStreamStringDynamic
        !          3581:  */
        !          3582: TRIO_PRIVATE void
        !          3583: TrioOutStreamStringDynamic
        !          3584: TRIO_ARGS2((self, output),
        !          3585:           trio_class_t *self,
        !          3586:           int output)
        !          3587: {
        !          3588:   assert(VALID(self));
        !          3589:   assert(VALID(self->location));
        !          3590: 
        !          3591:   if (self->error == 0)
        !          3592:     {
        !          3593:       trio_xstring_append_char((trio_string_t *)self->location,
        !          3594:                               (char)output);
        !          3595:       self->committed++;
        !          3596:     }
        !          3597:   /* The processed variable must always be increased */
        !          3598:   self->processed++;
        !          3599: }
        !          3600: 
        !          3601: /*************************************************************************
        !          3602:  *
        !          3603:  * Formatted printing functions
        !          3604:  *
        !          3605:  ************************************************************************/
        !          3606: 
        !          3607: #if defined(TRIO_DOCUMENTATION)
        !          3608: # include "doc/doc_printf.h"
        !          3609: #endif
        !          3610: /** @addtogroup Printf
        !          3611:     @{
        !          3612: */
        !          3613: 
        !          3614: /*************************************************************************
        !          3615:  * printf
        !          3616:  */
        !          3617: 
        !          3618: /**
        !          3619:    Print to standard output stream.
        !          3620: 
        !          3621:    @param format Formatting string.
        !          3622:    @param ... Arguments.
        !          3623:    @return Number of printed characters.
        !          3624:  */
        !          3625: TRIO_PUBLIC int
        !          3626: trio_printf
        !          3627: TRIO_VARGS2((format, va_alist),
        !          3628:            TRIO_CONST char *format,
        !          3629:            TRIO_VA_DECL)
        !          3630: {
        !          3631:   int status;
        !          3632:   va_list args;
        !          3633: 
        !          3634:   assert(VALID(format));
        !          3635:   
        !          3636:   TRIO_VA_START(args, format);
        !          3637:   status = TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
        !          3638:   TRIO_VA_END(args);
        !          3639:   return status;
        !          3640: }
        !          3641: 
        !          3642: /**
        !          3643:    Print to standard output stream.
        !          3644: 
        !          3645:    @param format Formatting string.
        !          3646:    @param args Arguments.
        !          3647:    @return Number of printed characters.
        !          3648:  */
        !          3649: TRIO_PUBLIC int
        !          3650: trio_vprintf
        !          3651: TRIO_ARGS2((format, args),
        !          3652:           TRIO_CONST char *format,
        !          3653:           va_list args)
        !          3654: {
        !          3655:   assert(VALID(format));
        !          3656: 
        !          3657:   return TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
        !          3658: }
        !          3659: 
        !          3660: /**
        !          3661:    Print to standard output stream.
        !          3662: 
        !          3663:    @param format Formatting string.
        !          3664:    @param args Arguments.
        !          3665:    @return Number of printed characters.
        !          3666:  */
        !          3667: TRIO_PUBLIC int
        !          3668: trio_printfv
        !          3669: TRIO_ARGS2((format, args),
        !          3670:           TRIO_CONST char *format,
        !          3671:           trio_pointer_t * args)
        !          3672: {
        !          3673:   assert(VALID(format));
        !          3674: 
        !          3675:   return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
        !          3676: }
        !          3677: 
        !          3678: /*************************************************************************
        !          3679:  * fprintf
        !          3680:  */
        !          3681: 
        !          3682: /**
        !          3683:    Print to file.
        !          3684: 
        !          3685:    @param file File pointer.
        !          3686:    @param format Formatting string.
        !          3687:    @param ... Arguments.
        !          3688:    @return Number of printed characters.
        !          3689:  */
        !          3690: TRIO_PUBLIC int
        !          3691: trio_fprintf
        !          3692: TRIO_VARGS3((file, format, va_alist),
        !          3693:            FILE *file,
        !          3694:            TRIO_CONST char *format,
        !          3695:            TRIO_VA_DECL)
        !          3696: {
        !          3697:   int status;
        !          3698:   va_list args;
        !          3699: 
        !          3700:   assert(VALID(file));
        !          3701:   assert(VALID(format));
        !          3702:   
        !          3703:   TRIO_VA_START(args, format);
        !          3704:   status = TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
        !          3705:   TRIO_VA_END(args);
        !          3706:   return status;
        !          3707: }
        !          3708: 
        !          3709: /**
        !          3710:    Print to file.
        !          3711: 
        !          3712:    @param file File pointer.
        !          3713:    @param format Formatting string.
        !          3714:    @param args Arguments.
        !          3715:    @return Number of printed characters.
        !          3716:  */
        !          3717: TRIO_PUBLIC int
        !          3718: trio_vfprintf
        !          3719: TRIO_ARGS3((file, format, args),
        !          3720:           FILE *file,
        !          3721:           TRIO_CONST char *format,
        !          3722:           va_list args)
        !          3723: {
        !          3724:   assert(VALID(file));
        !          3725:   assert(VALID(format));
        !          3726:   
        !          3727:   return TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
        !          3728: }
        !          3729: 
        !          3730: /**
        !          3731:    Print to file.
        !          3732: 
        !          3733:    @param file File pointer.
        !          3734:    @param format Formatting string.
        !          3735:    @param args Arguments.
        !          3736:    @return Number of printed characters.
        !          3737:  */
        !          3738: TRIO_PUBLIC int
        !          3739: trio_fprintfv
        !          3740: TRIO_ARGS3((file, format, args),
        !          3741:           FILE *file,
        !          3742:           TRIO_CONST char *format,
        !          3743:           trio_pointer_t * args)
        !          3744: {
        !          3745:   assert(VALID(file));
        !          3746:   assert(VALID(format));
        !          3747:   
        !          3748:   return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
        !          3749: }
        !          3750: 
        !          3751: /*************************************************************************
        !          3752:  * dprintf
        !          3753:  */
        !          3754: 
        !          3755: /**
        !          3756:    Print to file descriptor.
        !          3757: 
        !          3758:    @param fd File descriptor.
        !          3759:    @param format Formatting string.
        !          3760:    @param ... Arguments.
        !          3761:    @return Number of printed characters.
        !          3762:  */
        !          3763: TRIO_PUBLIC int
        !          3764: trio_dprintf
        !          3765: TRIO_VARGS3((fd, format, va_alist),
        !          3766:            int fd,
        !          3767:            TRIO_CONST char *format,
        !          3768:            TRIO_VA_DECL)
        !          3769: {
        !          3770:   int status;
        !          3771:   va_list args;
        !          3772: 
        !          3773:   assert(VALID(format));
        !          3774:   
        !          3775:   TRIO_VA_START(args, format);
        !          3776:   status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
        !          3777:   TRIO_VA_END(args);
        !          3778:   return status;
        !          3779: }
        !          3780: 
        !          3781: /**
        !          3782:    Print to file descriptor.
        !          3783: 
        !          3784:    @param fd File descriptor.
        !          3785:    @param format Formatting string.
        !          3786:    @param args Arguments.
        !          3787:    @return Number of printed characters.
        !          3788:  */
        !          3789: TRIO_PUBLIC int
        !          3790: trio_vdprintf
        !          3791: TRIO_ARGS3((fd, format, args),
        !          3792:           int fd,
        !          3793:           TRIO_CONST char *format,
        !          3794:           va_list args)
        !          3795: {
        !          3796:   assert(VALID(format));
        !          3797:   
        !          3798:   return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
        !          3799: }
        !          3800: 
        !          3801: /**
        !          3802:    Print to file descriptor.
        !          3803: 
        !          3804:    @param fd File descriptor.
        !          3805:    @param format Formatting string.
        !          3806:    @param args Arguments.
        !          3807:    @return Number of printed characters.
        !          3808:  */
        !          3809: TRIO_PUBLIC int
        !          3810: trio_dprintfv
        !          3811: TRIO_ARGS3((fd, format, args),
        !          3812:           int fd,
        !          3813:           TRIO_CONST char *format,
        !          3814:           trio_pointer_t *args)
        !          3815: {
        !          3816:   assert(VALID(format));
        !          3817:   
        !          3818:   return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
        !          3819: }
        !          3820: 
        !          3821: /*************************************************************************
        !          3822:  * cprintf
        !          3823:  */
        !          3824: TRIO_PUBLIC int
        !          3825: trio_cprintf
        !          3826: TRIO_VARGS4((stream, closure, format, va_alist),
        !          3827:            trio_outstream_t stream,
        !          3828:            trio_pointer_t closure,
        !          3829:            TRIO_CONST char *format,
        !          3830:            TRIO_VA_DECL)
        !          3831: {
        !          3832:   int status;
        !          3833:   va_list args;
        !          3834:   trio_custom_t data;
        !          3835: 
        !          3836:   assert(VALID(stream));
        !          3837:   assert(VALID(format));
        !          3838: 
        !          3839:   TRIO_VA_START(args, format);
        !          3840:   data.stream.out = stream;
        !          3841:   data.closure = closure;
        !          3842:   status = TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
        !          3843:   TRIO_VA_END(args);
        !          3844:   return status;
        !          3845: }
        !          3846: 
        !          3847: TRIO_PUBLIC int
        !          3848: trio_vcprintf
        !          3849: TRIO_ARGS4((stream, closure, format, args),
        !          3850:           trio_outstream_t stream,
        !          3851:           trio_pointer_t closure,
        !          3852:           TRIO_CONST char *format,
        !          3853:           va_list args)
        !          3854: {
        !          3855:   trio_custom_t data;
        !          3856: 
        !          3857:   assert(VALID(stream));
        !          3858:   assert(VALID(format));
        !          3859: 
        !          3860:   data.stream.out = stream;
        !          3861:   data.closure = closure;
        !          3862:   return TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
        !          3863: }
        !          3864: 
        !          3865: TRIO_PUBLIC int
        !          3866: trio_cprintfv
        !          3867: TRIO_ARGS4((stream, closure, format, args),
        !          3868:           trio_outstream_t stream,
        !          3869:           trio_pointer_t closure,
        !          3870:           TRIO_CONST char *format,
        !          3871:           void **args)
        !          3872: {
        !          3873:   trio_custom_t data;
        !          3874: 
        !          3875:   assert(VALID(stream));
        !          3876:   assert(VALID(format));
        !          3877: 
        !          3878:   data.stream.out = stream;
        !          3879:   data.closure = closure;
        !          3880:   return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args);
        !          3881: }
        !          3882: 
        !          3883: /*************************************************************************
        !          3884:  * sprintf
        !          3885:  */
        !          3886: 
        !          3887: /**
        !          3888:    Print to string.
        !          3889: 
        !          3890:    @param buffer Output string.
        !          3891:    @param format Formatting string.
        !          3892:    @param ... Arguments.
        !          3893:    @return Number of printed characters.
        !          3894:  */
        !          3895: TRIO_PUBLIC int
        !          3896: trio_sprintf
        !          3897: TRIO_VARGS3((buffer, format, va_alist),
        !          3898:            char *buffer,
        !          3899:            TRIO_CONST char *format,
        !          3900:            TRIO_VA_DECL)
        !          3901: {
        !          3902:   int status;
        !          3903:   va_list args;
        !          3904: 
        !          3905:   assert(VALID(buffer));
        !          3906:   assert(VALID(format));
        !          3907:   
        !          3908:   TRIO_VA_START(args, format);
        !          3909:   status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
        !          3910:   *buffer = NIL; /* Terminate with NIL character */
        !          3911:   TRIO_VA_END(args);
        !          3912:   return status;
        !          3913: }
        !          3914: 
        !          3915: /**
        !          3916:    Print to string.
        !          3917: 
        !          3918:    @param buffer Output string.
        !          3919:    @param format Formatting string.
        !          3920:    @param args Arguments.
        !          3921:    @return Number of printed characters.
        !          3922:  */
        !          3923: TRIO_PUBLIC int
        !          3924: trio_vsprintf
        !          3925: TRIO_ARGS3((buffer, format, args),
        !          3926:           char *buffer,
        !          3927:           TRIO_CONST char *format,
        !          3928:           va_list args)
        !          3929: {
        !          3930:   int status;
        !          3931: 
        !          3932:   assert(VALID(buffer));
        !          3933:   assert(VALID(format));
        !          3934: 
        !          3935:   status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
        !          3936:   *buffer = NIL;
        !          3937:   return status;
        !          3938: }
        !          3939: 
        !          3940: /**
        !          3941:    Print to string.
        !          3942: 
        !          3943:    @param buffer Output string.
        !          3944:    @param format Formatting string.
        !          3945:    @param args Arguments.
        !          3946:    @return Number of printed characters.
        !          3947:  */
        !          3948: TRIO_PUBLIC int
        !          3949: trio_sprintfv
        !          3950: TRIO_ARGS3((buffer, format, args),
        !          3951:           char *buffer,
        !          3952:           TRIO_CONST char *format,
        !          3953:           trio_pointer_t *args)
        !          3954: {
        !          3955:   int status;
        !          3956: 
        !          3957:   assert(VALID(buffer));
        !          3958:   assert(VALID(format));
        !          3959: 
        !          3960:   status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
        !          3961:   *buffer = NIL;
        !          3962:   return status;
        !          3963: }
        !          3964: 
        !          3965: /*************************************************************************
        !          3966:  * snprintf
        !          3967:  */
        !          3968: 
        !          3969: /**
        !          3970:    Print at most @p max characters to string.
        !          3971: 
        !          3972:    @param buffer Output string.
        !          3973:    @param max Maximum number of characters to print.
        !          3974:    @param format Formatting string.
        !          3975:    @param ... Arguments.
        !          3976:    @return Number of printed characters.
        !          3977:  */
        !          3978: TRIO_PUBLIC int
        !          3979: trio_snprintf
        !          3980: TRIO_VARGS4((buffer, max, format, va_alist),
        !          3981:            char *buffer,
        !          3982:            size_t max,
        !          3983:            TRIO_CONST char *format,
        !          3984:            TRIO_VA_DECL)
        !          3985: {
        !          3986:   int status;
        !          3987:   va_list args;
        !          3988: 
        !          3989:   assert(VALID(buffer));
        !          3990:   assert(VALID(format));
        !          3991: 
        !          3992:   TRIO_VA_START(args, format);
        !          3993:   status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
        !          3994:                      TrioOutStreamStringMax, format, &args, NULL);
        !          3995:   if (max > 0)
        !          3996:     *buffer = NIL;
        !          3997:   TRIO_VA_END(args);
        !          3998:   return status;
        !          3999: }
        !          4000: 
        !          4001: /**
        !          4002:    Print at most @p max characters to string.
        !          4003: 
        !          4004:    @param buffer Output string.
        !          4005:    @param max Maximum number of characters to print.
        !          4006:    @param format Formatting string.
        !          4007:    @param args Arguments.
        !          4008:    @return Number of printed characters.
        !          4009:  */
        !          4010: TRIO_PUBLIC int
        !          4011: trio_vsnprintf
        !          4012: TRIO_ARGS4((buffer, max, format, args),
        !          4013:           char *buffer,
        !          4014:           size_t max,
        !          4015:           TRIO_CONST char *format,
        !          4016:           va_list args)
        !          4017: {
        !          4018:   int status;
        !          4019: 
        !          4020:   assert(VALID(buffer));
        !          4021:   assert(VALID(format));
        !          4022: 
        !          4023:   status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
        !          4024:                      TrioOutStreamStringMax, format, &args, NULL);
        !          4025:   if (max > 0)
        !          4026:     *buffer = NIL;
        !          4027:   return status;
        !          4028: }
        !          4029: 
        !          4030: /**
        !          4031:    Print at most @p max characters to string.
        !          4032: 
        !          4033:    @param buffer Output string.
        !          4034:    @param max Maximum number of characters to print.
        !          4035:    @param format Formatting string.
        !          4036:    @param args Arguments.
        !          4037:    @return Number of printed characters.
        !          4038:  */
        !          4039: TRIO_PUBLIC int
        !          4040: trio_snprintfv
        !          4041: TRIO_ARGS4((buffer, max, format, args),
        !          4042:           char *buffer,
        !          4043:           size_t max,
        !          4044:           TRIO_CONST char *format,
        !          4045:           trio_pointer_t *args)
        !          4046: {
        !          4047:   int status;
        !          4048: 
        !          4049:   assert(VALID(buffer));
        !          4050:   assert(VALID(format));
        !          4051: 
        !          4052:   status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
        !          4053:                      TrioOutStreamStringMax, format, NULL, args);
        !          4054:   if (max > 0)
        !          4055:     *buffer = NIL;
        !          4056:   return status;
        !          4057: }
        !          4058: 
        !          4059: /*************************************************************************
        !          4060:  * snprintfcat
        !          4061:  * Appends the new string to the buffer string overwriting the '\0'
        !          4062:  * character at the end of buffer.
        !          4063:  */
        !          4064: TRIO_PUBLIC int
        !          4065: trio_snprintfcat
        !          4066: TRIO_VARGS4((buffer, max, format, va_alist),
        !          4067:            char *buffer,
        !          4068:            size_t max,
        !          4069:            TRIO_CONST char *format,
        !          4070:            TRIO_VA_DECL)
        !          4071: {
        !          4072:   int status;
        !          4073:   va_list args;
        !          4074:   size_t buf_len;
        !          4075: 
        !          4076:   TRIO_VA_START(args, format);
        !          4077: 
        !          4078:   assert(VALID(buffer));
        !          4079:   assert(VALID(format));
        !          4080: 
        !          4081:   buf_len = trio_length(buffer);
        !          4082:   buffer = &buffer[buf_len];
        !          4083: 
        !          4084:   status = TrioFormat(&buffer, max - 1 - buf_len,
        !          4085:                      TrioOutStreamStringMax, format, &args, NULL);
        !          4086:   TRIO_VA_END(args);
        !          4087:   *buffer = NIL;
        !          4088:   return status;
        !          4089: }
        !          4090: 
        !          4091: TRIO_PUBLIC int
        !          4092: trio_vsnprintfcat
        !          4093: TRIO_ARGS4((buffer, max, format, args),
        !          4094:           char *buffer,
        !          4095:           size_t max,
        !          4096:           TRIO_CONST char *format,
        !          4097:           va_list args)
        !          4098: {
        !          4099:   int status;
        !          4100:   size_t buf_len;
        !          4101:   
        !          4102:   assert(VALID(buffer));
        !          4103:   assert(VALID(format));
        !          4104: 
        !          4105:   buf_len = trio_length(buffer);
        !          4106:   buffer = &buffer[buf_len];
        !          4107:   status = TrioFormat(&buffer, max - 1 - buf_len,
        !          4108:                      TrioOutStreamStringMax, format, &args, NULL);
        !          4109:   *buffer = NIL;
        !          4110:   return status;
        !          4111: }
        !          4112: 
        !          4113: /*************************************************************************
        !          4114:  * trio_aprintf
        !          4115:  */
        !          4116: 
        !          4117: /* Deprecated */
        !          4118: TRIO_PUBLIC char *
        !          4119: trio_aprintf
        !          4120: TRIO_VARGS2((format, va_alist),
        !          4121:            TRIO_CONST char *format,
        !          4122:            TRIO_VA_DECL)
        !          4123: {
        !          4124:   va_list args;
        !          4125:   trio_string_t *info;
        !          4126:   char *result = NULL;
        !          4127: 
        !          4128:   assert(VALID(format));
        !          4129:   
        !          4130:   info = trio_xstring_duplicate("");
        !          4131:   if (info)
        !          4132:     {
        !          4133:       TRIO_VA_START(args, format);
        !          4134:       (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
        !          4135:                       format, &args, NULL);
        !          4136:       TRIO_VA_END(args);
        !          4137: 
        !          4138:       trio_string_terminate(info);
        !          4139:       result = trio_string_extract(info);
        !          4140:       trio_string_destroy(info);
        !          4141:     }
        !          4142:   return result;
        !          4143: }
        !          4144: 
        !          4145: /* Deprecated */
        !          4146: TRIO_PUBLIC char *
        !          4147: trio_vaprintf
        !          4148: TRIO_ARGS2((format, args),
        !          4149:           TRIO_CONST char *format,
        !          4150:           va_list args)
        !          4151: {
        !          4152:   trio_string_t *info;
        !          4153:   char *result = NULL;
        !          4154:   
        !          4155:   assert(VALID(format));
        !          4156:   
        !          4157:   info = trio_xstring_duplicate("");
        !          4158:   if (info)
        !          4159:     {
        !          4160:       (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
        !          4161:                       format, &args, NULL);
        !          4162:       trio_string_terminate(info);
        !          4163:       result = trio_string_extract(info);
        !          4164:       trio_string_destroy(info);
        !          4165:     }
        !          4166:   return result;
        !          4167: }
        !          4168: 
        !          4169: TRIO_PUBLIC int
        !          4170: trio_asprintf
        !          4171: TRIO_VARGS3((result, format, va_alist),
        !          4172:            char **result,
        !          4173:            TRIO_CONST char *format,
        !          4174:            TRIO_VA_DECL)
        !          4175: {
        !          4176:   va_list args;
        !          4177:   int status;
        !          4178:   trio_string_t *info;
        !          4179: 
        !          4180:   assert(VALID(format));
        !          4181: 
        !          4182:   *result = NULL;
        !          4183:   
        !          4184:   info = trio_xstring_duplicate("");
        !          4185:   if (info == NULL)
        !          4186:     {
        !          4187:       status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
        !          4188:     }
        !          4189:   else
        !          4190:     {
        !          4191:       TRIO_VA_START(args, format);
        !          4192:       status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
        !          4193:                          format, &args, NULL);
        !          4194:       TRIO_VA_END(args);
        !          4195:       if (status >= 0)
        !          4196:        {
        !          4197:          trio_string_terminate(info);
        !          4198:          *result = trio_string_extract(info);
        !          4199:        }
        !          4200:       trio_string_destroy(info);
        !          4201:     }
        !          4202:   return status;
        !          4203: }
        !          4204: 
        !          4205: TRIO_PUBLIC int
        !          4206: trio_vasprintf
        !          4207: TRIO_ARGS3((result, format, args),
        !          4208:           char **result,
        !          4209:           TRIO_CONST char *format,
        !          4210:           va_list args)
        !          4211: {
        !          4212:   int status;
        !          4213:   trio_string_t *info;
        !          4214:   
        !          4215:   assert(VALID(format));
        !          4216: 
        !          4217:   *result = NULL;
        !          4218:   
        !          4219:   info = trio_xstring_duplicate("");
        !          4220:   if (info == NULL)
        !          4221:     {
        !          4222:       status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
        !          4223:     }
        !          4224:   else
        !          4225:     {
        !          4226:       status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
        !          4227:                          format, &args, NULL);
        !          4228:       if (status >= 0)
        !          4229:        {
        !          4230:          trio_string_terminate(info);
        !          4231:          *result = trio_string_extract(info);
        !          4232:        }
        !          4233:       trio_string_destroy(info);
        !          4234:     }
        !          4235:   return status;
        !          4236: }
        !          4237: 
        !          4238: /** @} End of Printf documentation module */
        !          4239: 
        !          4240: /*************************************************************************
        !          4241:  *
        !          4242:  * CALLBACK
        !          4243:  *
        !          4244:  ************************************************************************/
        !          4245: 
        !          4246: #if defined(TRIO_DOCUMENTATION)
        !          4247: # include "doc/doc_register.h"
        !          4248: #endif
        !          4249: /**
        !          4250:    @addtogroup UserDefined
        !          4251:    @{
        !          4252: */
        !          4253: 
        !          4254: #if TRIO_EXTENSION
        !          4255: 
        !          4256: /*************************************************************************
        !          4257:  * trio_register
        !          4258:  */
        !          4259: 
        !          4260: /**
        !          4261:    Register new user-defined specifier.
        !          4262: 
        !          4263:    @param callback
        !          4264:    @param name
        !          4265:    @return Handle.
        !          4266:  */
        !          4267: TRIO_PUBLIC trio_pointer_t 
        !          4268: trio_register
        !          4269: TRIO_ARGS2((callback, name),
        !          4270:           trio_callback_t callback,
        !          4271:           TRIO_CONST char *name)
        !          4272: {
        !          4273:   trio_userdef_t *def;
        !          4274:   trio_userdef_t *prev = NULL;
        !          4275: 
        !          4276:   if (callback == NULL)
        !          4277:     return NULL;
        !          4278: 
        !          4279:   if (name)
        !          4280:     {
        !          4281:       /* Handle built-in namespaces */
        !          4282:       if (name[0] == ':')
        !          4283:        {
        !          4284:          if (trio_equal(name, ":enter"))
        !          4285:            {
        !          4286:              internalEnterCriticalRegion = callback;
        !          4287:            }
        !          4288:          else if (trio_equal(name, ":leave"))
        !          4289:            {
        !          4290:              internalLeaveCriticalRegion = callback;
        !          4291:            }
        !          4292:          return NULL;
        !          4293:        }
        !          4294:       
        !          4295:       /* Bail out if namespace is too long */
        !          4296:       if (trio_length(name) >= MAX_USER_NAME)
        !          4297:        return NULL;
        !          4298:       
        !          4299:       /* Bail out if namespace already is registered */
        !          4300:       def = TrioFindNamespace(name, &prev);
        !          4301:       if (def)
        !          4302:        return NULL;
        !          4303:     }
        !          4304:   
        !          4305:   def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t));
        !          4306:   if (def)
        !          4307:     {
        !          4308:       if (internalEnterCriticalRegion)
        !          4309:        (void)internalEnterCriticalRegion(NULL);
        !          4310:       
        !          4311:       if (name)
        !          4312:        {
        !          4313:          /* Link into internal list */
        !          4314:          if (prev == NULL)
        !          4315:            internalUserDef = def;
        !          4316:          else
        !          4317:            prev->next = def;
        !          4318:        }
        !          4319:       /* Initialize */
        !          4320:       def->callback = callback;
        !          4321:       def->name = (name == NULL)
        !          4322:        ? NULL
        !          4323:        : trio_duplicate(name);
        !          4324:       def->next = NULL;
        !          4325: 
        !          4326:       if (internalLeaveCriticalRegion)
        !          4327:        (void)internalLeaveCriticalRegion(NULL);
        !          4328:     }
        !          4329:   return (trio_pointer_t)def;
        !          4330: }
        !          4331: 
        !          4332: /**
        !          4333:    Unregister an existing user-defined specifier.
        !          4334: 
        !          4335:    @param handle
        !          4336:  */
        !          4337: void
        !          4338: trio_unregister
        !          4339: TRIO_ARGS1((handle),
        !          4340:           trio_pointer_t handle)
        !          4341: {
        !          4342:   trio_userdef_t *self = (trio_userdef_t *)handle;
        !          4343:   trio_userdef_t *def;
        !          4344:   trio_userdef_t *prev = NULL;
        !          4345: 
        !          4346:   assert(VALID(self));
        !          4347: 
        !          4348:   if (self->name)
        !          4349:     {
        !          4350:       def = TrioFindNamespace(self->name, &prev);
        !          4351:       if (def)
        !          4352:        {
        !          4353:          if (internalEnterCriticalRegion)
        !          4354:            (void)internalEnterCriticalRegion(NULL);
        !          4355:          
        !          4356:          if (prev == NULL)
        !          4357:            internalUserDef = NULL;
        !          4358:          else
        !          4359:            prev->next = def->next;
        !          4360:          
        !          4361:          if (internalLeaveCriticalRegion)
        !          4362:            (void)internalLeaveCriticalRegion(NULL);
        !          4363:        }
        !          4364:       trio_destroy(self->name);
        !          4365:     }
        !          4366:   TRIO_FREE(self);
        !          4367: }
        !          4368: 
        !          4369: /*************************************************************************
        !          4370:  * trio_get_format [public]
        !          4371:  */
        !          4372: TRIO_CONST char *
        !          4373: trio_get_format
        !          4374: TRIO_ARGS1((ref),
        !          4375:           trio_pointer_t ref)
        !          4376: {
        !          4377: #if defined(FORMAT_USER_DEFINED)
        !          4378:   assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
        !          4379: #endif
        !          4380:   
        !          4381:   return (((trio_reference_t *)ref)->parameter->user_data);
        !          4382: }
        !          4383: 
        !          4384: /*************************************************************************
        !          4385:  * trio_get_argument [public]
        !          4386:  */
        !          4387: trio_pointer_t 
        !          4388: trio_get_argument
        !          4389: TRIO_ARGS1((ref),
        !          4390:           trio_pointer_t ref)
        !          4391: {
        !          4392: #if defined(FORMAT_USER_DEFINED)
        !          4393:   assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
        !          4394: #endif
        !          4395:   
        !          4396:   return ((trio_reference_t *)ref)->parameter->data.pointer;
        !          4397: }
        !          4398: 
        !          4399: /*************************************************************************
        !          4400:  * trio_get_width / trio_set_width [public]
        !          4401:  */
        !          4402: int
        !          4403: trio_get_width
        !          4404: TRIO_ARGS1((ref),
        !          4405:           trio_pointer_t ref)
        !          4406: {
        !          4407:   return ((trio_reference_t *)ref)->parameter->width;
        !          4408: }
        !          4409: 
        !          4410: void
        !          4411: trio_set_width
        !          4412: TRIO_ARGS2((ref, width),
        !          4413:           trio_pointer_t ref,
        !          4414:           int width)
        !          4415: {
        !          4416:   ((trio_reference_t *)ref)->parameter->width = width;
        !          4417: }
        !          4418: 
        !          4419: /*************************************************************************
        !          4420:  * trio_get_precision / trio_set_precision [public]
        !          4421:  */
        !          4422: int
        !          4423: trio_get_precision
        !          4424: TRIO_ARGS1((ref),
        !          4425:           trio_pointer_t ref)
        !          4426: {
        !          4427:   return (((trio_reference_t *)ref)->parameter->precision);
        !          4428: }
        !          4429: 
        !          4430: void
        !          4431: trio_set_precision
        !          4432: TRIO_ARGS2((ref, precision),
        !          4433:           trio_pointer_t ref,
        !          4434:           int precision)
        !          4435: {
        !          4436:   ((trio_reference_t *)ref)->parameter->precision = precision;
        !          4437: }
        !          4438: 
        !          4439: /*************************************************************************
        !          4440:  * trio_get_base / trio_set_base [public]
        !          4441:  */
        !          4442: int
        !          4443: trio_get_base
        !          4444: TRIO_ARGS1((ref),
        !          4445:           trio_pointer_t ref)
        !          4446: {
        !          4447:   return (((trio_reference_t *)ref)->parameter->base);
        !          4448: }
        !          4449: 
        !          4450: void
        !          4451: trio_set_base
        !          4452: TRIO_ARGS2((ref, base),
        !          4453:           trio_pointer_t ref,
        !          4454:           int base)
        !          4455: {
        !          4456:   ((trio_reference_t *)ref)->parameter->base = base;
        !          4457: }
        !          4458: 
        !          4459: /*************************************************************************
        !          4460:  * trio_get_long / trio_set_long [public]
        !          4461:  */
        !          4462: int
        !          4463: trio_get_long
        !          4464: TRIO_ARGS1((ref),
        !          4465:           trio_pointer_t ref)
        !          4466: {
        !          4467:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG)
        !          4468:     ? TRUE
        !          4469:     : FALSE;
        !          4470: }
        !          4471: 
        !          4472: void
        !          4473: trio_set_long
        !          4474: TRIO_ARGS2((ref, is_long),
        !          4475:           trio_pointer_t ref,
        !          4476:           int is_long)
        !          4477: {
        !          4478:   if (is_long)
        !          4479:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG;
        !          4480:   else
        !          4481:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG;
        !          4482: }
        !          4483: 
        !          4484: /*************************************************************************
        !          4485:  * trio_get_longlong / trio_set_longlong [public]
        !          4486:  */
        !          4487: int
        !          4488: trio_get_longlong
        !          4489: TRIO_ARGS1((ref),
        !          4490:           trio_pointer_t ref)
        !          4491: {
        !          4492:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD)
        !          4493:     ? TRUE
        !          4494:     : FALSE;
        !          4495: }
        !          4496: 
        !          4497: void
        !          4498: trio_set_longlong
        !          4499: TRIO_ARGS2((ref, is_longlong),
        !          4500:           trio_pointer_t ref,
        !          4501:           int is_longlong)
        !          4502: {
        !          4503:   if (is_longlong)
        !          4504:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD;
        !          4505:   else
        !          4506:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD;
        !          4507: }
        !          4508: 
        !          4509: /*************************************************************************
        !          4510:  * trio_get_longdouble / trio_set_longdouble [public]
        !          4511:  */
        !          4512: int
        !          4513: trio_get_longdouble
        !          4514: TRIO_ARGS1((ref),
        !          4515:           trio_pointer_t ref)
        !          4516: {
        !          4517:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE)
        !          4518:     ? TRUE
        !          4519:     : FALSE;
        !          4520: }
        !          4521: 
        !          4522: void
        !          4523: trio_set_longdouble
        !          4524: TRIO_ARGS2((ref, is_longdouble),
        !          4525:           trio_pointer_t ref,
        !          4526:           int is_longdouble)
        !          4527: {
        !          4528:   if (is_longdouble)
        !          4529:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE;
        !          4530:   else
        !          4531:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE;
        !          4532: }
        !          4533: 
        !          4534: /*************************************************************************
        !          4535:  * trio_get_short / trio_set_short [public]
        !          4536:  */
        !          4537: int
        !          4538: trio_get_short
        !          4539: TRIO_ARGS1((ref),
        !          4540:           trio_pointer_t ref)
        !          4541: {
        !          4542:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT)
        !          4543:     ? TRUE
        !          4544:     : FALSE;
        !          4545: }
        !          4546: 
        !          4547: void
        !          4548: trio_set_short
        !          4549: TRIO_ARGS2((ref, is_short),
        !          4550:           trio_pointer_t ref,
        !          4551:           int is_short)
        !          4552: {
        !          4553:   if (is_short)
        !          4554:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT;
        !          4555:   else
        !          4556:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT;
        !          4557: }
        !          4558: 
        !          4559: /*************************************************************************
        !          4560:  * trio_get_shortshort / trio_set_shortshort [public]
        !          4561:  */
        !          4562: int
        !          4563: trio_get_shortshort
        !          4564: TRIO_ARGS1((ref),
        !          4565:           trio_pointer_t ref)
        !          4566: {
        !          4567:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT)
        !          4568:     ? TRUE
        !          4569:     : FALSE;
        !          4570: }
        !          4571: 
        !          4572: void
        !          4573: trio_set_shortshort
        !          4574: TRIO_ARGS2((ref, is_shortshort),
        !          4575:           trio_pointer_t ref,
        !          4576:           int is_shortshort)
        !          4577: {
        !          4578:   if (is_shortshort)
        !          4579:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT;
        !          4580:   else
        !          4581:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT;
        !          4582: }
        !          4583: 
        !          4584: /*************************************************************************
        !          4585:  * trio_get_alternative / trio_set_alternative [public]
        !          4586:  */
        !          4587: int
        !          4588: trio_get_alternative
        !          4589: TRIO_ARGS1((ref),
        !          4590:           trio_pointer_t ref)
        !          4591: {
        !          4592:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE)
        !          4593:     ? TRUE
        !          4594:     : FALSE;
        !          4595: }
        !          4596: 
        !          4597: void
        !          4598: trio_set_alternative
        !          4599: TRIO_ARGS2((ref, is_alternative),
        !          4600:           trio_pointer_t ref,
        !          4601:           int is_alternative)
        !          4602: {
        !          4603:   if (is_alternative)
        !          4604:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE;
        !          4605:   else
        !          4606:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE;
        !          4607: }
        !          4608: 
        !          4609: /*************************************************************************
        !          4610:  * trio_get_alignment / trio_set_alignment [public]
        !          4611:  */
        !          4612: int
        !          4613: trio_get_alignment
        !          4614: TRIO_ARGS1((ref),
        !          4615:           trio_pointer_t ref)
        !          4616: {
        !          4617:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST)
        !          4618:     ? TRUE
        !          4619:     : FALSE;
        !          4620: }
        !          4621: 
        !          4622: void
        !          4623: trio_set_alignment
        !          4624: TRIO_ARGS2((ref, is_leftaligned),
        !          4625:           trio_pointer_t ref,
        !          4626:           int is_leftaligned)
        !          4627: {
        !          4628:   if (is_leftaligned)
        !          4629:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST;
        !          4630:   else
        !          4631:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST;
        !          4632: }
        !          4633: 
        !          4634: /*************************************************************************
        !          4635:  * trio_get_spacing /trio_set_spacing [public]
        !          4636:  */
        !          4637: int
        !          4638: trio_get_spacing
        !          4639: TRIO_ARGS1((ref),
        !          4640:           trio_pointer_t ref)
        !          4641: {
        !          4642:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE)
        !          4643:     ? TRUE
        !          4644:     : FALSE;
        !          4645: }
        !          4646: 
        !          4647: void
        !          4648: trio_set_spacing
        !          4649: TRIO_ARGS2((ref, is_space),
        !          4650:           trio_pointer_t ref,
        !          4651:           int is_space)
        !          4652: {
        !          4653:   if (is_space)
        !          4654:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE;
        !          4655:   else
        !          4656:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE;
        !          4657: }
        !          4658: 
        !          4659: /*************************************************************************
        !          4660:  * trio_get_sign / trio_set_sign [public]
        !          4661:  */
        !          4662: int
        !          4663: trio_get_sign
        !          4664: TRIO_ARGS1((ref),
        !          4665:           trio_pointer_t ref)
        !          4666: {
        !          4667:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN)
        !          4668:     ? TRUE
        !          4669:     : FALSE;
        !          4670: }
        !          4671: 
        !          4672: void
        !          4673: trio_set_sign
        !          4674: TRIO_ARGS2((ref, is_sign),
        !          4675:           trio_pointer_t ref,
        !          4676:           int is_sign)
        !          4677: {
        !          4678:   if (is_sign)
        !          4679:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN;
        !          4680:   else
        !          4681:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN;
        !          4682: }
        !          4683: 
        !          4684: /*************************************************************************
        !          4685:  * trio_get_padding / trio_set_padding [public]
        !          4686:  */
        !          4687: int
        !          4688: trio_get_padding
        !          4689: TRIO_ARGS1((ref),
        !          4690:           trio_pointer_t ref)
        !          4691: {
        !          4692:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING)
        !          4693:     ? TRUE
        !          4694:     : FALSE;
        !          4695: }
        !          4696: 
        !          4697: void
        !          4698: trio_set_padding
        !          4699: TRIO_ARGS2((ref, is_padding),
        !          4700:           trio_pointer_t ref,
        !          4701:           int is_padding)
        !          4702: {
        !          4703:   if (is_padding)
        !          4704:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING;
        !          4705:   else
        !          4706:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING;
        !          4707: }
        !          4708: 
        !          4709: /*************************************************************************
        !          4710:  * trio_get_quote / trio_set_quote [public]
        !          4711:  */
        !          4712: int
        !          4713: trio_get_quote
        !          4714: TRIO_ARGS1((ref),
        !          4715:           trio_pointer_t ref)
        !          4716: {
        !          4717:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE)
        !          4718:     ? TRUE
        !          4719:     : FALSE;
        !          4720: }
        !          4721: 
        !          4722: void
        !          4723: trio_set_quote
        !          4724: TRIO_ARGS2((ref, is_quote),
        !          4725:           trio_pointer_t ref,
        !          4726:           int is_quote)
        !          4727: {
        !          4728:   if (is_quote)
        !          4729:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE;
        !          4730:   else
        !          4731:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE;
        !          4732: }
        !          4733: 
        !          4734: /*************************************************************************
        !          4735:  * trio_get_upper / trio_set_upper [public]
        !          4736:  */
        !          4737: int
        !          4738: trio_get_upper
        !          4739: TRIO_ARGS1((ref),
        !          4740:           trio_pointer_t ref)
        !          4741: {
        !          4742:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER)
        !          4743:     ? TRUE
        !          4744:     : FALSE;
        !          4745: }
        !          4746: 
        !          4747: void
        !          4748: trio_set_upper
        !          4749: TRIO_ARGS2((ref, is_upper),
        !          4750:           trio_pointer_t ref,
        !          4751:           int is_upper)
        !          4752: {
        !          4753:   if (is_upper)
        !          4754:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER;
        !          4755:   else
        !          4756:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER;
        !          4757: }
        !          4758: 
        !          4759: /*************************************************************************
        !          4760:  * trio_get_largest / trio_set_largest [public]
        !          4761:  */
        !          4762: #if TRIO_C99
        !          4763: int
        !          4764: trio_get_largest
        !          4765: TRIO_ARGS1((ref),
        !          4766:           trio_pointer_t ref)
        !          4767: {
        !          4768:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T)
        !          4769:     ? TRUE
        !          4770:     : FALSE;
        !          4771: }
        !          4772: 
        !          4773: void
        !          4774: trio_set_largest
        !          4775: TRIO_ARGS2((ref, is_largest),
        !          4776:           trio_pointer_t ref,
        !          4777:           int is_largest)
        !          4778: {
        !          4779:   if (is_largest)
        !          4780:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T;
        !          4781:   else
        !          4782:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T;
        !          4783: }
        !          4784: #endif
        !          4785: 
        !          4786: /*************************************************************************
        !          4787:  * trio_get_ptrdiff / trio_set_ptrdiff [public]
        !          4788:  */
        !          4789: int
        !          4790: trio_get_ptrdiff
        !          4791: TRIO_ARGS1((ref),
        !          4792:           trio_pointer_t ref)
        !          4793: {
        !          4794:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T)
        !          4795:     ? TRUE
        !          4796:     : FALSE;
        !          4797: }
        !          4798: 
        !          4799: void
        !          4800: trio_set_ptrdiff
        !          4801: TRIO_ARGS2((ref, is_ptrdiff),
        !          4802:           trio_pointer_t ref,
        !          4803:           int is_ptrdiff)
        !          4804: {
        !          4805:   if (is_ptrdiff)
        !          4806:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T;
        !          4807:   else
        !          4808:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
        !          4809: }
        !          4810: 
        !          4811: /*************************************************************************
        !          4812:  * trio_get_size / trio_set_size [public]
        !          4813:  */
        !          4814: #if TRIO_C99
        !          4815: int
        !          4816: trio_get_size
        !          4817: TRIO_ARGS1((ref),
        !          4818:           trio_pointer_t ref)
        !          4819: {
        !          4820:   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T)
        !          4821:     ? TRUE
        !          4822:     : FALSE;
        !          4823: }
        !          4824: 
        !          4825: void
        !          4826: trio_set_size
        !          4827: TRIO_ARGS2((ref, is_size),
        !          4828:           trio_pointer_t ref,
        !          4829:           int is_size)
        !          4830: {
        !          4831:   if (is_size)
        !          4832:     ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T;
        !          4833:   else
        !          4834:     ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T;
        !          4835: }
        !          4836: #endif
        !          4837: 
        !          4838: /*************************************************************************
        !          4839:  * trio_print_int [public]
        !          4840:  */
        !          4841: void
        !          4842: trio_print_int
        !          4843: TRIO_ARGS2((ref, number),
        !          4844:           trio_pointer_t ref,
        !          4845:           int number)
        !          4846: {
        !          4847:   trio_reference_t *self = (trio_reference_t *)ref;
        !          4848: 
        !          4849:   TrioWriteNumber(self->data,
        !          4850:                  (trio_uintmax_t)number,
        !          4851:                  self->parameter->flags,
        !          4852:                  self->parameter->width,
        !          4853:                  self->parameter->precision,
        !          4854:                  self->parameter->base);
        !          4855: }
        !          4856: 
        !          4857: /*************************************************************************
        !          4858:  * trio_print_uint [public]
        !          4859:  */
        !          4860: void
        !          4861: trio_print_uint
        !          4862: TRIO_ARGS2((ref, number),
        !          4863:           trio_pointer_t ref,
        !          4864:           unsigned int number)
        !          4865: {
        !          4866:   trio_reference_t *self = (trio_reference_t *)ref;
        !          4867: 
        !          4868:   TrioWriteNumber(self->data,
        !          4869:                  (trio_uintmax_t)number,
        !          4870:                  self->parameter->flags | FLAGS_UNSIGNED,
        !          4871:                  self->parameter->width,
        !          4872:                  self->parameter->precision,
        !          4873:                  self->parameter->base);
        !          4874: }
        !          4875: 
        !          4876: /*************************************************************************
        !          4877:  * trio_print_double [public]
        !          4878:  */
        !          4879: void
        !          4880: trio_print_double
        !          4881: TRIO_ARGS2((ref, number),
        !          4882:           trio_pointer_t ref,
        !          4883:           double number)
        !          4884: {
        !          4885:   trio_reference_t *self = (trio_reference_t *)ref;
        !          4886: 
        !          4887:   TrioWriteDouble(self->data,
        !          4888:                  number,
        !          4889:                  self->parameter->flags,
        !          4890:                  self->parameter->width,
        !          4891:                  self->parameter->precision,
        !          4892:                  self->parameter->base);
        !          4893: }
        !          4894: 
        !          4895: /*************************************************************************
        !          4896:  * trio_print_string [public]
        !          4897:  */
        !          4898: void
        !          4899: trio_print_string
        !          4900: TRIO_ARGS2((ref, string),
        !          4901:           trio_pointer_t ref,
        !          4902:           char *string)
        !          4903: {
        !          4904:   trio_reference_t *self = (trio_reference_t *)ref;
        !          4905: 
        !          4906:   TrioWriteString(self->data,
        !          4907:                  string,
        !          4908:                  self->parameter->flags,
        !          4909:                  self->parameter->width,
        !          4910:                  self->parameter->precision);
        !          4911: }
        !          4912: 
        !          4913: /*************************************************************************
        !          4914:  * trio_print_ref [public]
        !          4915:  */
        !          4916: int
        !          4917: trio_print_ref
        !          4918: TRIO_VARGS3((ref, format, va_alist),
        !          4919:            trio_pointer_t ref,
        !          4920:            TRIO_CONST char *format,
        !          4921:            TRIO_VA_DECL)
        !          4922: {
        !          4923:   int status;
        !          4924:   va_list arglist;
        !          4925: 
        !          4926:   assert(VALID(format));
        !          4927:   
        !          4928:   TRIO_VA_START(arglist, format);
        !          4929:   status = TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
        !          4930:   TRIO_VA_END(arglist);
        !          4931:   return status;
        !          4932: }
        !          4933: 
        !          4934: /*************************************************************************
        !          4935:  * trio_vprint_ref [public]
        !          4936:  */
        !          4937: int
        !          4938: trio_vprint_ref
        !          4939: TRIO_ARGS3((ref, format, arglist),
        !          4940:           trio_pointer_t ref,
        !          4941:           TRIO_CONST char *format,
        !          4942:           va_list arglist)
        !          4943: {
        !          4944:   assert(VALID(format));
        !          4945:   
        !          4946:   return TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
        !          4947: }
        !          4948: 
        !          4949: /*************************************************************************
        !          4950:  * trio_printv_ref [public]
        !          4951:  */
        !          4952: int
        !          4953: trio_printv_ref
        !          4954: TRIO_ARGS3((ref, format, argarray),
        !          4955:           trio_pointer_t ref,
        !          4956:           TRIO_CONST char *format,
        !          4957:           trio_pointer_t *argarray)
        !          4958: {
        !          4959:   assert(VALID(format));
        !          4960:   
        !          4961:   return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray);
        !          4962: }
        !          4963: 
        !          4964: #endif /* TRIO_EXTENSION */
        !          4965: 
        !          4966: /*************************************************************************
        !          4967:  * trio_print_pointer [public]
        !          4968:  */
        !          4969: void
        !          4970: trio_print_pointer
        !          4971: TRIO_ARGS2((ref, pointer),
        !          4972:           trio_pointer_t ref,
        !          4973:           trio_pointer_t pointer)
        !          4974: {
        !          4975:   trio_reference_t *self = (trio_reference_t *)ref;
        !          4976:   trio_flags_t flags;
        !          4977:   trio_uintmax_t number;
        !          4978: 
        !          4979:   if (NULL == pointer)
        !          4980:     {
        !          4981:       TRIO_CONST char *string = internalNullString;
        !          4982:       while (*string)
        !          4983:        self->data->OutStream(self->data, *string++);
        !          4984:     }
        !          4985:   else
        !          4986:     {
        !          4987:       /*
        !          4988:        * The subtraction of the null pointer is a workaround
        !          4989:        * to avoid a compiler warning. The performance overhead
        !          4990:        * is negligible (and likely to be removed by an
        !          4991:        * optimizing compiler). The (char *) casting is done
        !          4992:        * to please ANSI C++.
        !          4993:        */
        !          4994:       number = (trio_uintmax_t)((char *)pointer - (char *)0);
        !          4995:       /* Shrink to size of pointer */
        !          4996:       number &= (trio_uintmax_t)-1;
        !          4997:       flags = self->parameter->flags;
        !          4998:       flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE |
        !          4999:                FLAGS_NILPADDING);
        !          5000:       TrioWriteNumber(self->data,
        !          5001:                      number,
        !          5002:                      flags,
        !          5003:                      POINTER_WIDTH,
        !          5004:                      NO_PRECISION,
        !          5005:                      BASE_HEX);
        !          5006:     }
        !          5007: }
        !          5008: 
        !          5009: /** @} End of UserDefined documentation module */
        !          5010: 
        !          5011: /*************************************************************************
        !          5012:  *
        !          5013:  * LOCALES
        !          5014:  *
        !          5015:  ************************************************************************/
        !          5016: 
        !          5017: /*************************************************************************
        !          5018:  * trio_locale_set_decimal_point
        !          5019:  *
        !          5020:  * Decimal point can only be one character. The input argument is a
        !          5021:  * string to enable multibyte characters. At most MB_LEN_MAX characters
        !          5022:  * will be used.
        !          5023:  */
        !          5024: TRIO_PUBLIC void
        !          5025: trio_locale_set_decimal_point
        !          5026: TRIO_ARGS1((decimalPoint),
        !          5027:           char *decimalPoint)
        !          5028: {
        !          5029: #if defined(USE_LOCALE)
        !          5030:   if (NULL == internalLocaleValues)
        !          5031:     {
        !          5032:       TrioSetLocale();
        !          5033:     }
        !          5034: #endif
        !          5035:   internalDecimalPointLength = trio_length(decimalPoint);
        !          5036:   if (internalDecimalPointLength == 1)
        !          5037:     {
        !          5038:       internalDecimalPoint = *decimalPoint;
        !          5039:     }
        !          5040:   else
        !          5041:     {
        !          5042:       internalDecimalPoint = NIL;
        !          5043:       trio_copy_max(internalDecimalPointString,
        !          5044:                    sizeof(internalDecimalPointString),
        !          5045:                    decimalPoint);
        !          5046:     }
        !          5047: }
        !          5048: 
        !          5049: /*************************************************************************
        !          5050:  * trio_locale_set_thousand_separator
        !          5051:  *
        !          5052:  * See trio_locale_set_decimal_point
        !          5053:  */
        !          5054: TRIO_PUBLIC void
        !          5055: trio_locale_set_thousand_separator
        !          5056: TRIO_ARGS1((thousandSeparator),
        !          5057:           char *thousandSeparator)
        !          5058: {
        !          5059: #if defined(USE_LOCALE)
        !          5060:   if (NULL == internalLocaleValues)
        !          5061:     {
        !          5062:       TrioSetLocale();
        !          5063:     }
        !          5064: #endif
        !          5065:   trio_copy_max(internalThousandSeparator,
        !          5066:                sizeof(internalThousandSeparator),
        !          5067:                thousandSeparator);
        !          5068:   internalThousandSeparatorLength = trio_length(internalThousandSeparator);
        !          5069: }
        !          5070: 
        !          5071: /*************************************************************************
        !          5072:  * trio_locale_set_grouping
        !          5073:  *
        !          5074:  * Array of bytes. Reversed order.
        !          5075:  *
        !          5076:  *  CHAR_MAX : No further grouping
        !          5077:  *  0        : Repeat last group for the remaining digits (not necessary
        !          5078:  *             as C strings are zero-terminated)
        !          5079:  *  n        : Set current group to n
        !          5080:  *
        !          5081:  * Same order as the grouping attribute in LC_NUMERIC.
        !          5082:  */
        !          5083: TRIO_PUBLIC void
        !          5084: trio_locale_set_grouping
        !          5085: TRIO_ARGS1((grouping),
        !          5086:           char *grouping)
        !          5087: {
        !          5088: #if defined(USE_LOCALE)
        !          5089:   if (NULL == internalLocaleValues)
        !          5090:     {
        !          5091:       TrioSetLocale();
        !          5092:     }
        !          5093: #endif
        !          5094:   trio_copy_max(internalGrouping,
        !          5095:                sizeof(internalGrouping),
        !          5096:                grouping);
        !          5097: }
        !          5098: 
        !          5099: 
        !          5100: /*************************************************************************
        !          5101:  *
        !          5102:  * SCANNING
        !          5103:  *
        !          5104:  ************************************************************************/
        !          5105: 
        !          5106: /*************************************************************************
        !          5107:  * TrioSkipWhitespaces
        !          5108:  */
        !          5109: TRIO_PRIVATE int
        !          5110: TrioSkipWhitespaces
        !          5111: TRIO_ARGS1((self),
        !          5112:           trio_class_t *self)
        !          5113: {
        !          5114:   int ch;
        !          5115: 
        !          5116:   ch = self->current;
        !          5117:   while (isspace(ch))
        !          5118:     {
        !          5119:       self->InStream(self, &ch);
        !          5120:     }
        !          5121:   return ch;
        !          5122: }
        !          5123: 
        !          5124: /*************************************************************************
        !          5125:  * TrioGetCollation
        !          5126:  */
        !          5127: #if TRIO_EXTENSION
        !          5128: TRIO_PRIVATE void
        !          5129: TrioGetCollation(TRIO_NOARGS)
        !          5130: {
        !          5131:   int i;
        !          5132:   int j;
        !          5133:   int k;
        !          5134:   char first[2];
        !          5135:   char second[2];
        !          5136: 
        !          5137:   /* This is computationally expensive */
        !          5138:   first[1] = NIL;
        !          5139:   second[1] = NIL;
        !          5140:   for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5141:     {
        !          5142:       k = 0;
        !          5143:       first[0] = (char)i;
        !          5144:       for (j = 0; j < MAX_CHARACTER_CLASS; j++)
        !          5145:        {
        !          5146:          second[0] = (char)j;
        !          5147:          if (trio_equal_locale(first, second))
        !          5148:            internalCollationArray[i][k++] = (char)j;
        !          5149:        }
        !          5150:       internalCollationArray[i][k] = NIL;
        !          5151:     }
        !          5152: }
        !          5153: #endif
        !          5154: 
        !          5155: /*************************************************************************
        !          5156:  * TrioGetCharacterClass
        !          5157:  *
        !          5158:  * FIXME:
        !          5159:  *  multibyte
        !          5160:  */
        !          5161: TRIO_PRIVATE int
        !          5162: TrioGetCharacterClass
        !          5163: TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
        !          5164:           TRIO_CONST char *format,
        !          5165:           int *indexPointer,
        !          5166:           trio_flags_t *flagsPointer,
        !          5167:           int *characterclass)
        !          5168: {
        !          5169:   int index = *indexPointer;
        !          5170:   int i;
        !          5171:   char ch;
        !          5172:   char range_begin;
        !          5173:   char range_end;
        !          5174: 
        !          5175:   *flagsPointer &= ~FLAGS_EXCLUDE;
        !          5176: 
        !          5177:   if (format[index] == QUALIFIER_CIRCUMFLEX)
        !          5178:     {
        !          5179:       *flagsPointer |= FLAGS_EXCLUDE;
        !          5180:       index++;
        !          5181:     }
        !          5182:   /*
        !          5183:    * If the ungroup character is at the beginning of the scanlist,
        !          5184:    * it will be part of the class, and a second ungroup character
        !          5185:    * must follow to end the group.
        !          5186:    */
        !          5187:   if (format[index] == SPECIFIER_UNGROUP)
        !          5188:     {
        !          5189:       characterclass[(int)SPECIFIER_UNGROUP]++;
        !          5190:       index++;
        !          5191:     }
        !          5192:   /*
        !          5193:    * Minus is used to specify ranges. To include minus in the class,
        !          5194:    * it must be at the beginning of the list
        !          5195:    */
        !          5196:   if (format[index] == QUALIFIER_MINUS)
        !          5197:     {
        !          5198:       characterclass[(int)QUALIFIER_MINUS]++;
        !          5199:       index++;
        !          5200:     }
        !          5201:   /* Collect characters */
        !          5202:   for (ch = format[index];
        !          5203:        (ch != SPECIFIER_UNGROUP) && (ch != NIL);
        !          5204:        ch = format[++index])
        !          5205:     {
        !          5206:       switch (ch)
        !          5207:        {
        !          5208:        case QUALIFIER_MINUS: /* Scanlist ranges */
        !          5209:          
        !          5210:          /*
        !          5211:           * Both C99 and UNIX98 describes ranges as implementation-
        !          5212:           * defined.
        !          5213:           *
        !          5214:           * We support the following behaviour (although this may
        !          5215:           * change as we become wiser)
        !          5216:           * - only increasing ranges, ie. [a-b] but not [b-a]
        !          5217:           * - transitive ranges, ie. [a-b-c] == [a-c]
        !          5218:           * - trailing minus, ie. [a-] is interpreted as an 'a'
        !          5219:           *   and a '-'
        !          5220:           * - duplicates (although we can easily convert these
        !          5221:           *   into errors)
        !          5222:           */
        !          5223:          range_begin = format[index - 1];
        !          5224:          range_end = format[++index];
        !          5225:          if (range_end == SPECIFIER_UNGROUP)
        !          5226:            {
        !          5227:              /* Trailing minus is included */
        !          5228:              characterclass[(int)ch]++;
        !          5229:              ch = range_end;
        !          5230:              break; /* for */
        !          5231:            }
        !          5232:          if (range_end == NIL)
        !          5233:            return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          5234:          if (range_begin > range_end)
        !          5235:            return TRIO_ERROR_RETURN(TRIO_ERANGE, index);
        !          5236:            
        !          5237:          for (i = (int)range_begin; i <= (int)range_end; i++)
        !          5238:            characterclass[i]++;
        !          5239:            
        !          5240:          ch = range_end;
        !          5241:          break;
        !          5242:          
        !          5243: #if TRIO_EXTENSION
        !          5244: 
        !          5245:        case SPECIFIER_GROUP:
        !          5246:          
        !          5247:          switch (format[index + 1])
        !          5248:            {
        !          5249:            case QUALIFIER_DOT: /* Collating symbol */
        !          5250:              /*
        !          5251:               * FIXME: This will be easier to implement when multibyte
        !          5252:               * characters have been implemented. Until now, we ignore
        !          5253:               * this feature.
        !          5254:               */
        !          5255:              for (i = index + 2; ; i++)
        !          5256:                {
        !          5257:                  if (format[i] == NIL)
        !          5258:                    /* Error in syntax */
        !          5259:                    return -1;
        !          5260:                  else if (format[i] == QUALIFIER_DOT)
        !          5261:                    break; /* for */
        !          5262:                }
        !          5263:              if (format[++i] != SPECIFIER_UNGROUP)
        !          5264:                return -1;
        !          5265:              
        !          5266:              index = i;
        !          5267:              break;
        !          5268:          
        !          5269:            case QUALIFIER_EQUAL: /* Equivalence class expressions */
        !          5270:              {
        !          5271:                unsigned int j;
        !          5272:                unsigned int k;
        !          5273:            
        !          5274:                if (internalCollationUnconverted)
        !          5275:                  {
        !          5276:                    /* Lazy evaluation of collation array */
        !          5277:                    TrioGetCollation();
        !          5278:                    internalCollationUnconverted = FALSE;
        !          5279:                  }
        !          5280:                for (i = index + 2; ; i++)
        !          5281:                  {
        !          5282:                    if (format[i] == NIL)
        !          5283:                      /* Error in syntax */
        !          5284:                      return -1;
        !          5285:                    else if (format[i] == QUALIFIER_EQUAL)
        !          5286:                      break; /* for */
        !          5287:                    else
        !          5288:                      {
        !          5289:                        /* Mark any equivalent character */
        !          5290:                        k = (unsigned int)format[i];
        !          5291:                        for (j = 0; internalCollationArray[k][j] != NIL; j++)
        !          5292:                          characterclass[(int)internalCollationArray[k][j]]++;
        !          5293:                      }
        !          5294:                  }
        !          5295:                if (format[++i] != SPECIFIER_UNGROUP)
        !          5296:                  return -1;
        !          5297:                
        !          5298:                index = i;
        !          5299:              }
        !          5300:              break;
        !          5301:          
        !          5302:            case QUALIFIER_COLON: /* Character class expressions */
        !          5303:          
        !          5304:              if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
        !          5305:                                 &format[index]))
        !          5306:                {
        !          5307:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5308:                    if (isalnum(i))
        !          5309:                      characterclass[i]++;
        !          5310:                  index += sizeof(CLASS_ALNUM) - 1;
        !          5311:                }
        !          5312:              else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
        !          5313:                                      &format[index]))
        !          5314:                {
        !          5315:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5316:                    if (isalpha(i))
        !          5317:                      characterclass[i]++;
        !          5318:                  index += sizeof(CLASS_ALPHA) - 1;
        !          5319:                }
        !          5320:              else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
        !          5321:                                      &format[index]))
        !          5322:                {
        !          5323:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5324:                    if (iscntrl(i))
        !          5325:                      characterclass[i]++;
        !          5326:                  index += sizeof(CLASS_CNTRL) - 1;
        !          5327:                }
        !          5328:              else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
        !          5329:                                      &format[index]))
        !          5330:                {
        !          5331:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5332:                    if (isdigit(i))
        !          5333:                      characterclass[i]++;
        !          5334:                  index += sizeof(CLASS_DIGIT) - 1;
        !          5335:                }
        !          5336:              else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
        !          5337:                                      &format[index]))
        !          5338:                {
        !          5339:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5340:                    if (isgraph(i))
        !          5341:                      characterclass[i]++;
        !          5342:                  index += sizeof(CLASS_GRAPH) - 1;
        !          5343:                }
        !          5344:              else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
        !          5345:                                      &format[index]))
        !          5346:                {
        !          5347:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5348:                    if (islower(i))
        !          5349:                      characterclass[i]++;
        !          5350:                  index += sizeof(CLASS_LOWER) - 1;
        !          5351:                }
        !          5352:              else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
        !          5353:                                      &format[index]))
        !          5354:                {
        !          5355:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5356:                    if (isprint(i))
        !          5357:                      characterclass[i]++;
        !          5358:                  index += sizeof(CLASS_PRINT) - 1;
        !          5359:                }
        !          5360:              else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
        !          5361:                                      &format[index]))
        !          5362:                {
        !          5363:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5364:                    if (ispunct(i))
        !          5365:                      characterclass[i]++;
        !          5366:                  index += sizeof(CLASS_PUNCT) - 1;
        !          5367:                }
        !          5368:              else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
        !          5369:                                      &format[index]))
        !          5370:                {
        !          5371:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5372:                    if (isspace(i))
        !          5373:                      characterclass[i]++;
        !          5374:                  index += sizeof(CLASS_SPACE) - 1;
        !          5375:                }
        !          5376:              else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
        !          5377:                                      &format[index]))
        !          5378:                {
        !          5379:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5380:                    if (isupper(i))
        !          5381:                      characterclass[i]++;
        !          5382:                  index += sizeof(CLASS_UPPER) - 1;
        !          5383:                }
        !          5384:              else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
        !          5385:                                      &format[index]))
        !          5386:                {
        !          5387:                  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
        !          5388:                    if (isxdigit(i))
        !          5389:                      characterclass[i]++;
        !          5390:                  index += sizeof(CLASS_XDIGIT) - 1;
        !          5391:                }
        !          5392:              else
        !          5393:                {
        !          5394:                  characterclass[(int)ch]++;
        !          5395:                }
        !          5396:              break;
        !          5397: 
        !          5398:            default:
        !          5399:              characterclass[(int)ch]++;
        !          5400:              break;
        !          5401:            }
        !          5402:          break;
        !          5403:          
        !          5404: #endif /* TRIO_EXTENSION */
        !          5405:          
        !          5406:        default:
        !          5407:          characterclass[(int)ch]++;
        !          5408:          break;
        !          5409:        }
        !          5410:     }
        !          5411:   return 0;
        !          5412: }
        !          5413: 
        !          5414: /*************************************************************************
        !          5415:  * TrioReadNumber
        !          5416:  *
        !          5417:  * We implement our own number conversion in preference of strtol and
        !          5418:  * strtoul, because we must handle 'long long' and thousand separators.
        !          5419:  */
        !          5420: TRIO_PRIVATE BOOLEAN_T
        !          5421: TrioReadNumber
        !          5422: TRIO_ARGS5((self, target, flags, width, base),
        !          5423:           trio_class_t *self,
        !          5424:           trio_uintmax_t *target,
        !          5425:           trio_flags_t flags,
        !          5426:           int width,
        !          5427:           int base)
        !          5428: {
        !          5429:   trio_uintmax_t number = 0;
        !          5430:   int digit;
        !          5431:   int count;
        !          5432:   BOOLEAN_T isNegative = FALSE;
        !          5433:   BOOLEAN_T gotNumber = FALSE;
        !          5434:   int j;
        !          5435: 
        !          5436:   assert(VALID(self));
        !          5437:   assert(VALID(self->InStream));
        !          5438:   assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE));
        !          5439: 
        !          5440:   if (internalDigitsUnconverted)
        !          5441:     {
        !          5442:       /* Lazy evaluation of digits array */
        !          5443:       memset(internalDigitArray, -1, sizeof(internalDigitArray));
        !          5444:       for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++)
        !          5445:        {
        !          5446:          internalDigitArray[(int)internalDigitsLower[j]] = j;
        !          5447:          internalDigitArray[(int)internalDigitsUpper[j]] = j;
        !          5448:        }
        !          5449:       internalDigitsUnconverted = FALSE;
        !          5450:     }
        !          5451:   
        !          5452:   TrioSkipWhitespaces(self);
        !          5453:   
        !          5454:   if (!(flags & FLAGS_UNSIGNED))
        !          5455:     {
        !          5456:       /* Leading sign */
        !          5457:       if (self->current == '+')
        !          5458:        {
        !          5459:          self->InStream(self, NULL);
        !          5460:        }
        !          5461:       else if (self->current == '-')
        !          5462:        {
        !          5463:          self->InStream(self, NULL);
        !          5464:          isNegative = TRUE;
        !          5465:        }
        !          5466:     }
        !          5467:   
        !          5468:   count = self->processed;
        !          5469:   
        !          5470:   if (flags & FLAGS_ALTERNATIVE)
        !          5471:     {
        !          5472:       switch (base)
        !          5473:        {
        !          5474:        case NO_BASE:
        !          5475:        case BASE_OCTAL:
        !          5476:        case BASE_HEX:
        !          5477:        case BASE_BINARY:
        !          5478:          if (self->current == '0')
        !          5479:            {
        !          5480:              self->InStream(self, NULL);
        !          5481:              if (self->current)
        !          5482:                {
        !          5483:                  if ((base == BASE_HEX) &&
        !          5484:                      (trio_to_upper(self->current) == 'X'))
        !          5485:                    {
        !          5486:                      self->InStream(self, NULL);
        !          5487:                    }
        !          5488:                  else if ((base == BASE_BINARY) &&
        !          5489:                           (trio_to_upper(self->current) == 'B'))
        !          5490:                    {
        !          5491:                      self->InStream(self, NULL);
        !          5492:                    }
        !          5493:                }
        !          5494:            }
        !          5495:          else
        !          5496:            return FALSE;
        !          5497:          break;
        !          5498:        default:
        !          5499:          break;
        !          5500:        }
        !          5501:     }
        !          5502: 
        !          5503:   while (((width == NO_WIDTH) || (self->processed - count < width)) &&
        !          5504:         (! ((self->current == EOF) || isspace(self->current))))
        !          5505:     {
        !          5506:       if (isascii(self->current))
        !          5507:        {
        !          5508:          digit = internalDigitArray[self->current];
        !          5509:          /* Abort if digit is not allowed in the specified base */
        !          5510:          if ((digit == -1) || (digit >= base))
        !          5511:            break;
        !          5512:        }
        !          5513:       else if (flags & FLAGS_QUOTE)
        !          5514:        {
        !          5515:          /* Compare with thousands separator */
        !          5516:          for (j = 0; internalThousandSeparator[j] && self->current; j++)
        !          5517:            {
        !          5518:              if (internalThousandSeparator[j] != self->current)
        !          5519:                break;
        !          5520: 
        !          5521:              self->InStream(self, NULL);
        !          5522:            }
        !          5523:          if (internalThousandSeparator[j])
        !          5524:            break; /* Mismatch */
        !          5525:          else
        !          5526:            continue; /* Match */
        !          5527:        }
        !          5528:       else
        !          5529:        break;
        !          5530:             
        !          5531:       number *= base;
        !          5532:       number += digit;
        !          5533:       gotNumber = TRUE; /* we need at least one digit */
        !          5534: 
        !          5535:       self->InStream(self, NULL);
        !          5536:     }
        !          5537: 
        !          5538:   /* Was anything read at all? */
        !          5539:   if (!gotNumber)
        !          5540:     return FALSE;
        !          5541:   
        !          5542:   if (target)
        !          5543:     *target = (isNegative) ? -((trio_intmax_t)number) : number;
        !          5544:   return TRUE;
        !          5545: }
        !          5546: 
        !          5547: /*************************************************************************
        !          5548:  * TrioReadChar
        !          5549:  */
        !          5550: TRIO_PRIVATE int
        !          5551: TrioReadChar
        !          5552: TRIO_ARGS4((self, target, flags, width),
        !          5553:           trio_class_t *self,
        !          5554:           char *target,
        !          5555:           trio_flags_t flags,
        !          5556:           int width)
        !          5557: {
        !          5558:   int i;
        !          5559:   char ch;
        !          5560:   trio_uintmax_t number;
        !          5561:   
        !          5562:   assert(VALID(self));
        !          5563:   assert(VALID(self->InStream));
        !          5564: 
        !          5565:   for (i = 0;
        !          5566:        (self->current != EOF) && (i < width);
        !          5567:        i++)
        !          5568:     {
        !          5569:       ch = (char)self->current;
        !          5570:       self->InStream(self, NULL);
        !          5571:       if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH))
        !          5572:        {
        !          5573:          switch (self->current)
        !          5574:            {
        !          5575:            case '\\': ch = '\\'; break;
        !          5576:            case 'a': ch = '\007'; break;
        !          5577:            case 'b': ch = '\b'; break;
        !          5578:            case 'f': ch = '\f'; break;
        !          5579:            case 'n': ch = '\n'; break;
        !          5580:            case 'r': ch = '\r'; break;
        !          5581:            case 't': ch = '\t'; break;
        !          5582:            case 'v': ch = '\v'; break;
        !          5583:            default:
        !          5584:              if (isdigit(self->current))
        !          5585:                {
        !          5586:                  /* Read octal number */
        !          5587:                  if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL))
        !          5588:                    return 0;
        !          5589:                  ch = (char)number;
        !          5590:                }
        !          5591:              else if (trio_to_upper(self->current) == 'X')
        !          5592:                {
        !          5593:                  /* Read hexadecimal number */
        !          5594:                  self->InStream(self, NULL);
        !          5595:                  if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX))
        !          5596:                    return 0;
        !          5597:                  ch = (char)number;
        !          5598:                }
        !          5599:              else
        !          5600:                {
        !          5601:                  ch = (char)self->current;
        !          5602:                }
        !          5603:              break;
        !          5604:            }
        !          5605:        }
        !          5606:       
        !          5607:       if (target)
        !          5608:        target[i] = ch;
        !          5609:     }
        !          5610:   return i + 1;
        !          5611: }
        !          5612: 
        !          5613: /*************************************************************************
        !          5614:  * TrioReadString
        !          5615:  */
        !          5616: TRIO_PRIVATE BOOLEAN_T
        !          5617: TrioReadString
        !          5618: TRIO_ARGS4((self, target, flags, width),
        !          5619:           trio_class_t *self,
        !          5620:           char *target,
        !          5621:           trio_flags_t flags,
        !          5622:           int width)
        !          5623: {
        !          5624:   int i;
        !          5625:   
        !          5626:   assert(VALID(self));
        !          5627:   assert(VALID(self->InStream));
        !          5628: 
        !          5629:   TrioSkipWhitespaces(self);
        !          5630:     
        !          5631:   /*
        !          5632:    * Continue until end of string is reached, a whitespace is encountered,
        !          5633:    * or width is exceeded
        !          5634:    */
        !          5635:   for (i = 0;
        !          5636:        ((width == NO_WIDTH) || (i < width)) &&
        !          5637:        (! ((self->current == EOF) || isspace(self->current)));
        !          5638:        i++)
        !          5639:     {
        !          5640:       if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0)
        !          5641:        break; /* for */
        !          5642:     }
        !          5643:   if (target)
        !          5644:     target[i] = NIL;
        !          5645:   return TRUE;
        !          5646: }
        !          5647: 
        !          5648: /*************************************************************************
        !          5649:  * TrioReadWideChar
        !          5650:  */
        !          5651: #if TRIO_WIDECHAR
        !          5652: TRIO_PRIVATE int
        !          5653: TrioReadWideChar
        !          5654: TRIO_ARGS4((self, target, flags, width),
        !          5655:           trio_class_t *self,
        !          5656:           trio_wchar_t *target,
        !          5657:           trio_flags_t flags,
        !          5658:           int width)
        !          5659: {
        !          5660:   int i;
        !          5661:   int j;
        !          5662:   int size;
        !          5663:   int amount = 0;
        !          5664:   trio_wchar_t wch;
        !          5665:   char buffer[MB_LEN_MAX + 1];
        !          5666:   
        !          5667:   assert(VALID(self));
        !          5668:   assert(VALID(self->InStream));
        !          5669: 
        !          5670:   for (i = 0;
        !          5671:        (self->current != EOF) && (i < width);
        !          5672:        i++)
        !          5673:     {
        !          5674:       if (isascii(self->current))
        !          5675:        {
        !          5676:          if (TrioReadChar(self, buffer, flags, 1) == 0)
        !          5677:            return 0;
        !          5678:          buffer[1] = NIL;
        !          5679:        }
        !          5680:       else
        !          5681:        {
        !          5682:          /*
        !          5683:           * Collect a multibyte character, by enlarging buffer until
        !          5684:           * it contains a fully legal multibyte character, or the
        !          5685:           * buffer is full.
        !          5686:           */
        !          5687:          j = 0;
        !          5688:          do
        !          5689:            {
        !          5690:              buffer[j++] = (char)self->current;
        !          5691:              buffer[j] = NIL;
        !          5692:              self->InStream(self, NULL);
        !          5693:            }
        !          5694:          while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j));
        !          5695:        }
        !          5696:       if (target)
        !          5697:        {
        !          5698:          size = mbtowc(&wch, buffer, sizeof(buffer));
        !          5699:          if (size > 0)
        !          5700:            target[i] = wch;
        !          5701:        }
        !          5702:       amount += size;
        !          5703:       self->InStream(self, NULL);
        !          5704:     }
        !          5705:   return amount;
        !          5706: }
        !          5707: #endif /* TRIO_WIDECHAR */
        !          5708: 
        !          5709: /*************************************************************************
        !          5710:  * TrioReadWideString
        !          5711:  */
        !          5712: #if TRIO_WIDECHAR
        !          5713: TRIO_PRIVATE BOOLEAN_T
        !          5714: TrioReadWideString
        !          5715: TRIO_ARGS4((self, target, flags, width),
        !          5716:           trio_class_t *self,
        !          5717:           trio_wchar_t *target,
        !          5718:           trio_flags_t flags,
        !          5719:           int width)
        !          5720: {
        !          5721:   int i;
        !          5722:   int size;
        !          5723:   
        !          5724:   assert(VALID(self));
        !          5725:   assert(VALID(self->InStream));
        !          5726: 
        !          5727:   TrioSkipWhitespaces(self);
        !          5728: 
        !          5729: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          5730:   (void)mblen(NULL, 0);
        !          5731: #endif
        !          5732:   
        !          5733:   /*
        !          5734:    * Continue until end of string is reached, a whitespace is encountered,
        !          5735:    * or width is exceeded
        !          5736:    */
        !          5737:   for (i = 0;
        !          5738:        ((width == NO_WIDTH) || (i < width)) &&
        !          5739:        (! ((self->current == EOF) || isspace(self->current)));
        !          5740:        )
        !          5741:     {
        !          5742:       size = TrioReadWideChar(self, &target[i], flags, 1);
        !          5743:       if (size == 0)
        !          5744:        break; /* for */
        !          5745: 
        !          5746:       i += size;
        !          5747:     }
        !          5748:   if (target)
        !          5749:     target[i] = WCONST('\0');
        !          5750:   return TRUE;
        !          5751: }
        !          5752: #endif /* TRIO_WIDECHAR */
        !          5753: 
        !          5754: /*************************************************************************
        !          5755:  * TrioReadGroup
        !          5756:  *
        !          5757:  * FIXME: characterclass does not work with multibyte characters
        !          5758:  */
        !          5759: TRIO_PRIVATE BOOLEAN_T
        !          5760: TrioReadGroup
        !          5761: TRIO_ARGS5((self, target, characterclass, flags, width),
        !          5762:           trio_class_t *self,
        !          5763:           char *target,
        !          5764:           int *characterclass,
        !          5765:           trio_flags_t flags,
        !          5766:           int width)
        !          5767: {
        !          5768:   int ch;
        !          5769:   int i;
        !          5770:   
        !          5771:   assert(VALID(self));
        !          5772:   assert(VALID(self->InStream));
        !          5773: 
        !          5774:   ch = self->current;
        !          5775:   for (i = 0;
        !          5776:        ((width == NO_WIDTH) || (i < width)) &&
        !          5777:        (! ((ch == EOF) ||
        !          5778:           (((flags & FLAGS_EXCLUDE) != 0) ^ (characterclass[ch] == 0))));
        !          5779:        i++)
        !          5780:     {
        !          5781:       if (target)
        !          5782:        target[i] = (char)ch;
        !          5783:       self->InStream(self, &ch);
        !          5784:     }
        !          5785:   
        !          5786:   if (target)
        !          5787:     target[i] = NIL;
        !          5788:   return TRUE;
        !          5789: }
        !          5790: 
        !          5791: /*************************************************************************
        !          5792:  * TrioReadDouble
        !          5793:  *
        !          5794:  * FIXME:
        !          5795:  *  add long double
        !          5796:  *  handle base
        !          5797:  */
        !          5798: TRIO_PRIVATE BOOLEAN_T
        !          5799: TrioReadDouble
        !          5800: TRIO_ARGS4((self, target, flags, width),
        !          5801:           trio_class_t *self,
        !          5802:           trio_pointer_t target,
        !          5803:           trio_flags_t flags,
        !          5804:           int width)
        !          5805: {
        !          5806:   int ch;
        !          5807:   char doubleString[512];
        !          5808:   int index = 0;
        !          5809:   int start;
        !          5810:   int j;
        !          5811:   BOOLEAN_T isHex = FALSE;
        !          5812: 
        !          5813:   doubleString[0] = 0;
        !          5814:   
        !          5815:   if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1))
        !          5816:     width = sizeof(doubleString) - 1;
        !          5817:   
        !          5818:   TrioSkipWhitespaces(self);
        !          5819:   
        !          5820:   /*
        !          5821:    * Read entire double number from stream. trio_to_double requires
        !          5822:    * a string as input, but InStream can be anything, so we have to
        !          5823:    * collect all characters.
        !          5824:    */
        !          5825:   ch = self->current;
        !          5826:   if ((ch == '+') || (ch == '-'))
        !          5827:     {
        !          5828:       doubleString[index++] = (char)ch;
        !          5829:       self->InStream(self, &ch);
        !          5830:       width--;
        !          5831:     }
        !          5832: 
        !          5833:   start = index;
        !          5834:   switch (ch)
        !          5835:     {
        !          5836:     case 'n':
        !          5837:     case 'N':
        !          5838:       /* Not-a-number */
        !          5839:       if (index != 0)
        !          5840:        break;
        !          5841:       /* FALLTHROUGH */
        !          5842:     case 'i':
        !          5843:     case 'I':
        !          5844:       /* Infinity */
        !          5845:       while (isalpha(ch) && (index - start < width))
        !          5846:        {
        !          5847:          doubleString[index++] = (char)ch;
        !          5848:          self->InStream(self, &ch);
        !          5849:        }
        !          5850:       doubleString[index] = NIL;
        !          5851: 
        !          5852:       /* Case insensitive string comparison */
        !          5853:       if (trio_equal(&doubleString[start], INFINITE_UPPER) ||
        !          5854:          trio_equal(&doubleString[start], LONG_INFINITE_UPPER))
        !          5855:        {
        !          5856:          if (flags & FLAGS_LONGDOUBLE)
        !          5857:            {
        !          5858:              if ((start == 1) && (doubleString[0] == '-'))
        !          5859:                {
        !          5860:                  *((trio_long_double_t *)target) = trio_ninf();
        !          5861:                }
        !          5862:              else
        !          5863:                {
        !          5864:                  *((trio_long_double_t *)target) = trio_pinf();
        !          5865:                }
        !          5866:            }
        !          5867:          else
        !          5868:            {
        !          5869:              if ((start == 1) && (doubleString[0] == '-'))
        !          5870:                {
        !          5871:                  *((double *)target) = trio_ninf();
        !          5872:                }
        !          5873:              else
        !          5874:                {
        !          5875:                  *((double *)target) = trio_pinf();
        !          5876:                }
        !          5877:            }
        !          5878:          return TRUE;
        !          5879:        }
        !          5880:       if (trio_equal(doubleString, NAN_UPPER))
        !          5881:        {
        !          5882:          /* NaN must not have a preceeding + nor - */
        !          5883:          if (flags & FLAGS_LONGDOUBLE)
        !          5884:            {
        !          5885:              *((trio_long_double_t *)target) = trio_nan();
        !          5886:            }
        !          5887:          else
        !          5888:            {
        !          5889:              *((double *)target) = trio_nan();
        !          5890:            }
        !          5891:          return TRUE;
        !          5892:        }
        !          5893:       return FALSE;
        !          5894: 
        !          5895:     case '0':
        !          5896:       doubleString[index++] = (char)ch;
        !          5897:       self->InStream(self, &ch);
        !          5898:       if (trio_to_upper(ch) == 'X')
        !          5899:        {
        !          5900:          isHex = TRUE;
        !          5901:          doubleString[index++] = (char)ch;
        !          5902:          self->InStream(self, &ch);
        !          5903:        }
        !          5904:       break;
        !          5905:       
        !          5906:     default:
        !          5907:       break;
        !          5908:     }
        !          5909:   
        !          5910:   while ((ch != EOF) && (index - start < width))
        !          5911:     {
        !          5912:       /* Integer part */
        !          5913:       if (isHex ? isxdigit(ch) : isdigit(ch))
        !          5914:        {
        !          5915:          doubleString[index++] = (char)ch;
        !          5916:          self->InStream(self, &ch);
        !          5917:        }
        !          5918:       else if (flags & FLAGS_QUOTE)
        !          5919:        {
        !          5920:          /* Compare with thousands separator */
        !          5921:          for (j = 0; internalThousandSeparator[j] && self->current; j++)
        !          5922:            {
        !          5923:              if (internalThousandSeparator[j] != self->current)
        !          5924:                break;
        !          5925: 
        !          5926:              self->InStream(self, &ch);
        !          5927:            }
        !          5928:          if (internalThousandSeparator[j])
        !          5929:            break; /* Mismatch */
        !          5930:          else
        !          5931:            continue; /* Match */
        !          5932:        }
        !          5933:       else
        !          5934:        break; /* while */
        !          5935:     }
        !          5936:   if (ch == '.')
        !          5937:     {
        !          5938:       /* Decimal part */
        !          5939:       doubleString[index++] = (char)ch;
        !          5940:       self->InStream(self, &ch);
        !          5941:       while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
        !          5942:             (index - start < width))
        !          5943:        {
        !          5944:          doubleString[index++] = (char)ch;
        !          5945:          self->InStream(self, &ch);
        !          5946:        }
        !          5947:       if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
        !          5948:        {
        !          5949:          /* Exponent */
        !          5950:          doubleString[index++] = (char)ch;
        !          5951:          self->InStream(self, &ch);
        !          5952:          if ((ch == '+') || (ch == '-'))
        !          5953:            {
        !          5954:              doubleString[index++] = (char)ch;
        !          5955:              self->InStream(self, &ch);
        !          5956:            }
        !          5957:          while (isdigit(ch) && (index - start < width))
        !          5958:            {
        !          5959:              doubleString[index++] = (char)ch;
        !          5960:              self->InStream(self, &ch);
        !          5961:            }
        !          5962:        }
        !          5963:     }
        !          5964: 
        !          5965:   if ((index == start) || (*doubleString == NIL))
        !          5966:     return FALSE;
        !          5967: 
        !          5968:   doubleString[index] = 0;
        !          5969:   
        !          5970:   if (flags & FLAGS_LONGDOUBLE)
        !          5971:     {
        !          5972:       *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL);
        !          5973:     }
        !          5974:   else
        !          5975:     {
        !          5976:       *((double *)target) = trio_to_double(doubleString, NULL);
        !          5977:     }
        !          5978:   return TRUE;
        !          5979: }
        !          5980: 
        !          5981: /*************************************************************************
        !          5982:  * TrioReadPointer
        !          5983:  */
        !          5984: TRIO_PRIVATE BOOLEAN_T
        !          5985: TrioReadPointer
        !          5986: TRIO_ARGS3((self, target, flags),
        !          5987:           trio_class_t *self,
        !          5988:           trio_pointer_t *target,
        !          5989:           trio_flags_t flags)
        !          5990: {
        !          5991:   trio_uintmax_t number;
        !          5992:   char buffer[sizeof(internalNullString)];
        !          5993: 
        !          5994:   flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING);
        !          5995:   
        !          5996:   if (TrioReadNumber(self,
        !          5997:                     &number,
        !          5998:                     flags,
        !          5999:                     POINTER_WIDTH,
        !          6000:                     BASE_HEX))
        !          6001:     {
        !          6002:       /*
        !          6003:        * The strange assignment of number is a workaround for a compiler
        !          6004:        * warning
        !          6005:        */
        !          6006:       if (target)
        !          6007:        *target = (char *)0 + number;
        !          6008:       return TRUE;
        !          6009:     }
        !          6010:   else if (TrioReadString(self,
        !          6011:                          (flags & FLAGS_IGNORE)
        !          6012:                          ? NULL
        !          6013:                          : buffer,
        !          6014:                          0,
        !          6015:                          sizeof(internalNullString) - 1))
        !          6016:     {  
        !          6017:       if (trio_equal_case(buffer, internalNullString))
        !          6018:        {
        !          6019:          if (target)
        !          6020:            *target = NULL;
        !          6021:          return TRUE;
        !          6022:        }
        !          6023:     }
        !          6024:   return FALSE;
        !          6025: }
        !          6026: 
        !          6027: /*************************************************************************
        !          6028:  * TrioScanProcess
        !          6029:  */
        !          6030: TRIO_PRIVATE int
        !          6031: TrioScanProcess
        !          6032: TRIO_ARGS3((data, format, parameters),
        !          6033:           trio_class_t *data,
        !          6034:           TRIO_CONST char *format,
        !          6035:           trio_parameter_t *parameters)
        !          6036: {
        !          6037: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          6038:   int charlen;
        !          6039:   int cnt;
        !          6040: #endif
        !          6041:   int assignment;
        !          6042:   int ch;
        !          6043:   int index; /* Index of format string */
        !          6044:   int i; /* Index of current parameter */
        !          6045:   trio_flags_t flags;
        !          6046:   int width;
        !          6047:   int base;
        !          6048:   trio_pointer_t pointer;
        !          6049: 
        !          6050:   assignment = 0;
        !          6051:   i = 0;
        !          6052:   index = 0;
        !          6053:   data->InStream(data, &ch);
        !          6054: 
        !          6055: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          6056:   (void)mblen(NULL, 0);
        !          6057: #endif
        !          6058: 
        !          6059:   while (format[index])
        !          6060:     {
        !          6061: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
        !          6062:       if (! isascii(format[index]))
        !          6063:        {
        !          6064:          charlen = mblen(&format[index], MB_LEN_MAX);
        !          6065:          if (charlen != -1)
        !          6066:            {
        !          6067:              /* Compare multibyte characters in format string */
        !          6068:              for (cnt = 0; cnt < charlen - 1; cnt++)
        !          6069:                {
        !          6070:                  if (ch != format[index + cnt])
        !          6071:                    {
        !          6072:                      return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          6073:                    }
        !          6074:                  data->InStream(data, &ch);
        !          6075:                }
        !          6076:              continue; /* while characters left in formatting string */
        !          6077:            }
        !          6078:        }
        !          6079: #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
        !          6080:       
        !          6081:       if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
        !          6082:        {
        !          6083:          return (assignment > 0) ? assignment : EOF;
        !          6084:        }
        !          6085:       
        !          6086:       if (CHAR_IDENTIFIER == format[index])
        !          6087:        {
        !          6088:          if (CHAR_IDENTIFIER == format[index + 1])
        !          6089:            {
        !          6090:              /* Two % in format matches one % in input stream */
        !          6091:              if (CHAR_IDENTIFIER == ch)
        !          6092:                {
        !          6093:                  data->InStream(data, &ch);
        !          6094:                  index += 2;
        !          6095:                  continue; /* while format chars left */
        !          6096:                }
        !          6097:              else
        !          6098:                return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          6099:            }
        !          6100: 
        !          6101:          /* Skip the parameter entries */
        !          6102:          while (parameters[i].type == FORMAT_PARAMETER)
        !          6103:            i++;
        !          6104:          
        !          6105:          flags = parameters[i].flags;
        !          6106:          /* Find width */
        !          6107:          width = parameters[i].width;
        !          6108:          if (flags & FLAGS_WIDTH_PARAMETER)
        !          6109:            {
        !          6110:              /* Get width from parameter list */
        !          6111:              width = (int)parameters[width].data.number.as_signed;
        !          6112:            }
        !          6113:          /* Find base */
        !          6114:          base = parameters[i].base;
        !          6115:          if (flags & FLAGS_BASE_PARAMETER)
        !          6116:            {
        !          6117:              /* Get base from parameter list */
        !          6118:              base = (int)parameters[base].data.number.as_signed;
        !          6119:            }
        !          6120:          
        !          6121:          switch (parameters[i].type)
        !          6122:            {
        !          6123:            case FORMAT_INT:
        !          6124:              {
        !          6125:                trio_uintmax_t number;
        !          6126: 
        !          6127:                if (0 == base)
        !          6128:                  base = BASE_DECIMAL;
        !          6129: 
        !          6130:                if (!TrioReadNumber(data,
        !          6131:                                    &number,
        !          6132:                                    flags,
        !          6133:                                    width,
        !          6134:                                    base))
        !          6135:                  return assignment;
        !          6136: 
        !          6137:                if (!(flags & FLAGS_IGNORE))
        !          6138:                  {
        !          6139:                    assignment++;
        !          6140: 
        !          6141:                    pointer = parameters[i].data.pointer;
        !          6142: #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
        !          6143:                    if (flags & FLAGS_SIZE_T)
        !          6144:                      *(size_t *)pointer = (size_t)number;
        !          6145:                    else
        !          6146: #endif
        !          6147: #if defined(QUALIFIER_PTRDIFF_T)
        !          6148:                    if (flags & FLAGS_PTRDIFF_T)
        !          6149:                      *(ptrdiff_t *)pointer = (ptrdiff_t)number;
        !          6150:                    else
        !          6151: #endif
        !          6152: #if defined(QUALIFIER_INTMAX_T)
        !          6153:                    if (flags & FLAGS_INTMAX_T)
        !          6154:                      *(trio_intmax_t *)pointer = (trio_intmax_t)number;
        !          6155:                    else
        !          6156: #endif
        !          6157:                    if (flags & FLAGS_QUAD)
        !          6158:                      *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
        !          6159:                    else if (flags & FLAGS_LONG)
        !          6160:                      *(long int *)pointer = (long int)number;
        !          6161:                    else if (flags & FLAGS_SHORT)
        !          6162:                      *(short int *)pointer = (short int)number;
        !          6163:                    else
        !          6164:                      *(int *)pointer = (int)number;
        !          6165:                  }
        !          6166:              }
        !          6167:              break; /* FORMAT_INT */
        !          6168:              
        !          6169:            case FORMAT_STRING:
        !          6170: #if TRIO_WIDECHAR
        !          6171:              if (flags & FLAGS_WIDECHAR)
        !          6172:                {
        !          6173:                  if (!TrioReadWideString(data,
        !          6174:                                          (flags & FLAGS_IGNORE)
        !          6175:                                          ? NULL
        !          6176:                                          : parameters[i].data.wstring,
        !          6177:                                          flags,
        !          6178:                                          width))
        !          6179:                    return assignment;
        !          6180:                }
        !          6181:              else
        !          6182: #endif
        !          6183:                {
        !          6184:                  if (!TrioReadString(data,
        !          6185:                                      (flags & FLAGS_IGNORE)
        !          6186:                                      ? NULL
        !          6187:                                      : parameters[i].data.string,
        !          6188:                                      flags,
        !          6189:                                      width))
        !          6190:                    return assignment;
        !          6191:                }
        !          6192:              if (!(flags & FLAGS_IGNORE))
        !          6193:                assignment++;
        !          6194:              break; /* FORMAT_STRING */
        !          6195: 
        !          6196:            case FORMAT_DOUBLE:
        !          6197:              {
        !          6198:                trio_pointer_t pointer;
        !          6199: 
        !          6200:                if (flags & FLAGS_IGNORE)
        !          6201:                  {
        !          6202:                    pointer = NULL;
        !          6203:                  }
        !          6204:                else
        !          6205:                  {
        !          6206:                    pointer = (flags & FLAGS_LONGDOUBLE)
        !          6207:                      ? (trio_pointer_t)parameters[i].data.longdoublePointer
        !          6208:                      : (trio_pointer_t)parameters[i].data.doublePointer;
        !          6209:                  }
        !          6210:                if (!TrioReadDouble(data, pointer, flags, width))
        !          6211:                  {
        !          6212:                    return assignment;
        !          6213:                  }
        !          6214:                if (!(flags & FLAGS_IGNORE))
        !          6215:                  {
        !          6216:                    assignment++;
        !          6217:                  }
        !          6218:                break; /* FORMAT_DOUBLE */
        !          6219:              }
        !          6220:            case FORMAT_GROUP:
        !          6221:              {
        !          6222:                int characterclass[MAX_CHARACTER_CLASS + 1];
        !          6223:                int rc;
        !          6224: 
        !          6225:                /* Skip over modifiers */
        !          6226:                while (format[index] != SPECIFIER_GROUP)
        !          6227:                  {
        !          6228:                    index++;
        !          6229:                  }
        !          6230:                /* Skip over group specifier */
        !          6231:                index++;
        !          6232:                
        !          6233:                memset(characterclass, 0, sizeof(characterclass));
        !          6234:                rc = TrioGetCharacterClass(format,
        !          6235:                                           &index,
        !          6236:                                           &flags,
        !          6237:                                           characterclass);
        !          6238:                if (rc < 0)
        !          6239:                  return rc;
        !          6240: 
        !          6241:                if (!TrioReadGroup(data,
        !          6242:                                   (flags & FLAGS_IGNORE)
        !          6243:                                   ? NULL
        !          6244:                                   : parameters[i].data.string,
        !          6245:                                   characterclass,
        !          6246:                                   flags,
        !          6247:                                   parameters[i].width))
        !          6248:                  return assignment;
        !          6249:                if (!(flags & FLAGS_IGNORE))
        !          6250:                  assignment++;
        !          6251:              }
        !          6252:              break; /* FORMAT_GROUP */
        !          6253: 
        !          6254:            case FORMAT_COUNT:
        !          6255:              pointer = parameters[i].data.pointer;
        !          6256:              if (NULL != pointer)
        !          6257:                {
        !          6258:                  int count = data->committed;
        !          6259:                  if (ch != EOF)
        !          6260:                    count--; /* a character is read, but is not consumed yet */
        !          6261: #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
        !          6262:                  if (flags & FLAGS_SIZE_T)
        !          6263:                    *(size_t *)pointer = (size_t)count;
        !          6264:                  else
        !          6265: #endif
        !          6266: #if defined(QUALIFIER_PTRDIFF_T)
        !          6267:                  if (flags & FLAGS_PTRDIFF_T)
        !          6268:                    *(ptrdiff_t *)pointer = (ptrdiff_t)count;
        !          6269:                  else
        !          6270: #endif
        !          6271: #if defined(QUALIFIER_INTMAX_T)
        !          6272:                  if (flags & FLAGS_INTMAX_T)
        !          6273:                    *(trio_intmax_t *)pointer = (trio_intmax_t)count;
        !          6274:                  else
        !          6275: #endif
        !          6276:                  if (flags & FLAGS_QUAD)
        !          6277:                    {
        !          6278:                      *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
        !          6279:                    }
        !          6280:                  else if (flags & FLAGS_LONG)
        !          6281:                    {
        !          6282:                      *(long int *)pointer = (long int)count;
        !          6283:                    }
        !          6284:                  else if (flags & FLAGS_SHORT)
        !          6285:                    {
        !          6286:                      *(short int *)pointer = (short int)count;
        !          6287:                    }
        !          6288:                  else
        !          6289:                    {
        !          6290:                      *(int *)pointer = (int)count;
        !          6291:                    }
        !          6292:                }
        !          6293:              break; /* FORMAT_COUNT */
        !          6294:              
        !          6295:            case FORMAT_CHAR:
        !          6296: #if TRIO_WIDECHAR
        !          6297:              if (flags & FLAGS_WIDECHAR)
        !          6298:                {
        !          6299:                  if (TrioReadWideChar(data,
        !          6300:                                       (flags & FLAGS_IGNORE)
        !          6301:                                       ? NULL
        !          6302:                                       : parameters[i].data.wstring,
        !          6303:                                       flags,
        !          6304:                                       (width == NO_WIDTH) ? 1 : width) == 0)
        !          6305:                    return assignment;
        !          6306:                }
        !          6307:              else
        !          6308: #endif
        !          6309:                {
        !          6310:                  if (TrioReadChar(data,
        !          6311:                                   (flags & FLAGS_IGNORE)
        !          6312:                                   ? NULL
        !          6313:                                   : parameters[i].data.string,
        !          6314:                                   flags,
        !          6315:                                   (width == NO_WIDTH) ? 1 : width) == 0)
        !          6316:                    return assignment;
        !          6317:                }
        !          6318:              if (!(flags & FLAGS_IGNORE))
        !          6319:                assignment++;
        !          6320:              break; /* FORMAT_CHAR */
        !          6321: 
        !          6322:            case FORMAT_POINTER:
        !          6323:              if (!TrioReadPointer(data,
        !          6324:                                   (flags & FLAGS_IGNORE)
        !          6325:                                   ? NULL
        !          6326:                                   : (trio_pointer_t *)parameters[i].data.pointer,
        !          6327:                                   flags))
        !          6328:                return assignment;
        !          6329:              if (!(flags & FLAGS_IGNORE))
        !          6330:                assignment++;
        !          6331:              break; /* FORMAT_POINTER */
        !          6332: 
        !          6333:            case FORMAT_PARAMETER:
        !          6334:              break; /* FORMAT_PARAMETER */
        !          6335: 
        !          6336:            default:
        !          6337:              return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
        !          6338:            }
        !          6339:          ch = data->current;
        !          6340:          index = parameters[i].indexAfterSpecifier;
        !          6341:          i++;
        !          6342:        }
        !          6343:       else /* Not an % identifier */
        !          6344:        {
        !          6345:          if (isspace((int)format[index]))
        !          6346:            {
        !          6347:              /* Whitespaces may match any amount of whitespaces */
        !          6348:              ch = TrioSkipWhitespaces(data);
        !          6349:            }
        !          6350:          else if (ch == format[index])
        !          6351:            {
        !          6352:              data->InStream(data, &ch);
        !          6353:            }
        !          6354:          else
        !          6355:            return assignment;
        !          6356:          
        !          6357:          index++;
        !          6358:        }
        !          6359:     }
        !          6360:   return assignment;
        !          6361: }
        !          6362: 
        !          6363: /*************************************************************************
        !          6364:  * TrioScan
        !          6365:  */
        !          6366: TRIO_PRIVATE int
        !          6367: TrioScan
        !          6368: TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
        !          6369:           trio_pointer_t source,
        !          6370:           size_t sourceSize,
        !          6371:           void (*InStream) TRIO_PROTO((trio_class_t *, int *)),
        !          6372:           TRIO_CONST char *format,
        !          6373:           va_list *arglist,
        !          6374:           trio_pointer_t *argarray)
        !          6375: {
        !          6376:   int status;
        !          6377:   trio_parameter_t parameters[MAX_PARAMETERS];
        !          6378:   trio_class_t data;
        !          6379: 
        !          6380:   assert(VALID(InStream));
        !          6381:   assert(VALID(format));
        !          6382: 
        !          6383:   memset(&data, 0, sizeof(data));
        !          6384:   data.InStream = InStream;
        !          6385:   data.location = (trio_pointer_t)source;
        !          6386:   data.max = sourceSize;
        !          6387:   data.error = 0;
        !          6388: 
        !          6389: #if defined(USE_LOCALE)
        !          6390:   if (NULL == internalLocaleValues)
        !          6391:     {
        !          6392:       TrioSetLocale();
        !          6393:     }
        !          6394: #endif
        !          6395:   
        !          6396:   status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray);
        !          6397:   if (status < 0)
        !          6398:     return status;
        !          6399: 
        !          6400:   status = TrioScanProcess(&data, format, parameters);
        !          6401:   if (data.error != 0)
        !          6402:     {
        !          6403:       status = data.error;
        !          6404:     }
        !          6405:   return status;
        !          6406: }
        !          6407: 
        !          6408: /*************************************************************************
        !          6409:  * TrioInStreamFile
        !          6410:  */
        !          6411: TRIO_PRIVATE void
        !          6412: TrioInStreamFile
        !          6413: TRIO_ARGS2((self, intPointer),
        !          6414:           trio_class_t *self,
        !          6415:           int *intPointer)
        !          6416: {
        !          6417:   FILE *file = (FILE *)self->location;
        !          6418: 
        !          6419:   assert(VALID(self));
        !          6420:   assert(VALID(file));
        !          6421: 
        !          6422:   self->current = fgetc(file);
        !          6423:   if (self->current == EOF)
        !          6424:     {
        !          6425:       self->error = (ferror(file))
        !          6426:        ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0)
        !          6427:        : TRIO_ERROR_RETURN(TRIO_EOF, 0);
        !          6428:     }
        !          6429:   else
        !          6430:     {
        !          6431:       self->processed++;
        !          6432:       self->committed++;
        !          6433:     }
        !          6434:   
        !          6435:   if (VALID(intPointer))
        !          6436:     {
        !          6437:       *intPointer = self->current;
        !          6438:     }
        !          6439: }
        !          6440: 
        !          6441: /*************************************************************************
        !          6442:  * TrioInStreamFileDescriptor
        !          6443:  */
        !          6444: TRIO_PRIVATE void
        !          6445: TrioInStreamFileDescriptor
        !          6446: TRIO_ARGS2((self, intPointer),
        !          6447:           trio_class_t *self,
        !          6448:           int *intPointer)
        !          6449: {
        !          6450:   int fd = *((int *)self->location);
        !          6451:   int size;
        !          6452:   unsigned char input;
        !          6453: 
        !          6454:   assert(VALID(self));
        !          6455: 
        !          6456:   size = read(fd, &input, sizeof(char));
        !          6457:   if (size == -1)
        !          6458:     {
        !          6459:       self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
        !          6460:       self->current = EOF;
        !          6461:     }
        !          6462:   else
        !          6463:     {
        !          6464:       self->current = (size == 0) ? EOF : input;
        !          6465:     }
        !          6466:   if (self->current != EOF)
        !          6467:     {
        !          6468:       self->committed++;
        !          6469:       self->processed++;
        !          6470:     }
        !          6471:   
        !          6472:   if (VALID(intPointer))
        !          6473:     {
        !          6474:       *intPointer = self->current;
        !          6475:     }
        !          6476: }
        !          6477: 
        !          6478: /*************************************************************************
        !          6479:  * TrioInStreamCustom
        !          6480:  */
        !          6481: TRIO_PRIVATE void
        !          6482: TrioInStreamCustom
        !          6483: TRIO_ARGS2((self, intPointer),
        !          6484:           trio_class_t *self,
        !          6485:           int *intPointer)
        !          6486: {
        !          6487:   trio_custom_t *data;
        !          6488:   
        !          6489:   assert(VALID(self));
        !          6490:   assert(VALID(self->location));
        !          6491: 
        !          6492:   data = (trio_custom_t *)self->location;
        !          6493: 
        !          6494:   self->current = (data->stream.in == NULL)
        !          6495:     ? NIL
        !          6496:     : (data->stream.in)(data->closure);
        !          6497:   
        !          6498:   if (self->current == NIL)
        !          6499:     {
        !          6500:       self->current = EOF;
        !          6501:     }
        !          6502:   else
        !          6503:     {
        !          6504:       self->processed++;
        !          6505:       self->committed++;
        !          6506:     }
        !          6507:   
        !          6508:   if (VALID(intPointer))
        !          6509:     {
        !          6510:       *intPointer = self->current;
        !          6511:     }
        !          6512: }
        !          6513: 
        !          6514: /*************************************************************************
        !          6515:  * TrioInStreamString
        !          6516:  */
        !          6517: TRIO_PRIVATE void
        !          6518: TrioInStreamString
        !          6519: TRIO_ARGS2((self, intPointer),
        !          6520:           trio_class_t *self,
        !          6521:           int *intPointer)
        !          6522: {
        !          6523:   unsigned char **buffer;
        !          6524: 
        !          6525:   assert(VALID(self));
        !          6526:   assert(VALID(self->location));
        !          6527: 
        !          6528:   buffer = (unsigned char **)self->location;
        !          6529:   self->current = (*buffer)[0];
        !          6530:   if (self->current == NIL)
        !          6531:     {
        !          6532:       self->current = EOF;
        !          6533:     }
        !          6534:   else
        !          6535:     {
        !          6536:       (*buffer)++;
        !          6537:       self->processed++;
        !          6538:       self->committed++;
        !          6539:     }
        !          6540:   
        !          6541:   if (VALID(intPointer))
        !          6542:     {
        !          6543:       *intPointer = self->current;
        !          6544:     }
        !          6545: }
        !          6546: 
        !          6547: /*************************************************************************
        !          6548:  *
        !          6549:  * Formatted scanning functions
        !          6550:  *
        !          6551:  ************************************************************************/
        !          6552: 
        !          6553: #if defined(TRIO_DOCUMENTATION)
        !          6554: # include "doc/doc_scanf.h"
        !          6555: #endif
        !          6556: /** @addtogroup Scanf
        !          6557:     @{
        !          6558: */
        !          6559: 
        !          6560: /*************************************************************************
        !          6561:  * scanf
        !          6562:  */
        !          6563: 
        !          6564: /**
        !          6565:    Scan characters from standard input stream.
        !          6566: 
        !          6567:    @param format Formatting string.
        !          6568:    @param ... Arguments.
        !          6569:    @return Number of scanned characters.
        !          6570:  */
        !          6571: TRIO_PUBLIC int
        !          6572: trio_scanf
        !          6573: TRIO_VARGS2((format, va_alist),
        !          6574:            TRIO_CONST char *format,
        !          6575:            TRIO_VA_DECL)
        !          6576: {
        !          6577:   int status;
        !          6578:   va_list args;
        !          6579: 
        !          6580:   assert(VALID(format));
        !          6581:   
        !          6582:   TRIO_VA_START(args, format);
        !          6583:   status = TrioScan((trio_pointer_t)stdin, 0,
        !          6584:                    TrioInStreamFile,
        !          6585:                    format, &args, NULL);
        !          6586:   TRIO_VA_END(args);
        !          6587:   return status;
        !          6588: }
        !          6589: 
        !          6590: TRIO_PUBLIC int
        !          6591: trio_vscanf
        !          6592: TRIO_ARGS2((format, args),
        !          6593:           TRIO_CONST char *format,
        !          6594:           va_list args)
        !          6595: {
        !          6596:   assert(VALID(format));
        !          6597:   
        !          6598:   return TrioScan((trio_pointer_t)stdin, 0,
        !          6599:                  TrioInStreamFile,
        !          6600:                  format, &args, NULL);
        !          6601: }
        !          6602: 
        !          6603: TRIO_PUBLIC int
        !          6604: trio_scanfv
        !          6605: TRIO_ARGS2((format, args),
        !          6606:           TRIO_CONST char *format,
        !          6607:           trio_pointer_t *args)
        !          6608: {
        !          6609:   assert(VALID(format));
        !          6610:   
        !          6611:   return TrioScan((trio_pointer_t)stdin, 0,
        !          6612:                  TrioInStreamFile,
        !          6613:                  format, NULL, args);
        !          6614: }
        !          6615: 
        !          6616: /*************************************************************************
        !          6617:  * fscanf
        !          6618:  */
        !          6619: TRIO_PUBLIC int
        !          6620: trio_fscanf
        !          6621: TRIO_VARGS3((file, format, va_alist),
        !          6622:            FILE *file,
        !          6623:            TRIO_CONST char *format,
        !          6624:            TRIO_VA_DECL)
        !          6625: {
        !          6626:   int status;
        !          6627:   va_list args;
        !          6628: 
        !          6629:   assert(VALID(file));
        !          6630:   assert(VALID(format));
        !          6631:   
        !          6632:   TRIO_VA_START(args, format);
        !          6633:   status = TrioScan((trio_pointer_t)file, 0,
        !          6634:                    TrioInStreamFile,
        !          6635:                    format, &args, NULL);
        !          6636:   TRIO_VA_END(args);
        !          6637:   return status;
        !          6638: }
        !          6639: 
        !          6640: TRIO_PUBLIC int
        !          6641: trio_vfscanf
        !          6642: TRIO_ARGS3((file, format, args),
        !          6643:           FILE *file,
        !          6644:           TRIO_CONST char *format,
        !          6645:           va_list args)
        !          6646: {
        !          6647:   assert(VALID(file));
        !          6648:   assert(VALID(format));
        !          6649:   
        !          6650:   return TrioScan((trio_pointer_t)file, 0,
        !          6651:                  TrioInStreamFile,
        !          6652:                  format, &args, NULL);
        !          6653: }
        !          6654: 
        !          6655: TRIO_PUBLIC int
        !          6656: trio_fscanfv
        !          6657: TRIO_ARGS3((file, format, args),
        !          6658:           FILE *file,
        !          6659:           TRIO_CONST char *format,
        !          6660:           trio_pointer_t *args)
        !          6661: {
        !          6662:   assert(VALID(file));
        !          6663:   assert(VALID(format));
        !          6664:   
        !          6665:   return TrioScan((trio_pointer_t)file, 0,
        !          6666:                  TrioInStreamFile,
        !          6667:                  format, NULL, args);
        !          6668: }
        !          6669: 
        !          6670: /*************************************************************************
        !          6671:  * dscanf
        !          6672:  */
        !          6673: TRIO_PUBLIC int
        !          6674: trio_dscanf
        !          6675: TRIO_VARGS3((fd, format, va_alist),
        !          6676:            int fd,
        !          6677:            TRIO_CONST char *format,
        !          6678:            TRIO_VA_DECL)
        !          6679: {
        !          6680:   int status;
        !          6681:   va_list args;
        !          6682: 
        !          6683:   assert(VALID(format));
        !          6684:   
        !          6685:   TRIO_VA_START(args, format);
        !          6686:   status = TrioScan((trio_pointer_t)&fd, 0,
        !          6687:                    TrioInStreamFileDescriptor,
        !          6688:                    format, &args, NULL);
        !          6689:   TRIO_VA_END(args);
        !          6690:   return status;
        !          6691: }
        !          6692: 
        !          6693: TRIO_PUBLIC int
        !          6694: trio_vdscanf
        !          6695: TRIO_ARGS3((fd, format, args),
        !          6696:           int fd,
        !          6697:           TRIO_CONST char *format,
        !          6698:           va_list args)
        !          6699: {
        !          6700:   assert(VALID(format));
        !          6701:   
        !          6702:   return TrioScan((trio_pointer_t)&fd, 0,
        !          6703:                  TrioInStreamFileDescriptor,
        !          6704:                  format, &args, NULL);
        !          6705: }
        !          6706: 
        !          6707: TRIO_PUBLIC int
        !          6708: trio_dscanfv
        !          6709: TRIO_ARGS3((fd, format, args),
        !          6710:           int fd,
        !          6711:           TRIO_CONST char *format,
        !          6712:           trio_pointer_t *args)
        !          6713: {
        !          6714:   assert(VALID(format));
        !          6715:   
        !          6716:   return TrioScan((trio_pointer_t)&fd, 0,
        !          6717:                  TrioInStreamFileDescriptor,
        !          6718:                  format, NULL, args);
        !          6719: }
        !          6720: 
        !          6721: /*************************************************************************
        !          6722:  * cscanf
        !          6723:  */
        !          6724: TRIO_PUBLIC int
        !          6725: trio_cscanf
        !          6726: TRIO_VARGS4((stream, closure, format, va_alist),
        !          6727:            trio_instream_t stream,
        !          6728:            trio_pointer_t closure,
        !          6729:            TRIO_CONST char *format,
        !          6730:            TRIO_VA_DECL)
        !          6731: {
        !          6732:   int status;
        !          6733:   va_list args;
        !          6734:   trio_custom_t data;
        !          6735: 
        !          6736:   assert(VALID(stream));
        !          6737:   assert(VALID(format));
        !          6738:   
        !          6739:   TRIO_VA_START(args, format);
        !          6740:   data.stream.in = stream;
        !          6741:   data.closure = closure;
        !          6742:   status = TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
        !          6743:   TRIO_VA_END(args);
        !          6744:   return status;
        !          6745: }
        !          6746: 
        !          6747: TRIO_PUBLIC int
        !          6748: trio_vcscanf
        !          6749: TRIO_ARGS4((stream, closure, format, args),
        !          6750:           trio_instream_t stream,
        !          6751:           trio_pointer_t closure,
        !          6752:           TRIO_CONST char *format,
        !          6753:           va_list args)
        !          6754: {
        !          6755:   trio_custom_t data;
        !          6756:   
        !          6757:   assert(VALID(stream));
        !          6758:   assert(VALID(format));
        !          6759: 
        !          6760:   data.stream.in = stream;
        !          6761:   data.closure = closure;
        !          6762:   return TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
        !          6763: }
        !          6764: 
        !          6765: TRIO_PUBLIC int
        !          6766: trio_cscanfv
        !          6767: TRIO_ARGS4((stream, closure, format, args),
        !          6768:           trio_instream_t stream,
        !          6769:           trio_pointer_t closure,
        !          6770:           TRIO_CONST char *format,
        !          6771:           trio_pointer_t *args)
        !          6772: {
        !          6773:   trio_custom_t data;
        !          6774:   
        !          6775:   assert(VALID(stream));
        !          6776:   assert(VALID(format));
        !          6777: 
        !          6778:   data.stream.in = stream;
        !          6779:   data.closure = closure;
        !          6780:   return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args);
        !          6781: }
        !          6782: 
        !          6783: /*************************************************************************
        !          6784:  * sscanf
        !          6785:  */
        !          6786: TRIO_PUBLIC int
        !          6787: trio_sscanf
        !          6788: TRIO_VARGS3((buffer, format, va_alist),
        !          6789:            TRIO_CONST char *buffer,
        !          6790:            TRIO_CONST char *format,
        !          6791:            TRIO_VA_DECL)
        !          6792: {
        !          6793:   int status;
        !          6794:   va_list args;
        !          6795: 
        !          6796:   assert(VALID(buffer));
        !          6797:   assert(VALID(format));
        !          6798:   
        !          6799:   TRIO_VA_START(args, format);
        !          6800:   status = TrioScan((trio_pointer_t)&buffer, 0,
        !          6801:                    TrioInStreamString,
        !          6802:                    format, &args, NULL);
        !          6803:   TRIO_VA_END(args);
        !          6804:   return status;
        !          6805: }
        !          6806: 
        !          6807: TRIO_PUBLIC int
        !          6808: trio_vsscanf
        !          6809: TRIO_ARGS3((buffer, format, args),
        !          6810:           TRIO_CONST char *buffer,
        !          6811:           TRIO_CONST char *format,
        !          6812:           va_list args)
        !          6813: {
        !          6814:   assert(VALID(buffer));
        !          6815:   assert(VALID(format));
        !          6816:   
        !          6817:   return TrioScan((trio_pointer_t)&buffer, 0,
        !          6818:                  TrioInStreamString,
        !          6819:                  format, &args, NULL);
        !          6820: }
        !          6821: 
        !          6822: TRIO_PUBLIC int
        !          6823: trio_sscanfv
        !          6824: TRIO_ARGS3((buffer, format, args),
        !          6825:           TRIO_CONST char *buffer,
        !          6826:           TRIO_CONST char *format,
        !          6827:           trio_pointer_t *args)
        !          6828: {
        !          6829:   assert(VALID(buffer));
        !          6830:   assert(VALID(format));
        !          6831:   
        !          6832:   return TrioScan((trio_pointer_t)&buffer, 0,
        !          6833:                  TrioInStreamString,
        !          6834:                  format, NULL, args);
        !          6835: }
        !          6836: 
        !          6837: /** @} End of Scanf documentation module */
        !          6838: 
        !          6839: /*************************************************************************
        !          6840:  * trio_strerror
        !          6841:  */
        !          6842: TRIO_PUBLIC TRIO_CONST char *
        !          6843: trio_strerror
        !          6844: TRIO_ARGS1((errorcode),
        !          6845:           int errorcode)
        !          6846: {
        !          6847:   /* Textual versions of the error codes */
        !          6848:   switch (TRIO_ERROR_CODE(errorcode))
        !          6849:     {
        !          6850:     case TRIO_EOF:
        !          6851:       return "End of file";
        !          6852:     case TRIO_EINVAL:
        !          6853:       return "Invalid argument";
        !          6854:     case TRIO_ETOOMANY:
        !          6855:       return "Too many arguments";
        !          6856:     case TRIO_EDBLREF:
        !          6857:       return "Double reference";
        !          6858:     case TRIO_EGAP:
        !          6859:       return "Reference gap";
        !          6860:     case TRIO_ENOMEM:
        !          6861:       return "Out of memory";
        !          6862:     case TRIO_ERANGE:
        !          6863:       return "Invalid range";
        !          6864:     case TRIO_ECUSTOM:
        !          6865:       return "Custom error";
        !          6866:     default:
        !          6867:       return "Unknown";
        !          6868:     }
        !          6869: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>