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

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

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