File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / trio.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 19:53:28 2014 UTC (9 years, 11 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_9_1p0, v2_9_1, HEAD
libxml2 2.9.1

    1: /*************************************************************************
    2:  *
    3:  * $Id: trio.c,v 1.1.1.2 2014/06/15 19:53:28 misho Exp $
    4:  *
    5:  * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
    6:  *
    7:  * Permission to use, copy, modify, and distribute this software for any
    8:  * purpose with or without fee is hereby granted, provided that the above
    9:  * copyright notice and this permission notice appear in all copies.
   10:  *
   11:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
   12:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
   13:  * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
   14:  * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
   15:  *
   16:  *************************************************************************
   17:  *
   18:  * A note to trio contributors:
   19:  *
   20:  * Avoid heap allocation at all costs to ensure that the trio functions
   21:  * are async-safe. The exceptions are the printf/fprintf functions, which
   22:  * uses fputc, and the asprintf functions and the <alloc> modifier, which
   23:  * by design are required to allocate form the heap.
   24:  *
   25:  ************************************************************************/
   26: 
   27: /*
   28:  * TODO:
   29:  *  - Scan is probably too permissive about its modifiers.
   30:  *  - C escapes in %#[] ?
   31:  *  - Multibyte characters (done for format parsing, except scan groups)
   32:  *  - Complex numbers? (C99 _Complex)
   33:  *  - Boolean values? (C99 _Bool)
   34:  *  - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used
   35:  *    to print the mantissa, e.g. NaN(0xc000000000000000)
   36:  *  - Should we support the GNU %a alloc modifier? GNU has an ugly hack
   37:  *    for %a, because C99 used %a for other purposes. If specified as
   38:  *    %as or %a[ it is interpreted as the alloc modifier, otherwise as
   39:  *    the C99 hex-float. This means that you cannot scan %as as a hex-float
   40:  *    immediately followed by an 's'.
   41:  *  - Scanning of collating symbols.
   42:  */
   43: 
   44: /*************************************************************************
   45:  * Trio include files
   46:  */
   47: #include "triodef.h"
   48: #include "trio.h"
   49: #include "triop.h"
   50: #include "trionan.h"
   51: #if !defined(TRIO_MINIMAL)
   52: # include "triostr.h"
   53: #endif
   54: 
   55: /**************************************************************************
   56:  *
   57:  * Definitions
   58:  *
   59:  *************************************************************************/
   60: 
   61: #include <math.h>
   62: #include <limits.h>
   63: #include <float.h>
   64: 
   65: #if (defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) \
   66:      || defined(USE_MULTIBYTE) || TRIO_WIDECHAR) \
   67:     && !defined(_WIN32_WCE)
   68: # define TRIO_COMPILER_SUPPORTS_MULTIBYTE
   69: # if !defined(MB_LEN_MAX)
   70: #  define MB_LEN_MAX 6
   71: # endif
   72: #endif
   73: 
   74: #if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
   75: # define TRIO_COMPILER_SUPPORTS_MSVC_INT
   76: #endif
   77: 
   78: #if defined(_WIN32_WCE)
   79: #include <wincecompat.h>
   80: #endif
   81: 
   82: /*************************************************************************
   83:  * Generic definitions
   84:  */
   85: 
   86: #if !(defined(DEBUG) || defined(NDEBUG))
   87: # define NDEBUG
   88: #endif
   89: 
   90: #include <assert.h>
   91: #include <ctype.h>
   92: #if !defined(TRIO_COMPILER_SUPPORTS_C99)
   93: # define isblank(x) (((x)==32) || ((x)==9))
   94: #endif
   95: #if defined(TRIO_COMPILER_ANCIENT)
   96: # include <varargs.h>
   97: #else
   98: # include <stdarg.h>
   99: #endif
  100: #include <stddef.h>
  101: 
  102: #ifdef HAVE_ERRNO_H
  103: #include <errno.h>
  104: #endif
  105: 
  106: #ifndef NULL
  107: # define NULL 0
  108: #endif
  109: #define NIL ((char)0)
  110: #ifndef FALSE
  111: # define FALSE (1 == 0)
  112: # define TRUE (! FALSE)
  113: #endif
  114: #define BOOLEAN_T int
  115: 
  116: /* mincore() can be used for debugging purposes */
  117: #define VALID(x) (NULL != (x))
  118: 
  119: #if TRIO_ERRORS
  120:   /*
  121:    * Encode the error code and the position. This is decoded
  122:    * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
  123:    */
  124: # define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
  125: #else
  126: # define TRIO_ERROR_RETURN(x,y) (-1)
  127: #endif
  128: 
  129: typedef unsigned long trio_flags_t;
  130: 
  131: 
  132: /*************************************************************************
  133:  * Platform specific definitions
  134:  */
  135: #if defined(TRIO_PLATFORM_UNIX)
  136: # include <unistd.h>
  137: # include <signal.h>
  138: # include <locale.h>
  139: # define USE_LOCALE
  140: #endif /* TRIO_PLATFORM_UNIX */
  141: #if defined(TRIO_PLATFORM_VMS)
  142: # include <unistd.h>
  143: #endif
  144: #if defined(TRIO_PLATFORM_WIN32)
  145: # if defined(_WIN32_WCE)
  146: #  include <wincecompat.h>
  147: # else
  148: #  include <io.h>
  149: #  define read _read
  150: #  define write _write
  151: # endif
  152: #endif /* TRIO_PLATFORM_WIN32 */
  153: 
  154: #if TRIO_WIDECHAR
  155: # if defined(TRIO_COMPILER_SUPPORTS_ISO94)
  156: #  include <wchar.h>
  157: #  include <wctype.h>
  158: typedef wchar_t trio_wchar_t;
  159: typedef wint_t trio_wint_t;
  160: # else
  161: typedef char trio_wchar_t;
  162: typedef int trio_wint_t;
  163: #  define WCONST(x) L ## x
  164: #  define WEOF EOF
  165: #  define iswalnum(x) isalnum(x)
  166: #  define iswalpha(x) isalpha(x)
  167: #  define iswblank(x) isblank(x)
  168: #  define iswcntrl(x) iscntrl(x)
  169: #  define iswdigit(x) isdigit(x)
  170: #  define iswgraph(x) isgraph(x)
  171: #  define iswlower(x) islower(x)
  172: #  define iswprint(x) isprint(x)
  173: #  define iswpunct(x) ispunct(x)
  174: #  define iswspace(x) isspace(x)
  175: #  define iswupper(x) isupper(x)
  176: #  define iswxdigit(x) isxdigit(x)
  177: # endif
  178: #endif
  179: 
  180: 
  181: /*************************************************************************
  182:  * Compiler dependent definitions
  183:  */
  184: 
  185: /* Support for long long */
  186: #ifndef __cplusplus
  187: # if !defined(USE_LONGLONG)
  188: #  if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
  189: #   define USE_LONGLONG
  190: #  elif defined(TRIO_COMPILER_SUNPRO)
  191: #   define USE_LONGLONG
  192: #  elif defined(_LONG_LONG) || defined(_LONGLONG)
  193: #   define USE_LONGLONG
  194: #  endif
  195: # endif
  196: #endif
  197: 
  198: /* The extra long numbers */
  199: #if defined(USE_LONGLONG)
  200: typedef signed long long int trio_longlong_t;
  201: typedef unsigned long long int trio_ulonglong_t;
  202: #elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
  203: typedef signed __int64 trio_longlong_t;
  204: typedef unsigned __int64 trio_ulonglong_t;
  205: #else
  206: typedef TRIO_SIGNED long int trio_longlong_t;
  207: typedef unsigned long int trio_ulonglong_t;
  208: #endif
  209: 
  210: /* Maximal and fixed integer types */
  211: #if defined(TRIO_COMPILER_SUPPORTS_C99)
  212: # include <stdint.h>
  213: typedef intmax_t trio_intmax_t;
  214: typedef uintmax_t trio_uintmax_t;
  215: typedef int8_t trio_int8_t;
  216: typedef int16_t trio_int16_t;
  217: typedef int32_t trio_int32_t;
  218: typedef int64_t trio_int64_t;
  219: #elif defined(TRIO_COMPILER_SUPPORTS_UNIX98)
  220: # include <inttypes.h>
  221: typedef intmax_t trio_intmax_t;
  222: typedef uintmax_t trio_uintmax_t;
  223: typedef int8_t trio_int8_t;
  224: typedef int16_t trio_int16_t;
  225: typedef int32_t trio_int32_t;
  226: typedef int64_t trio_int64_t;
  227: #elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
  228: typedef trio_longlong_t trio_intmax_t;
  229: typedef trio_ulonglong_t trio_uintmax_t;
  230: typedef __int8 trio_int8_t;
  231: typedef __int16 trio_int16_t;
  232: typedef __int32 trio_int32_t;
  233: typedef __int64 trio_int64_t;
  234: #else
  235: typedef trio_longlong_t trio_intmax_t;
  236: typedef trio_ulonglong_t trio_uintmax_t;
  237: # if defined(TRIO_INT8_T)
  238: typedef TRIO_INT8_T trio_int8_t;
  239: # else
  240: typedef TRIO_SIGNED char trio_int8_t;
  241: # endif
  242: # if defined(TRIO_INT16_T)
  243: typedef TRIO_INT16_T trio_int16_t;
  244: # else
  245: typedef TRIO_SIGNED short trio_int16_t;
  246: # endif
  247: # if defined(TRIO_INT32_T)
  248: typedef TRIO_INT32_T trio_int32_t;
  249: # else
  250: typedef TRIO_SIGNED int trio_int32_t;
  251: # endif
  252: # if defined(TRIO_INT64_T)
  253: typedef TRIO_INT64_T trio_int64_t;
  254: # else
  255: typedef trio_longlong_t trio_int64_t;
  256: # endif
  257: #endif
  258: 
  259: #if (!(defined(TRIO_COMPILER_SUPPORTS_C99) \
  260:  || defined(TRIO_COMPILER_SUPPORTS_UNIX01))) \
  261:  && !defined(_WIN32_WCE)
  262: # define floorl(x) floor((double)(x))
  263: # define fmodl(x,y) fmod((double)(x),(double)(y))
  264: # define powl(x,y) pow((double)(x),(double)(y))
  265: #endif
  266: 
  267: #define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
  268: 
  269: /*************************************************************************
  270:  * Internal Definitions
  271:  */
  272: 
  273: #ifndef DECIMAL_DIG
  274: # define DECIMAL_DIG DBL_DIG
  275: #endif
  276: 
  277: /* Long double sizes */
  278: #ifdef LDBL_DIG
  279: # define MAX_MANTISSA_DIGITS LDBL_DIG
  280: # define MAX_EXPONENT_DIGITS 4
  281: # define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
  282: #else
  283: # define MAX_MANTISSA_DIGITS DECIMAL_DIG
  284: # define MAX_EXPONENT_DIGITS 3
  285: # define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
  286: #endif
  287: 
  288: #if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
  289: # undef LDBL_DIG
  290: # undef LDBL_MANT_DIG
  291: # undef LDBL_EPSILON
  292: # define LDBL_DIG DBL_DIG
  293: # define LDBL_MANT_DIG DBL_MANT_DIG
  294: # define LDBL_EPSILON DBL_EPSILON
  295: #endif
  296: 
  297: /* The maximal number of digits is for base 2 */
  298: #define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
  299: /* The width of a pointer. The number of bits in a hex digit is 4 */
  300: #define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
  301: 
  302: /* Infinite and Not-A-Number for floating-point */
  303: #define INFINITE_LOWER "inf"
  304: #define INFINITE_UPPER "INF"
  305: #define LONG_INFINITE_LOWER "infinite"
  306: #define LONG_INFINITE_UPPER "INFINITE"
  307: #define NAN_LOWER "nan"
  308: #define NAN_UPPER "NAN"
  309: 
  310: #if !defined(HAVE_ISASCII) && !defined(isascii)
  311: #  define isascii(x) ((unsigned int)(x) < 128)
  312: #endif
  313: 
  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,
  383: 
  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: trio.c,v 1.1.1.2 2014/06/15 19:53:28 misho Exp $";
  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;
 1027: 
 1028:   if (internalEnterCriticalRegion)
 1029:     (void)internalEnterCriticalRegion(NULL);
 1030: 
 1031:   for (def = internalUserDef; def; def = def->next)
 1032:     {
 1033:       /* Case-sensitive string comparison */
 1034:       if (trio_equal_case(def->name, name))
 1035: 	break;
 1036: 
 1037:       if (prev)
 1038: 	*prev = def;
 1039:     }
 1040: 
 1041:   if (internalLeaveCriticalRegion)
 1042:     (void)internalLeaveCriticalRegion(NULL);
 1043: 
 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));
 1207: 
 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
 1220: 
 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;
 1298: 
 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++;
 1343: 
 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);
 1542: 
 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
 1570: 
 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: 	    }
 1635: 
 1636: 	  indices[currentParam] = pos;
 1637: 
 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;
 1696: 
 1697: 	    case SPECIFIER_INTEGER:
 1698: 	      parameters[pos].type = FORMAT_INT;
 1699: 	      break;
 1700: 
 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;
 1800: 
 1801: 		parameters[pos].type = FORMAT_USER_DEFINED;
 1802: 		parameters[pos].user_name[0] = NIL;
 1803: 		tmpformat = (char *)&format[index];
 1804: 
 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) */
 1852: 
 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;
 1860: 
 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: 	    }
 1883: 
 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++;
 1891: 
 1892: 	  if (! positional)
 1893: 	    parameterPosition++;
 1894: 
 1895: 	} /* if identifier */
 1896: 
 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: 	}
 1908: 
 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)
 1976:                 parameters[i].data.pointer =
 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;
 2016: 
 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;
 2220: 
 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;
 2267: 
 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);
 2502: 
 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
 2544: 
 2545:   if (wstring == NULL)
 2546:     {
 2547:       TrioWriteString(self, NULL, flags, width, precision);
 2548:       return;
 2549:     }
 2550: 
 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;
 2645: 
 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;
 2660: 
 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:     }
 2687: 
 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:     }
 2735: 
 2736:   if (isNegative)
 2737:     number = -number;
 2738: 
 2739:   if (isHex)
 2740:     flags |= FLAGS_FLOAT_E;
 2741: 
 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;
 2794: 
 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);
 2809: 
 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:     }
 2862: 
 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;
 2898: 
 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:     }
 2944: 
 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;
 2960: 
 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:     }
 2972: 
 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:     }
 3021: 
 3022:   if (keepTrailingZeroes)
 3023:     {
 3024:       while (trailingZeroes > 0)
 3025: 	{
 3026: 	  self->OutStream(self, digits[0]);
 3027: 	  trailingZeroes--;
 3028: 	}
 3029:     }
 3030: 
 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;
 3087: 
 3088:   index = 0;
 3089:   i = 0;
 3090: #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
 3091:   (void)mblen(NULL, 0);
 3092: #endif
 3093: 
 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++;
 3127: 
 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: 		}
 3147: 
 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: 		}
 3178: 
 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;
 3258: 
 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) */
 3361: 
 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));
 3571: 
 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));
 3639: 
 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));
 3706: 
 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));
 3730: 
 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));
 3751: 
 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));
 3778: 
 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));
 3801: 
 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));
 3821: 
 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));
 3911: 
 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;
 4105: 
 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));
 4133: 
 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;
 4158: 
 4159:   assert(VALID(format));
 4160: 
 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;
 4187: 
 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;
 4218: 
 4219:   assert(VALID(format));
 4220: 
 4221:   *result = NULL;
 4222: 
 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:  */
 4271: TRIO_PUBLIC trio_pointer_t
 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: 	}
 4298: 
 4299:       /* Bail out if namespace is too long */
 4300:       if (trio_length(name) >= MAX_USER_NAME)
 4301: 	return NULL;
 4302: 
 4303:       /* Bail out if namespace already is registered */
 4304:       def = TrioFindNamespace(name, &prev);
 4305:       if (def)
 4306: 	return NULL;
 4307:     }
 4308: 
 4309:   def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t));
 4310:   if (def)
 4311:     {
 4312:       if (internalEnterCriticalRegion)
 4313: 	(void)internalEnterCriticalRegion(NULL);
 4314: 
 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);
 4359: 
 4360: 	  if (prev == NULL)
 4361: 	    internalUserDef = NULL;
 4362: 	  else
 4363: 	    prev->next = def->next;
 4364: 
 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
 4384: 
 4385:   return (((trio_reference_t *)ref)->parameter->user_data);
 4386: }
 4387: 
 4388: /*************************************************************************
 4389:  * trio_get_argument [public]
 4390:  */
 4391: trio_pointer_t
 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
 4399: 
 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));
 4931: 
 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));
 4949: 
 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));
 4964: 
 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 */
 5213: 
 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);
 5240: 
 5241: 	  for (i = (int)range_begin; i <= (int)range_end; i++)
 5242: 	    characterclass[i]++;
 5243: 
 5244: 	  ch = range_end;
 5245: 	  break;
 5246: 
 5247: #if TRIO_EXTENSION
 5248: 
 5249: 	case SPECIFIER_GROUP:
 5250: 
 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;
 5269: 
 5270: 	      index = i;
 5271: 	      break;
 5272: 
 5273: 	    case QUALIFIER_EQUAL: /* Equivalence class expressions */
 5274: 	      {
 5275: 		unsigned int j;
 5276: 		unsigned int k;
 5277: 
 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;
 5301: 
 5302: 		index = i;
 5303: 	      }
 5304: 	      break;
 5305: 
 5306: 	    case QUALIFIER_COLON: /* Character class expressions */
 5307: 
 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;
 5407: 
 5408: #endif /* TRIO_EXTENSION */
 5409: 
 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:     }
 5455: 
 5456:   TrioSkipWhitespaces(self);
 5457: 
 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:     }
 5471: 
 5472:   count = self->processed;
 5473: 
 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;
 5534: 
 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;
 5545: 
 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;
 5565: 
 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: 	}
 5610: 
 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;
 5629: 
 5630:   assert(VALID(self));
 5631:   assert(VALID(self->InStream));
 5632: 
 5633:   TrioSkipWhitespaces(self);
 5634: 
 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];
 5670: 
 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;
 5727: 
 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
 5736: 
 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;
 5774: 
 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:     }
 5789: 
 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;
 5818: 
 5819:   if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1))
 5820:     width = sizeof(doubleString) - 1;
 5821: 
 5822:   TrioSkipWhitespaces(self);
 5823: 
 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;
 5909: 
 5910:     default:
 5911:       break;
 5912:     }
 5913: 
 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;
 5973: 
 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);
 5999: 
 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))
 6020:     {
 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 */
 6084: 
 6085:       if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
 6086: 	{
 6087: 	  return (assignment > 0) ? assignment : EOF;
 6088: 	}
 6089: 
 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++;
 6108: 
 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: 	    }
 6124: 
 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 */
 6172: 
 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++;
 6236: 
 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 */
 6298: 
 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;
 6360: 
 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
 6399: 
 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:     }
 6438: 
 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:     }
 6475: 
 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;
 6492: 
 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);
 6501: 
 6502:   if (self->current == NIL)
 6503:     {
 6504:       self->current = EOF;
 6505:     }
 6506:   else
 6507:     {
 6508:       self->processed++;
 6509:       self->committed++;
 6510:     }
 6511: 
 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:     }
 6544: 
 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));
 6585: 
 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));
 6601: 
 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));
 6614: 
 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));
 6635: 
 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));
 6653: 
 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));
 6668: 
 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));
 6688: 
 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));
 6705: 
 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));
 6719: 
 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));
 6742: 
 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;
 6760: 
 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;
 6778: 
 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));
 6802: 
 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));
 6820: 
 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));
 6835: 
 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>